fallow 3.17.0 → 3.19.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/README.md +2 -2
- package/capabilities.json +166 -17
- package/issue-registry.json +2 -2
- package/package.json +11 -10
- package/schema.json +43 -4
- package/scripts/lazy-verify.js +20 -6
- package/scripts/lazy-verify.test.js +86 -103
- package/scripts/sentinel-path.test.js +9 -2
- package/scripts/verify-binary.js +10 -9
- package/scripts/verify-binary.test.js +56 -10
- package/skills/fallow/SKILL.md +21 -21
- package/skills/fallow/references/cli-reference.md +74 -6
- package/skills/fallow/references/gotchas.md +2 -2
- package/skills/fallow/references/mcp.md +47 -5
- package/skills/fallow/references/node-bindings.md +3 -2
- package/skills/fallow/references/patterns.md +2 -2
- package/skills/fallow/references/similar-code.md +47 -0
- package/types/output-contract.d.ts +786 -76
package/skills/fallow/SKILL.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fallow
|
|
3
|
-
description: Codebase intelligence for TypeScript and JavaScript. Static analysis
|
|
3
|
+
description: Codebase intelligence for TypeScript and JavaScript. 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. Optional local similar-code discovery finds functions that may implement the same intent despite different syntax. Runtime coverage can merge production execution data. Use when asked to audit PR risk, find unused code or dependencies, compare semantically similar functions, detect duplicates, inspect architecture boundaries, merge runtime coverage, auto-fix supported issues, or run fallow.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Fallow: codebase intelligence for TypeScript and JavaScript
|
|
8
8
|
|
|
9
|
-
Codebase intelligence for TypeScript and JavaScript. The static layer analyzes code and styles and 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.
|
|
9
|
+
Codebase intelligence for TypeScript and JavaScript. The static layer analyzes code and styles and 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. Broad framework plugin coverage, zero configuration, sub-second static analysis.
|
|
10
10
|
|
|
11
11
|
## When to Use
|
|
12
12
|
- Find cleanup opportunities: unused files, exports, types, members, dependencies, or stale flags.
|
|
13
13
|
- Detect code duplication, circular dependencies, architecture boundary issues, and complexity hotspots.
|
|
14
|
+
- Find functions that may implement the same intent despite different names, syntax, or control flow (`fallow similar-code`).
|
|
14
15
|
- Check styling consistency, CSS dead surface, and design-token drift.
|
|
15
16
|
- Audit changed code before a commit, PR, release, or refactor.
|
|
16
17
|
- Set up CI quality gates, duplication thresholds, and regression baselines.
|
|
@@ -31,7 +32,6 @@ Codebase intelligence for TypeScript and JavaScript. The static layer analyzes c
|
|
|
31
32
|
- Projects that are not JavaScript or TypeScript
|
|
32
33
|
|
|
33
34
|
## Prerequisites
|
|
34
|
-
|
|
35
35
|
Fallow must be installed. If not available, install it:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
@@ -41,9 +41,8 @@ cargo install fallow-cli # build from source
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Agent Rules
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
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)
|
|
44
|
+
1. **Always use `--format json --quiet`** for machine-readable output and parse stdout as JSON. Compact JSON is the default; never depend on whitespace or add `--pretty` in agent pipelines. Keep stderr separate so diagnostics remain visible; never merge it into the JSON stream with `2>&1`.
|
|
45
|
+
2. **Preserve and interpret the exit status.** Codes 0 and 1 are successful analysis outcomes: 0 is clean and 1 means findings. Treat every other code according to `fallow schema.exit_codes`. Do not force a successful status, because that hides validation, license, setup, network, and security-gate outcomes.
|
|
47
46
|
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.
|
|
48
47
|
4. **Use the root `kind` field** to identify typed JSON envelopes (`dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, etc.).
|
|
49
48
|
5. **Use issue type filters** (`--unused-exports`, `--unused-files`, etc.) to limit output scope
|
|
@@ -55,6 +54,8 @@ cargo install fallow-cli # build from source
|
|
|
55
54
|
11. **Never enable telemetry on the user's behalf**. Fallow's product telemetry is opt-in and off by default; only the user may run `fallow telemetry enable`. You MAY set `FALLOW_AGENT_SOURCE=<allowlisted-value>` (for example `claude_code`, `codex`, `cursor`, `windsurf`, `gemini`, `cline`) so that, IF the user has already enabled telemetry, your integration is correctly attributed. Setting `FALLOW_AGENT_SOURCE` never enables telemetry by itself and uploads no codebase content.
|
|
56
55
|
12. **Use type-aware analysis only for Fallow-owned project questions**. Reach for `--type-aware` to prove exact symbol use, preserve TypeScript class contracts, guard class-member cleanup, find cross-file private type leaks, suggest targeted tests, or inspect public-signature coupling. Keep `tsc --noEmit` responsible for compiler correctness and Oxlint responsible for local typed lint rules. Treat partial or unavailable semantic results as retained findings, never as deletion proof. Unknown external consumers of a published library remain outside checker-visible evidence, so preserve declared public API unless every relevant consumer project is explicitly in scope.
|
|
57
56
|
13. **Use `fallow impact statusline` only for a user-facing status surface**. It intentionally emits one plain-text, path-free line and ignores `--format`. It starts no analysis, never enables Impact, and compares only whole-project scans. Do not parse this line as JSON.
|
|
57
|
+
14. **Treat similar-code output as discovery only**. Never describe its score as a probability, finding, proof of equivalent behavior, or safe-refactor decision. Agents must not authorize setup. Inspect a candidate before judging it: save discovery as `similar-code.json`, inspect with `--candidates similar-code.json`, and pass the unchanged file to `fallow similar-code review`. Over MCP use `find_similar_code` with `paths:` and `inspect_similar_code` with a typed `snapshot`; it fails closed on stale source. Keep `candidate_worthy`, `behaviorally_equivalent`, and `refactor_safe` separate, use `needs-human-review`, and abstain when evidence is incomplete. Only `completion.status: "complete"` makes an empty result conclusive. Follow [the complete workflow to compare semantically similar functions](references/similar-code.md).
|
|
58
|
+
|
|
58
59
|
## Onboarding And Insight
|
|
59
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`.
|
|
60
61
|
## Task Cheat Sheet
|
|
@@ -79,7 +80,6 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
79
80
|
<!-- generated:task-matrix:end -->
|
|
80
81
|
|
|
81
82
|
## Commands
|
|
82
|
-
|
|
83
83
|
<!-- generated:commands:start -->
|
|
84
84
|
| Command | Purpose | Key Flags |
|
|
85
85
|
|---|---|---|
|
|
@@ -87,11 +87,13 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
87
87
|
| `dead-code` | Dead code analysis (`check` is an alias) | `--unused-exports`, `--changed-since`, `--changed-workspaces`, `--production`, `--file`, `--include-entry-exports`, `--stale-suppressions`, `--ci`, `--group-by`, `--summary`, `--fail-on-regression`, `--tolerance`, `--regression-baseline`, `--save-regression-baseline` |
|
|
88
88
|
| `watch` | Watch for changes and re-run analysis | `--no-clear` |
|
|
89
89
|
| `type-aware` | Inspect the optional TypeScript semantic companion | |
|
|
90
|
+
| `similar-code` | Find semantically similar functions with a pinned local model (opt-in) | `--threshold`, `--min-lines`, `--top`, `--file` |
|
|
90
91
|
| `inspect` | Compose one evidence bundle for a file or exported symbol | `--file <path>`, `--symbol <file>:<export>` |
|
|
91
92
|
| `trace` | Trace a symbol's call chain (best-effort, syntactic; OFF the ranked path) | `symbol`, `--callers`, `--callees`, `--depth` |
|
|
92
93
|
| `fix` | Auto-remove unused exports/deps | `--dry-run`, `--yes` (required in non-TTY) |
|
|
93
94
|
| `init` | Generate config file, AGENTS.md agent guide, or pre-commit hook | `--toml`, `--agents`, `--hooks`, `--branch` |
|
|
94
95
|
| `hooks` | Inspect, install, or remove fallow-managed Git and agent hooks | `status`, `install --target git`, `install --target agent`, `uninstall --target git`, `uninstall --target agent` |
|
|
96
|
+
| `agent` | Wire fallow into Claude Code, Codex, or Cursor in one pass: AGENTS.md task map, skill, MCP server, commit/push gate; `status` and `uninstall` cover the same surfaces | `install --harness auto\|claude\|codex\|cursor`, `install --dry-run`, `install --approve`, `install --without <guide\|skill\|mcp\|hooks>`, `status`, `uninstall` |
|
|
95
97
|
| `ci` | CI helpers for PR/MR feedback envelopes | |
|
|
96
98
|
| `ci reconcile-review` | Resolve stale review threads on a PR/MR by joining a typed review envelope (`--format review-github` / `review-gitlab`) against the provider's existing comments + threads. Posts an idempotent "Resolved in `<sha>`" follow-up per stale fingerprint, marker keyed on (fingerprint, short-sha) so re-runs on the same commit don't duplicate. Provider mutations are fail-fast; JSON can include `apply_hint`, `failed_fingerprints`, and `unapplied_fingerprints` when `apply_errors` is non-empty. | `--provider`, `--pr` (GH) / `--mr` (GL), `--repo` / `--project-id`, `--api-url`, `--envelope`, `--dry-run` |
|
|
97
99
|
| `config-schema` | Print the JSON Schema for fallow configuration files | |
|
|
@@ -122,14 +124,13 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
122
124
|
| `telemetry` | Manage opt-in, off-by-default product telemetry (never collects code, paths, or names). Agents must not enable it; only the user may | `status`, `enable`, `disable`, `inspect --example` |
|
|
123
125
|
| `coverage` | Runtime coverage setup, focused analysis, and cloud inventory workflow helper | `setup`, `setup --yes`, `setup --non-interactive`, `analyze --runtime-coverage <path>`, `analyze --cloud --repo owner/repo`, `upload-inventory` |
|
|
124
126
|
| `coverage upload-source-maps` | Upload build source maps from CI so bundled runtime coverage resolves to original source paths. Retries 429 `Retry-After` and transient gateway failures. Use `FALLOW_CA_BUNDLE` for complete custom PEM trust bundles. | `--dir dist`, `--git-sha <sha>`, `--repo <name>`, `--strip-path=false`, `--dry-run` |
|
|
125
|
-
| `setup-hooks` |
|
|
127
|
+
| `setup-hooks` | Deprecated (removed in the next major): use `agent install` or `hooks install --target agent`; still installs the Claude Code PreToolUse gate with a stderr warning | `--agent`, `--dry-run`, `--force`, `--user`, `--gitignore-claude`, `--uninstall` |
|
|
126
128
|
| `viz` | Render the codebase as a self-contained interactive HTML map (treemap + import graph, four lenses: dead code, duplication, boundaries, complexity, with click-through detail panels), or emit the import graph as text. Read-only. | `--out <path>`, `--no-open`, `--viz-format html\|dot\|mermaid`, `--root`, `--config`, `--production`, `--no-cache` |
|
|
127
129
|
|
|
128
130
|
Run `fallow <command> --help` for the full flag list per command (see also references/cli-reference.md).
|
|
129
131
|
<!-- generated:commands:end -->
|
|
130
132
|
|
|
131
133
|
## Issue Types
|
|
132
|
-
|
|
133
134
|
<!-- generated:issue-types:start -->
|
|
134
135
|
| Type | Filter flag | Fixable | Suppress comment | Description |
|
|
135
136
|
|---|---|---|---|---|
|
|
@@ -160,8 +161,8 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
|
|
|
160
161
|
| `unused-catalog-entry` | `--unused-catalog-entries` | yes | - | `pnpm-workspace.yaml` entries no workspace package.json references via `catalog:` (default `warn`) |
|
|
161
162
|
| `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`. |
|
|
162
163
|
| `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). |
|
|
163
|
-
| `unused-dependency-override` | `--unused-dependency-overrides` | - | - | `pnpm-workspace.yaml#overrides
|
|
164
|
-
| `misconfigured-dependency-override` | `--misconfigured-dependency-overrides` | - | - |
|
|
164
|
+
| `unused-dependency-override` | `--unused-dependency-overrides` | - | - | Entries in `pnpm-workspace.yaml#overrides`, `package.json#pnpm.overrides`, npm or Bun `package.json#overrides`, or Bun `package.json#resolutions` whose target package is not declared by any workspace `package.json` and is not present in the active readable lockfile. Default `warn`. pnpm and npm projects without a readable lockfile degrade to a manifest-only fallback with a verification `hint`; Bun projects with only binary `bun.lockb` fail closed and emit no finding. Suppress via `ignoreDependencyOverrides: [{ package, source? }]` in fallow config. |
|
|
165
|
+
| `misconfigured-dependency-override` | `--misconfigured-dependency-overrides` | - | - | Package-manager override entries whose key is unparsable or whose value is missing or empty. The active package manager may reject or ignore the entry. Default `error`. Suppression: same `ignoreDependencyOverrides` config rule. |
|
|
165
166
|
| `invalid-client-export` | - | - | `// fallow-ignore-next-line invalid-client-export` | "use client" file exports a server-only / route-config name; Requires the project to declare next |
|
|
166
167
|
| `mixed-client-server-barrel` | - | - | `// fallow-ignore-next-line mixed-client-server-barrel` | Barrel re-exports both a "use client" module and a server-only module; Requires the project to declare next |
|
|
167
168
|
| `misplaced-directive` | - | - | `// fallow-ignore-next-line misplaced-directive` | "use client" / "use server" directive is not in the leading position and is ignored; Requires the project to declare next |
|
|
@@ -204,13 +205,16 @@ Runtime-coverage verdicts and the full security sink catalogue are listed by `fa
|
|
|
204
205
|
|
|
205
206
|
Fallow ships an MCP server (`fallow-mcp`) that exposes these same analyses as agent tools. When the server is connected, its tools are already in your context with typed params and structured JSON returns, and each maps to a CLI fallback command. Prefer them when you want JSON without shelling out, or `code_execute` (Code Mode) to compose several read-only analyses in one sandboxed snippet (no single-call CLI equivalent). Otherwise use the CLI.
|
|
206
207
|
|
|
207
|
-
|
|
208
|
+
The server also serves read-only reference resources (no subprocess, no analysis run, cacheable by URI; your client reads them through its own resource tool): `fallow://tools`, `fallow://issue-types`, `fallow://explain/{issue_type}`, `fallow://task-matrix`, and the config, plugin, and rule-pack JSON Schemas. Every payload is JSON and carries `fallow_version`.
|
|
209
|
+
|
|
210
|
+
Full tool catalogue, resource catalogue, key params, runtime source-map confidence tiers, shared timeouts, and the `next_steps` dispatch mapping: **[references/mcp.md](references/mcp.md)**.
|
|
208
211
|
|
|
209
212
|
## References
|
|
210
213
|
- [CLI Reference](references/cli-reference.md): complete command and flag specifications, plus configuration field details
|
|
211
|
-
- [MCP Tools](references/mcp.md): MCP server tool
|
|
214
|
+
- [MCP Tools](references/mcp.md): MCP server tool and resource catalogues, CLI fallbacks, params, and agent dispatch guidance
|
|
212
215
|
- [Gotchas](references/gotchas.md): common pitfalls, edge cases, and correct usage patterns
|
|
213
216
|
- [Patterns](references/patterns.md): workflow recipes for CI, monorepos, migration, and incremental adoption
|
|
217
|
+
- [Similar Code](references/similar-code.md): snapshot-stable discovery, inspection, and verdict workflow
|
|
214
218
|
- [Node Bindings](references/node-bindings.md): embed the analysis engine in a Node.js process via NAPI
|
|
215
219
|
|
|
216
220
|
## Common Workflows
|
|
@@ -257,7 +261,7 @@ fallow list --entry-points --format json --quiet
|
|
|
257
261
|
fallow list --plugins --format json --quiet
|
|
258
262
|
```
|
|
259
263
|
|
|
260
|
-
Shows detected entry points and active framework plugins
|
|
264
|
+
Shows detected entry points and active framework plugins. Read `fallow schema.plugins.count` when the exact current registry size matters.
|
|
261
265
|
|
|
262
266
|
### Production-only analysis
|
|
263
267
|
```bash
|
|
@@ -428,11 +432,7 @@ fallow hooks install --target git # pre-commit gate; --branch <ref> sets the f
|
|
|
428
432
|
|
|
429
433
|
## Exit Codes
|
|
430
434
|
|
|
431
|
-
|
|
432
|
-
|------|---------|
|
|
433
|
-
| 0 | Success, no error-severity issues |
|
|
434
|
-
| 1 | Error-severity issues found |
|
|
435
|
-
| 2 | Runtime error (invalid config, parse failure, or `fix` without `--yes` in non-TTY) |
|
|
435
|
+
Codes 0 and 1 are successful analysis outcomes: 0 is clean and 1 means findings. Read `fallow schema.exit_codes` for validation, resource, runtime, network, security-gate, and upload failures instead of maintaining another copied table.
|
|
436
436
|
|
|
437
437
|
When `--format json` is active and exit code is 2, errors are emitted as JSON on stdout:
|
|
438
438
|
```json
|
|
@@ -441,7 +441,7 @@ When `--format json` is active and exit code is 2, errors are emitted as JSON on
|
|
|
441
441
|
|
|
442
442
|
## Configuration
|
|
443
443
|
|
|
444
|
-
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
|
|
444
|
+
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 auto-detecting framework plugins; read `fallow schema.plugins` for the current registry.
|
|
445
445
|
|
|
446
446
|
```jsonc
|
|
447
447
|
{
|
|
@@ -478,7 +478,7 @@ export const deprecatedHelper = () => {};
|
|
|
478
478
|
## Key Gotchas
|
|
479
479
|
|
|
480
480
|
- **`fix --yes` is required** in non-TTY (agent) environments. Without it, `fix` exits with code 2
|
|
481
|
-
- **Zero config by default.**
|
|
481
|
+
- **Zero config by default.** Built-in framework plugins auto-detect, including Wuchale config, Contentlayer content roots, tap and tsd test entry points. Read `fallow schema.plugins` for the current registry and don't create config unless customization is needed
|
|
482
482
|
- **Syntactic analysis only.** No TypeScript compiler, so fully dynamic `import(variable)` is not resolved
|
|
483
483
|
- **Function overloads are deduplicated.** TypeScript function overload signatures are merged into a single export (not reported as separate unused exports)
|
|
484
484
|
- **Re-export chains are resolved.** Exports through barrel files are tracked, not falsely flagged
|
|
@@ -11,6 +11,7 @@ Complete command and flag specifications for all fallow CLI commands.
|
|
|
11
11
|
- [`fix`: Auto-Remove Unused Code](#fix-auto-remove-unused-code)
|
|
12
12
|
- [`list`: Project Introspection](#list-project-introspection)
|
|
13
13
|
- [`init`: Config Generation](#init-config-generation)
|
|
14
|
+
- [`agent`: One-Pass Agent Onboarding](#agent-one-pass-agent-onboarding)
|
|
14
15
|
- [`migrate`: Config Migration](#migrate-config-migration)
|
|
15
16
|
- [`health`: Function Complexity and File Health Analysis](#health-function-complexity-and-file-health-analysis)
|
|
16
17
|
- [`audit`: Changed-File Quality Gate](#audit-changed-file-quality-gate)
|
|
@@ -89,8 +90,8 @@ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#
|
|
|
89
90
|
| `--unused-catalog-entries` | Unused pnpm catalog entries |
|
|
90
91
|
| `--empty-catalog-groups` | Empty named pnpm catalog groups |
|
|
91
92
|
| `--unresolved-catalog-references` | Package references to missing pnpm catalog entries |
|
|
92
|
-
| `--unused-dependency-overrides` | Unused
|
|
93
|
-
| `--misconfigured-dependency-overrides` |
|
|
93
|
+
| `--unused-dependency-overrides` | Unused package-manager dependency overrides |
|
|
94
|
+
| `--misconfigured-dependency-overrides` | Misconfigured package-manager dependency overrides |
|
|
94
95
|
<!-- generated:flags:dead-code-filters:end -->
|
|
95
96
|
### Examples
|
|
96
97
|
|
|
@@ -298,7 +299,7 @@ fallow list --workspaces --format json --quiet
|
|
|
298
299
|
fallow workspaces --format json --quiet # alias of `fallow list --workspaces`
|
|
299
300
|
```
|
|
300
301
|
|
|
301
|
-
The `--workspaces` JSON output carries `workspaces[]` (name, project-root-relative path, `is_internal_dependency` bool) plus `workspace_diagnostics[]`. Each diagnostic has a `kind` discriminator (`undeclared-workspace`, `malformed-package-json`, `glob-matched-no-package-json`, `malformed-tsconfig`, `tsconfig-reference-dir-missing`) with a typed payload (`error`, `pattern`, or none). The same `workspace_diagnostics[]` array is also surfaced on `fallow dead-code --format json`, `fallow dupes --format json`, and `fallow health --format json` envelopes (omitted when empty). A malformed ROOT `package.json` exits 2 at config load; everything else warns and continues.
|
|
302
|
+
The `--workspaces` JSON output carries `workspaces[]` (name, project-root-relative path, `is_internal_dependency` bool) plus `workspace_diagnostics[]`. Each diagnostic has a `kind` discriminator (`undeclared-workspace`, `malformed-package-json`, `glob-matched-no-package-json`, `malformed-tsconfig`, `tsconfig-reference-dir-missing`, `malformed-pnpm-workspace-yaml`, `skipped-large-file`, `skipped-minified-file`, `source-read-failure`, `bun-lockb-override-resolution-skipped`) with a typed payload (`error`, `pattern`, or none), and a `path` that is project-root-relative with forward slashes on every envelope that carries the array. The same `workspace_diagnostics[]` array is also surfaced on the `fallow dead-code --format json`, `fallow dupes --format json`, and `fallow health --format json` envelopes, at the top level of the bare combined `fallow --format json` envelope, on `fallow audit --format json` under `dead_code`, and on the `audit-brief` envelope shared by `fallow review --format json` and `fallow audit --brief --format json`, also under `dead_code` (omitted when empty). The combined carrier is the envelope root, not a section, so `--skip check`, `--only health`, and `--only dupes` all still report what their analyses recorded. The combined root is the union of what every analysis in the run recorded, deduplicated on the whole `kind` (typed payload included) plus `path`, so two overlapping globs still report the same package-less directory once per `pattern` (a declared glob's no-op `./` prefix is normalised away, so one glob written `"./apps/**"` in `package.json` and `apps/**` in `pnpm-workspace.yaml` stays one entry): a combined run walks the project once per analysis, and a per-analysis `production` mode (`production: { deadCode, health, dupes }`, `--production-health`) can give those walks different file sets, so only the union reports what the run as a whole saw. Each analysis contributes the workspace-discovery list its own config load produced, the same list `fallow list --workspaces` reports, so the combined root can carry an `undeclared-workspace` or `glob-matched-no-package-json` entry that the standalone `dead-code`, `check`, `health`, and `dupes` envelopes, which read the process diagnostics registry instead, do not. `fallow audit --format json` and the `audit-brief` envelope are on the same broad side: they fold the dead-code analysis's own list into their `dead_code.workspace_diagnostics[]`, so they too report an `undeclared-workspace` entry the standalone envelopes miss. The CLI and the programmatic route (MCP code mode, NAPI, embedders) agree on everything an analysis records: both folds close with the same process-registry read, which covers what an analysis records after its section captured its list (a `source-read-failure`, or the analysis-stage kinds a health run's own dead-code precompute records) and skips `skipped-large-file` and `skipped-minified-file`, since those reach an envelope only from the walk that recorded them. The two analysis-stage kinds (`malformed-pnpm-workspace-yaml`, `bun-lockb-override-resolution-skipped`) are recorded by the dead-code analyze pass, so they only appear on runs that include it: `fallow dupes --format json` and `fallow --only dupes` report the workspace-discovery and source-discovery kinds alone. A malformed ROOT `package.json` exits 2 at config load; everything else warns and continues.
|
|
302
303
|
|
|
303
304
|
The `--boundaries` JSON output carries `boundaries.logical_groups[]` alongside the existing `zones[]` / `rules[]` arrays. Each logical-group entry surfaces a user-authored `autoDiscover` parent zone (which expansion otherwise flattens into per-child zones like `features/auth` / `features/billing`): `name`, `children`, `auto_discover` (verbatim user strings), `status` (`ok` / `empty` / `invalid_path`), `source_zone_index`, summed `file_count`, optional `authored_rule` (the pre-expansion `{ allow, allowTypeOnly }` keyed on the parent), optional `fallback_zone` cross-reference when the parent also kept its own `patterns` (Bulletproof case), optional `merged_from` (parent zone indices when the user declared the same parent name twice; surfaces the duplicate in JSON instead of only in `tracing::warn!`), optional `original_zone_root` (echo of the parent's `root` subtree scope for monorepo patchers), and optional `child_source_indices` (parallel to `children`, attributing each child to a specific `auto_discover` entry when multiple paths were authored). The full shape is documented in `docs/output-schema.json` under `ListBoundariesOutput`.
|
|
304
305
|
|
|
@@ -345,6 +346,73 @@ fallow hooks uninstall --target agent
|
|
|
345
346
|
|
|
346
347
|
---
|
|
347
348
|
|
|
349
|
+
## `agent`: One-Pass Agent Onboarding
|
|
350
|
+
|
|
351
|
+
Wires fallow into the coding-agent harnesses a project uses. `install` detects Claude Code, Codex, and Cursor from the project (`.claude/`, `CLAUDE.md`, `.mcp.json`, `.codex/`, `.cursor/`; `AGENTS.md` is not a signal because every harness and fallow itself write it), the home directory, and the session environment (`CLAUDECODE`, `CODEX_THREAD_ID`, `CURSOR_AGENT`), or takes `--harness`. When nothing is detected only harness-neutral files are written (`AGENTS.md` and `.agents/skills/fallow`).
|
|
352
|
+
|
|
353
|
+
Steps per harness:
|
|
354
|
+
|
|
355
|
+
| Step | Claude Code | Codex | Cursor |
|
|
356
|
+
|---|---|---|---|
|
|
357
|
+
| `guide` | `AGENTS.md` task map; `CLAUDE.md` gains an `@AGENTS.md` import (created when absent, appended as a marked block otherwise) | `AGENTS.md` task map | `AGENTS.md` task map (Cursor reads it) |
|
|
358
|
+
| `skill` | `.claude/skills/fallow/` | `.agents/skills/fallow/` | `.agents/skills/fallow/` |
|
|
359
|
+
| `mcp` | `mcpServers.fallow` in `.mcp.json` (`--approve` also lists it in `.claude/settings.local.json`) | `[mcp_servers.fallow]` in `.codex/config.toml` (applies once the project is trusted; the `codex mcp add` next step works immediately) | `mcpServers.fallow` in `.cursor/mcp.json` |
|
|
360
|
+
| `hooks` | `.claude/settings.json` PreToolUse gate plus `.claude/hooks/fallow-gate.sh` | marked gate block in `AGENTS.md` | skipped (`unsupported_harness`) |
|
|
361
|
+
|
|
362
|
+
The skill is a small pointer to `node_modules/fallow/skills/fallow` when that copy exists (so it never drifts from the installed binary); otherwise the tree embedded in the binary is written. The MCP command is probed before anything is written: `npx --no fallow-mcp` for an npm-installed project, `fallow-mcp` from `PATH`, or the running multicall binary; when none exists the step is `skipped` with `mcp_entry_unavailable` rather than writing a config that cannot start.
|
|
363
|
+
|
|
364
|
+
Every file or block carries a `<!-- fallow:agent-install v1 ... -->` marker. Re-running is byte-stable. An existing skill named `fallow` without a marker is `refused` (`skill_name_taken`) unless `--force`. JSON and TOML cannot carry a marker, so a `fallow` MCP entry counts as fallow-managed only when its command is one fallow writes; any other entry is `refused` (`mcp_entry_foreign`) and never removed without `--force`. `--force` on an unparsable config file saves the old bytes as `<file>.fallow-bak` before rewriting. `uninstall` removes managed content, deletes a config file it emptied (and an emptied `.cursor/` or `.codex/` directory), and deletes `AGENTS.md` or `CLAUDE.md` only while the file still matches what fallow authored.
|
|
365
|
+
|
|
366
|
+
### Flags
|
|
367
|
+
|
|
368
|
+
| Flag | Applies to | Description |
|
|
369
|
+
|---|---|---|
|
|
370
|
+
| `--harness <auto\|claude\|codex\|cursor>` | `install`, `uninstall` | Repeatable; default `auto` |
|
|
371
|
+
| `--without <guide\|skill\|mcp\|hooks>` | `install` | Skip a step; repeatable |
|
|
372
|
+
| `--dry-run` | `install`, `uninstall` | Print the plan without touching the filesystem |
|
|
373
|
+
| `--force` | `install`, `uninstall` | Replace or remove skills, hook scripts, or config files fallow did not write |
|
|
374
|
+
| `--approve` | `install` | Pre-approve the project MCP server for yourself in `.claude/settings.local.json`; refused when that file is tracked by git |
|
|
375
|
+
| `--user` | `install`, `uninstall` | Skill and MCP config under `$HOME` (`~/.claude/skills`, `~/.agents/skills`, `~/.codex/config.toml`, `~/.cursor/mcp.json`); the guide step is skipped, and Claude Code prints the `claude mcp add --scope user` command instead of editing `~/.claude.json` |
|
|
376
|
+
| `--gitignore-claude` | `install` | Append `.claude/` to `.gitignore` |
|
|
377
|
+
|
|
378
|
+
Root: the git toplevel of the current directory unless `--root` is passed explicitly, so a run from a monorepo package still writes where the harnesses read. The chosen root is the first line of output and `root` in JSON.
|
|
379
|
+
|
|
380
|
+
### Output
|
|
381
|
+
|
|
382
|
+
Human output groups paths under "Shared with your team (commit these)" and "Local to you". JSON:
|
|
383
|
+
|
|
384
|
+
```json
|
|
385
|
+
{
|
|
386
|
+
"kind": "agent-install",
|
|
387
|
+
"schema_version": 1,
|
|
388
|
+
"fallow_version": "3.19.0",
|
|
389
|
+
"root": "/abs/path",
|
|
390
|
+
"mode": "install",
|
|
391
|
+
"dry_run": false,
|
|
392
|
+
"harnesses": ["claude", "codex"],
|
|
393
|
+
"detected": true,
|
|
394
|
+
"evidence": [{"harness": "claude", "evidence": [".claude", "$CLAUDECODE"]}],
|
|
395
|
+
"steps": [
|
|
396
|
+
{"harness": null, "step": "guide", "status": "written", "scope": "shared", "path": "AGENTS.md"},
|
|
397
|
+
{"harness": "claude", "step": "mcp", "status": "skipped", "scope": "local", "path": ".claude/settings.local.json", "reason": "approval_not_requested"}
|
|
398
|
+
],
|
|
399
|
+
"next_actions": [{"id": "codex-mcp-add", "command": "codex mcp add fallow -- npx --no fallow-mcp", "reason": "...", "mutating": true}]
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
`status` values: `written`, `removed`, `unchanged`, `skipped`, `refused`, `failed`. Exit code 2 when any step is `refused` or `failed`; every other step still runs. `kind` is `agent-install`, `agent-uninstall`, or `agent-status`; `schema_version` is `1`; `agent status` reports `surfaces[]` with `installed`, `stale`, `absent`, or `foreign`. `next_actions` is deliberately not `next_steps`: entries flagged `mutating: true` write harness config when run, unlike the read-only `next_steps[]` of the analysis commands.
|
|
404
|
+
|
|
405
|
+
### Examples
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
fallow agent install --dry-run # show the plan for the detected harnesses
|
|
409
|
+
fallow agent install # wire everything detected
|
|
410
|
+
fallow agent install --harness claude --approve
|
|
411
|
+
fallow agent install --without hooks --format json --quiet
|
|
412
|
+
fallow agent status --format json
|
|
413
|
+
fallow agent uninstall --dry-run
|
|
414
|
+
```
|
|
415
|
+
|
|
348
416
|
## `migrate`: Config Migration
|
|
349
417
|
|
|
350
418
|
Migrates configuration from knip and/or jscpd to fallow. Auto-detects config files.
|
|
@@ -838,8 +906,8 @@ Audits changed files for dead code, complexity, duplication, and styling. Return
|
|
|
838
906
|
| `--health-baseline` | `string` | - | Baseline file (produced by `fallow health --save-baseline`). Pre-existing complexity findings are excluded from the verdict. |
|
|
839
907
|
| `--dupes-baseline` | `string` | - | Baseline file (produced by `fallow dupes --save-baseline`). Pre-existing clone groups are excluded from the verdict. |
|
|
840
908
|
| `--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. |
|
|
841
|
-
| `--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
|
|
842
|
-
| `--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). |
|
|
909
|
+
| `--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`, then `health.coverage` (the same chain as `fallow health`). Relative paths resolve against `--root`. |
|
|
910
|
+
| `--coverage-root` | `string` | - | Absolute prefix to strip from file paths in coverage data before prepending the project root. Also configurable via `FALLOW_COVERAGE_ROOT`, then `health.coverageRoot`. Use when coverage was generated under a different checkout root in CI / Docker (e.g., `/home/runner/work/myapp` on GitHub Actions). |
|
|
843
911
|
| `--no-css` | `bool` | `false` | Disable styling analytics in audit |
|
|
844
912
|
| `--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` |
|
|
845
913
|
| `--no-css-deep` | `bool` | `false` | Disable deep CSS analysis while keeping local styling analytics on |
|
|
@@ -1779,7 +1847,7 @@ These are global flags with behavior specific to bare `fallow` combined mode.
|
|
|
1779
1847
|
| `FALLOW_FORMAT` | Default output format. CLI `--format` overrides. |
|
|
1780
1848
|
| `FALLOW_QUIET` | Set to `1` to suppress progress. CLI `--quiet` overrides. |
|
|
1781
1849
|
| `FALLOW_BIN` | Path to fallow binary (used by the MCP server). |
|
|
1782
|
-
| `FALLOW_TIMEOUT_SECS` | MCP server subprocess timeout in seconds (default: `120`). Increase
|
|
1850
|
+
| `FALLOW_TIMEOUT_SECS` | MCP server subprocess timeout in seconds (default: `120`; similar-code discovery and inspection default to `900`). Increase or reduce it to override either bound. |
|
|
1783
1851
|
| `FALLOW_EXTENDS_TIMEOUT_SECS` | Timeout for fetching remote config inheritance in seconds (default: `5`). Do not raise this for untrusted sources. |
|
|
1784
1852
|
| `FALLOW_CACHE_DIR` | Override the persistent extraction cache directory. Wins over `cache.dir`. Useful for read-only checkouts or CI cache volumes. `--no-cache` disables this knob. |
|
|
1785
1853
|
| `FALLOW_CACHE_MAX_SIZE` | Maximum on-disk extraction cache (`.fallow/cache.bin`) size in megabytes (default: `256`). Triggers LRU eviction when crossed. Wins over `cache.maxSizeMb` config field. Intended for CI runners with disk quotas. `--no-cache` short-circuits this knob. |
|
|
@@ -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
|
|
26
|
+
Fallow works with zero configuration for most projects thanks to auto-detecting framework plugins. Read `fallow schema.plugins` for the current registry. 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
|
|
@@ -486,7 +486,7 @@ The detector intentionally abstains when a Tailwind plugin or published CSS surf
|
|
|
486
486
|
|
|
487
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
488
|
|
|
489
|
-
`token_consumers` also covers CSS-in-JS token DEFINITIONS (StyleX `defineVars`, vanilla-extract `createTheme` / `createThemeContract` / `createGlobalTheme`, and PandaCSS `defineTokens`)
|
|
489
|
+
`token_consumers` also covers CSS-in-JS token DEFINITIONS (StyleX `defineVars` / `unstable_defineVarsNested`, vanilla-extract `createTheme` / `createThemeContract` / `createGlobalTheme`, and PandaCSS `defineTokens`). Member reads use `kind` `js-member`; StyleX `createTheme` / `unstable_createThemeNested` calls apply the complete resolved variable group and use `kind` `js-call`, including partial overrides and empty reset themes. `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 also tagged `js-call`. The cross-file scan uses fallow's shared import resolver, so direct named token-contract imports through relative paths, tsconfig `paths` aliases, and workspace packages can resolve to the token definition. Same-file StyleX reads are included. Dynamic import strings, unresolved aliases, generated package state, dynamic computed token access, and dynamic token-object structure 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. Detection is gated on imports in the analyzed source files, including workspace packages whose root manifest does not declare the styling library. StyleX's built-in `@stylexjs/stylex` and `stylex` sources are recognized, with named aliases plus namespace/default imports supported for calls to the StyleX API itself. Barrel re-exports and default or namespace imports of token contracts conservatively abstain. Compiler-configured `importSources`, custom package aliases, CommonJS, and `stylex.env`-backed token structures are outside the current support boundary.
|
|
490
490
|
|
|
491
491
|
## CSS Health Candidates Are Advisory
|
|
492
492
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The fallow MCP server (`fallow-mcp`) exposes fallow's analyses as agent tools. This is the full catalogue: each tool's kind, license, nearest CLI fallback, key params, plus the agent guidance the live tool schemas do not carry (CLI-fallback mapping, runtime-coverage confidence tiers, and `next_steps` dispatch). SKILL.md keeps only a short pointer; load this file when driving fallow through MCP.
|
|
4
4
|
|
|
5
|
-
The `generated:mcp-tools`
|
|
5
|
+
The `generated:mcp-tools` and `generated:mcp-resources` tables below are regenerated from `fallow schema` by scripts/generate-agent-docs.mjs; edit the curated Description cells in place, never the identity columns.
|
|
6
6
|
|
|
7
7
|
## Tool catalogue
|
|
8
8
|
|
|
@@ -11,10 +11,12 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
|
|
|
11
11
|
<!-- generated:mcp-tools:start -->
|
|
12
12
|
| Tool | Kind | License | CLI fallback | Key params | Description |
|
|
13
13
|
|---|---|---|---|---|---|
|
|
14
|
-
| `code_execute` | composition | free | - | `code`, `timeout_ms`, `max_output_bytes` | Bounded read-only Code Mode for composing multiple fallow analysis calls in one JavaScript snippet. The snippet receives `{ fallow, root }`, returns JSON-serializable data, and can call read-only helpers such as `fallow.projectInfo`, `fallow.audit`, `fallow.checkHealth`, and `fallow.run(tool, params)` for the same allowlist. Mutating fix tools are not exposed. The sandbox has no filesystem, network, imports, `eval`, `Function`, `process`, `require`, `Deno`, `Bun`, or shell access. Params: `code`, optional `root`, `timeout_ms` (capped at 30000), and `max_output_bytes` (capped at 4000000). |
|
|
14
|
+
| `code_execute` | composition | free | - | `code`, `timeout_ms`, `max_output_bytes` | Bounded read-only Code Mode for composing multiple fallow analysis calls in one JavaScript snippet. The snippet receives `{ fallow, root }`, returns JSON-serializable data, and can call read-only helpers such as `fallow.projectInfo`, `fallow.audit`, `fallow.checkHealth`, and `fallow.run(tool, params)` for the same allowlist. Similar-code is excluded because Code Mode is capped at 30 seconds; use standalone `find_similar_code` and `inspect_similar_code`, which have dedicated 15-minute timeouts. Mutating fix tools are not exposed. The sandbox has no filesystem, network, imports, `eval`, `Function`, `process`, `require`, `Deno`, `Bun`, or shell access. Params: `code`, optional `root`, `timeout_ms` (capped at 30000), and `max_output_bytes` (capped at 4000000). |
|
|
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
|
+
| `find_similar_code` | analysis | free | `fallow similar-code --format json --quiet` | `threshold`, `min_lines`, `top`, `changed_since`, `paths` | Find unverified semantically similar function candidates with the exact pinned local model. Discovery is read-only and never authorizes or performs model setup. Scoped output materializes the exact admitted files once in `generation.scope.paths` as provenance. Ask the user to run `fallow similar-code setup --local` when setup is missing. Cold local inference has a dedicated 15-minute subprocess window. |
|
|
19
|
+
| `inspect_similar_code` | trace | free | `fallow similar-code inspect <candidate-id> --candidates <report.json> --format json --quiet` | `candidate_id`, `snapshot` | Inspect one exact unverified candidate without rerunning provider retrieval or global ranking. Pass `candidate_id` plus a bounded typed snapshot containing the unchanged discovery `schema_version`, `generation`, selected `candidate`, `completion`, and `diagnostics`. Current source is re-extracted and both endpoint hashes must still match, so stale source fails closed. Keep candidate worthiness, behavioral equivalence, and refactor safety as separate verdicts, and abstain when evidence is incomplete. |
|
|
18
20
|
| `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
21
|
| `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
22
|
| `find_dupes` | analysis | free | `fallow dupes --format json --quiet` | `mode`, `near`, `min_tokens`, `min_occurrences`, `top`, `threshold` | Code duplication detection. Set `near: true` for function-level clones with small structural edits. 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. Each `clone_groups[]` entry carries a normalized `fingerprint` and `spread`; near groups also carry `similarity`. `stats.clone_groups_ignored` reports reviewed groups hidden by config, while `stats.near_candidates_skipped` signals bounded near comparisons that were skipped. Pass the fingerprint to `trace_clone` to inspect the group |
|
|
@@ -24,7 +26,7 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
|
|
|
24
26
|
| `get_blast_radius` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `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. |
|
|
25
27
|
| `get_importance` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `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. |
|
|
26
28
|
| `get_cleanup_candidates` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `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`. |
|
|
27
|
-
| `get_token_blast_radius` | analysis | free | `fallow health --css --format json --quiet` | - | 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 |
|
|
29
|
+
| `get_token_blast_radius` | analysis | free | `fallow health --css --format json --quiet` | - | 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 (StyleX theme-group and Panda token calls); descriptive context for sizing a token change, never a deletion gate |
|
|
28
30
|
| `audit` | analysis | free | `fallow audit --format json --quiet` | `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. |
|
|
29
31
|
| `decision_surface` | analysis | free | `fallow decision-surface --format json --quiet` | `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 |
|
|
30
32
|
| `fallow_explain` | introspection | free | `fallow explain <issue-type> --format json --quiet` | `issue_type` | Explain one issue type without running analysis. Required `issue_type`; returns rationale, examples, fix guidance, and docs URL |
|
|
@@ -38,7 +40,7 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
|
|
|
38
40
|
| `impact` | introspection | free | `fallow impact --format json --quiet` | `root` | Read the local, opt-in Fallow Impact value report (`fallow impact --format json`). Runs no analysis: current surfacing counts, trend since the last recorded run, pre-commit gate containment, and (on impact v1.5+) resolved/suppressed attribution. History is read from a per-project file in the user's private config dir (never inside the repo). Read-only and `root`-only; the mutating `enable` / `disable` / `default` lifecycle is not exposed. A never-enabled project returns a populated `{"enabled": false, ...}` report (never `{}`); branch on `enabled` and `enabled_source` (`project` / `user` / `default`) then `record_count`, recommending `fallow impact enable` only when `explicit_decision` is `false` (never asked) and staying silent when `true` (deliberately disabled here). Local-developer signal: fallow never records in CI, so empty there and not a CI metric |
|
|
39
41
|
| `impact_all` | introspection | free | `fallow impact --all --format json --quiet` | `sort`, `limit` | Roll every tracked fallow project on this machine into one cross-repo value report (hashed keys plus basename labels, never paths; local-dev only) |
|
|
40
42
|
| `trace_export` | trace | free | `fallow dead-code --trace <file:export> --format json --quiet` | `file`, `export_name` | Trace why an export is used or unused (`fallow dead-code --trace FILE:EXPORT_NAME --format json`). Required `file` and `export_name`. Returns file reachability, entry-point status, direct references, re-export chains, and a reason string. If `export_name` is a class / enum / store MEMBER, returns a member trace instead (`member_name`, `member_kind`, `owner_export`, `owner_is_used`) plus a `--unused-<kind>-members` pointer; branch on field presence. Use before deleting a supposedly-unused export or debugging an unused-class-member finding |
|
|
41
|
-
| `trace_symbol` | trace | free | `fallow dead-code --type-aware --trace <file:export> --format json --quiet` | `file`, `export_name`, `type_aware_projects`, `type_aware_require` | Trace an exact TypeScript symbol with checker-backed references, namespace identity, aliases, and re-export hops. Root trace fields preserve syntactic context; treat `semantic.references`, `semantic.status`, and `semantic.identity` as the authoritative exact evidence. This is project-wide evidence for Fallow decisions, not a compiler-diagnostic or lint-rule surface. |
|
|
43
|
+
| `trace_symbol` | trace | free | `fallow dead-code --type-aware --trace <file:export> --format json --quiet` | `file`, `export_name`, `type_aware_projects`, `type_aware_require` | Trace an exact TypeScript symbol with checker-backed references, namespace identity, aliases, and re-export hops. Root trace fields preserve syntactic context; treat `semantic.references`, `semantic.status`, and `semantic.identity` as the authoritative exact evidence. The proof covers only the lane named by `semantic.target.namespace`, so a root trace that lists a reference the proof does not is wider evidence rather than stale. This is project-wide evidence for Fallow decisions, not a compiler-diagnostic or lint-rule surface. |
|
|
42
44
|
| `symbol_impact` | impact | free | `fallow dead-code --type-aware --symbol-impact <file:export-or-class.member> --format json --quiet` | `file`, `export_name`, `class_name`, `member_name`, `type_aware_projects`, `type_aware_require` | Return exact-symbol consumers, affected files, and targeted tests for a TypeScript export or exported class method. Select either `export_name`, or both `class_name` and `member_name`. Advisory change-impact evidence, not a substitute for `tsc` or Oxlint |
|
|
43
45
|
| `trace_file` | trace | free | `fallow dead-code --trace-file <file> --format json --quiet` | `file` | Trace all graph edges for a file (`fallow dead-code --trace-file PATH --format json`). Required `file`. Returns reachability, exports, imports-from, imported-by, and re-exports. Use to decide whether a file is isolated, barrel-only, or imported by live entry points |
|
|
44
46
|
| `impact_closure` | trace | free | `fallow dead-code --impact-closure <path> --format json --quiet` | `path` | Trace the transitive affected-but-not-in-diff set and coordination gaps for one file. Supports `root`, `config`, `production`, `workspace`, `no_cache`, and `threads`. Use as review-planning evidence for a file contract, not proof that affected files are wrong |
|
|
@@ -46,6 +48,46 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
|
|
|
46
48
|
| `trace_clone` | trace | free | `fallow dupes --trace <file:line> --format json --quiet` | `file`, `line`, `fingerprint`, `near`, `min_occurrences` | Deep-dive a duplicate-code clone group (`fallow dupes --trace <spec> --format json`). Address by exactly one of: `file` + `line` (a source location), or `fingerprint` (a `dup:<id>` from a prior `find_dupes` `clone_groups[].fingerprint`, usually `dup:<8hex>` and widened only on rare report collisions). Returns the matched clone instance plus every clone group containing it; each traced group carries its `fingerprint`, an extract-function `suggestion` with estimated savings, and a best-effort `suggested_name` (omitted when no confident name). Supports `mode`, `near`, `min_tokens`, `min_lines`, `min_occurrences`, `threshold`, `skip_local`, `cross_language`, `ignore_imports`. Use the same `near` value as the originating `find_dupes` call. Use to consolidate duplication when you need exact sibling locations and a refactor target |
|
|
47
49
|
<!-- generated:mcp-tools:end -->
|
|
48
50
|
|
|
51
|
+
## Resource catalogue
|
|
52
|
+
|
|
53
|
+
Resources are the server's read-only reference channel: compile-time material an agent can list (`resources/list`, `resources/templates/list`) and read (`resources/read`) with no subprocess and no analysis run, cacheable by URI (your client reads them through its own resource tool). Each content item carries the server version in `_meta.fallow_version`; the payload itself is the plain document, so the schema resources are valid strict JSON Schema. Unknown URIs return a structured error whose `data` lists the known URIs (or the nearest issue types); the numeric code is `-32002` on protocol versions before 2026-07-28 and `-32602` from then on, so key on `data`. Every payload is JSON and carries `fallow_version`, so cache by URI and invalidate when the server version changes. The catalogue is static (no `subscribe`, no `listChanged`). Read `fallow://explain/{issue_type}` instead of calling `fallow_explain` when you only need the reference document; `issue_type` accepts the bare id (`unused-export`), the namespaced rule id (`security/sql-injection`), or the CLI filter spelling (`unused-exports`). An unknown URI or issue type returns a structured `resource_not_found` error listing the known URIs or the nearest issue types.
|
|
54
|
+
|
|
55
|
+
<!-- generated:mcp-resources:start -->
|
|
56
|
+
| Resource | Name | Kind | MIME | Description |
|
|
57
|
+
|---|---|---|---|---|
|
|
58
|
+
| `fallow://tools` | `tools` | static | `application/json` | MCP tool manifest: name, kind, one-line description, nearest CLI fallback, key params, license, and read-only flag for every tool |
|
|
59
|
+
| `fallow://issue-types` | `issue-types` | static | `application/json` | Every issue type with its command, category, config key, zero-config default severity, opt-in flag, fixable flag, docs URL, and explain resource URI |
|
|
60
|
+
| `fallow://explain` | `explain` | static | `application/json` | Index of every explainable issue type with its one-line summary and the fallow://explain/{issue_type} URI to read |
|
|
61
|
+
| `fallow://task-matrix` | `task-matrix` | static | `application/json` | Agent task-to-command matrix: which read-only fallow command to run before deleting, refactoring, committing, or scoping work |
|
|
62
|
+
| `fallow://schema/config` | `schema-config` | static | `application/json` | JSON Schema of the fallow config file (same document as fallow config-schema) |
|
|
63
|
+
| `fallow://schema/plugin` | `schema-plugin` | static | `application/json` | JSON Schema of a user-authored external plugin (same document as fallow plugin-schema) |
|
|
64
|
+
| `fallow://schema/rule-pack` | `schema-rule-pack` | static | `application/json` | JSON Schema of a declarative rule pack (same document as fallow rule-pack-schema) |
|
|
65
|
+
| `fallow://explain/{issue_type}` | `explain-issue-type` | template | `application/json` | Explain document for one issue type (same payload as fallow explain <issue-type> --format json): name, summary, rationale, example, fix guidance, docs URL |
|
|
66
|
+
<!-- generated:mcp-resources:end -->
|
|
67
|
+
|
|
68
|
+
## How type-aware proof relates to the root trace
|
|
69
|
+
|
|
70
|
+
`trace_symbol` is the only tool that returns a checker-backed `semantic` block
|
|
71
|
+
next to a syntactic root trace. The checker resolves actual reads through local
|
|
72
|
+
aliases, import types, namespace-qualified names, and barrels to the exact type
|
|
73
|
+
or value declaration. Import and re-export declarations alone are not reads.
|
|
74
|
+
The root trace stays authoritative for graph reachability and star ambiguity,
|
|
75
|
+
and its optional `direct_references_by_namespace` keeps type and value evidence
|
|
76
|
+
separate without changing the selected root `namespace`. Type-aware
|
|
77
|
+
reconciliation fails closed: unreachable-only, re-export-only, or
|
|
78
|
+
different-declaration evidence cannot suppress a syntactic finding. Treat an
|
|
79
|
+
ambiguous root as an abstention, and investigate any remaining mismatch before
|
|
80
|
+
deleting a symbol.
|
|
81
|
+
|
|
82
|
+
`symbol_impact` carries no `semantic` block and no root trace. Its top-level
|
|
83
|
+
checker evidence uses the same declaration-safe alias and namespace resolution
|
|
84
|
+
as `trace_symbol`. A listed consumer's `relation` names the traced symbol's own
|
|
85
|
+
lane, not the consumer's syntax. Confirm a clean impact result with
|
|
86
|
+
`trace_export` or `trace_symbol` before deletion when the graph reports
|
|
87
|
+
ambiguity or reachable references.
|
|
88
|
+
|
|
89
|
+
`trace_export` never carries a `semantic` block: it is API-backed in-process and answers from the graph alone.
|
|
90
|
+
|
|
49
91
|
## Runtime source-map confidence for cloud runtime tools
|
|
50
92
|
|
|
51
93
|
| Values | Meaning | Agent action |
|
|
@@ -57,7 +99,7 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
|
|
|
57
99
|
|
|
58
100
|
## Shared params, JSON output, and next_steps
|
|
59
101
|
|
|
60
|
-
Most tools accept `root`, `config`, `no_cache`, and `threads` params. Exceptions: `impact` takes only `root`; `code_execute` takes `code`, optional `root`, `timeout_ms`, and `max_output_bytes`.
|
|
102
|
+
Most tools accept `root`, `config`, `no_cache`, and `threads` params. Exceptions: `impact` takes only `root`; `code_execute` takes `code`, optional `root`, `timeout_ms`, and `max_output_bytes`. Similar-code file scope is named `paths` on both standalone MCP tools and forwards repeated CLI `--file` flags. MCP subprocesses default to 120 seconds, except similar-code discovery and inspection which default to 15 minutes for cold local inference. `FALLOW_TIMEOUT_SECS` overrides either default. Code Mode does not expose similar-code because its 30-second cap cannot satisfy that contract.
|
|
61
103
|
|
|
62
104
|
All JSON responses include structured `actions` arrays on every finding (dead code, health, duplication), enabling programmatic fix application or suppression.
|
|
63
105
|
|
|
@@ -7,14 +7,15 @@ npm install @fallow-cli/fallow-node
|
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { detectDeadCode, detectDuplication,
|
|
10
|
+
import { computeHealth, detectDeadCode, detectDuplication, detectSimilarCode } from '@fallow-cli/fallow-node';
|
|
11
11
|
|
|
12
12
|
const deadCode = await detectDeadCode({ root: process.cwd(), explain: true });
|
|
13
13
|
const dupes = await detectDuplication({ root: process.cwd(), mode: 'mild', minTokens: 30 });
|
|
14
|
+
const similarCode = await detectSimilarCode({ root: process.cwd(), files: ['src/services/api.ts'] });
|
|
14
15
|
const health = await computeHealth({ root: process.cwd(), score: true, ownershipEmails: 'handle' });
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
Eight async functions: `detectDeadCode`, `detectCircularDependencies`, `detectBoundaryViolations`, `detectDuplication`, `detectSimilarCode`, `detectFeatureFlags`, `computeComplexity`, `computeHealth`. Each returns the same JSON envelope the CLI emits for `--format json`. `detectSimilarCode` returns a precisely typed `SimilarCodeReport`, including generation provenance, embedding semantics, effective `generation.scope.paths`, completion, skips, cache accounting, diagnostics, and read-only candidate actions. Treat the materialized scope as provenance and preserve the raw report when a candidate may be inspected later. The Node binding exposes discovery only. Use CLI `similar-code inspect --candidates <report.json>` or MCP `inspect_similar_code` with the exact typed candidate snapshot so global retrieval and ranking are not repeated. Its loader resolves and verifies the exact-version local companion; it never downloads the model or authorizes setup. Rejected promises throw a `FallowNodeError` with `message`, `exitCode`, and optional `code`, `help`, `context` fields that mirror the CLI's structured error surface.
|
|
18
19
|
|
|
19
20
|
Enum-like fields take lowercase CLI-style literals (`"mild"`, `"cyclomatic"`, `"handle"`, `"low"`). Write-path commands (`fix`, `init`, `hooks install`, `hooks uninstall`, `license activate`, `coverage setup`) are not exposed; use the CLI for those.
|
|
20
21
|
|
|
@@ -645,7 +645,7 @@ Focus on findings that are BOTH dead code and duplicated:
|
|
|
645
645
|
|
|
646
646
|
## Custom Plugin Setup
|
|
647
647
|
|
|
648
|
-
For frameworks not covered by the
|
|
648
|
+
For frameworks not covered by the current built-in registry from `fallow schema.plugins`.
|
|
649
649
|
|
|
650
650
|
### Option 1: Inline framework config
|
|
651
651
|
|
|
@@ -717,7 +717,7 @@ fallow dead-code --format sarif --quiet > fallow.sarif
|
|
|
717
717
|
fallow dead-code --ci > fallow.sarif
|
|
718
718
|
```
|
|
719
719
|
|
|
720
|
-
The `--ci` flag is equivalent to `--format sarif --fail-on-issues --quiet`.
|
|
720
|
+
The `--ci` flag is equivalent to `--format sarif --fail-on-issues --quiet`. Exit code 1 means findings exist. Capture that status, let the SARIF upload step run, then reapply the captured status in a final gate step. Do not discard every outcome, because validation and execution failures need to remain distinguishable from findings.
|
|
721
721
|
|
|
722
722
|
---
|
|
723
723
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Semantic Similar-Code Workflow
|
|
2
|
+
|
|
3
|
+
Similar-code is an opt-in, local semantic discovery workflow. It complements deterministic `fallow dupes`; it does not replace clone detection, tests, or human judgment.
|
|
4
|
+
|
|
5
|
+
1. Check readiness with `fallow similar-code status --format json --quiet`. If the pinned model is missing, ask the user to run `fallow similar-code setup --local`. Agents must not authorize setup or run it on the user's behalf.
|
|
6
|
+
2. Run discovery once. Preserve its independent JSON envelope so inspection and review use the exact candidate set:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
fallow similar-code --file src/services/api.ts --format json --quiet > similar-code.json
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
In Node, call `detectSimilarCode({ files: ["src/services/api.ts"] })`. Over MCP, call standalone `find_similar_code` with `paths: ["src/services/api.ts"]`. Do not use Code Mode for similar-code because its 30-second window cannot accommodate documented cold inference. The standalone MCP tools have a dedicated 15-minute timeout.
|
|
13
|
+
3. Inspect a candidate before judging it. Hand off the original raw discovery document so inspect selects that exact candidate without rerunning global retrieval or ranking:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
fallow similar-code inspect sc_example --candidates similar-code.json \
|
|
17
|
+
--format json --quiet
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Over MCP, call standalone `inspect_similar_code` with `candidate_id` and a typed `snapshot` containing the unchanged discovery `schema_version`, `generation`, selected `candidate`, `completion`, and `diagnostics`. Treat `generation.scope.paths` as provenance, not as an argument list. Inspect re-extracts only the two snapshot endpoints, validates both current source hashes, and fails closed on stale source. Review source, callers, callees, tests, side effects, ownership, and missing evidence.
|
|
21
|
+
4. Author a separate verdict document. Keep the three axes independent. `refactor_safe: true` requires `behaviorally_equivalent: true`, which requires `candidate_worthy: true`. Use `null` for an undecided axis, use `needs-human-review`, and abstain when evidence is incomplete.
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"schema_version": "1",
|
|
26
|
+
"verdicts": [
|
|
27
|
+
{
|
|
28
|
+
"candidate_id": "sc_example",
|
|
29
|
+
"review_key": "scr_example",
|
|
30
|
+
"candidate_worthy": true,
|
|
31
|
+
"behaviorally_equivalent": false,
|
|
32
|
+
"refactor_safe": false,
|
|
33
|
+
"outcome": "related-but-distinct",
|
|
34
|
+
"rationale": "Both normalize input, but only one preserves empty values."
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
5. Join raw candidates and verdicts without changing either input:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
fallow similar-code review --candidates similar-code.json --verdicts verdicts.json \
|
|
44
|
+
--require-verdict-for-each-candidate --format json --quiet
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Only `completion.status: "complete"` makes an empty candidate list conclusive for the admitted scope. Candidates remain advisory and unverified until the separate verdict flow supplies source-grounded judgment.
|