fallow 2.103.0 → 3.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fallow",
3
- "version": "2.103.0",
3
+ "version": "3.0.0",
4
4
  "description": "Deterministic codebase intelligence for TypeScript and JavaScript. Quality, risk, architecture, dependencies, duplication, and safe cleanup evidence for humans, CI, and agents. Optional runtime intelligence layer (Fallow Runtime) adds production execution evidence. Rust-native, sub-second, zero-config framework support.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -51,7 +51,9 @@
51
51
  "./bin/*": "./bin/*",
52
52
  "./scripts/*": "./scripts/*",
53
53
  "./skills/*": "./skills/*",
54
- "./schema.json": "./schema.json"
54
+ "./schema.json": "./schema.json",
55
+ "./capabilities.json": "./capabilities.json",
56
+ "./issue-registry.json": "./issue-registry.json"
55
57
  },
56
58
  "typesVersions": {
57
59
  "*": {
@@ -67,7 +69,9 @@
67
69
  "!skills/_artifacts",
68
70
  "types",
69
71
  "README.md",
70
- "schema.json"
72
+ "schema.json",
73
+ "capabilities.json",
74
+ "issue-registry.json"
71
75
  ],
72
76
  "scripts": {
73
77
  "test:platform": "node --test scripts/platform-package.test.js",
@@ -80,16 +84,16 @@
80
84
  "detect-libc": "2.1.2"
81
85
  },
82
86
  "devDependencies": {
83
- "@tanstack/intent": "0.1.1"
87
+ "@tanstack/intent": "0.3.2"
84
88
  },
85
89
  "optionalDependencies": {
86
- "@fallow-cli/darwin-arm64": "2.103.0",
87
- "@fallow-cli/darwin-x64": "2.103.0",
88
- "@fallow-cli/linux-x64-gnu": "2.103.0",
89
- "@fallow-cli/linux-arm64-gnu": "2.103.0",
90
- "@fallow-cli/linux-x64-musl": "2.103.0",
91
- "@fallow-cli/linux-arm64-musl": "2.103.0",
92
- "@fallow-cli/win32-arm64-msvc": "2.103.0",
93
- "@fallow-cli/win32-x64-msvc": "2.103.0"
90
+ "@fallow-cli/darwin-arm64": "3.0.0",
91
+ "@fallow-cli/darwin-x64": "3.0.0",
92
+ "@fallow-cli/linux-x64-gnu": "3.0.0",
93
+ "@fallow-cli/linux-arm64-gnu": "3.0.0",
94
+ "@fallow-cli/linux-x64-musl": "3.0.0",
95
+ "@fallow-cli/linux-arm64-musl": "3.0.0",
96
+ "@fallow-cli/win32-arm64-msvc": "3.0.0",
97
+ "@fallow-cli/win32-x64-msvc": "3.0.0"
94
98
  }
95
99
  }
package/schema.json CHANGED
@@ -167,6 +167,11 @@
167
167
  "prop-drilling": "off",
168
168
  "thin-wrapper": "off",
169
169
  "duplicate-prop-shape": "off",
170
+ "css-token-drift": "warn",
171
+ "css-duplicate-block": "warn",
172
+ "css-selector-complexity": "warn",
173
+ "css-dead-surface": "warn",
174
+ "css-broken-reference": "warn",
170
175
  "unresolved-imports": "error",
171
176
  "unlisted-dependencies": "error",
172
177
  "duplicate-exports": "error",
@@ -194,6 +199,9 @@
194
199
  "dynamic-segment-name-conflict": "error"
195
200
  }
196
201
  },
202
+ "unusedComponentProps": {
203
+ "$ref": "#/$defs/UnusedComponentPropsConfig"
204
+ },
197
205
  "boundaries": {
198
206
  "$ref": "#/$defs/BoundaryConfig",
199
207
  "default": {
@@ -1096,6 +1104,31 @@
1096
1104
  "$ref": "#/$defs/Severity",
1097
1105
  "default": "off"
1098
1106
  },
1107
+ "css-token-drift": {
1108
+ "description": "A CSS / CSS-in-JS design-token DRIFT finding (a hardcoded value where a\ndesign token exists, e.g. a Tailwind arbitrary value). A styling-domain\nadvisory surfaced in `fallow audit`; defaults to `warn` (verdict-neutral).\nSet to `error` to gate CI on styling drift, or `off` to silence.",
1109
+ "$ref": "#/$defs/Severity",
1110
+ "default": "warn"
1111
+ },
1112
+ "css-duplicate-block": {
1113
+ "description": "A CSS / CSS-in-JS DUPLICATE declaration block (copy-pasted rule body).\nA styling-domain advisory surfaced in `fallow audit`; defaults to `warn`\n(verdict-neutral). Set to `error` to gate, or `off` to silence.",
1114
+ "$ref": "#/$defs/Severity",
1115
+ "default": "warn"
1116
+ },
1117
+ "css-selector-complexity": {
1118
+ "description": "CSS selector / nesting / important-density complexity. A styling-domain\nadvisory surfaced in `fallow audit`; defaults to `warn`\n(verdict-neutral). Set to `error` to gate, or `off` to silence.",
1119
+ "$ref": "#/$defs/Severity",
1120
+ "default": "warn"
1121
+ },
1122
+ "css-dead-surface": {
1123
+ "description": "CSS dead surface, such as unused scoped SFC classes. A styling-domain\nadvisory surfaced in `fallow audit`; defaults to `warn`\n(verdict-neutral). Set to `error` to gate, or `off` to silence.",
1124
+ "$ref": "#/$defs/Severity",
1125
+ "default": "warn"
1126
+ },
1127
+ "css-broken-reference": {
1128
+ "description": "CSS broken references, such as missing classes or keyframes. A\nstyling-domain advisory surfaced by deep CSS audit mode; defaults\nto `warn` (verdict-neutral). Set to `error` to gate, or `off` to silence.",
1129
+ "$ref": "#/$defs/Severity",
1130
+ "default": "warn"
1131
+ },
1099
1132
  "unresolved-imports": {
1100
1133
  "$ref": "#/$defs/Severity",
1101
1134
  "default": "error"
@@ -1227,6 +1260,20 @@
1227
1260
  }
1228
1261
  ]
1229
1262
  },
1263
+ "UnusedComponentPropsConfig": {
1264
+ "description": "Options for the `unused-component-props` rule.\n\nLets a project exempt component props whose local destructure binding name\nmatches a regex from `unused-component-props`, honoring the\n\"accepted-but-intentionally-unused\" leading-underscore convention (Svelte 5\n`$props()`, React destructure) that mirrors TypeScript `noUnusedParameters`\nand ESLint `@typescript-eslint/no-unused-vars` `varsIgnorePattern` /\n`argsIgnorePattern`. Opt-in; an unset `ignorePattern` leaves the rule's\nbehavior unchanged.",
1265
+ "type": "object",
1266
+ "properties": {
1267
+ "ignorePattern": {
1268
+ "description": "Regex matched against each declared prop's LOCAL destructure binding name\n(e.g. `_stage` in `let { stage: _stage } = $props()`), which falls back\nto the public prop name when there is no alias. A prop whose local name\nmatches is treated as intentionally unused and never reported as\n`unused-component-props`. Matching is unanchored (substring), like\nESLint's `RegExp.test`, so anchor with `^_` to match a leading\nunderscore. Compiled and validated at config load (an invalid regex fails\nload). Applies to Vue, Svelte, Astro, and React/Preact props.",
1269
+ "type": [
1270
+ "string",
1271
+ "null"
1272
+ ]
1273
+ }
1274
+ },
1275
+ "additionalProperties": false
1276
+ },
1230
1277
  "BoundaryConfig": {
1231
1278
  "description": "Architecture boundary configuration.",
1232
1279
  "type": "object",
@@ -1835,6 +1882,56 @@
1835
1882
  }
1836
1883
  ]
1837
1884
  },
