fallow 3.4.2 → 3.5.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.
@@ -48,7 +48,7 @@ cargo install fallow-cli # build from source
48
48
  1. **Always use `--format json --quiet 2>/dev/null`** for machine-readable output. The `2>/dev/null` discards stderr so progress messages and threshold warnings don't corrupt the JSON on stdout. Never use `2>&1`
49
49
  2. **Always append `|| true`** to every fallow command. Exit code 1 means "issues found" (normal), not a runtime error. Without `|| true`, the Bash tool treats exit 1 as failure and cancels parallel commands. Only exit code 2 is a real error (invalid config, parse failure)
50
50
  3. **Use `--explain`** to include a `_meta` object in JSON output with metric definitions, ranges, and interpretation hints. In human format, `--explain` prints a `Description:` line under each section header.
51
- 4. **Use the root `kind` field** to identify typed JSON envelopes (`dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, etc.). `--legacy-envelope` exists only for one-cycle compatibility with older consumers.
51
+ 4. **Use the root `kind` field** to identify typed JSON envelopes (`dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, etc.).
52
52
  5. **Use issue type filters** (`--unused-exports`, `--unused-files`, etc.) to limit output scope
53
53
  6. **Always `--dry-run` before `fix`**, then `fix --yes` to apply
54
54
  7. **All output paths are relative** to the project root
