fallow 3.5.0 → 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.
- package/README.md +40 -81
- package/capabilities.json +2 -2
- package/package.json +10 -10
- package/scripts/run-binary.test.js +71 -0
- package/skills/fallow/SKILL.md +6 -4
- package/skills/fallow/references/cli-reference.md +13 -12
- package/types/output-contract.d.ts +3 -3
package/README.md
CHANGED
|
@@ -2,98 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
**Codebase intelligence for TypeScript and JavaScript.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
One binary finds unused code, circular dependencies, duplication, complexity hotspots, boundary violations, and design-system styling drift. An optional paid layer, Fallow Runtime, adds production execution evidence. No AI inside the analyzer, and no TypeScript compiler or Node.js runtime needed for static analysis: runs are deterministic, with typed output contracts and traceable explanations.
|
|
6
6
|
|
|
7
7
|
[](https://github.com/fallow-rs/fallow/actions/workflows/ci.yml)
|
|
8
8
|
[](https://www.npmjs.com/package/fallow)
|
|
9
9
|
[](https://github.com/fallow-rs/fallow/blob/main/LICENSE)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
It helps you answer: what changed, what got riskier, what should be reviewed, what should be refactored, and what can be safely removed. No AI inside the analyzer. Fallow produces deterministic findings, typed output contracts, and traceable explanations that downstream tools can trust.
|
|
14
|
-
|
|
15
|
-
Static analysis is open source. An optional runtime layer adds production execution evidence. Rust-native, sub-second, 123 framework plugins, no Node.js runtime dependency for analysis. fallow's edge is doing more in one pass: dead code, duplication, dependencies, complexity, architecture, styling consistency, and security candidates in a single tool. For head-to-head timings against [knip](https://knip.dev) and [jscpd](https://github.com/kucherenko/jscpd), see the [benchmarks](https://github.com/fallow-rs/fallow/tree/main/benchmarks): fallow is faster than knip on smaller projects, knip is faster on several larger repos, and jscpd's Rust rewrite is faster for raw duplication scanning.
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
11
|
+
## Install
|
|
18
12
|
|
|
19
13
|
```bash
|
|
20
|
-
npm install --save-dev fallow # or: pnpm add -D fallow / yarn add -D fallow
|
|
14
|
+
npm install --save-dev fallow # or: pnpm add -D fallow / yarn add -D fallow
|
|
21
15
|
```
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
The package also ships a version-matched Agent Skill under `skills/fallow`.
|
|
26
|
-
For tools that need CLI and issue-surface metadata without spawning the binary,
|
|
27
|
-
`fallow/capabilities.json` mirrors `fallow schema` for the installed version.
|
|
28
|
-
TanStack Intent discovers it from `node_modules` automatically:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npx @tanstack/intent list
|
|
32
|
-
npx @tanstack/intent load fallow#fallow
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
For one-off CLI use without project-local skill discovery, run `npx fallow`.
|
|
36
|
-
|
|
37
|
-
Parsing fallow's JSON output in TypeScript? Import the typed shapes:
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import type { CheckOutput, FallowJsonOutput } from "fallow/types";
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The types are generated from the same schema as the VS Code extension and pin to the CLI version you install. See [docs.fallow.tools](https://docs.fallow.tools) for the full output contract.
|
|
17
|
+
This installs the `fallow` CLI plus the `fallow-lsp` and `fallow-mcp` launchers, so editor and agent integrations resolve the project-local binary instead of whatever happens to be on `PATH`. For one-off use, run `npx fallow` without installing. Other channels (cargo, Docker, prebuilt binaries) are covered in the [installation guide](https://docs.fallow.tools/installation).
|
|
44
18
|
|
|
45
19
|
## Quick start
|
|
46
20
|
|
|
47
21
|
```bash
|
|
48
|
-
npx fallow
|
|
49
|
-
npx fallow audit
|
|
50
|
-
npx fallow health --score #
|
|
51
|
-
npx fallow
|
|
52
|
-
npx fallow dead-code # Cleanup-specific findings
|
|
22
|
+
npx fallow # Full pipeline: dead code + duplication + health
|
|
23
|
+
npx fallow audit # Gate only what a PR changed: verdict pass/warn/fail
|
|
24
|
+
npx fallow health --score # 0 to 100 health score with a letter grade
|
|
25
|
+
npx fallow dupes # Duplication; modes strict, mild (default), weak, semantic
|
|
53
26
|
npx fallow fix --dry-run # Preview automatic cleanup
|
|
54
27
|
```
|
|
55
28
|
|
|
56
|
-
##
|
|
57
|
-
|
|
58
|
-
- **Quality score** -- compact health score with grade and trend delta when snapshot history is enabled
|
|
59
|
-
- **PR risk** -- changed-code analysis with pass / warn / fail verdict and per-finding attribution
|
|
60
|
-
- **Hotspots** -- functions, files, and packages combining complexity, churn, size, and coupling
|
|
61
|
-
- **Duplication** -- clone families across four detection modes (strict, mild, weak, semantic)
|
|
62
|
-
- **Design-system styling** -- CSS, Sass/Less, CSS Modules, Tailwind/shadcn/CVA, StyleX/PandaCSS, vanilla-extract, styled-components, and Emotion consistency signals
|
|
63
|
-
- **Architecture** -- circular dependencies, boundary violations, re-export chains
|
|
64
|
-
- **Dependency hygiene** -- unused, unlisted, unresolved, duplicate, and type-only deps; pnpm catalog and overrides
|
|
65
|
-
- **Cleanup opportunities** -- unused files, exports, types, enum members, class members, stale suppressions
|
|
66
|
-
- **Runtime intelligence (optional)** -- hot paths, cold code, runtime-weighted health, stale flags
|
|
29
|
+
## Output and exit codes
|
|
67
30
|
|
|
68
|
-
|
|
31
|
+
Add `--format json --quiet` to any command for one typed JSON document on stdout. Exit code 1 means findings, not failure; 0 is clean (or an audit pass or warn verdict); 2 is a validation or runtime error, reported as a JSON error envelope rather than a stack trace.
|
|
69
32
|
|
|
70
|
-
|
|
33
|
+
Parsing the output in TypeScript? Import the typed shapes, version-pinned to the CLI you install:
|
|
71
34
|
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
fallow dupes --mode semantic # Catch clones with renamed variables
|
|
75
|
-
fallow dupes --threshold 5 # Fail CI if duplication exceeds 5%
|
|
76
|
-
fallow dupes --save-baseline # Save current duplication as baseline
|
|
35
|
+
```ts
|
|
36
|
+
import type { CheckOutput, FallowJsonOutput } from "fallow/types";
|
|
77
37
|
```
|
|
78
38
|
|
|
79
|
-
|
|
39
|
+
Every issue carries an `actions[]` array with an `auto_fixable` flag, so scripts and agents know which findings they can hand to `fallow fix`. The full contract lives at [docs.fallow.tools](https://docs.fallow.tools).
|
|
80
40
|
|
|
81
|
-
##
|
|
41
|
+
## What fallow reports
|
|
82
42
|
|
|
83
|
-
|
|
43
|
+
- Unused files, exports, types, enum and class members, and dependencies
|
|
44
|
+
- Circular dependencies and re-export cycles
|
|
45
|
+
- Code duplication as clone families, across four detection modes
|
|
46
|
+
- Complexity hotspots and a 0 to 100 health score
|
|
47
|
+
- Architecture boundary violations, with zero-config presets
|
|
48
|
+
- Design-system styling drift for CSS and CSS-in-JS (Sass/Less, CSS Modules, Tailwind, styled-components, Emotion, and more)
|
|
49
|
+
- A changed-file PR gate with per-finding attribution (`fallow audit`)
|
|
50
|
+
- Optional runtime intelligence: hot paths, cold code, runtime-weighted health, stale flags (licensed Fallow Runtime; a single local coverage capture is free)
|
|
84
51
|
|
|
85
|
-
-
|
|
86
|
-
- Why is this export considered used or unused?
|
|
87
|
-
- What changed in this PR?
|
|
88
|
-
- Which files are risky to touch?
|
|
89
|
-
- What duplicate siblings exist?
|
|
90
|
-
- What cleanup action is safest?
|
|
52
|
+
For head-to-head timings against [knip](https://knip.dev) and [jscpd](https://github.com/kucherenko/jscpd), see [BENCHMARKS.md](https://github.com/fallow-rs/fallow/blob/main/BENCHMARKS.md): fallow is faster than knip on smaller projects, knip is faster on several larger repos, and jscpd's Rust rewrite is faster at raw duplication scanning.
|
|
91
53
|
|
|
92
|
-
|
|
54
|
+
## Built for agents
|
|
93
55
|
|
|
94
|
-
|
|
56
|
+
Agents get structured repo truth instead of inferring everything from grep: who imports a symbol, why an export counts as used, what a PR changed, which cleanup action is safest.
|
|
95
57
|
|
|
96
|
-
|
|
58
|
+
The bundled `fallow-mcp` server lives in `node_modules/.bin/` when installed as a devDependency, so launch it through your package manager's runner:
|
|
97
59
|
|
|
98
60
|
```json
|
|
99
61
|
{
|
|
@@ -106,15 +68,22 @@ Agents that speak MCP can launch the bundled `fallow-mcp` server. Installed as a
|
|
|
106
68
|
}
|
|
107
69
|
```
|
|
108
70
|
|
|
109
|
-
Swap `npx` for `pnpm exec`
|
|
71
|
+
Swap `npx` for `pnpm exec` or `yarn` to match your package manager; a globally installed `fallow-mcp` works as `"command": "fallow-mcp"` directly. See the [MCP integration guide](https://docs.fallow.tools/integrations/mcp).
|
|
72
|
+
|
|
73
|
+
The package also ships a version-matched agent skill under `skills/fallow`, and `fallow/capabilities.json` mirrors `fallow schema` for tools that need CLI and issue-surface metadata without spawning the binary. TanStack Intent discovers both from `node_modules`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx @tanstack/intent list
|
|
77
|
+
npx @tanstack/intent load fallow#fallow
|
|
78
|
+
```
|
|
110
79
|
|
|
111
80
|
## Framework support
|
|
112
81
|
|
|
113
|
-
|
|
82
|
+
Over 100 built-in framework plugins covering Next.js, Nuxt, Remix, Qwik, SvelteKit, Gatsby, Astro, Angular, NestJS, AdonisJS, Ember, Expo Router, Vite, Webpack, Vitest, Jest, Playwright, Cypress, Storybook, ESLint, TypeScript, Tailwind, UnoCSS, Prisma, Drizzle, Convex, Turborepo, Hardhat, and more. Entry points are auto-detected from `package.json`, so the first run needs no configuration.
|
|
114
83
|
|
|
115
84
|
## Configuration
|
|
116
85
|
|
|
117
|
-
|
|
86
|
+
Works out of the box. To customize, let [`fallow recommend`](https://docs.fallow.tools/cli/recommend) propose a config from the detected stack (read-only; `--format json` returns the full decision set for agents), run `fallow init`, or create a config file in your project root:
|
|
118
87
|
|
|
119
88
|
```jsonc
|
|
120
89
|
// .fallowrc.json
|
|
@@ -130,23 +99,13 @@ Create a config file in your project root, or run `fallow init`:
|
|
|
130
99
|
}
|
|
131
100
|
```
|
|
132
101
|
|
|
133
|
-
`$schema` gives editors autocomplete and validation and has no effect on
|
|
134
|
-
analysis. As an npm package, `fallow` always ships a version-aligned schema at
|
|
135
|
-
`./node_modules/fallow/schema.json`, which `fallow init` and
|
|
136
|
-
`fallow recommend` point at by default: offline, no editor trust prompt. If
|
|
137
|
-
you install fallow another way (cargo, homebrew, a bare binary) with no
|
|
138
|
-
`node_modules/fallow` to point at, use the remote fallback instead:
|
|
139
|
-
`https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json`. Some
|
|
140
|
-
editors, including VS Code, refuse to load a remote schema URL until you
|
|
141
|
-
explicitly trust the domain.
|
|
142
|
-
|
|
143
|
-
Also supports TOML (`fallow init --toml` creates `fallow.toml`).
|
|
102
|
+
`$schema` gives editors autocomplete and validation and has no effect on analysis. The npm package ships a version-aligned schema at `./node_modules/fallow/schema.json`, so validation works offline with no editor trust prompt. TOML works too: `fallow init --toml` creates `fallow.toml`. Full reference: [configuration overview](https://docs.fallow.tools/configuration/overview).
|
|
144
103
|
|
|
145
104
|
## Documentation
|
|
146
105
|
|
|
147
|
-
- [
|
|
106
|
+
- [docs.fallow.tools](https://docs.fallow.tools)
|
|
148
107
|
- [GitHub repository](https://github.com/fallow-rs/fallow)
|
|
149
|
-
- [Plugin
|
|
108
|
+
- [Plugin authoring guide](https://github.com/fallow-rs/fallow/blob/main/docs/plugin-authoring.md)
|
|
150
109
|
|
|
151
110
|
## License
|
|
152
111
|
|
package/capabilities.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"manifest_version": "1",
|
|
5
5
|
"description": "Codebase analyzer for TypeScript/JavaScript: unused code, circular dependencies, code duplication, complexity hotspots, and architecture boundary violations",
|
|
6
6
|
"global_flags": [
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
"name": "--save-regression-baseline",
|
|
312
312
|
"type": "string",
|
|
313
313
|
"required": false,
|
|
314
|
-
"description": "Save the current issue counts as a regression baseline"
|
|
314
|
+
"description": "Save the current issue counts as a regression baseline. Omit PATH to update regression.baseline in the discovered fallow config, or create .fallowrc.json when none exists. Provide PATH to write a standalone file"
|
|
315
315
|
},
|
|
316
316
|
{
|
|
317
317
|
"name": "--only",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "Codebase intelligence for TypeScript and JavaScript. Free static analysis of code and styles, optional paid runtime intelligence (Fallow Runtime). Quality, risk, architecture, dependencies, duplication, and design-system drift for humans, CI, and the agents writing your code. Zero-config framework support.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -84,16 +84,16 @@
|
|
|
84
84
|
"detect-libc": "2.1.2"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"@tanstack/intent": "0.3.
|
|
87
|
+
"@tanstack/intent": "0.3.5"
|
|
88
88
|
},
|
|
89
89
|
"optionalDependencies": {
|
|
90
|
-
"@fallow-cli/darwin-arm64": "3.5.
|
|
91
|
-
"@fallow-cli/darwin-x64": "3.5.
|
|
92
|
-
"@fallow-cli/linux-x64-gnu": "3.5.
|
|
93
|
-
"@fallow-cli/linux-arm64-gnu": "3.5.
|
|
94
|
-
"@fallow-cli/linux-x64-musl": "3.5.
|
|
95
|
-
"@fallow-cli/linux-arm64-musl": "3.5.
|
|
96
|
-
"@fallow-cli/win32-arm64-msvc": "3.5.
|
|
97
|
-
"@fallow-cli/win32-x64-msvc": "3.5.
|
|
90
|
+
"@fallow-cli/darwin-arm64": "3.5.1",
|
|
91
|
+
"@fallow-cli/darwin-x64": "3.5.1",
|
|
92
|
+
"@fallow-cli/linux-x64-gnu": "3.5.1",
|
|
93
|
+
"@fallow-cli/linux-arm64-gnu": "3.5.1",
|
|
94
|
+
"@fallow-cli/linux-x64-musl": "3.5.1",
|
|
95
|
+
"@fallow-cli/linux-arm64-musl": "3.5.1",
|
|
96
|
+
"@fallow-cli/win32-arm64-msvc": "3.5.1",
|
|
97
|
+
"@fallow-cli/win32-x64-msvc": "3.5.1"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -1,10 +1,61 @@
|
|
|
1
1
|
const test = require("node:test");
|
|
2
2
|
const assert = require("node:assert/strict");
|
|
3
|
+
const fs = require("node:fs");
|
|
3
4
|
const os = require("node:os");
|
|
4
5
|
const { spawnSync } = require("node:child_process");
|
|
5
6
|
const path = require("node:path");
|
|
6
7
|
|
|
7
8
|
const RUN_BINARY = path.join(__dirname, "run-binary.js");
|
|
9
|
+
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
10
|
+
|
|
11
|
+
function currentPlatformPackage() {
|
|
12
|
+
const { getPlatformPackage } = require("./platform-package");
|
|
13
|
+
if (process.platform !== "linux") {
|
|
14
|
+
return getPlatformPackage(process.platform, process.arch);
|
|
15
|
+
}
|
|
16
|
+
let libcFamily;
|
|
17
|
+
try {
|
|
18
|
+
libcFamily = require("detect-libc").familySync();
|
|
19
|
+
} catch {
|
|
20
|
+
libcFamily = undefined;
|
|
21
|
+
}
|
|
22
|
+
return getPlatformPackage(process.platform, process.arch, libcFamily);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function runLauncher(t, launcher, args) {
|
|
26
|
+
const work = fs.mkdtempSync(path.join(os.tmpdir(), "fallow-launcher-"));
|
|
27
|
+
t.after(() => fs.rmSync(work, { recursive: true, force: true }));
|
|
28
|
+
|
|
29
|
+
const pkg = currentPlatformPackage();
|
|
30
|
+
assert.ok(pkg, "the test host must map to a supported platform package");
|
|
31
|
+
const pkgDir = path.join(work, "node_modules", ...pkg.split("/"));
|
|
32
|
+
fs.mkdirSync(pkgDir, { recursive: true });
|
|
33
|
+
fs.writeFileSync(
|
|
34
|
+
path.join(pkgDir, "package.json"),
|
|
35
|
+
JSON.stringify({ name: pkg, version: "3.5.0" }),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const binary = path.join(pkgDir, "fallow");
|
|
39
|
+
fs.writeFileSync(
|
|
40
|
+
binary,
|
|
41
|
+
"#!/usr/bin/env node\n" +
|
|
42
|
+
'require("node:fs").writeFileSync(process.env.FALLOW_TEST_ARGS, JSON.stringify(process.argv.slice(2)));\n',
|
|
43
|
+
);
|
|
44
|
+
fs.chmodSync(binary, 0o755);
|
|
45
|
+
|
|
46
|
+
const argsFile = path.join(work, "args.json");
|
|
47
|
+
const result = spawnSync(process.execPath, [path.join(BIN_DIR, launcher), ...args], {
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
env: {
|
|
50
|
+
...process.env,
|
|
51
|
+
NODE_PATH: path.join(work, "node_modules"),
|
|
52
|
+
FALLOW_SKIP_BINARY_VERIFY: "1",
|
|
53
|
+
FALLOW_TEST_ARGS: argsFile,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
assert.equal(result.status, 0, result.stderr);
|
|
57
|
+
return JSON.parse(fs.readFileSync(argsFile, "utf8"));
|
|
58
|
+
}
|
|
8
59
|
|
|
9
60
|
// Run a child that installs guardBrokenStdout, then emits a synthetic stdout
|
|
10
61
|
// 'error' with the given code. Node delivers a broken-pipe failure as exactly
|
|
@@ -91,3 +142,23 @@ test("exitCodeForChildFailure preserves status codes and maps signal deaths", ()
|
|
|
91
142
|
assert.equal(exitCodeForChildFailure({ status: null, signal: undefined }), 1);
|
|
92
143
|
assert.equal(exitCodeForChildFailure({ status: null, signal: "NOT_A_SIGNAL" }), 1);
|
|
93
144
|
});
|
|
145
|
+
|
|
146
|
+
test(
|
|
147
|
+
"fallow-lsp executes the multicall binary with the lsp-server subcommand",
|
|
148
|
+
{ skip: process.platform === "win32" },
|
|
149
|
+
(t) => {
|
|
150
|
+
assert.deepEqual(runLauncher(t, "fallow-lsp", ["--stdio"]), ["lsp-server", "--stdio"]);
|
|
151
|
+
},
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
test(
|
|
155
|
+
"fallow-mcp executes the multicall binary with the mcp-server subcommand",
|
|
156
|
+
{ skip: process.platform === "win32" },
|
|
157
|
+
(t) => {
|
|
158
|
+
assert.deepEqual(runLauncher(t, "fallow-mcp", ["--transport", "stdio"]), [
|
|
159
|
+
"mcp-server",
|
|
160
|
+
"--transport",
|
|
161
|
+
"stdio",
|
|
162
|
+
]);
|
|
163
|
+
},
|
|
164
|
+
);
|
package/skills/fallow/SKILL.md
CHANGED
|
@@ -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.).
|
|
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
|
|
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 --
|
|
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
|
|
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:
|
|
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.5.
|
|
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.5.
|
|
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.5.
|
|
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.5.
|
|
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.5.
|
|
1116
|
+
"version": "3.5.1",
|
|
1116
1117
|
"elapsed_ms": 42,
|
|
1117
1118
|
"config": {
|
|
1118
1119
|
"rules": {
|
|
@@ -1667,8 +1668,8 @@ Available on all commands:
|
|
|
1667
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` |
|
|
1668
1669
|
| `--fail-on-regression` | `bool` | `false` | Fail if issue count increased beyond tolerance vs a regression baseline |
|
|
1669
1670
|
| `--tolerance` | `string` | `0` | Allowed increase: `"2%"` (percentage) or `"5"` (absolute). Default: `"0"` |
|
|
1670
|
-
| `--regression-baseline` | `string` | - | Path to regression baseline file
|
|
1671
|
-
| `--save-regression-baseline` | `string` | - | Save current issue counts
|
|
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 |
|
|
1672
1673
|
| `--only` | `dead-code\|dupes\|health` | - | Run only specific analyses (e.g., `--only dead-code,dupes`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
|
|
1673
1674
|
| `--skip` | `dead-code\|dupes\|health` | - | Skip specific analyses (e.g., `--skip health`). Values: `dead-code` (alias: `check`), `dupes`, `health` |
|
|
1674
1675
|
| `--dupes-mode` | `strict\|mild\|weak\|semantic` | - | Override duplication detection mode in combined mode |
|
|
@@ -1836,7 +1837,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
|
|
|
1836
1837
|
{
|
|
1837
1838
|
"kind": "dead-code",
|
|
1838
1839
|
"schema_version": 7,
|
|
1839
|
-
"version": "3.5.
|
|
1840
|
+
"version": "3.5.1",
|
|
1840
1841
|
"elapsed_ms": 45,
|
|
1841
1842
|
"total_issues": 12,
|
|
1842
1843
|
"entry_points": {
|
|
@@ -1996,7 +1997,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
|
|
|
1996
1997
|
{
|
|
1997
1998
|
"kind": "dupes",
|
|
1998
1999
|
"schema_version": 7,
|
|
1999
|
-
"version": "3.5.
|
|
2000
|
+
"version": "3.5.1",
|
|
2000
2001
|
"elapsed_ms": 82,
|
|
2001
2002
|
"total_clones": 15,
|
|
2002
2003
|
"total_lines_duplicated": 230,
|
|
@@ -2040,11 +2041,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
2040
2041
|
{
|
|
2041
2042
|
"kind": "combined",
|
|
2042
2043
|
"schema_version": 7,
|
|
2043
|
-
"version": "3.5.
|
|
2044
|
+
"version": "3.5.1",
|
|
2044
2045
|
"elapsed_ms": 159,
|
|
2045
2046
|
"check": {
|
|
2046
2047
|
"schema_version": 7,
|
|
2047
|
-
"version": "3.5.
|
|
2048
|
+
"version": "3.5.1",
|
|
2048
2049
|
"elapsed_ms": 45,
|
|
2049
2050
|
"total_issues": 12,
|
|
2050
2051
|
"unused_files": [],
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* `npm/fallow/types/output-contract.d.ts` (published as `fallow/types`).
|
|
8
8
|
*
|
|
9
9
|
* To change a shape:
|
|
10
|
-
* 1.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* 1. Find the Rust owner through `derived_definition_names()` and its
|
|
11
|
+
* imports in `crates/cli/src/bin/schema_emit.rs`, then edit that type.
|
|
12
|
+
* Rust is the runtime source of truth for the JSON output.
|
|
13
13
|
* 2. Regenerate `docs/output-schema.json` with
|
|
14
14
|
* `cargo run -p fallow-cli --features schema-emit --bin fallow-schema-emit`.
|
|
15
15
|
* The schema-emit drift tests compare the committed schema against the
|