fallow 2.99.0 → 2.100.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 CHANGED
@@ -88,6 +88,23 @@ Fallow gives AI agents structured repo truth instead of forcing them to infer ev
88
88
 
89
89
  Every issue in `--format json` carries a machine-actionable `actions` array with an `auto_fixable` flag so agents can self-correct.
90
90
 
91
+ ### MCP server
92
+
93
+ Agents that speak MCP can launch the bundled `fallow-mcp` server. Installed as a devDependency, the binary lives in `node_modules/.bin/` and is not on your `PATH`, so launch it through your package manager's runner:
94
+
95
+ ```json
96
+ {
97
+ "mcpServers": {
98
+ "fallow": {
99
+ "command": "npx",
100
+ "args": ["fallow-mcp"]
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ Swap `npx` for `pnpm exec` / `yarn` / `bunx` to match your package manager. If `fallow-mcp` is installed globally (on your `PATH`), `"command": "fallow-mcp"` works directly. See the [MCP integration guide](https://docs.fallow.tools/integrations/mcp).
107
+
91
108
  ## Framework support
92
109
 
93
110
  122 built-in 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 many more. Auto-detected from your `package.json`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fallow",
3
- "version": "2.99.0",
3
+ "version": "2.100.0",
4
4
  "description": "Deterministic codebase intelligence for TypeScript and JavaScript. Quality, risk, architecture, dependencies, duplication, and safe cleanup evidence for humans, CI, and agents. Optional runtime intelligence layer (Fallow Runtime) adds production execution evidence. Rust-native, sub-second, zero-config framework support.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -83,13 +83,13 @@
83
83
  "@tanstack/intent": "0.0.42"
84
84
  },
85
85
  "optionalDependencies": {
86
- "@fallow-cli/darwin-arm64": "2.99.0",
87
- "@fallow-cli/darwin-x64": "2.99.0",
88
- "@fallow-cli/linux-x64-gnu": "2.99.0",
89
- "@fallow-cli/linux-arm64-gnu": "2.99.0",
90
- "@fallow-cli/linux-x64-musl": "2.99.0",
91
- "@fallow-cli/linux-arm64-musl": "2.99.0",
92
- "@fallow-cli/win32-arm64-msvc": "2.99.0",
93
- "@fallow-cli/win32-x64-msvc": "2.99.0"
86
+ "@fallow-cli/darwin-arm64": "2.100.0",
87
+ "@fallow-cli/darwin-x64": "2.100.0",
88
+ "@fallow-cli/linux-x64-gnu": "2.100.0",
89
+ "@fallow-cli/linux-arm64-gnu": "2.100.0",
90
+ "@fallow-cli/linux-x64-musl": "2.100.0",
91
+ "@fallow-cli/linux-arm64-musl": "2.100.0",
92
+ "@fallow-cli/win32-arm64-msvc": "2.100.0",
93
+ "@fallow-cli/win32-x64-msvc": "2.100.0"
94
94
  }
95
95
  }
package/schema.json CHANGED
@@ -235,7 +235,7 @@
235
235
  "default": []
236
236
  },
237
237
  "rulePacks": {
238
- "description": "Paths to declarative rule-pack files (JSON or JSONC), relative to the\nproject root. Each pack declares `banned-call` / `banned-import` rules\nthat report as `policy-violation` findings. Packs are pure data: no\nproject code is executed. Invalid or missing packs fail config load.",
238
+ "description": "Paths to declarative rule-pack files (JSON or JSONC), relative to the\nproject root. Each pack declares `banned-call`, `banned-import`, or\n`banned-effect` rules that report as `policy-violation` findings. Packs\nare pure data: no project code is executed. Invalid or missing packs\nfail config load.",
239
239
  "type": "array",
240
240
  "items": {
241
241
  "type": "string"
@@ -1047,7 +1047,7 @@
1047
1047
  "default": "error"
1048
1048
  },
1049
1049
  "unused-component-props": {
1050
- "description": "Vue `<script setup>` `defineProps` declared prop referenced nowhere\ninside its own single-file component (neither `<script>` nor\n`<template>`). The single-file dead-input direction. Defaults to `warn`,\nnot `error`: a prop can be part of a deliberately-stable public component\nAPI, so analyzer confidence is lower; warn encodes that without failing\nCI.",
1050
+ "description": "Vue `<script setup>` `defineProps`, Svelte 5 `$props()`, or React\ndeclared prop referenced nowhere inside its own component. The\nsingle-component dead-input direction. Defaults to `warn`, not `error`: a\nprop can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower; warn encodes that without failing CI.",
1051
1051
  "$ref": "#/$defs/Severity",
1052
1052
  "default": "error"
1053
1053
  },
@@ -95,6 +95,7 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
95
95
  | `fallow` | Run full codebase analysis: cleanup + duplication + health (default) | `--only`, `--skip`, `--production`, `--production-dead-code`, `--production-health`, `--production-dupes`, `--ci`, `--fail-on-issues`, `--group-by`, `--summary`, `--fail-on-regression`, `--tolerance`, `--regression-baseline`, `--save-regression-baseline`, `--score`, `--trend`, `--save-snapshot`, `--include-entry-exports` |
96
96
  | `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` |
97
97
  | `watch` | Watch for changes and re-run analysis | `--no-clear` |
98
+ | `inspect` | Compose one evidence bundle for a file or exported symbol | `--file <path>`, `--symbol <file>:<export>` |
98
99
  | `fix` | Auto-remove unused exports/deps | `--dry-run`, `--yes` (required in non-TTY) |
99
100
  | `init` | Generate config file, AGENTS.md agent guide, or pre-commit hook | `--toml`, `--agents`, `--hooks`, `--branch` |
100
101
  | `hooks` | Inspect, install, or remove fallow-managed Git and agent hooks | `status`, `install --target git`, `install --target agent`, `uninstall --target git`, `uninstall --target agent` |
@@ -150,7 +151,7 @@ Run `fallow <command> --help` for the full flag list per command (see also refer
150
151
  | `boundary-violation` | `--boundary-violations` | - | `// fallow-ignore-next-line boundary-violation` | Imports crossing architecture zone boundaries. Presets: `layered`, `hexagonal`, `feature-sliced`, `bulletproof`; `autoDiscover` can create one zone per feature directory; per-rule `allowTypeOnly: [zones]` admits `import type` / `export type` crossings while still blocking value imports. Optional sections: `boundaries.coverage.requireAllFiles` reports unzoned source files (`allowUnmatched` globs exempt intentional ones), and `boundaries.calls.forbidden` bans callee patterns per zone (segment-aware and import-resolved, so `child_process.*` covers `node:child_process` named/namespace/default imports; direct callees only, zoned files only). The whole family shares the `boundary-violation` rule and suppression token (`boundary-call-violation` and `boundary-call-violations` accepted as aliases); start the rule at `warn` for a staged rollout |