@@ -350,15 +350,17 @@ Adds a per-decision-point `contributions[]` array to every complexity finding (e
350
350
  ### Gate CI on regressions (baselines)
351
351
  ```bash
352
352
  # 1. Save the current issue counts as a regression baseline
353
- fallow dead-code --format json --quiet --save-regression-baseline .fallow/baseline.json
353
+ fallow dead-code --format json --quiet --save-regression-baseline
354
354
  # 2. In CI: fail only if issues increase beyond tolerance
355
- fallow dead-code --format json --quiet --regression-baseline .fallow/baseline.json --fail-on-regression --tolerance 0
355
+ fallow dead-code --format json --quiet --fail-on-regression --tolerance 0
356
356
  # Identity-based baseline (fail only on NEW findings, not raw counts)
357
357
  fallow dead-code --format json --quiet --save-baseline .fallow/snapshot.json
358
358
  fallow dead-code --format json --quiet --baseline .fallow/snapshot.json
359
359
  ```
360
360
 
361
- `--save-regression-baseline` / `--regression-baseline` / `--fail-on-regression` / `--tolerance` are count-based gates; `--save-baseline` / `--baseline` are identity-based (track finding identity, fail on new). All six are global flags, so they also work on `health` and `dupes`. `audit` rejects the global baseline flags and uses `--dead-code-baseline` / `--health-baseline` / `--dupes-baseline` instead.
361
+ `--save-regression-baseline` / `--regression-baseline` / `--fail-on-regression` / `--tolerance` are count-based gates for `dead-code` and bare combined mode. `--save-baseline` / `--baseline` are identity-based (track finding identity, fail on new). `audit` rejects the global baseline flags and uses `--dead-code-baseline` / `--health-baseline` / `--dupes-baseline` instead.
362
+
363
+ With no path, `--save-regression-baseline` updates `regression.baseline` in the discovered fallow config, or creates `.fallowrc.json` when none exists. Pass a path only when a standalone baseline file is preferred.
362
364
 
363
365
  ### Explain an issue type without running analysis
364
366
  ```bash
@@ -130,8 +130,9 @@ fallow dead-code --format json --quiet --trace src/utils.ts:myFunction
130
130
  fallow dead-code --format json --quiet --save-baseline fallow-baselines/dead-code.json
131
131
  fallow dead-code --format json --quiet --baseline fallow-baselines/dead-code.json --fail-on-issues
132
132
 
133
- # Regression detection: save baseline on main, compare on PRs
133
+ # Regression detection: update regression.baseline in the discovered config
134
134
  fallow dead-code --format json --quiet --save-regression-baseline
135
+ # Then compare on PRs
135
136
  fallow dead-code --format json --quiet --fail-on-regression --tolerance 2%
136
137
 
137
138
  # Scope to specific files (e.g., lint-staged)
@@ -509,7 +510,7 @@ fallow health --format json --quiet --trend
509
510
  {
510
511
  "kind": "health",
511
512
  "schema_version": 7,
512
- "version": "3.4.2",
513
+ "version": "3.5.1",
513
514
  "elapsed_ms": 32,
514
515
  "summary": {
515
516
  "files_analyzed": 482,
@@ -907,7 +908,7 @@ fallow audit \
907
908
  {
908
909
  "kind": "audit",
909
910
  "schema_version": 7,
910
- "version": "3.4.2",
911
+ "version": "3.5.1",
911
912
  "command": "audit",
912
913
  "verdict": "fail",
913
914
  "changed_files_count": 12,
@@ -982,7 +983,7 @@ fallow flags --format json --quiet --workspace my-package
982
983
  ```json
983
984
  {
984
985
  "schema_version": 7,
985
- "version": "3.4.2",
986
+ "version": "3.5.1",
986
987
  "elapsed_ms": 116,
987
988
  "feature_flags": [],
988
989
  "total_flags": 0
@@ -1083,7 +1084,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1083
1084
  {
1084
1085
  "kind": "security",
1085
1086
  "schema_version": "4",
1086
- "version": "3.4.2",
1087
+ "version": "3.5.1",
1087
1088
  "elapsed_ms": 42,
1088
1089
  "config": {
1089
1090
  "rules": {
@@ -1112,7 +1113,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1112
1113
  {
1113
1114
  "kind": "security",
1114
1115
  "schema_version": "4",
1115
- "version": "3.4.2",
1116
+ "version": "3.5.1",
1116
1117
  "elapsed_ms": 42,
1117
1118
  "config": {
1118
1119
  "rules": {
@@ -1185,6 +1186,7 @@ Compose one evidence bundle before editing a file or exported symbol. This is th
1185
1186
  ```bash
1186
1187
  fallow inspect --file src/api.ts --format json --quiet
1187
1188
  fallow inspect --symbol src/api.ts:fetchUser --format json --quiet
1189
+ fallow inspect --file src/api.ts --churn --format json --quiet
1188
1190
  ```
1189
1191
 
1190
1192
  ### Target Flags
@@ -1193,6 +1195,7 @@ fallow inspect --symbol src/api.ts:fetchUser --format json --quiet
1193
1195
  |------|-------------|
1194
1196
  | `--file <PATH>` | Inspect one project-relative file |
1195
1197
  | `--symbol <FILE:EXPORT>` | Inspect one exported symbol. Supporting dead-code, duplication, complexity, and security evidence is file-scoped in the first version |
1198
+ | `--churn` | Add target-level git churn evidence. Off by default; missing git history is reported as `unavailable` |
1196
1199
 
1197
1200
  Common global flags: `--format`, `--quiet`, `--root`, `--config`, `--workspace`, `--production`, `--no-cache`, `--threads`.
1198
1201
 
@@ -1215,13 +1218,14 @@ Common global flags: `--format`, `--quiet`, `--root`, `--config`, `--workspace`,
1215
1218
  "dead_code": { "status": "ok", "scope": "file", "data": {} },
1216
1219
  "duplication": { "status": "ok", "scope": "project_filtered_to_file", "data": {} },
1217
1220
  "complexity": { "status": "ok", "scope": "project_filtered_to_file", "data": {} },
1218
- "security": { "status": "ok", "scope": "file", "data": {} }
1221
+ "security": { "status": "ok", "scope": "file", "data": {} },
1222
+ "churn": { "status": "ok", "scope": "project_filtered_to_file", "data": {} }
1219
1223
  },
1220
1224
  "warnings": []
1221
1225
  }
1222
1226
  ```
1223
1227
 
1224
- Each evidence section carries `status` and `scope`. Non-fatal child-analysis failures become section-level errors and warnings, so callers can still use the remaining evidence.
1228
+ Each evidence section carries `status` and `scope`. The optional churn section can report `ok`, `unavailable`, or `error`. Non-fatal analysis failures become section-level errors and warnings, so callers can still use the remaining evidence.
1225
1229
 
1226
1230
  ---
1227
1231
 
@@ -1664,8 +1668,8 @@ Available on all commands:
1664
1668
  | `--report-path-prefix` | `string` | - | Prefix prepended to every path in the CI-facing formats (`github-annotations`, `github-summary`, `codeclimate`, `review-github`, `review-gitlab`). CI platforms address files by repository-root-relative path, so when the analyzed project lives in a subdirectory (e.g. `packages/app/`), paths need that offset. fallow detects the offset via the git toplevel automatically; this flag overrides the detection. Pass an empty string to disable rebasing and emit paths relative to `--root` |
1665
1669
  | `--fail-on-regression` | `bool` | `false` | Fail if issue count increased beyond tolerance vs a regression baseline |
1666
1670
  | `--tolerance` | `string` | `0` | Allowed increase: `"2%"` (percentage) or `"5"` (absolute). Default: `"0"` |
1667
- | `--regression-baseline` | `string` | - | Path to regression baseline file (default: `.fallow/regression-baseline.json`) |
1668
- | `--save-regression-baseline` | `string` | - | Save current issue counts as a regression baseline |
1671
+ | `--regression-baseline` | `string` | - | Path to a standalone regression baseline file. Without it, fallow uses `regression.baseline` from the config |
1672
+ | `--save-regression-baseline` | `string` | - | Save current issue counts. With no path, update `regression.baseline` in the discovered fallow config or create `.fallowrc.json`; with a path, write a standalone baseline file |
1669
1673
  | `--only` | `dead-code\|dupes\|health` | - | Run only specific analyses (e.g., `--only dead-code,dupes`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1670
1674
  | `--skip` | `dead-code\|dupes\|health` | - | Skip specific analyses (e.g., `--skip health`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
1671
1675
  | `--dupes-mode` | `strict\|mild\|weak\|semantic` | - | Override duplication detection mode in combined mode |
@@ -1798,7 +1802,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1798
1802
 
1799
1803
  ## CI Integration
1800
1804
 
1801
- - **GitHub Actions**: `uses: fallow-rs/fallow@v2` - supports SARIF upload to Code Scanning, inline PR annotations (`annotations: true`), PR comments, all commands. Annotations use workflow commands (no Advanced Security required); limit with `max-annotations` (default 50). Set `score: true` to compute health score and enable the health delta header in PR comments
1805
+ - **GitHub Actions**: `uses: fallow-rs/fallow@v3` - supports SARIF upload to Code Scanning, inline PR annotations (`annotations: true`), PR comments, all commands. Annotations use workflow commands (no Advanced Security required); limit with `max-annotations` (default 50). Set `score: true` to compute health score and enable the health delta header in PR comments
1802
1806
  - **GitLab CI**: include `ci/gitlab-ci.yml` template and extend `.fallow` - generates Code Quality reports via `--format codeclimate` / `--format gitlab-codequality` (inline MR annotations), rich MR comments, code review comments, all commands. Use `fallow ci-template gitlab --vendor` when runners cannot reach `raw.githubusercontent.com`; commit the generated `ci/` and `action/` files and use GitLab's local include syntax. Variables use `FALLOW_` prefix (e.g., `FALLOW_COMMAND`, `FALLOW_FAIL_ON_ISSUES`). Set `FALLOW_SCORE: "true"` to compute health score; `FALLOW_TREND: "true"` to compare against saved snapshots
1803
1807
  - **Any CI**: `npx fallow --ci` - equivalent to `--format sarif --fail-on-issues --quiet`
1804
1808
 
@@ -1833,7 +1837,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1833
1837
  {
1834
1838
  "kind": "dead-code",
1835
1839
  "schema_version": 7,
1836
- "version": "3.4.2",
1840
+ "version": "3.5.1",
1837
1841
  "elapsed_ms": 45,
1838
1842
  "total_issues": 12,
1839
1843
  "entry_points": {
@@ -1993,7 +1997,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
1993
1997
  {
1994
1998
  "kind": "dupes",
1995
1999
  "schema_version": 7,
1996
- "version": "3.4.2",
2000
+ "version": "3.5.1",
1997
2001
  "elapsed_ms": 82,
1998
2002
  "total_clones": 15,
1999
2003
  "total_lines_duplicated": 230,
@@ -2037,11 +2041,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
2037
2041
  {
2038
2042
  "kind": "combined",
2039
2043
  "schema_version": 7,
2040
- "version": "3.4.2",
2044
+ "version": "3.5.1",
2041
2045
  "elapsed_ms": 159,
2042
2046
  "check": {
2043
2047
  "schema_version": 7,
2044
- "version": "3.4.2",
2048
+ "version": "3.5.1",
2045
2049
  "elapsed_ms": 45,
2046
2050
  "total_issues": 12,
2047
2051
  "unused_files": [],
@@ -15,7 +15,7 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
15
15
  | `analyze` | analysis | free | `fallow dead-code --format json --quiet` | `issue_types`, `production`, `workspace`, `baseline`, `group_by`, `file` | Full dead code analysis (unused files/exports/types/dependencies/members + circular dependencies + re-export cycles (barrel files that form a structural loop, silently breaking re-exports) + boundary violations + rule-pack policy violations (banned calls, imports, and catalogue-derived effects declared via the `rulePacks` config key) + stale suppressions). Private type leaks are an opt-in API hygiene check via `issue_types: ["private-type-leaks"]`. Set `boundary_violations: true` as a convenience alias for `issue_types: ["boundary-violations"]`. Set `group_by` to `"owner"`, `"directory"`, `"package"`, or `"section"` to partition results. The `section` mode reads GitLab CODEOWNERS `[Section]` headers and emits `owners` metadata per group |
16
16
  | `check_changed` | analysis | free | `fallow dead-code --changed-since <ref> --format json --quiet` | `since`, `baseline`, `fail_on_regression` | Incremental analysis of files changed since a git ref |
17
17
  | `security_candidates` | analysis | free | `fallow security --format json --quiet` | `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. |
18
- | `inspect_target` | analysis | free | `fallow inspect --format json --quiet` | `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. |
18
+ | `inspect_target` | analysis | free | `fallow inspect --format json --quiet` | `target`, `production`, `include_churn` | 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. Set `include_churn: true` to add target-level git churn from the health hotspot subsystem. Churn is off by default, and unavailable git history or analysis failures remain explicit section states. Evidence sections carry `status` and `scope`; symbol targets warn when supporting evidence is file-scoped. Supports `root`, `config`, `production`, `workspace`, `include_churn`, `no_cache`, and `threads`; `production` applies to trace, dead-code, and health evidence only. Raise `FALLOW_TIMEOUT_SECS` for large repos. |
19
19
  | `guard` | introspection | free | `fallow guard <file> --format json --quiet` | `files` | Report the architecture rules that apply to given files before editing them: boundary zone, allowed import zones, forbidden calls, and rule-pack policies |
20
20
  | `find_dupes` | analysis | free | `fallow dupes --format json --quiet` | `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 |
21
21
  | `check_health` | analysis | free | `fallow health --format json --quiet` | `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 |
@@ -111,7 +111,7 @@ Parse the JSON to list specific files and exports that became unused.
111
111
  ### GitHub Actions: Using the Official Action
112
112
 
113
113
  ```yaml
114
- - uses: fallow-rs/fallow@v2
114
+ - uses: fallow-rs/fallow@v3
115
115
  with:
116
116
  command: dead-code
117
117
  fail-on-issues: true
@@ -123,7 +123,7 @@ Parse the JSON to list specific files and exports that became unused.
123
123
  Fail a PR only when it introduces new security candidates (or makes existing ones newly reachable). Gated failures exit with code 8; the `issues` output counts only matching gate candidates. PR comment and review renderers skip security envelopes.
124
124
 
125
125
  ```yaml
126
- - uses: fallow-rs/fallow@v2
126
+ - uses: fallow-rs/fallow@v3
127
127
  with:
128
128
  command: security
129
129
  security-gate: new # or newly-reachable (needs a base ref via changed-since or PR auto-scoping)
@@ -134,7 +134,7 @@ GitLab equivalent: `FALLOW_COMMAND: "security"` with `FALLOW_SECURITY_GATE: "new
134
134
  ### GitHub Actions: With Health Score
135
135
 
136
136
  ```yaml
137
- - uses: fallow-rs/fallow@v2
137
+ - uses: fallow-rs/fallow@v3
138
138
  with:
139
139
  score: true
140
140
  changed-since: main
@@ -145,7 +145,7 @@ Computes a health score (0-100 with letter grade) in combined mode and enables t
145
145
  ### GitHub Actions: Severity-Aware PR Quality Gate (Audit)
146
146
 
147
147
  ```yaml
148
- - uses: fallow-rs/fallow@v2
148
+ - uses: fallow-rs/fallow@v3
149
149
  with:
150
150
  command: audit
151
151
  gate: new-only # default; fails only on findings introduced by this PR
@@ -157,7 +157,7 @@ Runs `fallow audit` to combine dead-code + complexity + duplication scoped to ch
157
157
  The action exposes `outputs.verdict` (`pass`/`warn`/`fail`) and `outputs.gate` for downstream conditionals; `outputs.issues` holds the introduced count under `gate: new-only` and the total count under `gate: all`.
158
158
 
159
159
  ```yaml
160
- - uses: fallow-rs/fallow@v2
160
+ - uses: fallow-rs/fallow@v3
161
161
  id: fallow
162
162
  with:
163
163
  command: audit
@@ -174,7 +174,7 @@ Three additional outputs surface silent failures in the action's PR comment / re
174
174
  The official action supports inline PR annotations via GitHub workflow commands. This does not require Advanced Security (unlike SARIF upload) and works on any GitHub plan.
175
175
 
176
176
  ```yaml
177
- - uses: fallow-rs/fallow@v2
177
+ - uses: fallow-rs/fallow@v3
178
178
  with:
179
179
  command: dead-code
180
180
  changed-since: main