1885
+ "css-token-drift": {
1886
+ "anyOf": [
1887
+ {
1888
+ "$ref": "#/$defs/Severity"
1889
+ },
1890
+ {
1891
+ "type": "null"
1892
+ }
1893
+ ]
1894
+ },
1895
+ "css-duplicate-block": {
1896
+ "anyOf": [
1897
+ {
1898
+ "$ref": "#/$defs/Severity"
1899
+ },
1900
+ {
1901
+ "type": "null"
1902
+ }
1903
+ ]
1904
+ },
1905
+ "css-selector-complexity": {
1906
+ "anyOf": [
1907
+ {
1908
+ "$ref": "#/$defs/Severity"
1909
+ },
1910
+ {
1911
+ "type": "null"
1912
+ }
1913
+ ]
1914
+ },
1915
+ "css-dead-surface": {
1916
+ "anyOf": [
1917
+ {
1918
+ "$ref": "#/$defs/Severity"
1919
+ },
1920
+ {
1921
+ "type": "null"
1922
+ }
1923
+ ]
1924
+ },
1925
+ "css-broken-reference": {
1926
+ "anyOf": [
1927
+ {
1928
+ "$ref": "#/$defs/Severity"
1929
+ },
1930
+ {
1931
+ "type": "null"
1932
+ }
1933
+ ]
1934
+ },
1838
1935
  "unresolved-imports": {
1839
1936
  "anyOf": [
1840
1937
  {
@@ -2233,6 +2330,18 @@
2233
2330
  "gate": {
2234
2331
  "$ref": "#/$defs/AuditGate"
2235
2332
  },
2333
+ "css": {
2334
+ "type": [
2335
+ "boolean",
2336
+ "null"
2337
+ ]
2338
+ },
2339
+ "cssDeep": {
2340
+ "type": [
2341
+ "boolean",
2342
+ "null"
2343
+ ]
2344
+ },
2236
2345
  "deadCodeBaseline": {
2237
2346
  "type": [
2238
2347
  "string",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: fallow
3
- description: Codebase intelligence for JavaScript and TypeScript. Free static layer reports quality, changed-code risk, cleanup opportunities (unused files, exports, types, dependencies), code duplication, circular dependencies, complexity hotspots, architecture boundary violations, feature flag patterns, and opt-in security candidates. Runtime coverage merges production execution data into the same health report for hot-path review, cold-path deletion confidence, and stale-flag evidence, with a single local capture available by default and continuous/cloud runtime monitoring available as an optional mode. 122 framework plugins, zero configuration, sub-second static analysis. Use when asked to analyze code health, audit PR risk, find cleanup opportunities or unused code, detect duplicates, check circular dependencies, audit complexity, check architecture boundaries, detect feature flags, surface security candidates, clean up the codebase, auto-fix issues, merge runtime coverage, or run fallow.
3
+ description: Codebase intelligence for JavaScript, TypeScript, and styling. Static analysis reports changed-code risk, cleanup opportunities, duplication, circular dependencies, complexity hotspots, architecture boundaries, design-system drift, feature flags, and opt-in security candidates. Runtime coverage can merge production execution data for hot-path review, cold-path deletion confidence, and stale-flag evidence. 123 framework plugins, zero configuration, sub-second static analysis. Use when asked to audit PR risk, find unused code or dependencies, detect duplicates, check styling consistency, inspect architecture boundaries, merge runtime coverage, auto-fix supported issues, or run fallow.
4
4
  license: MIT
5
5
  metadata:
6
6
  author: Bart Waardenburg
@@ -8,27 +8,22 @@ metadata:
8
8
  homepage: https://docs.fallow.tools
9
9
  ---
10
10
 
11
- # Fallow: codebase intelligence for JavaScript and TypeScript
11
+ # Fallow: codebase intelligence for JavaScript, TypeScript, and styling
12
12
 
13
- Codebase intelligence for JavaScript and TypeScript. The free static layer reports quality, changed-code risk, cleanup opportunities, circular dependencies, code duplication, complexity hotspots, architecture boundary violations, feature flag patterns, and opt-in security candidates. Runtime coverage merges production execution data into the same `fallow health` report for hot-path review, cold-path deletion confidence, and stale-flag evidence, with a single local capture available by default and continuous/cloud runtime monitoring available as an optional mode. 122 framework plugins, zero configuration, sub-second static analysis.
13
+ Codebase intelligence for JavaScript, TypeScript, and styling. The static layer reports quality, changed-code risk, cleanup opportunities, circular dependencies, code duplication, complexity hotspots, architecture boundary violations, design-system styling drift, feature flag patterns, and opt-in security candidates. Runtime coverage merges production execution data into the same `fallow health` report for hot-path review, cold-path deletion confidence, and stale-flag evidence, with a single local capture available by default and continuous/cloud runtime monitoring available as an optional mode. 123 framework plugins, zero configuration, sub-second static analysis.
14
14
 
15
15
  ## When to Use
16
- - Finding cleanup opportunities (unused files, exports, types, enum/class members)
17
- - Finding unused or unlisted dependencies
18
- - Detecting code duplication and clones
19
- - Checking code health and complexity hotspots
20
- - Cleaning up a codebase before a release or refactor
21
- - Auditing a project for structural issues
22
- - Setting up CI quality gates or duplication thresholds
23
- - Auto-fixing unused exports and dependencies
24
- - Detecting feature flag patterns (environment gates, SDK calls, config objects) with `fallow flags`
25
- - Investigating why a specific export or file appears unused
26
- - Surfacing local security candidates for an agent to verify (`fallow security`)
27
- - Finding untested but runtime-reachable code (`fallow health --coverage-gaps`)
28
- - Ranking complexity hotspots, code owners, and refactoring targets (`fallow health --hotspots --ownership --targets`)
29
- - Gating CI on regressions with baselines (`--save-baseline` / `--save-regression-baseline`)
30
- - Explaining an issue type or why a function scored high (`fallow explain`, `fallow health --complexity-breakdown`)
31
- - Reviewing what fallow has surfaced over time (`fallow impact`)
16
+ - Find cleanup opportunities: unused files, exports, types, members, dependencies, or stale flags.
17
+ - Detect code duplication, circular dependencies, architecture boundary issues, and complexity hotspots.
18
+ - Check styling consistency, CSS dead surface, and design-token drift.
19
+ - Audit changed code before a commit, PR, release, or refactor.
20
+ - Set up CI quality gates, duplication thresholds, and regression baselines.
21
+ - Auto-fix supported unused exports and dependencies after `--dry-run`.
22
+ - Investigate why a specific export, dependency, file, or issue type was reported.
23
+ - Surface local security candidates for an agent to verify (`fallow security`).
24
+ - Find untested but runtime-reachable code (`fallow health --coverage-gaps`).
25
+ - Rank complexity hotspots, owners, and refactoring targets (`fallow health --hotspots --ownership --targets`).
26
+ - Review what fallow has surfaced over time (`fallow impact`).
32
27
 
33
28
  ## When NOT to Use
34
29
  - Runtime error analysis or debugging
@@ -43,11 +38,9 @@ Codebase intelligence for JavaScript and TypeScript. The free static layer repor
43
38
  Fallow must be installed. If not available, install it:
44
39
 
45
40
  ```bash
46
- npm install -g fallow # prebuilt binaries (fastest)
47
- # or
48
- npx fallow dead-code # run without installing
49
- # or
50
- cargo install fallow-cli # build from source
41
+ npm install -g fallow # prebuilt binaries (fastest, recommended)
42
+ npx fallow dead-code # run without installing
43
+ cargo install fallow-cli # build from source
51
44
  ```
52
45
 
53
46
  ## Agent Rules
@@ -66,7 +59,6 @@ cargo install fallow-cli # build from source
66
59
  ## Onboarding And Insight
67
60
  Offer setup only after a human-requested analysis shows findings and all signals match: `fallow config --path` exits 3, not CI, not a pipeline format, `fallow impact --format json --quiet` has `onboarding_declined: false`, and no offer happened this session. Ask after showing value. Choices: guard commits and PRs, baseline the existing backlog and clean by category, add AGENTS.md guidance, or keep as-is. On decline, run `fallow init --decline --quiet` and stay silent for this project. Mutate only after consent. For guards, inspect `fallow hooks status --format json --quiet`, then use `fallow hooks install --target agent` and `fallow hooks install --target git`; for large backlogs, pair the gate with `--save-baseline` / new-only guidance. Offer `fallow impact enable` as local-only value tracking, never as telemetry; also offer it once on already-configured projects when `fallow impact status --format json` has `enabled: false` and `explicit_decision: false`, and record a no with `fallow impact disable --quiet`. Surface value on clear events: if the agent gate blocked a commit or push and a later retry succeeded, mention what was contained; when `next_steps` carries id `impact-report`, run its command and relay the non-zero numbers to the user in one line. On request, summarize non-zero Impact counts. Ask about telemetry only after such a win, only if `fallow telemetry status --format json` has `explicit_decision: false`, and never run `fallow telemetry enable`.
68
61
  ## Task Cheat Sheet
69
-
70
62
  Route by intent before reaching for the big analysis commands. Same matrix as `fallow schema` (`task_matrix`) and the generated AGENTS.md section.
71
63
 
72
64
  <!-- generated:task-matrix:start -->
@@ -80,6 +72,7 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
80
72
  | check untested-but-reachable code | `fallow health --coverage-gaps` |
81
73
  | consolidate duplication | `fallow dupes --trace dup:<fingerprint>` |
82
74
  | find feature flags | `fallow flags` |
75
+ | check which architecture rules apply to a file before changing it | `fallow guard <files>` |
83
76
  | surface security candidates | `fallow security` |
84
77
  | understand a finding | `fallow explain <issue-type>` |
85
78
  | scope a monorepo | `--workspace <glob> / --changed-workspaces <ref>`; global flags, prefix any command |
@@ -103,6 +96,8 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
103
96
  | `config-schema` | Print the JSON Schema for fallow configuration files | |
104
97
  | `plugin-schema` | Print the JSON Schema for external plugin files | |
105
98
  | `rule-pack-schema` | Print the JSON Schema for rule pack files | |
99
+ | `rule-pack` | Manage declarative rule packs (policy-as-code) | |
100
+ | `guard` | Show which architecture rules apply to files before changing them | `files` |
106
101
  | `config` | Show the loaded config path and resolved config (verifies which `.fallowrc.json` is in effect) | `--path` |
107
102
  | `list` | Inspect project structure | `--files`, `--entry-points`, `--plugins`, `--boundaries`, `--workspaces` |
108
103
  | `workspaces` | Inspect monorepo workspaces + discovery diagnostics (shorthand for `list --workspaces`) | (no flags) |
@@ -110,7 +105,7 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
110
105
  | `health` | Function complexity analysis (also covers Angular templates as synthetic `<template>` findings: external `.html` files via `templateUrl` AND inline `@Component({ template: \`...\` })` literals; suppress external with `<!-- fallow-ignore-file complexity -->` at the top of the `.html` file, suppress inline with `// fallow-ignore-next-line complexity` directly above the `@Component` decorator) | `--complexity`, `--max-cyclomatic`, `--max-cognitive`, `--max-crap`, `--top`, `--sort`, `--file-scores`, `--hotspots`, `--ownership`, `--ownership-emails`, `--targets`, `--effort`, `--score`, `--min-score`, `--since`, `--min-commits`, `--save-snapshot`, `--trend`, `--coverage-gaps`, `--coverage`, `--coverage-root`, `--runtime-coverage`, `--min-invocations-hot`, `--min-observation-volume`, `--low-traffic-threshold`, `--css`, `--complexity-breakdown`, `--min-severity`, `--report-only`, `--workspace`, `--changed-workspaces`, `--baseline`, `--save-baseline` |
111
106
  | `flags` | Detect feature flag patterns (env vars, SDK calls, config objects) | `--top` |
112
107
  | `explain` | Explain one issue type without running analysis | `<issue-type>`, `--format json` |
113
- | `audit` | Combined dead-code + complexity + duplication for changed files, returns a verdict; `fallow review` is an alias for `fallow audit --brief` (advisory orientation brief, always exits 0) | `--base`, `--gate`, `--brief`, `--max-decisions`, `--walkthrough-guide`, `--walkthrough-file`, `--show-deprioritized`, `--production`, `--production-dead-code`, `--production-health`, `--production-dupes`, `--workspace`, `--changed-workspaces`, `--ci`, `--fail-on-issues`, `--explain`, `--explain-skipped`, `--dead-code-baseline`, `--health-baseline`, `--dupes-baseline`, `--max-crap`, `--coverage`, `--coverage-root`, `--include-entry-exports` |
108
+ | `audit` | Combined dead-code + complexity + duplication + styling for changed files, returns a verdict; `fallow review` is an alias for `fallow audit --brief` (advisory orientation brief, always exits 0) | `--base`, `--gate`, `--brief`, `--max-decisions`, `--walkthrough-guide`, `--walkthrough-file`, `--show-deprioritized`, `--production`, `--production-dead-code`, `--production-health`, `--production-dupes`, `--workspace`, `--changed-workspaces`, `--ci`, `--fail-on-issues`, `--explain`, `--explain-skipped`, `--dead-code-baseline`, `--health-baseline`, `--dupes-baseline`, `--max-crap`, `--coverage`, `--coverage-root`, `--no-css`, `--css-deep`, `--no-css-deep`, `--include-entry-exports` |
114
109
  | `decision-surface` | Surface the consequential structural DECISIONS a change embeds (the apex of the review brief), each framed as a judgment question with the routed expert to ask | `--max-decisions` |
115
110
  | `impact` | Show what fallow has done for you: how many issues it is surfacing, the trend since the last recorded run, and how many commits it contained at the pre-commit gate | `--all`, `--sort`, `--limit` |
116
111
  | `security` | Surface opt-in local security candidates for agent verification (not confirmed vulnerabilities). Rule families include the graph rule `client-server-leak`, a data-driven `tainted-sink` catalogue, and the include-required `hardcoded-secret` category for provider-prefix credentials and high-entropy literals assigned to secret-shaped identifiers. Most catalogue rows require non-literal input; narrowly literal-aware rows flag deterministic unsafe literals. Rules default off; suppress a file with `// fallow-ignore-file security-sink`; scope categories with `security.categories`. Add project-local request object names with `security.requestReceivers`; it extends the built-in `req` / `request` / `ctx` / `context` / `event` allowlist for HTTP `query`, `params`, and `body` reads. `hardcoded-secret` runs only when listed in `security.categories.include`. | `--format human\|json\|sarif`, `--changed-since`, `--file`, `--diff-file`, `--workspace`, `--changed-workspaces`, `--surface`, `--ci`, `--fail-on-issues`, `--sarif-file`, `--summary` |
@@ -153,7 +148,7 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
153
148
  | `boundary-call-violation` | `--boundary-violations` | - | `// fallow-ignore-next-line boundary-call-violation` | Zoned file calls a callee its zone forbids; Requires boundaries.calls.forbidden patterns |
154
149
  | `policy-violation` | `--policy-violations` | - | `// fallow-ignore-next-line policy-violation` | Calls, imports, or catalogue-derived effects banned by a declarative rule pack (`rulePacks` config key lists standalone JSON/JSONC files of `banned-call`, `banned-import`, and `banned-effect` rules; pure data, no project code executes). Findings identified as `<pack>/<rule-id>`. Default `warn` master; per-rule `severity` overrides per finding and the exit gate reads the effective severity. Invalid or missing packs fail config load with exit 2. `fallow rule-pack-schema` prints the pack JSON Schema. Use the scoped token to suppress one rule; bare `policy-violation` still covers every pack rule on the line or file. |
155
150
  | `stale-suppression` | `--stale-suppressions` | - | - | `fallow-ignore` comments or `@expected-unused` JSDoc tags that no longer match any issue |
156
- | `missing-suppression-reason` | - | - | - | Suppression comment omits a required reason |
151
+ | `missing-suppression-reason` | `--stale-suppressions` | - | - | Suppression comment omits a required reason |
157
152
  | `unused-catalog-entry` | `--unused-catalog-entries` | yes | - | `pnpm-workspace.yaml` entries no workspace package.json references via `catalog:` (default `warn`) |
158
153
  | `empty-catalog-group` | `--empty-catalog-groups` | - | - | Named `catalogs.<name>:` groups in `pnpm-workspace.yaml` with no entries. Top-level `catalog:` placeholders are ignored. Default `warn`. |
159
154
  | `unresolved-catalog-reference` | `--unresolved-catalog-references` | - | - | `package.json` references to `catalog:` / `catalog:<name>` whose catalog does not declare the package; `pnpm install` would fail. Default `error`. Suppress via `ignoreCatalogReferences: [{ package, catalog?, consumer? }]` in fallow config (package.json has no comment syntax). |
@@ -181,6 +176,11 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
181
176
  | `high-complexity` | `--complexity` | - | `// fallow-ignore-next-line complexity` | Function exceeds both complexity thresholds |
182
177
  | `high-crap-score` | `--complexity` | - | `// fallow-ignore-next-line complexity` | Function has a high CRAP score (complexity combined with low coverage) |
183
178
  | `refactoring-target` | `--targets` | - | - | File identified as a high-priority refactoring candidate |
179
+ | `css-token-drift` | - | - | `// fallow-ignore-next-line css-token-drift` | CSS or CSS-in-JS hardcoded styling value bypasses the design token system |
180
+ | `css-duplicate-block` | - | - | `// fallow-ignore-next-line css-duplicate-block` | CSS or CSS-in-JS declaration block is duplicated across rules |
181
+ | `css-selector-complexity` | - | - | `// fallow-ignore-next-line css-selector-complexity` | CSS selector, nesting, or important usage is structurally complex |
182
+ | `css-dead-surface` | - | - | `// fallow-ignore-next-line css-dead-surface` | CSS or CSS-in-JS surface appears unused |
183
+ | `css-broken-reference` | - | - | `// fallow-ignore-next-line css-broken-reference` | CSS or CSS-in-JS reference resolves to no stylesheet definition |
184
184
  | `untested-file` | `--coverage-gaps` | - | `// fallow-ignore-file coverage-gaps` | Runtime-reachable file has no test dependency path |
185
185
  | `untested-export` | `--coverage-gaps` | - | `// fallow-ignore-file coverage-gaps` | Runtime-reachable export has no test dependency path |
186
186
  | `code-duplication` | - | - | `// fallow-ignore-next-line code-duplication` | Duplicated code block; Reported by fallow dupes (and bare fallow / fallow audit) |
@@ -204,14 +204,16 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
204
204
  | `check_changed` | analysis | free | `since`, `baseline`, `fail_on_regression` | Incremental analysis of files changed since a git ref |
205
205
  | `security_candidates` | analysis | free | `gate`, `surface`, `changed_since`, `paths` | Unverified local security candidates, not confirmed vulnerabilities (`fallow security --format json`). Read `security_findings[]` for category, CWE, severity, evidence, trace, optional `reachability`, blind-spot counters, and optional `unresolved_callee_diagnostics` samples for dynamic callee follow-up. `severity` is a review-priority tier, not a verified vulnerability verdict. Each finding also carries an agent-actionable `candidate` (`source_kind`/`sink`/`boundary`), where URL-category sinks may include `url_shape` (`fixed-origin-dynamic-path` or `dynamic-origin`), an optional `taint_flow` source-to-sink triple, and a stable `finding_id` (equal to the SARIF fingerprint) for cross-run correlation; there is no `impact` field (deciding exploitability is the agent's job). Set `surface: true` to include top-level `attack_surface[]` entries with defensive-boundary prompts for a verifier. Set `gate` to `new` for changed-line candidates or `newly-reachable` for candidates that became reachable from entry points; `newly-reachable` requires `changed_since`. `reachability.untrusted_source_trace` is module-level import context only and does not prove value flow; `reachability.taint_confidence` tiers each reachable candidate as `arg-level` (sink argument traces to a same-module source read, strong) or `module-level` (only the module is import-reachable from a source, weak), so tier from this field instead of the evidence text. Verify trace, reachability context, severity, and evidence before editing code. Supports `root`, `config`, `workspace`, `paths`, `changed_since`, `changed_workspaces`, `surface`, `gate`, `no_cache`, and `threads`; `paths` forwards repeated `fallow security --file` filters for finding anchors, trace hops, untrusted-source reachability trace hops, and unresolved-callee diagnostics. See <https://docs.fallow.tools/cli/security-agent-verification> for the verifier packet and verdict recipe. Inherits `FALLOW_DIFF_FILE` from the server environment for line-level diff scoping; raise `FALLOW_TIMEOUT_SECS` for large repos. |
206
206
  | `inspect_target` | analysis | free | `target`, `production` | Compose one evidence bundle for a file or exported symbol. File targets use `target: { type: "file", file }`; symbol targets use `target: { type: "symbol", file, export_name }`. Returns `kind: "inspect_target"`, normalized target identity, `trace_file`, optional `trace_export`, file-scoped dead-code actions, duplication groups filtered to the file, complexity findings filtered to the file, and security candidates scoped to the file. Evidence sections carry `status` and `scope`; symbol targets warn when supporting evidence is file-scoped. Supports `root`, `config`, `production`, `workspace`, `no_cache`, and `threads`; `production` applies to trace, dead-code, and health evidence only. Raise `FALLOW_TIMEOUT_SECS` for large repos. |
207
+ | `guard` | introspection | free | `files` | Report the architecture rules that apply to given files before editing them: boundary zone, allowed import zones, forbidden calls, and rule-pack policies |
207
208
  | `find_dupes` | analysis | free | `mode`, `min_tokens`, `min_occurrences`, `top`, `threshold` | Code duplication detection. Set `changed_since` to scope to changed files since a git ref. Set `min_occurrences` (≥ 2, default 2) to hide pair-only clones and focus on widespread copy-paste; JSON gains `stats.clone_groups_below_min_occurrences` when the filter hides anything. Each `clone_groups[]` entry carries a stable `fingerprint`, usually `dup:<8hex>` and widened only on rare report collisions; pass it to `trace_clone` to deep-dive that group |
208
- | `check_health` | analysis | free | `score`, `file_scores`, `hotspots`, `targets`, `coverage`, `runtime_coverage`, `max_crap`, `group_by` | Complexity metrics, health scores, hotspots, and refactoring targets. Set `complexity_breakdown: true` to add a per-decision-point `contributions[]` array to each complexity finding (each `else-if`, nested `if`, boolean operator, loop, `case`, etc. with its source line and cyclomatic/cognitive weight) so you can explain WHY a function scored high and pinpoint refactor targets. Optional `runtime_coverage` merges a V8 or Istanbul dump; tune it with `min_invocations_hot` (default 100), `min_observation_volume` (default 5000), and `low_traffic_threshold` (default 0.001). When runtime evidence combines with static usage, test coverage, CRAP/complexity, ownership, or change scope, read `coverage_intelligence` for stable `fallow:coverage-intel:<hash>` recommendations. Set `group_by` to `owner`, `directory`, `package`, or `section` for per-group `vital_signs` / `health_score`; SARIF results gain `properties.group`, CodeClimate issues gain a top-level `group` field |
209
+ | `check_health` | analysis | free | `score`, `css`, `file_scores`, `hotspots`, `targets`, `coverage`, `runtime_coverage`, `max_crap`, `group_by` | Complexity metrics, health scores, hotspots, and refactoring targets. Set `complexity_breakdown: true` to add a per-decision-point `contributions[]` array to each complexity finding (each `else-if`, nested `if`, boolean operator, loop, `case`, etc. with its source line and cyclomatic/cognitive weight) so you can explain WHY a function scored high and pinpoint refactor targets. Optional `runtime_coverage` merges a V8 or Istanbul dump; tune it with `min_invocations_hot` (default 100), `min_observation_volume` (default 5000), and `low_traffic_threshold` (default 0.001). When runtime evidence combines with static usage, test coverage, CRAP/complexity, ownership, or change scope, read `coverage_intelligence` for stable `fallow:coverage-intel:<hash>` recommendations. Set `group_by` to `owner`, `directory`, `package`, or `section` for per-group `vital_signs` / `health_score`; SARIF results gain `properties.group`, CodeClimate issues gain a top-level `group` field |
209
210
  | `check_runtime_coverage` | runtime-coverage | freemium | `coverage`, `min_invocations_hot`, `min_observation_volume`, `low_traffic_threshold`, `group_by` | Merge V8 or Istanbul runtime-coverage data into the health report. One local capture is free; continuous/cloud or multi-capture runtime monitoring is paid. Required `coverage` param (V8 dir, V8 JSON, or Istanbul `coverage-final.json`). Tuning knobs: `min_invocations_hot` (default 100), `min_observation_volume` (default 5000), `low_traffic_threshold` (default 0.001), `max_crap` (default 30.0), `top`, `group_by`. Cloud runtime rows can expose `resolutionStatus` / `mappingQuality` on function-list JSON and `resolution_status` / `mapping_quality` in runtime-context JSON. Use `coverage_intelligence` and the confidence table below before acting on file-level runtime signals. Long dumps may exceed the 120s MCP timeout; raise `FALLOW_TIMEOUT_SECS`. Pick this over `check_health` when you have a coverage dump. |
210
211
  | `get_hot_paths` | runtime-coverage | freemium | `coverage`, `top`, `min_invocations_hot` | Runtime-context slice over the same runtime coverage pipeline. Same params as `check_runtime_coverage`; read `runtime_coverage.hot_paths` for production hot paths. |
211
212
  | `get_blast_radius` | runtime-coverage | freemium | `coverage`, `group_by` | Runtime-context slice for blast-radius review. Same params as `check_runtime_coverage`; read `runtime_coverage.blast_radius` for stable `fallow:blast:<hash>` IDs, caller counts, traffic-weighted caller reach, optional cloud deploy touch counts, and low/medium/high risk bands. |
212
213
  | `get_importance` | runtime-coverage | freemium | `coverage`, `group_by` | Runtime-context slice for production-importance review. Same params as `check_runtime_coverage`; read `runtime_coverage.importance` for stable `fallow:importance:<hash>` IDs, invocations, cyclomatic complexity, owner count, 0-100 score, and templated reason. |
213
214
  | `get_cleanup_candidates` | runtime-coverage | freemium | `coverage`, `group_by` | Runtime-context slice for cleanup review. Same params as `check_runtime_coverage`; read `runtime_coverage.findings` for `safe_to_delete`, `review_required`, `low_traffic`, and `coverage_unavailable`. |
214
- | `audit` | analysis | free | `gate`, `base`, `max_crap`, `coverage`, `runtime_coverage` | Combined dead-code + complexity + duplication for changed files, returns verdict. Set `gate` to `"new-only"` or `"all"`. Optional `runtime_coverage` (V8 dir / V8 JSON / Istanbul JSON) folds runtime findings into the same call; `min_invocations_hot` tunes the hot-path threshold (default 100). Runtime evidence appears under the audit `complexity` sub-result, including `coverage_intelligence` when combined evidence yields actionable recommendations. |
215
+ | `get_token_blast_radius` | analysis | free | - | Design-token blast radius for Tailwind v4 @theme tokens and CSS-in-JS token definitions (StyleX, vanilla-extract, PandaCSS): per token, a consumer_count (static lower bound) and a capped located consumers[] sample tagged theme-var/css-var/utility/apply (Tailwind), js-member (member access), or js-call (Panda token calls); descriptive context for sizing a token change, never a deletion gate |
216
+ | `audit` | analysis | free | `gate`, `base`, `css_deep`, `max_crap`, `coverage`, `runtime_coverage` | Combined dead-code + complexity + duplication + styling for changed files, returns verdict. Styling analytics are enabled by default; CSS and CSS-in-JS evidence can add `styling_findings`, `css_analytics`, and `styling_health` under the health sub-result. Set `gate` to `"new-only"` or `"all"`. Set `css_deep: false` to skip project-wide styling reachability while keeping local styling checks, or `css_deep: true` to force it back on when config disables it. Optional `runtime_coverage` (V8 dir / V8 JSON / Istanbul JSON) folds runtime findings into the same call; `min_invocations_hot` tunes the hot-path threshold (default 100). Runtime evidence appears under the audit `complexity` sub-result, including `coverage_intelligence` when combined evidence yields actionable recommendations. |
215
217
  | `decision_surface` | analysis | free | `base`, `max_decisions`, `workspace` | Surface the few consequential structural decisions a change embeds (coupling, public API, dependency), each as a judgment question with the routed expert; ranked, capped, and signal_id-anchored |
216
218
  | `fallow_explain` | introspection | free | `issue_type` | Explain one issue type without running analysis. Required `issue_type`; returns rationale, examples, fix guidance, and docs URL |
217
219
  | `fix_preview` | fix | free | `no_create_config` | Dry-run auto-fix preview |
@@ -244,9 +246,6 @@ All JSON responses include structured `actions` arrays on every finding (dead co
244
246
 
245
247
  `dead-code`, `health`, `dupes`, bare `fallow`, and `audit` JSON output also carry a top-level `next_steps` array of read-only follow-up commands computed from the run's findings: each entry is `{ id, command, reason }`. The `command` is runnable as-is (never a placeholder, never `fix` or any other mutating command); the stable kebab-case `id` (`setup`, `impact-report`, `trace-unused-export`, `trace-clone`, `complexity-breakdown`, `scope-workspaces`, `audit-changed`) maps to a verification step you should run BEFORE acting, for example tracing an export before deleting it. A leading `setup` step (command: `fallow schema`) appears only on unconfigured, non-CI projects with findings and doubles as the onboarding trigger below; it disappears after setup or `fallow init --decline`. An at-most-weekly `impact-report` step (command: `fallow impact`) carries the local value digest when impact tracking has non-zero results; it may ride a clean run. When running via MCP, dispatch on the `id` to the matching tool / `code_execute` host call (`trace_export`, `trace_clone`, `check_health` with `complexity_breakdown: true`, `audit`) rather than shelling out the CLI string. The array is deduplicated, capped at three, and omitted when empty; set `FALLOW_SUGGESTIONS=off` to suppress it.
246
248
 
247
- ## Node.js Bindings
248
- Embedding fallow in a Node.js process (editor extensions, servers, custom tooling)? Use the `@fallow-cli/fallow-node` NAPI bindings instead of spawning the CLI: six async functions (`detectDeadCode`, `detectCircularDependencies`, `detectBoundaryViolations`, `detectDuplication`, `computeComplexity`, `computeHealth`) returning the same JSON envelopes as `--format json`. Read-only analysis only; use the CLI for write-path commands. Details: [Node Bindings](references/node-bindings.md).
249
-
250
249
  ## References
251
250
  - [CLI Reference](references/cli-reference.md): complete command and flag specifications, plus configuration field details
252
251
  - [Gotchas](references/gotchas.md): common pitfalls, edge cases, and correct usage patterns
@@ -297,7 +296,7 @@ fallow list --entry-points --format json --quiet
297
296
  fallow list --plugins --format json --quiet
298
297
  ```
299
298
 
300
- Shows detected entry points and active framework plugins (122 built-in: Next.js, Vite, Ember, Wuchale, Jest, Storybook, Tailwind, PandaCSS, Contentlayer, tap, tsd, etc.).
299
+ Shows detected entry points and active framework plugins (123 built-in: Next.js, Vite, Ember, Wuchale, Jest, Storybook, Tailwind, PandaCSS, Contentlayer, tap, tsd, etc.).
301
300
 
302
301
  ### Production-only analysis
303
302
  ```bash
@@ -443,7 +442,7 @@ When `--format json` is active and exit code is 2, errors are emitted as JSON on
443
442
 
444
443
  ## Configuration
445
444
 
446
- Fallow reads config from project root: `.fallowrc.json` > `.fallowrc.jsonc` > `fallow.toml` > `.fallow.toml`. Both `.fallowrc.json` and `.fallowrc.jsonc` accept JSON-with-comments syntax (same parser); the `.jsonc` extension lets editors auto-detect JSONC syntax highlighting. Most projects work with zero configuration thanks to 122 auto-detecting framework plugins.
445
+ Fallow reads config from project root: `.fallowrc.json` > `.fallowrc.jsonc` > `fallow.toml` > `.fallow.toml`. Both `.fallowrc.json` and `.fallowrc.jsonc` accept JSON-with-comments syntax (same parser); the `.jsonc` extension lets editors auto-detect JSONC syntax highlighting. Most projects work with zero configuration thanks to 123 auto-detecting framework plugins.
447
446
 
448
447
  ```jsonc
449
448
  {
@@ -480,7 +479,7 @@ export const deprecatedHelper = () => {};
480
479
  ## Key Gotchas
481
480
 
482
481
  - **`fix --yes` is required** in non-TTY (agent) environments. Without it, `fix` exits with code 2
483
- - **Zero config by default.** 122 framework plugins auto-detect, including Wuchale config, Contentlayer content roots, tap and tsd test entry points. Don't create config unless customization is needed
482
+ - **Zero config by default.** 123 framework plugins auto-detect, including Wuchale config, Contentlayer content roots, tap and tsd test entry points. Don't create config unless customization is needed
484
483
  - **Syntactic analysis only.** No TypeScript compiler, so fully dynamic `import(variable)` is not resolved
485
484
  - **Function overloads are deduplicated.** TypeScript function overload signatures are merged into a single export (not reported as separate unused exports)
486
485
  - **Re-export chains are resolved.** Exports through barrel files are tracked, not falsely flagged
@@ -51,7 +51,7 @@ Analyzes the project for unused files, exports, dependencies, types, members, an
51
51
  | `--top` | `string` | - | Show only the top N items per category |
52
52
  | `--file` | `string` | - | Scope output to specific files. Only issues in the specified files are reported. Project-wide dependency issues are suppressed. Warns on non-existent paths. Useful for lint-staged |
53
53
 
54
- Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--output-file`](#global-flags), [`--legacy-envelope`](#global-flags), [`--changed-since`](#global-flags), [`--max-file-size`](#global-flags), [`--production`](#global-flags), [`--no-production`](#global-flags), [`--production-dead-code`](#global-flags), [`--baseline`](#global-flags), [`--save-baseline`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--include-entry-exports`](#global-flags).
54
+ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--output-file`](#global-flags), [`--changed-since`](#global-flags), [`--max-file-size`](#global-flags), [`--production`](#global-flags), [`--no-production`](#global-flags), [`--production-dead-code`](#global-flags), [`--baseline`](#global-flags), [`--save-baseline`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--include-entry-exports`](#global-flags).
55
55
  <!-- generated:flags:dead-code:end -->
56
56
  ### Issue Type Filters
57
57
 
@@ -398,7 +398,7 @@ Angular templates contribute synthetic `<template>` complexity findings whenever
398
398
  | `--ownership` | `bool` | `false` | Attach ownership signals to hotspot entries: bus factor (Avelino truck factor), contributor count, top contributor with stale-days, recent contributors (top-3), `suggested_reviewers`, declared CODEOWNERS owner, `ownership_state`, ownership drift, unowned-hotspot detection. Human output gains a project-level summary line. JSON adds `low-bus-factor`, `unowned-hotspot`, `ownership-drift` action types. Test files get a `[test]` tag. Implies `--hotspots`. Requires git. |
399
399
  | `--ownership-emails` | `raw\|handle\|anonymized\|hash` | - | Privacy mode for author emails. `handle` shows the local-part only (default, with GitHub noreply unwrap and deterministic same-handle disambiguation). `anonymized` emits stable `xxh3:` pseudonyms; `hash` remains accepted as the legacy spelling. `raw` shows full addresses. Use `anonymized` in regulated environments. Implies `--ownership`. Configure default via `health.ownership.emailMode`. |
400
400
  | `--targets` | `bool` | `false` | Show only refactoring targets: ranked recommendations based on complexity, coupling, churn, and dead code signals. Categories: churn+complexity, circular dep, high impact, dead code, complexity, coupling. When no section flags are set, all sections are shown by default. Each target's JSON can include `direct_callers[]` (direct importers with the symbols they import) and `clone_siblings[]` (duplicate-code siblings with stable `dup:<8hex>` fingerprints for `fallow dupes --trace`); both omitted when empty. Human output adds `importers:` / `clones:` lines only when that evidence is present. |
401
- | `--css` | `bool` | `false` | Add structural CSS analytics: specificity hotspots, !important density, over-complex selectors, deep nesting, and conservative cleanup candidates. Standard CSS is parsed structurally; preprocessor sources are scanned only where fallow can avoid expanding Sass/Less semantics. |
401
+ | `--css` | `bool` | `false` | Add structural CSS analytics: specificity hotspots, !important density, over-complex selectors, deep nesting, and conservative cleanup candidates. Standard CSS is parsed structurally; preprocessor sources are scanned only where fallow can avoid expanding Sass/Less semantics. Also derives `styling_health`, a descriptive A-F grade for CSS quality scored separately from the code `health_score` (never gates); it weights design-token drift (hardcoded value sprawl) over byte-identical repetition. |
402
402
  | `--effort` | `low\|medium\|high` | - | Filter refactoring targets by effort level. Implies `--targets`. |
403
403
  | `--score` | `bool` | `false` | Show only the project health score (0-100) with letter grade (A/B/C/D/F). The score is included by default when no section flags are set. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown. As of v2.55.0, plain `--score` skips the churn-backed hotspot penalty so it does not run a `git log` shell-out per invocation; pass `--hotspots` (or `--targets` with `--score`) to include the hotspot penalty. Snapshot (`--save-snapshot`) and trend (`--trend`) flows still trigger hotspot vital signs so saved data stays complete. |
404
404
  | `--min-score` | `string` | - | Fail (exit 1) only when the health score is below this threshold. Implies `--score`. Authoritative CI quality gate: when set, complexity findings are demoted to informational and the exit code is driven solely by the score, so `--min-score 0` always exits 0. Composes with `--min-severity`. |
@@ -508,7 +508,7 @@ fallow health --format json --quiet --trend
508
508
  {
509
509
  "kind": "health",
510
510
  "schema_version": 7,
511
- "version": "2.103.0",
511
+ "version": "3.0.0",
512
512
  "elapsed_ms": 32,
513
513
  "summary": {
514
514
  "files_analyzed": 482,
@@ -811,7 +811,7 @@ The snapshot `snapshot_schema_version` is independent of the report `schema_vers
811
811
 
812
812
  ## `audit`: Changed-File Quality Gate
813
813
 
814
- Audits changed files for dead code, complexity, and duplication. Returns a verdict (pass/warn/fail). Purpose-built for PR quality gates and reviewing AI-generated code. When `--base` is not set, the base is the `git merge-base` against the branch's upstream or the remote default (`origin/HEAD`, `origin/main`, `origin/master`); set `FALLOW_AUDIT_BASE` to pin it without a flag. Defaults to `--gate new-only`, which fails only on findings introduced by the current changeset and reports inherited findings as context.
814
+ Audits changed files for dead code, complexity, duplication, and styling. Returns a verdict (pass/warn/fail). Purpose-built for PR quality gates and reviewing AI-generated code. When `--base` is not set, the base is the `git merge-base` against the branch's upstream or the remote default (`origin/HEAD`, `origin/main`, `origin/master`); set `FALLOW_AUDIT_BASE` to pin it without a flag. Defaults to `--gate new-only`, which fails only on findings introduced by the current changeset and reports inherited findings as context.
815
815
 
816
816
  ### Flags
817
817
 
@@ -827,6 +827,9 @@ Audits changed files for dead code, complexity, and duplication. Returns a verdi
827
827
  | `--max-crap` | `string` | - | Forwarded to the health sub-analysis. Functions meeting or exceeding this CRAP score cause audit to fail. Same formula as `health --max-crap`. Pair with coverage data for accurate per-function CRAP. |
828
828
  | `--coverage` | `string` | - | Path to Istanbul-format coverage data (`coverage-final.json`) for accurate per-function CRAP scores in the health sub-analysis. Same format and semantics as `health --coverage`. Also configurable via `FALLOW_COVERAGE`. Relative paths resolve against `--root`. |
829
829
  | `--coverage-root` | `string` | - | Absolute prefix to strip from file paths in coverage data before prepending the project root. Also configurable via `FALLOW_COVERAGE_ROOT`. Use when coverage was generated under a different checkout root in CI / Docker (e.g., `/home/runner/work/myapp` on GitHub Actions). |
830
+ | `--no-css` | `bool` | `false` | Disable styling analytics in audit |
831
+ | `--css-deep` | `bool` | `false` | Enable deep CSS analysis for audit explicitly: project-wide styling reachability, narrowed back to changed anchors. Deep CSS is on by default; use this to override `audit.cssDeep = false` |
832
+ | `--no-css-deep` | `bool` | `false` | Disable deep CSS analysis while keeping local styling analytics on |
830
833
  | `--gate` | `new-only\|all` | - | Which findings affect the verdict. `new-only` gates only introduced findings; `all` gates every finding in changed files and skips the extra base-snapshot attribution pass. |
831
834
  | `--runtime-coverage` | `string` | - | Paid runtime-coverage sidecar input. Accepts a V8 directory, a single V8 JSON file, or an Istanbul coverage map JSON. Spawns the `fallow-cov` sidecar as part of the audit pipeline so the `hot-path-touched` verdict surfaces alongside dead-code and complexity findings without requiring a second `fallow health` invocation in CI. License-gated; the verdict is informational (no exit code change) until a future `--gate hot-path-touched` knob lands |
832
835
  | `--min-invocations-hot` | `string` | `100` | Threshold for hot-path classification, forwarded to the sidecar when `--runtime-coverage` is set |
@@ -835,6 +838,9 @@ Audits changed files for dead code, complexity, and duplication. Returns a verdi
835
838
  | `--max-decisions` | `string` | `4` | Cap on the number of consequential structural decisions surfaced in the review brief's decision surface (the working-memory limit). Default 4; clamped to the 3-5 band (4 plus or minus 1). Only consulted on the brief path |
836
839
  | `--walkthrough-guide` | `bool` | `false` | Emit the agent-contract WALKTHROUGH GUIDE: the current digest (brief + decision surface), the review direction, the JSON schema the agent must return, and a deterministic graph-snapshot hash pinned into the digest. The digest is built from the graph only (PR prose is never folded in, so it is injection-resistant). Implies the brief; always exits 0. A thin agent skill calls this to fetch the current guide, produces judgment JSON, then reopens with `--walkthrough-file` |
837
840
  | `--walkthrough-file` | `string` | - | Ingest an agent's judgment JSON and POST-VALIDATE it against the LIVE graph. Rejects any judgment whose `signal_id` fallow did not emit (anti-hallucination); refuses the whole payload as stale when the echoed graph-snapshot hash no longer matches (the tree moved). The verifier is the graph, not a second model. Implies the brief; always exits 0. The agent's free-text framing is fenced as non-deterministic and never gates or auto-posts |
841
+ | `--walkthrough` | `bool` | `false` | Render the existing walkthrough guide as a staged HUMAN terminal tour (Stage 1 load-bearing / Stage 2 mechanical), or markdown with `--format markdown`. Implies the brief; always exits 0. `--format json --walkthrough` emits the same agent-contract JSON as `--walkthrough-guide` |
842
+ | `--mark-viewed` | `string` | - | Record one or more changed files as VIEWED in the local walkthrough viewed-state ledger (`.fallow/walkthrough-state.json`), then render the tour. Files already viewed (and still current) collapse into the Cleared panel. Repeatable. Stale marks (the tree moved) are ignored on render but never deleted. Only consulted on the `--walkthrough` path |
843
+ | `--show-cleared` | `bool` | `false` | Expand the Cleared panel in the human/markdown walkthrough tour: list each de-prioritized and already-viewed file instead of the collapsed one-line summary. Only consulted on the `--walkthrough` path |
838
844
  | `--show-deprioritized` | `bool` | `false` | Expand the de-prioritized units in the review brief's weighted focus map ("show me what you de-prioritized"). The `deprioritized` escape-hatch list is ALWAYS present in `--format json` regardless; this flag only re-expands the collapse-by-default human focus render. Only consulted on the brief path |
839
845
 
840
846
  Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#global-flags), [`--changed-since`](#global-flags), [`--diff-file`](#global-flags), [`--diff-stdin`](#global-flags), [`--workspace`](#global-flags), [`--changed-workspaces`](#global-flags), [`--group-by`](#global-flags), [`--output-file`](#global-flags).
@@ -900,7 +906,7 @@ fallow audit \
900
906
  {
901
907
  "kind": "audit",
902
908
  "schema_version": 7,
903
- "version": "2.103.0",
909
+ "version": "3.0.0",
904
910
  "command": "audit",
905
911
  "verdict": "fail",
906
912
  "changed_files_count": 12,
@@ -975,7 +981,7 @@ fallow flags --format json --quiet --workspace my-package
975
981
  ```json
976
982
  {
977
983
  "schema_version": 7,
978
- "version": "2.103.0",
984
+ "version": "3.0.0",
979
985
  "elapsed_ms": 116,
980
986
  "feature_flags": [],
981
987
  "total_flags": 0
@@ -1076,7 +1082,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1076
1082
  {
1077
1083
  "kind": "security",
1078
1084
  "schema_version": "4",
1079
- "version": "2.103.0",
1085
+ "version": "3.0.0",
1080
1086
  "elapsed_ms": 42,
1081
1087
  "config": {
1082
1088
  "rules": {
@@ -1105,7 +1111,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1105
1111
  {
1106
1112
  "kind": "security",
1107
1113
  "schema_version": "4",
1108
- "version": "2.103.0",
1114
+ "version": "3.0.0",
1109
1115
  "elapsed_ms": 42,
1110
1116
  "config": {
1111
1117
  "rules": {
@@ -1637,7 +1643,6 @@ Available on all commands:
1637
1643
  | `--group-by` | `owner\|directory\|package\|section` | - | Group output by CODEOWNERS ownership (`owner`), first path component (`directory`), workspace package (`package`, aliases: `workspace`, `pkg`), or GitLab CODEOWNERS `[Section]` headers (`section`, alias: `gl-section`). All output formats partition issues into labeled groups. `section` mode attaches an `owners` array to each group in JSON output |
1638
1644
  | `--performance` | `bool` | `false` | Show pipeline timing breakdown |
1639
1645
  | `--explain` | `bool` | `false` | JSON: include metric definitions in `_meta`. Human: print a `Description:` line under each section header. Always on for MCP. |
1640
- | `--legacy-envelope` | `bool` | `false` | Emit the previous typed JSON root envelope without top-level `kind` |
1641
1646
  | `--explain-skipped` | `bool` | `false` | Show a per-pattern breakdown for default duplicate ignores |
1642
1647
  | `--summary` | `bool` | `false` | Show only category counts without individual items. Useful for dashboards and quick overviews |
1643
1648
  | `--ci` | `bool` | `false` | CI mode: `--format sarif --fail-on-issues --quiet` |
@@ -1721,6 +1726,7 @@ These are global flags with behavior specific to bare `fallow` combined mode.
1721
1726
  | `FALLOW_REVIEW` | GitLab CI: set to `true` to post inline code review comments on MR diffs. |
1722
1727
  | `FALLOW_REVIEW_GUIDANCE` | Add collapsed "What to do" guidance blocks to `review-github` / `review-gitlab` inline comments. |
1723
1728
  | `FALLOW_SUMMARY_SCOPE` | Sticky PR/MR summary scope for `pr-comment-github` / `pr-comment-gitlab`: `all` (default) keeps project-level findings outside the diff; `diff` applies the diff filter to those findings too. Inline review comments are unaffected. |
1729
+ | `FALLOW_PR_COMMENT_LAYOUT` | Sticky PR/MR summary layout for `pr-comment-github` / `pr-comment-gitlab`: `default`, `compact`, `gate-only`, or `details`. |
1724
1730
  | `FALLOW_SCORE` | GitLab CI: set to `true` to compute health score in combined mode. Enables health delta header in MR comments. |
1725
1731
  | `FALLOW_TREND` | GitLab CI: set to `true` to compare current health metrics against saved snapshot. Implies `FALLOW_SCORE`. |
1726
1732
  | `FALLOW_EXTRA_ARGS` | GitLab CI: additional CLI flags passed through to fallow. |
@@ -1794,6 +1800,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1794
1800
  | `FALLOW_REVIEW` | `false` | Post inline code review comments on MR diff lines where issues were found |
1795
1801
  | `FALLOW_REVIEW_GUIDANCE` | `false` | Add collapsed "What to do" guidance blocks to inline review comments |
1796
1802
  | `FALLOW_SUMMARY_SCOPE` | `all` | Sticky summary scope: `all` keeps project-level findings outside the diff; `diff` applies the diff filter to those findings too |
1803
+ | `FALLOW_PR_COMMENT_LAYOUT` | `default` | Sticky summary layout: `default`, `compact`, `gate-only`, or `details` |
1797
1804
  | `FALLOW_SCORE` | `false` | Compute health score (0-100 with letter grade) in combined mode. Enables the health delta header in MR comments |
1798
1805
  | `FALLOW_TREND` | `false` | Compare current health metrics against saved snapshot. Implies `FALLOW_SCORE`. Shows per-metric deltas |
1799
1806
  | `FALLOW_EXTRA_ARGS` | - | Additional CLI flags passed through to fallow |
@@ -1813,7 +1820,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1813
1820
  {
1814
1821
  "kind": "dead-code",
1815
1822
  "schema_version": 7,
1816
- "version": "2.103.0",
1823
+ "version": "3.0.0",
1817
1824
  "elapsed_ms": 45,
1818
1825
  "total_issues": 12,
1819
1826
  "entry_points": {
@@ -1973,7 +1980,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
1973
1980
  {
1974
1981
  "kind": "dupes",
1975
1982
  "schema_version": 7,
1976
- "version": "2.103.0",
1983
+ "version": "3.0.0",
1977
1984
  "elapsed_ms": 82,
1978
1985
  "total_clones": 15,
1979
1986
  "total_lines_duplicated": 230,
@@ -2017,11 +2024,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
2017
2024
  {
2018
2025
  "kind": "combined",
2019
2026
  "schema_version": 7,
2020
- "version": "2.103.0",
2027
+ "version": "3.0.0",
2021
2028
  "elapsed_ms": 159,
2022
2029
  "check": {
2023
2030
  "schema_version": 7,
2024
- "version": "2.103.0",
2031
+ "version": "3.0.0",
2025
2032
  "elapsed_ms": 45,
2026
2033
  "total_issues": 12,
2027
2034
  "unused_files": [],
@@ -2229,6 +2236,7 @@ preset = "bulletproof"
2229
2236
  - `cache.maxSizeMb`: cap the serialized extraction cache size in megabytes. `FALLOW_CACHE_MAX_SIZE` wins over this config field
2230
2237
  - `usedClassMembers`: class method/property names that extend the built-in Angular/React lifecycle allowlist with framework-invoked names. Each entry is a plain string (global suppression) or a scoped object `{ extends?, implements?, members }` matching only classes with the given heritage. Strings can be exact names (`"agInit"`) or glob patterns (`"*"` matches every member, `"enter*"` prefix, `"*Handler"` suffix, `"on*Event"` combined). Use scoped rules for common names like `refresh` or `execute` to avoid false negatives on unrelated classes; global strings for unique names like `agInit`. Example: `["agInit", { "implements": "ICellRendererAngularComp", "members": ["refresh"] }, { "extends": "BaseCommand", "members": ["execute"] }, { "extends": "GrammarBaseListener", "members": ["enter*", "exit*"] }]`. Glob patterns that match zero members emit a `WARN` so dead allowlist entries surface. An unconstrained scoped rule (no `extends` or `implements`) is rejected at load time. Use plugin-level `usedClassMembers` in a `.fallow/plugins/*.jsonc` file for library-specific allowlists
2231
2238
  - `resolve.conditions`: additional package.json `exports` / `imports` condition names to honor during module resolution. Baseline conditions (`development`, `import`, `require`, `default`, `types`, `node`, plus `react-native` / `browser` under RN/Expo) are always included; user entries prepend ahead of them. Use for community conditions like `worker`, `edge-light`, `deno`, or custom bundler conditions. Example: `{ "resolve": { "conditions": ["worker", "edge-light"] } }`
2239
+ - `unusedComponentProps.ignorePattern`: opt-in regex that exempts a component prop from `unused-component-props` when the prop's LOCAL destructure binding name matches (the leading-underscore "accepted-but-intentionally-unused" convention, mirroring TS `noUnusedParameters` + ESLint `varsIgnorePattern` / `argsIgnorePattern`). Applies to Vue, Svelte, Astro, and React/Preact props. The match is on the local alias (`_stage` in `let { stage: _stage } = $props()`), not the public prop name the finding reports (`stage`); matching is unanchored like ESLint's `RegExp.test`, so anchor with `^_`. An invalid regex fails config load. Example: `{ "unusedComponentProps": { "ignorePattern": "^_" } }`
2232
2240
 
2233
2241
  ---
2234
2242
 
@@ -23,7 +23,7 @@ Always preview with `--dry-run` before applying. This is a destructive operation
23
23
 
24
24
  ## Don't Create Config Unless Needed
25
25
 
26
- Fallow works with zero configuration for most projects thanks to 122 auto-detecting framework plugins. Creating an unnecessary config file can mask issues or override detection behavior.
26
+ Fallow works with zero configuration for most projects thanks to 123 auto-detecting framework plugins. Creating an unnecessary config file can mask issues or override detection behavior.
27
27
 
28
28
  ```bash
29
29
  # WRONG: creating config for a standard Next.js project
@@ -484,10 +484,16 @@ When `fallow health --css` reports `css_analytics.unused_theme_tokens`, treat th
484
484
 
485
485
  The detector intentionally abstains when a Tailwind plugin or published CSS surface could consume tokens invisibly. Always run the row's `actions[].command` verification before deleting a token, and do not run `fallow fix` for these rows.
486
486
 
487
+ The same Tailwind v4 projects also get `css_analytics.token_consumers`, the reverse index: per `@theme` token, where it is consumed (a `consumer_count` plus a located `consumers[]` sample tagged `theme-var` / `css-var` / `utility` / `apply`), so you can read a token's blast radius before changing it. Treat `consumer_count` as a static lower bound: a computed class name such as `bg-${color}` is invisible to the scan, so a `0` here is the same "nothing fallow can see consumes this" population as `unused_theme_tokens`, not a deletion proof. `token_consumers` is descriptive context with no `actions[]`; drive any deletion off `unused_theme_tokens` and its verification command.
488
+
489
+ `token_consumers` also covers CSS-in-JS token DEFINITIONS (StyleX `defineVars`, vanilla-extract `createTheme` / `createThemeContract` / `createGlobalTheme`, and PandaCSS `defineTokens`), disambiguated by the consumer `kind`: StyleX and vanilla-extract entries use `kind` `js-member`, `token` is the binding-qualified dotted access path (`vars.color.primary`), and `namespace` is the defining binding (`vars`); PandaCSS entries use the defining binding plus token path (`tokens.colors.brand`) and `token(...)` consumers are tagged `js-call`. The cross-file scan uses fallow's shared import resolver, so relative imports, tsconfig `paths` aliases, and workspace package imports can resolve to the token definition. Dynamic import strings, unresolved aliases, generated package state, and computed token access still keep `consumer_count` a lower bound, and unlike Tailwind there is no corroborating dead-token finding, so a CSS-in-JS `consumer_count` of `0` is a weaker signal. Gated on a declared CSS-in-JS library (`@stylexjs/stylex`, `@vanilla-extract/css`, or `@pandacss/dev`).
490
+
487
491
  ## CSS Health Candidates Are Advisory
488
492
 
489
493
  `fallow health --css` also emits advisory cleanup and typo candidates in `css_analytics.unreferenced_css_classes` (a plain-CSS class defined but matched by no `class`/`className` in project markup), `css_analytics.unresolved_class_references` (the reverse: a markup class one edit away from a defined class, a likely typo), `css_analytics.unused_font_faces`, `css_analytics.undefined_keyframes`, and `css_analytics.font_size_unit_mix`. Treat them like review prompts, not confirmed defects. Run each row's `actions[].command` before changing CSS, because fonts, classes, animations, and type scales can be driven by inline styles, JavaScript, CMS templates, or preprocessor expansion that static analysis intentionally does not execute.
490
494
 
495
+ `fallow health --css` also derives `styling_health`, a descriptive A-F grade (and 0-100 `score`) for CSS quality, scored SEPARATELY from the code `health_score`. It is descriptive-only: it never gates an exit code, badge, or CI, and never affects the code score, so do NOT branch automation on it. Read it as a design-system credibility signal. It weights design-token DRIFT over byte-identical repetition: the `token_erosion` penalty includes a hardcoded-value-sprawl term over distinct `box-shadow` / `border-radius` / `line-height` values, but counts only HARDCODED literals: a system that references its scale via `var(--*)` scores 0 sprawl regardless of how many tokens it defines (so "tokenize repeated values" is the remedy the human output suggests). A grade from a thin CSS surface (or predominantly compile-time-atomic CSS-in-JS like StyleX/Panda) is marked `confidence: "low"` with a reason. `styling_health.formula_version` bumps when the rubric is recalibrated; if you diff the score/grade over time, gate on it and re-baseline at a bump rather than reading the step-change as a regression.
496
+
491
497
  ---
492
498
 
493
499
  ## Library Packages: Use `publicPackages` Instead of Visibility Tags