151
152
  | `boundary-coverage` | - | - | `// fallow-ignore-file boundary-violation` | Source file matches no configured architecture boundary zone; Requires boundaries.coverage.requireAllFiles |
152
153
  | `boundary-call-violation` | - | - | `// fallow-ignore-next-line boundary-call-violation` | Zoned file calls a callee its zone forbids; Requires boundaries.calls.forbidden patterns |
153
- | `policy-violation` | `--policy-violations` | - | `// fallow-ignore-next-line policy-violation` | Calls or imports banned by a declarative rule pack (`rulePacks` config key lists standalone JSON/JSONC files of `banned-call` / `banned-import` rules; pure data, no project code executes). Findings identified as `<pack>/<rule-id>`. Default `warn` master; per-rule `severity` overrides per finding and the exit gate reads the effective severity. Invalid or missing packs fail config load with exit 2. `fallow rule-pack-schema` prints the pack JSON Schema. Use the scoped token to suppress one rule; bare `policy-violation` still covers every pack rule on the line or file. |
154
+ | `policy-violation` | `--policy-violations` | - | `// fallow-ignore-next-line policy-violation` | Calls, imports, or catalogue-derived effects banned by a declarative rule pack (`rulePacks` config key lists standalone JSON/JSONC files of `banned-call`, `banned-import`, and `banned-effect` rules; pure data, no project code executes). Findings identified as `<pack>/<rule-id>`. Default `warn` master; per-rule `severity` overrides per finding and the exit gate reads the effective severity. Invalid or missing packs fail config load with exit 2. `fallow rule-pack-schema` prints the pack JSON Schema. Use the scoped token to suppress one rule; bare `policy-violation` still covers every pack rule on the line or file. |
154
155
  | `stale-suppression` | `--stale-suppressions` | - | - | `fallow-ignore` comments or `@expected-unused` JSDoc tags that no longer match any issue |
155
156
  | `unused-catalog-entry` | `--unused-catalog-entries` | yes | - | `pnpm-workspace.yaml` entries no workspace package.json references via `catalog:` (default `warn`) |
156
157
  | `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`. |
@@ -198,7 +199,7 @@ When using fallow via MCP (`fallow-mcp`), the following tools are available:
198
199
  | Tool | Kind | License | Key params | Description |
199
200
  |---|---|---|---|---|
