fallow 2.74.0 → 2.76.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 +1 -1
- package/package.json +9 -9
- package/schema.json +61 -1
- package/skills/fallow/SKILL.md +3 -2
- package/skills/fallow/references/cli-reference.md +46 -14
- package/types/output-contract.d.ts +4446 -1496
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ fallow dupes --save-baseline # Save current duplication as baseline
|
|
|
75
75
|
|
|
76
76
|
## Framework support
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
95 built-in plugins covering Next.js, Nuxt, Remix, Qwik, SvelteKit, Gatsby, Astro, Angular, NestJS, AdonisJS, 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`.
|
|
79
79
|
|
|
80
80
|
## Configuration
|
|
81
81
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.76.0",
|
|
4
4
|
"description": "Codebase intelligence for TypeScript and JavaScript. Finds unused code, duplication, circular dependencies, complexity hotspots, and architecture drift. Optional runtime intelligence layer (Fallow Runtime) adds production execution evidence. Rust-native, sub-second, 94 framework plugins.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"@tanstack/intent": "0.0.40"
|
|
74
74
|
},
|
|
75
75
|
"optionalDependencies": {
|
|
76
|
-
"@fallow-cli/darwin-arm64": "2.
|
|
77
|
-
"@fallow-cli/darwin-x64": "2.
|
|
78
|
-
"@fallow-cli/linux-x64-gnu": "2.
|
|
79
|
-
"@fallow-cli/linux-arm64-gnu": "2.
|
|
80
|
-
"@fallow-cli/linux-x64-musl": "2.
|
|
81
|
-
"@fallow-cli/linux-arm64-musl": "2.
|
|
82
|
-
"@fallow-cli/win32-arm64-msvc": "2.
|
|
83
|
-
"@fallow-cli/win32-x64-msvc": "2.
|
|
76
|
+
"@fallow-cli/darwin-arm64": "2.76.0",
|
|
77
|
+
"@fallow-cli/darwin-x64": "2.76.0",
|
|
78
|
+
"@fallow-cli/linux-x64-gnu": "2.76.0",
|
|
79
|
+
"@fallow-cli/linux-arm64-gnu": "2.76.0",
|
|
80
|
+
"@fallow-cli/linux-x64-musl": "2.76.0",
|
|
81
|
+
"@fallow-cli/linux-arm64-musl": "2.76.0",
|
|
82
|
+
"@fallow-cli/win32-arm64-msvc": "2.76.0",
|
|
83
|
+
"@fallow-cli/win32-x64-msvc": "2.76.0"
|
|
84
84
|
}
|
|
85
85
|
}
|
package/schema.json
CHANGED
|
@@ -186,6 +186,15 @@
|
|
|
186
186
|
"configObjectHeuristics": false
|
|
187
187
|
}
|
|
188
188
|
},
|
|
189
|
+
"fix": {
|
|
190
|
+
"description": "Auto-fix behavior settings.",
|
|
191
|
+
"$ref": "#/$defs/FixConfig",
|
|
192
|
+
"default": {
|
|
193
|
+
"catalog": {
|
|
194
|
+
"deletePrecedingComments": "auto"
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
189
198
|
"resolve": {
|
|
190
199
|
"description": "Module resolver configuration (custom conditions, etc.).",
|
|
191
200
|
"$ref": "#/$defs/ResolveConfig",
|
|
@@ -1044,7 +1053,7 @@
|
|
|
1044
1053
|
"const": "feature-sliced"
|
|
1045
1054
|
},
|
|
1046
1055
|
{
|
|
1047
|
-
"description": "Bulletproof React: app → features → shared + server.\nFeature modules are isolated from each other via `autoDiscover`: every\nimmediate child of `src/features/` becomes its own `features/<name>` zone,\nand cross-feature imports are reported as boundary violations.\
|
|
1056
|
+
"description": "Bulletproof React: app → features → shared + server.\nFeature modules are isolated from each other via `autoDiscover`: every\nimmediate child of `src/features/` becomes its own `features/<name>` zone,\nand cross-feature imports are reported as boundary violations.\nTop-level files in `src/features/` are classified by the logical\n`features` parent zone, so barrels can re-export child features while\nnon-barrel top-level files still obey the `features` boundary rule.",
|
|
1048
1057
|
"type": "string",
|
|
1049
1058
|
"const": "bulletproof"
|
|
1050
1059
|
}
|
|
@@ -1099,6 +1108,13 @@
|
|
|
1099
1108
|
"type": "string"
|
|
1100
1109
|
},
|
|
1101
1110
|
"default": []
|
|
1111
|
+
},
|
|
1112
|
+
"allowTypeOnly": {
|
|
1113
|
+
"description": "Zones that `from` may type-only-import from even when not listed in\n`allow`. Mirrors the `allow` shape: a list of target zone names. A\ntype-only import declaration (`import type {...}`, `import type * as ns`,\nor a per-specifier inline `type` qualifier on every named specifier) to a\nlisted zone is not reported as a boundary violation. Mixed-specifier\nimports (`import { type Foo, Bar }`) that carry at least one value\nsymbol still fire because the runtime dependency on `Bar` is real.\nType-only re-exports (`export type { Foo } from \"...\"`) participate\nin the same allowance because they surface as edges flagged\n`is_type_only: true` and, like type-only imports, are erased at\ncompile time.",
|
|
1114
|
+
"type": "array",
|
|
1115
|
+
"items": {
|
|
1116
|
+
"type": "string"
|
|
1117
|
+
}
|
|
1102
1118
|
}
|
|
1103
1119
|
},
|
|
1104
1120
|
"required": [
|
|
@@ -1157,6 +1173,50 @@
|
|
|
1157
1173
|
"function"
|
|
1158
1174
|
]
|
|
1159
1175
|
},
|
|
1176
|
+
"FixConfig": {
|
|
1177
|
+
"description": "Auto-fix behavior settings.",
|
|
1178
|
+
"type": "object",
|
|
1179
|
+
"properties": {
|
|
1180
|
+
"catalog": {
|
|
1181
|
+
"description": "Auto-fix behavior for pnpm catalog edits.",
|
|
1182
|
+
"$ref": "#/$defs/CatalogFixConfig",
|
|
1183
|
+
"default": {
|
|
1184
|
+
"deletePrecedingComments": "auto"
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
"CatalogFixConfig": {
|
|
1190
|
+
"description": "Auto-fix behavior for pnpm catalog entries.",
|
|
1191
|
+
"type": "object",
|
|
1192
|
+
"properties": {
|
|
1193
|
+
"deletePrecedingComments": {
|
|
1194
|
+
"description": "Whether removing an unused catalog entry also removes the contiguous\nYAML comment block immediately above it.",
|
|
1195
|
+
"$ref": "#/$defs/CatalogPrecedingCommentPolicy",
|
|
1196
|
+
"default": "auto"
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
"CatalogPrecedingCommentPolicy": {
|
|
1201
|
+
"description": "Policy for deleting comments immediately above removed catalog entries.",
|
|
1202
|
+
"oneOf": [
|
|
1203
|
+
{
|
|
1204
|
+
"description": "Delete the comment block when it is separated from previous siblings by\na blank line, or when it directly follows the parent catalog header.",
|
|
1205
|
+
"type": "string",
|
|
1206
|
+
"const": "auto"
|
|
1207
|
+
},
|
|
1208
|
+
{
|
|
1209
|
+
"description": "Always delete the contiguous comment block immediately above the entry.",
|
|
1210
|
+
"type": "string",
|
|
1211
|
+
"const": "always"
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
"description": "Never delete leading comments; leave them in place as orphan comments.",
|
|
1215
|
+
"type": "string",
|
|
1216
|
+
"const": "never"
|
|
1217
|
+
}
|
|
1218
|
+
]
|
|
1219
|
+
},
|
|
1160
1220
|
"ResolveConfig": {
|
|
1161
1221
|
"description": "Module resolver configuration.\n\nControls how fallow resolves import specifiers against package.json\n`exports` / `imports` fields and tsconfig paths. Configured via the\n`resolve` section in `.fallowrc.json`, `.fallowrc.jsonc`, `fallow.toml`, or `.fallow.toml`.\n\n# Examples\n\n```json\n{\n \"resolve\": {\n \"conditions\": [\"development\", \"worker\"]\n }\n}\n```",
|
|
1162
1222
|
"type": "object",
|
package/skills/fallow/SKILL.md
CHANGED
|
@@ -95,12 +95,13 @@ cargo install fallow-cli # build from source
|
|
|
95
95
|
| Unlisted dependencies | `--unlisted-deps` | Used packages missing from package.json. In monorepos, importing a workspace package from a workspace whose own `package.json` does not list it is reported here too; self-references stay allowed without requiring a package to depend on itself. |
|
|
96
96
|
| Duplicate exports | `--duplicate-exports` | Same symbol exported from multiple modules |
|
|
97
97
|
| Circular dependencies | `--circular-deps` | Import cycles in the module graph |
|
|
98
|
-
| Boundary violations | `--boundary-violations` | Imports crossing architecture zone boundaries. Presets: `layered`, `hexagonal`, `feature-sliced`, `bulletproof` |
|
|
98
|
+
| Boundary violations | `--boundary-violations` | Imports crossing architecture zone boundaries. Presets: `layered`, `hexagonal`, `feature-sliced`, `bulletproof`; `autoDiscover` can create one zone per feature directory |
|
|
99
99
|
| Stale suppressions | `--stale-suppressions` | `fallow-ignore` comments or `@expected-unused` JSDoc tags that no longer match any issue |
|
|
100
100
|
| Test-only dependencies | n/a | Production deps only imported from test files (should be devDependencies) |
|
|
101
101
|
| Unused pnpm catalog entries | `--unused-catalog-entries` | `pnpm-workspace.yaml` entries no workspace package.json references via `catalog:` (default `warn`) |
|
|
102
|
+
| Empty pnpm catalog groups | `--empty-catalog-groups` | Named `catalogs.<name>:` groups in `pnpm-workspace.yaml` with no entries. Top-level `catalog:` placeholders are ignored. Default `warn`. |
|
|
102
103
|
| Unresolved pnpm catalog references | `--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). |
|
|
103
|
-
| Unused pnpm dependency overrides | `--unused-dependency-overrides` | `pnpm-workspace.yaml#overrides` / `package.json#pnpm.overrides` entries
|
|
104
|
+
| Unused pnpm dependency overrides | `--unused-dependency-overrides` | `pnpm-workspace.yaml#overrides` / `package.json#pnpm.overrides` entries whose target package is not declared by any workspace `package.json` and is not present in `pnpm-lock.yaml`. Default `warn`. When the lockfile is missing or unreadable the check degrades to a manifest-only fallback and every finding carries a `hint` reminding consumers to verify before removal. Suppress via `ignoreDependencyOverrides: [{ package, source? }]` in fallow config. |
|
|
104
105
|
| Misconfigured pnpm dependency overrides | `--misconfigured-dependency-overrides` | `pnpm.overrides` entries whose key is unparsable (empty, dangling separators, malformed selectors) or value is missing/empty. `pnpm install` would fail. Default `error`. Suppression: same `ignoreDependencyOverrides` config rule. |
|
|
105
106
|
|
|
106
107
|
## MCP Tools
|
|
@@ -72,6 +72,11 @@ Analyzes the project for unused files, exports, dependencies, types, members, an
|
|
|
72
72
|
| `--circular-deps` | Circular dependencies |
|
|
73
73
|
| `--boundary-violations` | Boundary violations (imports crossing architecture zone boundaries) |
|
|
74
74
|
| `--stale-suppressions` | Stale suppression comments or `@expected-unused` JSDoc tags |
|
|
75
|
+
| `--unused-catalog-entries` | Unused pnpm catalog entries |
|
|
76
|
+
| `--empty-catalog-groups` | Empty named pnpm catalog groups |
|
|
77
|
+
| `--unresolved-catalog-references` | Package references to missing pnpm catalog entries |
|
|
78
|
+
| `--unused-dependency-overrides` | Unused pnpm dependency overrides |
|
|
79
|
+
| `--misconfigured-dependency-overrides` | Malformed pnpm dependency overrides |
|
|
75
80
|
|
|
76
81
|
### Examples
|
|
77
82
|
|
|
@@ -198,9 +203,10 @@ Auto-removes unused exports, dependencies, enum members, and pnpm catalog entrie
|
|
|
198
203
|
|
|
199
204
|
| Flag | Type | Default | Description |
|
|
200
205
|
|------|------|---------|-------------|
|
|
201
|
-
| `--dry-run` | bool | `false` | Show what would be removed without modifying files |
|
|
206
|
+
| `--dry-run` | bool | `false` | Show what would be removed without modifying files. For `add-to-config` actions, prints a unified-diff preview of the proposed config write; JSON mode includes the diff under a `proposed_diff` field on the fix entry. |
|
|
202
207
|
| `--yes` | bool | `false` | Skip confirmation prompt (**required** in non-TTY) |
|
|
203
208
|
| `--force` | bool | `false` | Alias for `--yes` |
|
|
209
|
+
| `--no-create-config` | bool | `false` | Refuse to create a new `.fallowrc.json` when none exists. The duplicate-export config-add path is skipped with `skip_reason: "no_create_config"`; source-file edits proceed normally. Use in pre-commit hooks, CI bots, and `fallow watch` where silently materialising a new top-level file would surprise the user. |
|
|
204
210
|
| `--format` | `human\|json` | `human` | Output format |
|
|
205
211
|
| `--quiet` | bool | `false` | Suppress progress bars |
|
|
206
212
|
|
|
@@ -209,7 +215,8 @@ Auto-removes unused exports, dependencies, enum members, and pnpm catalog entrie
|
|
|
209
215
|
- Unused exports (removes the `export` keyword; whole-enum block when every member is unused)
|
|
210
216
|
- Unused dependencies (removed from `package.json`)
|
|
211
217
|
- Unused enum members (removed from the declaration)
|
|
212
|
-
- Unused pnpm catalog entries (removed from `pnpm-workspace.yaml` by line-aware deletion; comments
|
|
218
|
+
- Unused pnpm catalog entries (removed from `pnpm-workspace.yaml` by line-aware deletion). Object-form entries are removed as one block. By default, fallow also removes a contiguous YAML comment block immediately above the entry when it clearly belongs to that entry; configure this with `fix.catalog.deletePrecedingComments` (`"auto"`, `"always"`, or `"never"`). Two escape hatches keep curated comments safe regardless of policy: a `# fallow-keep` marker on any line in the block preserves it, and the `auto` policy additionally preserves section-banner blocks whose body starts with three or more `=`, `-`, `*`, `_`, `~`, `+`, or `#` characters (e.g. `# === React 18 production pins ===`). Other comments and stylistic choices are preserved. When the last entry of a catalog group is removed, the header is rewritten to `catalog: {}` / `<name>: {}` so pnpm doesn't reject the resulting null value. Entries with non-empty `hardcoded_consumers` are skipped to avoid breaking `pnpm install`; the skip is surfaced in the JSON fix output as `{"type": "remove_catalog_entry", "applied": false, "skipped": true, "skip_reason": "hardcoded_consumers", "consumers": [...]}`. The JSON action carries both `line` (first deleted line, the leading comment when policy absorbs one) and `entry_line` (the catalog entry's original 1-based line); use `entry_line` as a stable anchor across policy changes. After a successful catalog edit the CLI emits a one-line `Run pnpm install to refresh pnpm-lock.yaml` reminder, and the human stderr summary appends `(+M catalog comment lines)` to the fixed-issue count when comment lines were absorbed. The JSON envelope carries a top-level `"skipped"` count alongside `"total_fixed"` for partial-fix gating.
|
|
219
|
+
- Duplicate exports (appends an `ignoreExports` rule to your fallow config file). When no fallow config file exists, `.fallowrc.json` is created using the same scaffolding `fallow init` would emit (framework detection, `$schema`, `entry`, `ignorePatterns`, etc.) and the rules are layered on top. Inside a monorepo subpackage (`pnpm-workspace.yaml`, `package.json#workspaces`, `turbo.json`, `lerna.json`, or `rush.json` above the invocation directory) the create-fallback refuses to fire and emits `skip_reason: "monorepo_subpackage"` with a relative `workspace_root` path pointing at the workspace root. The applied entry carries `created_files: [".fallowrc.json"]` so consumers can detect file-creation side effects programmatically.
|
|
213
220
|
|
|
214
221
|
### Examples
|
|
215
222
|
|
|
@@ -234,7 +241,7 @@ Inspect discovered files, entry points, detected frameworks, and architecture bo
|
|
|
234
241
|
| `--files` | bool | List all discovered files |
|
|
235
242
|
| `--entry-points` | bool | List detected entry points |
|
|
236
243
|
| `--plugins` | bool | List active framework plugins |
|
|
237
|
-
| `--boundaries` | bool | Show architecture boundary zones, rules,
|
|
244
|
+
| `--boundaries` | bool | Show architecture boundary zones, rules, per-zone file counts, and `logical_groups[]` for `autoDiscover` parents |
|
|
238
245
|
| `--format` | `human\|json` | Output format |
|
|
239
246
|
| `--quiet` | bool | Suppress progress bars |
|
|
240
247
|
|
|
@@ -247,6 +254,8 @@ fallow list --plugins --format json --quiet
|
|
|
247
254
|
fallow list --boundaries --format json --quiet
|
|
248
255
|
```
|
|
249
256
|
|
|
257
|
+
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`.
|
|
258
|
+
|
|
250
259
|
---
|
|
251
260
|
|
|
252
261
|
## `init`: Config Generation
|
|
@@ -432,7 +441,7 @@ fallow health --format json --quiet --trend
|
|
|
432
441
|
```json
|
|
433
442
|
{
|
|
434
443
|
"schema_version": 3,
|
|
435
|
-
"version": "2.
|
|
444
|
+
"version": "2.75.0",
|
|
436
445
|
"elapsed_ms": 32,
|
|
437
446
|
"summary": {
|
|
438
447
|
"files_analyzed": 482,
|
|
@@ -818,7 +827,7 @@ fallow audit \
|
|
|
818
827
|
```json
|
|
819
828
|
{
|
|
820
829
|
"schema_version": 3,
|
|
821
|
-
"version": "2.
|
|
830
|
+
"version": "2.75.0",
|
|
822
831
|
"command": "audit",
|
|
823
832
|
"verdict": "fail",
|
|
824
833
|
"changed_files_count": 12,
|
|
@@ -891,7 +900,7 @@ fallow flags --format json --quiet --workspace my-package
|
|
|
891
900
|
```json
|
|
892
901
|
{
|
|
893
902
|
"schema_version": 3,
|
|
894
|
-
"version": "2.
|
|
903
|
+
"version": "2.75.0",
|
|
895
904
|
"elapsed_ms": 116,
|
|
896
905
|
"feature_flags": [],
|
|
897
906
|
"total_flags": 0
|
|
@@ -1126,7 +1135,7 @@ Coverage CI helper for bundled/minified runtime coverage. It scans a build direc
|
|
|
1126
1135
|
| `--dir <PATH>` | path | `dist` | Directory scanned recursively. |
|
|
1127
1136
|
| `--include <GLOB>` | glob | `**/*.map` | Include glob relative to `--dir`. |
|
|
1128
1137
|
| `--exclude <GLOB>` | glob | `**/node_modules/**` | Exclude glob, repeatable. |
|
|
1129
|
-
| `--repo <NAME>` | string | `package.json` `repository.url`, then `git remote get-url origin` | Repo
|
|
1138
|
+
| `--repo <NAME>` | string | `package.json` `repository.url`, then `git remote get-url origin` parsed to `owner/repo` | Repo identifier used in the source-map API path. Must match the beacon's `projectId` (and `upload-inventory`'s `--project-id`); pass `--repo <bare-name>` explicitly if the beacon reports a bare name. |
|
|
1130
1139
|
| `--git-sha <SHA>` | string | `$GITHUB_SHA` -> `$CI_COMMIT_SHA` -> `$COMMIT_SHA` -> `git rev-parse HEAD` | Commit SHA, 7-40 hex chars. |
|
|
1131
1140
|
| `--endpoint <URL>` | string | `$FALLOW_API_URL` or `https://api.fallow.cloud` | Override for staging / on-prem. |
|
|
1132
1141
|
| `--strip-path <BOOL>` | bool | `true` | Upload basename-only `fileName` values. Use `--strip-path=false` when runtime coverage reports paths like `assets/app.js`. |
|
|
@@ -1310,7 +1319,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
|
|
|
1310
1319
|
```json
|
|
1311
1320
|
{
|
|
1312
1321
|
"schema_version": 3,
|
|
1313
|
-
"version": "2.
|
|
1322
|
+
"version": "2.75.0",
|
|
1314
1323
|
"elapsed_ms": 45,
|
|
1315
1324
|
"total_issues": 12,
|
|
1316
1325
|
"entry_points": {
|
|
@@ -1362,7 +1371,7 @@ Every issue in `dead-code` JSON output includes an `actions` array with structur
|
|
|
1362
1371
|
| Field | Type | Required | Description |
|
|
1363
1372
|
|-------|------|----------|-------------|
|
|
1364
1373
|
| `type` | string | yes | Action type in kebab-case (for example `remove-export`, `remove-file`, `remove-dependency`, `move-dependency`, `suppress-line`, `add-to-config`) |
|
|
1365
|
-
| `auto_fixable` | bool | yes | `true` if `fallow fix` handles this action automatically |
|
|
1374
|
+
| `auto_fixable` | bool | yes | `true` if `fallow fix` handles this action automatically. Evaluated PER FINDING, not per action type: the same `type` may carry `true` on one finding and `false` on another when per-instance guards in the applier discriminate. Filter on this bool of each individual action, not on `type` alone. |
|
|
1366
1375
|
| `description` | string | yes | Human-readable description of the action |
|
|
1367
1376
|
| `comment` | string | no | Suppression comment text (on `suppress-line` actions) |
|
|
1368
1377
|
| `note` | string | no | Additional context on non-auto-fixable items |
|
|
@@ -1419,6 +1428,14 @@ Dependency issues use `add-to-config` with `config_key` and `value`:
|
|
|
1419
1428
|
|
|
1420
1429
|
When a dependency action is `move-dependency`, `auto_fixable` is `false`; the package is imported from another workspace and needs a package.json ownership move rather than removal.
|
|
1421
1430
|
|
|
1431
|
+
Per-instance `auto_fixable` flips today (the same action `type` flipping between findings):
|
|
1432
|
+
|
|
1433
|
+
- `remove-catalog-entry` (unused-catalog-entries): `true` only when `hardcoded_consumers` is empty; `false` otherwise (the applier skips the entry to avoid breaking `pnpm install`).
|
|
1434
|
+
- `remove-dependency` vs `move-dependency` (dependency findings): primary action flips between `remove-dependency` (`true`) and `move-dependency` (`false`) on `used_in_workspaces`.
|
|
1435
|
+
- `add-to-config` for `ignoreExports` (duplicate-exports): `true` when `fallow fix` can safely apply the action, which today means EITHER a fallow config file already exists OR no config exists and the working directory is NOT inside a monorepo subpackage. In the second case the applier creates `.fallowrc.json` using `fallow init`'s framework-aware scaffolding and layers the new rules on top. `false` inside a monorepo subpackage with no workspace-root config (the applier refuses to fragment per-package configs). Pass `--no-create-config` to `fallow fix` from pre-commit hooks, CI bots, and `fallow watch` to opt out of the create-fallback; the action then surfaces with `auto_fixable: false`.
|
|
1436
|
+
- `update-catalog-reference` (unresolved-catalog-references): always `false` today; non-singleton on the wire so a future applier can promote it without a schema change.
|
|
1437
|
+
- All `suppress-line` and `suppress-file` actions are uniformly `false`.
|
|
1438
|
+
|
|
1422
1439
|
#### Health `actions` array (CRAP findings)
|
|
1423
1440
|
|
|
1424
1441
|
Health findings (`fallow health` JSON output) include an `actions` array. Primary action selection is formula-aware: the rule first checks whether full coverage CAN bring CRAP under threshold (CRAP bottoms out at `cyclomatic` at 100% coverage, so `cyclomatic < maxCrap` means coverage is a viable remediation), then uses `coverage_tier` to choose the description.
|
|
@@ -1432,6 +1449,8 @@ Health findings (`fallow health` JSON output) include an `actions` array. Primar
|
|
|
1432
1449
|
|
|
1433
1450
|
The `coverage_tier` field is `"none"` (file not test-reachable / Istanbul 0%), `"partial"` (Istanbul `(0, 70)` / estimated 40%), or `"high"` (Istanbul `>= 70` / estimated 85%).
|
|
1434
1451
|
|
|
1452
|
+
Each CRAP finding also carries a `coverage_source` discriminator: `"istanbul"` (direct fnMap match for this function), `"estimated"` (graph-based estimate evaluated against the finding's own file), or `"estimated_component_inherited"` (graph-based estimate inherited from an Angular component `.ts` reached via the inverse `templateUrl` edge). Synthetic `<template>` findings on Angular `.html` templates use the `estimated_component_inherited` source and ship an `inherited_from` field with the project-relative path to the owning `.component.ts`. When the inherit path applies, the primary `increase-coverage` action targets that `.ts` file (description names the component path explicitly and includes a `target_path` field) so AI agents add component tests rather than scaffolding tests against a structurally untestable `.html` path. The human `fallow health` output renders `(inherited from foo.component.ts)` after the CRAP score on those rows. This is the JIT-test fallback (Angular's runtime renders templates via `ɵɵconditional` / `ɵɵrepeaterCreate` calls; Istanbul never has `fnMap` entries keyed at `.html` paths). AOT-compiled coverage with source-map back-mapping is planned as a tier 2 follow-up; when it lands, `coverage_source` will gain a `"measured_aot_source_map"` variant.
|
|
1453
|
+
|
|
1435
1454
|
When CRAP-only with cyclomatic count within 5 of `maxCyclomatic` AND cognitive at or above `maxCognitive / 2`, a secondary `refactor-function` is appended. The cognitive floor suppresses false positives on flat type-tag dispatchers and JSX render maps (high CC, near-zero cog). A single finding can carry multiple action types: e.g. a finding that exceeds both cyclomatic and CRAP at `coverage_tier=partial` gets `increase-coverage` AND `refactor-function`. Treat the first non-`suppress-line` action as primary.
|
|
1436
1455
|
|
|
1437
1456
|
The `suppress-line` action is auto-omitted when `--baseline`/`--save-baseline` is set, OR when `health.suggestInlineSuppression: false` in config. The report root carries an `actions_meta: { suppression_hints_omitted: true, reason: "baseline-active" | "config-disabled" }` breadcrumb in that case.
|
|
@@ -1457,7 +1476,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
|
|
|
1457
1476
|
```json
|
|
1458
1477
|
{
|
|
1459
1478
|
"schema_version": 3,
|
|
1460
|
-
"version": "2.
|
|
1479
|
+
"version": "2.75.0",
|
|
1461
1480
|
"elapsed_ms": 82,
|
|
1462
1481
|
"total_clones": 15,
|
|
1463
1482
|
"total_lines_duplicated": 230,
|
|
@@ -1501,7 +1520,7 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
1501
1520
|
{
|
|
1502
1521
|
"check": {
|
|
1503
1522
|
"schema_version": 3,
|
|
1504
|
-
"version": "2.
|
|
1523
|
+
"version": "2.75.0",
|
|
1505
1524
|
"elapsed_ms": 45,
|
|
1506
1525
|
"total_issues": 12,
|
|
1507
1526
|
"unused_files": [],
|
|
@@ -1523,7 +1542,7 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
1523
1542
|
},
|
|
1524
1543
|
"dupes": {
|
|
1525
1544
|
"schema_version": 3,
|
|
1526
|
-
"version": "2.
|
|
1545
|
+
"version": "2.75.0",
|
|
1527
1546
|
"elapsed_ms": 82,
|
|
1528
1547
|
"total_clones": 15,
|
|
1529
1548
|
"total_lines_duplicated": 230,
|
|
@@ -1532,7 +1551,7 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
1532
1551
|
},
|
|
1533
1552
|
"health": {
|
|
1534
1553
|
"schema_version": 3,
|
|
1535
|
-
"version": "2.
|
|
1554
|
+
"version": "2.75.0",
|
|
1536
1555
|
"elapsed_ms": 32,
|
|
1537
1556
|
"summary": {},
|
|
1538
1557
|
"findings": [],
|
|
@@ -1614,10 +1633,23 @@ Config files are searched in priority order: `.fallowrc.json` > `.fallowrc.jsonc
|
|
|
1614
1633
|
"ignorePatterns": ["**/*.generated.ts"]
|
|
1615
1634
|
},
|
|
1616
1635
|
|
|
1617
|
-
// Architecture boundaries (preset
|
|
1636
|
+
// Architecture boundaries (preset, custom zones/rules, or auto-discovered feature zones)
|
|
1618
1637
|
// Presets: "layered", "hexagonal", "feature-sliced", "bulletproof"
|
|
1638
|
+
// Rules accept an optional `allowTypeOnly: [zones]` list that admits type-only imports
|
|
1639
|
+
// (`import type`, inline `{ type Foo }`, namespace type imports, and `export type` re-exports)
|
|
1640
|
+
// to the listed zones even when not present in `allow`. Mixed-specifier imports still fire.
|
|
1619
1641
|
"boundaries": {
|
|
1620
1642
|
"preset": "bulletproof"
|
|
1643
|
+
// Or:
|
|
1644
|
+
// "zones": [
|
|
1645
|
+
// { "name": "app", "patterns": ["src/app/**"] },
|
|
1646
|
+
// { "name": "features", "patterns": ["src/features/**"], "autoDiscover": ["src/features"] },
|
|
1647
|
+
// { "name": "shared", "patterns": ["src/shared/**"] }
|
|
1648
|
+
// ],
|
|
1649
|
+
// "rules": [
|
|
1650
|
+
// { "from": "app", "allow": ["features", "shared"] },
|
|
1651
|
+
// { "from": "features", "allow": ["shared"], "allowTypeOnly": ["features"] }
|
|
1652
|
+
// ]
|
|
1621
1653
|
},
|
|
1622
1654
|
|
|
1623
1655
|
// Production mode
|