200
201
  | `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). |
201
- | `analyze` | analysis | free | `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 and banned imports 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 |
202
+ | `analyze` | analysis | free | `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 |
202
203
  | `check_changed` | analysis | free | `since`, `baseline`, `fail_on_regression` | Incremental analysis of files changed since a git ref |
203
204
  | `security_candidates` | analysis | free | `gate`, `surface`, `changed_since`, `paths` | Unverified local security candidates, not confirmed vulnerabilities (`fallow security --format json`). Read `security_findings[]` for category, CWE, severity, evidence, trace, optional `reachability`, blind-spot counters, and optional `unresolved_callee_diagnostics` samples for dynamic callee follow-up. `severity` is a review-priority tier, not a verified vulnerability verdict. Each finding also carries an agent-actionable `candidate` (`source_kind`/`sink`/`boundary`), where URL-category sinks may include `url_shape` (`fixed-origin-dynamic-path` or `dynamic-origin`), an optional `taint_flow` source-to-sink triple, and a stable `finding_id` (equal to the SARIF fingerprint) for cross-run correlation; there is no `impact` field (deciding exploitability is the agent's job). Set `surface: true` to include top-level `attack_surface[]` entries with defensive-boundary prompts for a verifier. Set `gate` to `new` for changed-line candidates or `newly-reachable` for candidates that became reachable from entry points; `newly-reachable` requires `changed_since`. `reachability.untrusted_source_trace` is module-level import context only and does not prove value flow; `reachability.taint_confidence` tiers each reachable candidate as `arg-level` (sink argument traces to a same-module source read, strong) or `module-level` (only the module is import-reachable from a source, weak), so tier from this field instead of the evidence text. Verify trace, reachability context, severity, and evidence before editing code. Supports `root`, `config`, `workspace`, `paths`, `changed_since`, `changed_workspaces`, `surface`, `gate`, `no_cache`, and `threads`; `paths` forwards repeated `fallow security --file` filters for finding anchors, trace hops, untrusted-source reachability trace hops, and unresolved-callee diagnostics. See <https://docs.fallow.tools/cli/security-agent-verification> for the verifier packet and verdict recipe. Inherits `FALLOW_DIFF_FILE` from the server environment for line-level diff scoping; raise `FALLOW_TIMEOUT_SECS` for large repos. |
204
205
  | `inspect_target` | analysis | free | `target`, `production` | Compose one evidence bundle for a file or exported symbol. File targets use `target: { type: "file", file }`; symbol targets use `target: { type: "symbol", file, export_name }`. Returns `kind: "inspect_target"`, normalized target identity, `trace_file`, optional `trace_export`, file-scoped dead-code actions, duplication groups filtered to the file, complexity findings filtered to the file, and security candidates scoped to the file. Evidence sections carry `status` and `scope`; symbol targets warn when supporting evidence is file-scoped. Supports `root`, `config`, `production`, `workspace`, `no_cache`, and `threads`; `production` applies to trace, dead-code, and health evidence only. Raise `FALLOW_TIMEOUT_SECS` for large repos. |
@@ -16,6 +16,7 @@ Complete command and flag specifications for all fallow CLI commands.
16
16
  - [`audit`: Changed-File Quality Gate](#audit-changed-file-quality-gate)
17
17
  - [`flags`: Feature Flag Detection](#flags-feature-flag-detection)
18
18
  - [`security`: Security Candidate Detection](#security-security-candidate-detection)
19
+ - [`inspect`: Target Evidence Bundle](#inspect-target-evidence-bundle)
19
20
  - [`explain`: Rule Explanation](#explain-rule-explanation)
20
21
  - [`schema`: CLI Introspection](#schema-cli-introspection)
21
22
  - [`config-schema`: Config JSON Schema](#config-schema-config-json-schema)
@@ -77,7 +78,7 @@ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#
77
78
  | `--circular-deps` | Circular dependencies |
78
79
  | `--re-export-cycles` | Re-export cycles (`kind: multi-node` for barrel files re-exporting from each other in a loop, `kind: self-loop` for a barrel re-exporting from itself). File-scoped finding; chain propagation through the loop is a no-op so imports may silently come up empty. Distinct from `--circular-deps` (runtime cycles). |
79
80
  | `--boundary-violations` | Boundary violations (imports crossing architecture zone boundaries, unzoned source files when `boundaries.coverage.requireAllFiles` is set, and forbidden calls from `boundaries.calls.forbidden`; suppression token `boundary-violation`, with `boundary-call-violation` and `boundary-call-violations` accepted as aliases for the whole family) |
80
- | `--policy-violations` | Rule-pack policy violations (banned calls and banned imports declared via the `rulePacks` config key) |
81
+ | `--policy-violations` | Rule-pack policy violations (banned calls, imports, and catalogue-derived effects declared via the `rulePacks` config key) |
81
82
  | `--stale-suppressions` | Stale suppression comments or `@expected-unused` JSDoc tags |
82
83
  | `--unused-catalog-entries` | Unused pnpm catalog entries |
83
84
  | `--empty-catalog-groups` | Empty named pnpm catalog groups |
@@ -504,7 +505,7 @@ fallow health --format json --quiet --trend
504
505
  {
505
506
  "kind": "health",
506
507
  "schema_version": 7,
507
- "version": "2.99.0",
508
+ "version": "2.100.0",
508
509
  "elapsed_ms": 32,
509
510
  "summary": {
510
511
  "files_analyzed": 482,
@@ -891,7 +892,7 @@ fallow audit \
891
892
  {
892
893
  "kind": "audit",
893
894
  "schema_version": 7,
894
- "version": "2.99.0",
895
+ "version": "2.100.0",
895
896
  "command": "audit",
896
897
  "verdict": "fail",
897
898
  "changed_files_count": 12,
@@ -966,7 +967,7 @@ fallow flags --format json --quiet --workspace my-package
966
967
  ```json
967
968
  {
968
969
  "schema_version": 7,
969
- "version": "2.99.0",
970
+ "version": "2.100.0",
970
971
  "elapsed_ms": 116,
971
972
  "feature_flags": [],
972
973
  "total_flags": 0
@@ -1066,7 +1067,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1066
1067
  {
1067
1068
  "kind": "security",
1068
1069
  "schema_version": "4",
1069
- "version": "2.99.0",
1070
+ "version": "2.100.0",
1070
1071
  "elapsed_ms": 42,
1071
1072
  "config": {
1072
1073
  "rules": {
@@ -1095,7 +1096,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1095
1096
  {
1096
1097
  "kind": "security",
1097
1098
  "schema_version": "4",
1098
- "version": "2.99.0",
1099
+ "version": "2.100.0",
1099
1100
  "elapsed_ms": 42,
1100
1101
  "config": {
1101
1102
  "rules": {
@@ -1159,6 +1160,55 @@ Every finding also carries an agent-actionable `candidate { source_kind, sink, b
1159
1160
 
1160
1161
  ---
1161
1162
 
1163
+ ## `inspect`: Target Evidence Bundle
1164
+
1165
+ Compose one evidence bundle before editing a file or exported symbol. This is the CLI equivalent of the MCP `inspect_target` tool.
1166
+
1167
+ ### Usage
1168
+
1169
+ ```bash
1170
+ fallow inspect --file src/api.ts --format json --quiet
1171
+ fallow inspect --symbol src/api.ts:fetchUser --format json --quiet
1172
+ ```
1173
+
1174
+ ### Target Flags
1175
+
1176
+ | Flag | Description |
1177
+ |------|-------------|
1178
+ | `--file <PATH>` | Inspect one project-relative file |
1179
+ | `--symbol <FILE:EXPORT>` | Inspect one exported symbol. Supporting dead-code, duplication, complexity, and security evidence is file-scoped in the first version |
1180
+
1181
+ Common global flags: `--format`, `--quiet`, `--root`, `--config`, `--workspace`, `--production`, `--no-cache`, `--threads`.
1182
+
1183
+ ### JSON Output Structure
1184
+
1185
+ ```json
1186
+ {
1187
+ "kind": "inspect_target",
1188
+ "target": { "type": "file", "file": "src/api.ts" },
1189
+ "identity": {
1190
+ "file": "src/api.ts",
1191
+ "is_reachable": true,
1192
+ "is_entry_point": false,
1193
+ "export_count": 3,
1194
+ "import_count": 2,
1195
+ "imported_by_count": 1
1196
+ },
1197
+ "evidence": {
1198
+ "trace_file": { "status": "ok", "scope": "file", "data": {} },
1199
+ "dead_code": { "status": "ok", "scope": "file", "data": {} },
1200
+ "duplication": { "status": "ok", "scope": "project_filtered_to_file", "data": {} },
1201
+ "complexity": { "status": "ok", "scope": "project_filtered_to_file", "data": {} },
1202
+ "security": { "status": "ok", "scope": "file", "data": {} }
1203
+ },
1204
+ "warnings": []
1205
+ }
1206
+ ```
1207
+
1208
+ Each evidence section carries `status` and `scope`. Non-fatal child-analysis failures become section-level errors and warnings, so callers can still use the remaining evidence.
1209
+
1210
+ ---
1211
+
1162
1212
  ## `explain`: Rule Explanation
1163
1213
 
1164
1214
  Print rule rationale, examples, fix guidance, and docs URL for one issue type without running analysis.
@@ -1645,7 +1695,7 @@ Set `FALLOW_FORMAT=json` and `FALLOW_QUIET=1` in your agent environment to avoid
1645
1695
  | `human` | Colored terminal output | Interactive use |
1646
1696
  | `json` | Machine-readable JSON | Agent integration, CI pipelines |
1647
1697
  | `sarif` | Static Analysis Results Interchange Format | GitHub Code Scanning, SARIF-compatible tools |
1648
- | `compact` | Grep-friendly: `type:path:line:name` per line | Quick filtering |
1698
+ | `compact` | Grep-friendly: one issue per line. Dupes lines include `code-duplication:path:start-end:fingerprint=dup:<id>,...` | Quick filtering |
1649
1699
  | `markdown` | Markdown tables | Documentation, PR comments |
1650
1700
  | `codeclimate` / `gitlab-codequality` | CodeClimate JSON array | GitLab Code Quality, CodeClimate-compatible tools |
1651
1701
  | `pr-comment-github` / `pr-comment-gitlab` | Sticky PR/MR comment markdown with HTML-comment marker for upsert | Posted by the action / template `comment.sh` scripts |
@@ -1712,7 +1762,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1712
1762
  {
1713
1763
  "kind": "dead-code",
1714
1764
  "schema_version": 7,
1715
- "version": "2.99.0",
1765
+ "version": "2.100.0",
1716
1766
  "elapsed_ms": 45,
1717
1767
  "total_issues": 12,
1718
1768
  "entry_points": {
@@ -1872,7 +1922,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
1872
1922
  {
1873
1923
  "kind": "dupes",
1874
1924
  "schema_version": 7,
1875
- "version": "2.99.0",
1925
+ "version": "2.100.0",
1876
1926
  "elapsed_ms": 82,
1877
1927
  "total_clones": 15,
1878
1928
  "total_lines_duplicated": 230,
@@ -1916,11 +1966,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
1916
1966
  {
1917
1967
  "kind": "combined",
1918
1968
  "schema_version": 7,
1919
- "version": "2.99.0",
1969
+ "version": "2.100.0",
1920
1970
  "elapsed_ms": 159,
1921
1971
  "check": {
1922
1972
  "schema_version": 7,
1923
- "version": "2.99.0",
1973
+ "version": "2.100.0",
1924
1974
  "elapsed_ms": 45,
1925
1975
  "total_issues": 12,
1926
1976
  "unused_files": [],
@@ -25,7 +25,7 @@
25
25
 
26
26
 
27
27
  /**
28
- * Schemas for the JSON output of fallow commands. Object-shaped envelopes covered by the `FallowOutput` contract carry a top-level `kind` discriminator (for example `dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, `explain`, `impact`, `security`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `review-envelope`, and `review-reconcile`). Consumers should branch on `kind` instead of probing for unique field presence. `--legacy-envelope` removes only the document-root `kind` for one compatibility cycle. `CodeClimateOutput` is a bare JSON array (per the Code Climate / GitLab Code Quality spec) and stays a sibling root branch discriminated by checking whether the document root is an array.
28
+ * Schemas for the JSON output of fallow commands. Object-shaped envelopes covered by the `FallowOutput` contract carry a top-level `kind` discriminator (for example `dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, `explain`, `inspect_target`, `impact`, `security`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `review-envelope`, and `review-reconcile`). Consumers should branch on `kind` instead of probing for unique field presence. `--legacy-envelope` removes only the document-root `kind` for one compatibility cycle. `CodeClimateOutput` is a bare JSON array (per the Code Climate / GitLab Code Quality spec) and stays a sibling root branch discriminated by checking whether the document root is an array.
29
29
  */
30
30
  export type FallowJsonOutput = (FallowOutput | CodeClimateOutput)
31
31
  /**
@@ -51,6 +51,8 @@ export type FallowOutput = ((AuditOutput & {
51
51
  kind: "audit"
52
52
  }) | (ExplainOutput & {
53
53
  kind: "explain"
54
+ }) | (InspectOutput & {
55
+ kind: "inspect_target"
54
56
  }) | (ReviewEnvelopeOutput & {
55
57
  kind: "review-envelope"
56
58
  }) | (ReviewReconcileOutput & {
@@ -75,6 +77,10 @@ kind: "impact"
75
77
  kind: "impact-cross-repo"
76
78
  }) | ((SecurityOutput | SecuritySummaryOutput) & {
77
79
  kind: "security"
80
+ }) | (SecuritySurvivorsOutput & {
81
+ kind: "security-survivors"
82
+ }) | (SecurityBlindSpotsOutput & {
83
+ kind: "security-blind-spots"
78
84
  }) | (CheckOutput & {
79
85
  kind: "dead-code"
80
86
  }) | (CombinedOutput & {
@@ -239,7 +245,7 @@ export type ReExportCycleKind = ("multi-node" | "self-loop")
239
245
  /**
240
246
  * Which rule-pack rule kind produced a [`PolicyViolation`].
241
247
  */
242
- export type PolicyRuleKind = ("banned-call" | "banned-import")
248
+ export type PolicyRuleKind = ("banned-call" | "banned-import" | "banned-effect")
243
249
  /**
244
250
  * Effective severity of a single [`PolicyViolation`]. Per-rule `severity`
245
251
  * overrides the `rules."policy-violation"` master; `off` rules emit nothing,
@@ -573,6 +579,10 @@ export type RefactoringTargetActionType = ("apply-refactoring" | "suppress-line"
573
579
  * Direction of a metric's change, semantically (improving/declining/stable).
574
580
  */
575
581
  export type TrendDirection = ("improving" | "declining" | "stable")
582
+ /**
583
+ * Detector status codes for framework health observability.
584
+ */
585
+ export type FrameworkHealthDetectorStatus = ("active" | "disabled_by_config" | "abstained" | "not_checked")
576
586
  /**
577
587
  * Discriminant for [`CssCandidateAction::kind`].
578
588
  */
@@ -581,6 +591,17 @@ export type CssCandidateActionType = ("verify-unused" | "verify-undefined" | "co
581
591
  * Discriminant for [`UnusedAtRule::kind`].
582
592
  */
583
593
  export type UnusedAtRuleKind = ("property-registration" | "layer")
594
+ export type InspectTargetDescriptor = ({
595
+ file: string
596
+ type: "file"
597
+ } | {
598
+ file: string
599
+ export_name: string
600
+ type: "symbol"
601
+ })
602
+ export type InspectIdentity = (InspectFileIdentity | InspectSymbolIdentity)
603
+ export type InspectSectionStatus = ("ok" | "error")
604
+ export type InspectEvidenceScope = ("symbol" | "file" | "project_filtered_to_file")
584
605
  /**
585
606
  * Singleton GitHub review-event marker.
586
607
  */
@@ -730,6 +751,18 @@ export type SkippedSecurityCalleeReason = ("computed-member" | "dynamic-dispatch
730
751
  * Syntactic expression shape for a skipped security callee.
731
752
  */
732
753
  export type SkippedSecurityCalleeExpressionKind = ("static-member-expression" | "computed-member-expression" | "identifier" | "other")
754
+ /**
755
+ * The `fallow security survivors --format json` schema version.
756
+ */
757
+ export type SecuritySurvivorsSchemaVersion = "2"
758
+ /**
759
+ * Verifier verdict status accepted by `fallow security survivors`.
760
+ */
761
+ export type SecurityVerifierVerdictStatus = ("survivor" | "dismissed" | "needs-human-review")
762
+ /**
763
+ * The `fallow security blind-spots --format json` schema version.
764
+ */
765
+ export type SecurityBlindSpotsSchemaVersion = "1"
733
766
  /**
734
767
  * Discriminator value for [`CodeClimateIssue::kind`].
735
768
  */
@@ -1031,7 +1064,8 @@ boundary_coverage_violations?: BoundaryCoverageViolationFinding[]
1031
1064
  */
1032
1065
  boundary_call_violations?: BoundaryCallViolationFinding[]
1033
1066
  /**
1034
- * Banned calls and banned imports matched by declarative rule packs
1067
+ * Banned calls, imports, and catalogue-derived effects matched by
1068
+ * declarative rule packs
1035
1069
  * (`rulePacks` config). Wrapped in [`PolicyViolationFinding`] so each
1036
1070
  * entry carries a typed `actions` array natively. Each finding carries
1037
1071
  * its effective per-rule severity.
@@ -1132,8 +1166,8 @@ route_collisions?: RouteCollisionFinding[]
1132
1166
  */
1133
1167
  dynamic_segment_name_conflicts?: DynamicSegmentNameConflictFinding[]
1134
1168
  /**
1135
- * Vue `<script setup>` `defineProps` props referenced nowhere in their own
1136
- * SFC (neither `<script>` nor `<template>`). Wrapped in
1169
+ * Vue `<script setup>` `defineProps`, Svelte 5 `$props()`, and React props
1170
+ * referenced nowhere in their own component. Wrapped in
1137
1171
  * [`UnusedComponentPropFinding`] so each entry carries a typed `actions`
1138
1172
  * array natively. Default severity is `warn`.
1139
1173
  */
@@ -1303,7 +1337,7 @@ unprovided_injects?: number
1303
1337
  */
1304
1338
  unrendered_components?: number
1305
1339
  /**
1306
- * Vue `<script setup>` props referenced nowhere inside their own SFC.
1340
+ * Vue, Svelte, or React props referenced nowhere inside their own component.
1307
1341
  */
1308
1342
  unused_component_props?: number
1309
1343
  /**
@@ -1376,7 +1410,8 @@ boundary_coverage_violations?: number
1376
1410
  */
1377
1411
  boundary_call_violations?: number
1378
1412
  /**
1379
- * Banned calls and banned imports matched by declarative rule packs.
1413
+ * Banned calls, imports, and catalogue-derived effects matched by
1414
+ * declarative rule packs.
1380
1415
  */
1381
1416
  policy_violations?: number
1382
1417
  /**
@@ -2134,7 +2169,7 @@ introduced?: (AuditIntroduced | null)
2134
2169
  */
2135
2170
  export interface TestOnlyDependencyFinding {
2136
2171
  /**
2137
- * Production dependency that is only imported by test files , consider
2172
+ * Production dependency that is only imported by test files, consider
2138
2173
  * moving to devDependencies.
2139
2174
  */
2140
2175
  package_name: string
@@ -2376,12 +2411,12 @@ introduced?: (AuditIntroduced | null)
2376
2411
  }
2377
2412
  /**
2378
2413
  * Wire-shape envelope for a [`PolicyViolation`] finding. Carries actions for
2379
- * replacing the banned call or import, or suppressing it with a scoped
2414
+ * replacing the banned call, import, or effect, or suppressing it with a scoped
2380
2415
  * `policy-violation:<pack>/<rule-id>` token.
2381
2416
  */
2382
2417
  export interface PolicyViolationFinding {
2383
2418
  /**
2384
- * The source file containing the banned call or import.
2419
+ * The source file containing the banned call, import, or effectful usage.
2385
2420
  */
2386
2421
  path: string
2387
2422
  /**
@@ -2404,8 +2439,8 @@ rule_id: string
2404
2439
  kind: PolicyRuleKind
2405
2440
  /**
2406
2441
  * What matched: the written callee path for `banned-call` (e.g.
2407
- * `cp.exec`), or the raw import specifier for `banned-import` (e.g.
2408
- * `moment/locale/nl`).
2442
+ * `cp.exec`), the raw import specifier for `banned-import` (e.g.
2443
+ * `moment/locale/nl`), or `<effect>: <callee>` for `banned-effect`.
2409
2444
  */
2410
2445
  matched: string
2411
2446
  severity: PolicyViolationSeverity
@@ -2976,11 +3011,11 @@ introduced?: (AuditIntroduced | null)
2976
3011
  */
2977
3012
  export interface UnusedComponentPropFinding {
2978
3013
  /**
2979
- * The `.vue` SFC declaring the unused prop.
3014
+ * The component file declaring the unused prop.
2980
3015
  */
2981
3016
  path: string
2982
3017
  /**
2983
- * The component name (the `.vue` file stem).
3018
+ * The component name.
2984
3019
  */
2985
3020
  component_name: string
2986
3021
  /**
@@ -3920,6 +3955,11 @@ health_trend?: (HealthTrend | null)
3920
3955
  * back to the report root.
3921
3956
  */
3922
3957
  actions_meta?: (HealthActionsMeta | null)
3958
+ /**
3959
+ * Optional framework-specific detector coverage. Present only when the
3960
+ * health run already needed the dead-code analysis output.
3961
+ */
3962
+ framework_health?: (FrameworkHealthDiagnostics | null)
3923
3963
  /**
3924
3964
  * Structural CSS analytics (specificity hotspots, `!important` density,
3925
3965
  * over-complex selectors, deep nesting). Present only with `--css`.
@@ -5557,6 +5597,37 @@ reason: string
5557
5597
  */
5558
5598
  scope: string
5559
5599
  }
5600
+ /**
5601
+ * Framework-specific health detector coverage surfaced for agent consumers.
5602
+ */
5603
+ export interface FrameworkHealthDiagnostics {
5604
+ /**
5605
+ * Detected framework IDs, sorted and deduplicated.
5606
+ */
5607
+ detected_frameworks: string[]
5608
+ /**
5609
+ * Detector coverage for the detected frameworks.
5610
+ */
5611
+ detectors: FrameworkHealthDetector[]
5612
+ }
5613
+ /**
5614
+ * Status for one framework-specific health detector.
5615
+ */
5616
+ export interface FrameworkHealthDetector {
5617
+ /**
5618
+ * Rule or detector ID, matching fallow's stable rule names where possible.
5619
+ */
5620
+ id: string
5621
+ /**
5622
+ * Framework ID that made this detector relevant.
5623
+ */
5624
+ framework: string
5625
+ status: FrameworkHealthDetectorStatus
5626
+ /**
5627
+ * Stable reason code for non-active statuses.
5628
+ */
5629
+ reason?: (string | null)
5630
+ }
5560
5631
  /**
5561
5632
  * Structural CSS analytics surfaced by `fallow health --css`.
5562
5633
  */
@@ -6350,6 +6421,45 @@ example: string
6350
6421
  how_to_fix: string
6351
6422
  docs: string
6352
6423
  }
6424
+ /**
6425
+ * Envelope emitted by `fallow inspect --format json`.
6426
+ */
6427
+ export interface InspectOutput {
6428
+ target: InspectTargetDescriptor
6429
+ identity: InspectIdentity
6430
+ evidence: InspectEvidence
6431
+ warnings: string[]
6432
+ }
6433
+ export interface InspectFileIdentity {
6434
+ file: string
6435
+ is_reachable?: unknown
6436
+ is_entry_point?: unknown
6437
+ export_count?: (number | null)
6438
+ import_count?: (number | null)
6439
+ imported_by_count?: (number | null)
6440
+ }
6441
+ export interface InspectSymbolIdentity {
6442
+ file: string
6443
+ export_name: string
6444
+ file_reachable?: unknown
6445
+ is_entry_point?: unknown
6446
+ is_used?: unknown
6447
+ reason?: unknown
6448
+ }
6449
+ export interface InspectEvidence {
6450
+ trace_file: InspectEvidenceSection
6451
+ trace_export?: (InspectEvidenceSection | null)
6452
+ dead_code: InspectEvidenceSection
6453
+ duplication: InspectEvidenceSection
6454
+ complexity: InspectEvidenceSection
6455
+ security: InspectEvidenceSection
6456
+ }
6457
+ export interface InspectEvidenceSection {
6458
+ status: InspectSectionStatus
6459
+ scope: InspectEvidenceScope
6460
+ message?: (string | null)
6461
+ data?: unknown
6462
+ }
6353
6463
  /**
6354
6464
  * Envelope emitted by `fallow --format review-github` / `review-gitlab`.
6355
6465
  */
@@ -6704,6 +6814,11 @@ health_trend?: (HealthTrend | null)
6704
6814
  * back to the report root.
6705
6815
  */
6706
6816
  actions_meta?: (HealthActionsMeta | null)
6817
+ /**
6818
+ * Optional framework-specific detector coverage. Present only when the
6819
+ * health run already needed the dead-code analysis output.
6820
+ */
6821
+ framework_health?: (FrameworkHealthDiagnostics | null)
6707
6822
  /**
6708
6823
  * Structural CSS analytics (specificity hotspots, `!important` density,
6709
6824
  * over-complex selectors, deep nesting). Present only with `--css`.
@@ -7126,7 +7241,8 @@ boundary_coverage_violations?: BoundaryCoverageViolationFinding[]
7126
7241
  */
7127
7242
  boundary_call_violations?: BoundaryCallViolationFinding[]
7128
7243
  /**
7129
- * Banned calls and banned imports matched by declarative rule packs
7244
+ * Banned calls, imports, and catalogue-derived effects matched by
7245
+ * declarative rule packs
7130
7246
  * (`rulePacks` config). Wrapped in [`PolicyViolationFinding`] so each
7131
7247
  * entry carries a typed `actions` array natively. Each finding carries
7132
7248
  * its effective per-rule severity.
@@ -7227,8 +7343,8 @@ route_collisions?: RouteCollisionFinding[]
7227
7343
  */
7228
7344
  dynamic_segment_name_conflicts?: DynamicSegmentNameConflictFinding[]
7229
7345
  /**
7230
- * Vue `<script setup>` `defineProps` props referenced nowhere in their own
7231
- * SFC (neither `<script>` nor `<template>`). Wrapped in
7346
+ * Vue `<script setup>` `defineProps`, Svelte 5 `$props()`, and React props
7347
+ * referenced nowhere in their own component. Wrapped in
7232
7348
  * [`UnusedComponentPropFinding`] so each entry carries a typed `actions`
7233
7349
  * array natively. Default severity is `warn`.
7234
7350
  */
@@ -8183,6 +8299,123 @@ coverage_unavailable: number
8183
8299
  runtime_unknown: number
8184
8300
  not_collected: number
8185
8301
  }
8302
+ /**
8303
+ * The `fallow security survivors --format json` envelope.
8304
+ */
8305
+ export interface SecuritySurvivorsOutput {
8306
+ schema_version: SecuritySurvivorsSchemaVersion
8307
+ version: ToolVersion
8308
+ elapsed_ms: ElapsedMs
8309
+ summary: SecuritySurvivorsSummary
8310
+ /**
8311
+ * Verifier-retained candidates keyed by finding id.
8312
+ */
8313
+ survivors: {
8314
+ [k: string]: SecuritySurvivor
8315
+ }
8316
+ /**
8317
+ * Ambiguous candidates keyed by finding id. These are not dismissed and are
8318
+ * kept explicit so queues can decide whether to include them.
8319
+ */
8320
+ needs_human_review: {
8321
+ [k: string]: SecuritySurvivor
8322
+ }
8323
+ }
8324
+ /**
8325
+ * Aggregate counts for survivor rendering.
8326
+ */
8327
+ export interface SecuritySurvivorsSummary {
8328
+ candidates: number
8329
+ verdicts: number
8330
+ survivors: number
8331
+ dismissed: number
8332
+ needs_human_review: number
8333
+ unverdicted: number
8334
+ }
8335
+ /**
8336
+ * One verifier-retained candidate row.
8337
+ */
8338
+ export interface SecuritySurvivor {
8339
+ /**
8340
+ * Stable candidate id from `security_findings[].finding_id`.
8341
+ */
8342
+ finding_id: string
8343
+ verdict: SecurityVerifierVerdictStatus
8344
+ /**
8345
+ * Short verifier reason.
8346
+ */
8347
+ reason?: (string | null)
8348
+ /**
8349
+ * Short verifier rationale.
8350
+ */
8351
+ rationale?: (string | null)
8352
+ /**
8353
+ * Optional verifier-provided confidence or review priority.
8354
+ */
8355
+ confidence?: (string | null)
8356
+ /**
8357
+ * Optional verifier-provided impact statement.
8358
+ */
8359
+ impact?: (string | null)
8360
+ /**
8361
+ * Optional verifier-owned remediation direction.
8362
+ */
8363
+ fix_direction?: (string | null)
8364
+ candidate: SecurityFinding
8365
+ }
8366
+ /**
8367
+ * The `fallow security blind-spots --format json` envelope.
8368
+ */
8369
+ export interface SecurityBlindSpotsOutput {
8370
+ schema_version: SecurityBlindSpotsSchemaVersion
8371
+ version: ToolVersion
8372
+ elapsed_ms: ElapsedMs
8373
+ summary: SecurityBlindSpotsSummary
8374
+ /**
8375
+ * Grouped unresolved callee diagnostics, derived from existing samples.
8376
+ */
8377
+ groups: SecurityBlindSpotGroup[]
8378
+ }
8379
+ /**
8380
+ * Aggregate counts for blind-spot output.
8381
+ */
8382
+ export interface SecurityBlindSpotsSummary {
8383
+ unresolved_edge_files: number
8384
+ unresolved_callee_sites: number
8385
+ sampled_callee_sites: number
8386
+ }
8387
+ /**
8388
+ * One actionable blind-spot group.
8389
+ */
8390
+ export interface SecurityBlindSpotGroup {
8391
+ reason: SkippedSecurityCalleeReason
8392
+ expression_kind: SkippedSecurityCalleeExpressionKind
8393
+ /**
8394
+ * Count in the bounded diagnostic sample.
8395
+ */
8396
+ sampled_count: number
8397
+ /**
8398
+ * Top files in this bounded diagnostic sample.
8399
+ */
8400
+ files: SecurityBlindSpotFile[]
8401
+ /**
8402
+ * Suggested next action for this group.
8403
+ */
8404
+ suggestion: string
8405
+ }
8406
+ /**
8407
+ * One file inside a blind-spot group.
8408
+ */
8409
+ export interface SecurityBlindSpotFile {
8410
+ /**
8411
+ * Project-relative source path.
8412
+ */
8413
+ path: string
8414
+ /**
8415
+ * Count in the bounded diagnostic sample.
8416
+ */
8417
+ sampled_count: number
8418
+ }
8186
8419
  /**
8187
8420
  * Bare `fallow --format json` envelope.
8188
8421
  */