fallow 2.95.0 → 2.97.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.
@@ -61,6 +61,13 @@ Common global flags for this command: [`--format`](#global-flags), [`--quiet`](#
61
61
  | `--private-type-leaks` | Opt-in API hygiene check (default `off`) for exported signatures that reference same-file private types. Storybook `*.stories.*` story files and framework routing convention files (Next.js App + Pages Router, Gatsby, Remix v2, TanStack Router, Expo Router) are skipped to avoid noise. Enable via this flag or `private-type-leaks: "warn"` / `"error"` in [`rules`](#rules-configuration). |
62
62
  | `--unused-enum-members` | Unused enum members |
63
63
  | `--unused-class-members` | Unused class members |
64
+ | `--unused-store-members` | Unused Pinia store members |
65
+ | `--unprovided-injects` | inject() / getContext() reads a key that no provide() / setContext() supplies |
66
+ | `--unrendered-components` | A Vue / Svelte component is reachable through a barrel but rendered nowhere |
67
+ | `--unused-component-props` | A Vue defineProps prop or React component prop is referenced nowhere in its own component |
68
+ | `--unused-component-emits` | A Vue <script setup> defineEmits event is emitted nowhere in its own component |
69
+ | `--unused-server-actions` | A Next.js Server Action exported from a "use server" file is referenced by no code in the project |
70
+ | `--unused-load-data-keys` | A SvelteKit load() return-object key is read by no consumer |
64
71
  | `--unresolved-imports` | Unresolved imports |
65
72
  | `--unlisted-deps` | Unlisted dependencies |
66
73
  | `--duplicate-exports` | Duplicate exports |
@@ -146,7 +153,8 @@ By default, `fallow dupes` skips generated framework output matching `**/.next/*
146
153
  | `--threshold` | `string` | - | Fail if duplication exceeds this percentage |
147
154
  | `--skip-local` | `bool` | `false` | Only report cross-directory duplicates |
148
155
  | `--cross-language` | `bool` | `false` | Strip type annotations for TS↔JS matching |
149
- | `--ignore-imports` | `bool` | `false` | Exclude import declarations from clone detection |
156
+ | `--ignore-imports` | `bool` | `false` | Exclude module wiring from clone detection |
157
+ | `--no-ignore-imports` | `bool` | `false` | Count module wiring as clone candidates (opt out of the default exclusion) |
150
158
  | `--top` | `string` | - | Show only the N most-duplicated clone groups (sorted by instance count desc, tiebreak: line count desc, then path/line). Summary stats reflect the full project. |
151
159
  | `--trace` | `string` | - | Deep-dive clones. `FILE:LINE` traces all clones at a location; `dup:<id>` traces a clone group by the stable fingerprint shown in the listing and on `clone_groups[].fingerprint` in JSON. Fingerprints are usually `dup:<8hex>` and widen only on rare report collisions. Trace output adds an extract-function suggestion, estimated savings, and a best-effort proposed name per group |
152
160
 
@@ -383,6 +391,7 @@ Angular templates contribute synthetic `<template>` complexity findings whenever
383
391
  | `--ownership` | `bool` | `false` | Attach ownership signals to hotspot entries: bus factor (Avelino truck factor), contributor count, top contributor with stale-days, recent contributors (top-3), `suggested_reviewers`, declared CODEOWNERS owner, `ownership_state`, ownership drift, unowned-hotspot detection. Human output gains a project-level summary line. JSON adds `low-bus-factor`, `unowned-hotspot`, `ownership-drift` action types. Test files get a `[test]` tag. Implies `--hotspots`. Requires git. |
384
392
  | `--ownership-emails` | `raw\|handle\|anonymized\|hash` | - | Privacy mode for author emails. `handle` shows the local-part only (default, with GitHub noreply unwrap and deterministic same-handle disambiguation). `anonymized` emits stable `xxh3:` pseudonyms; `hash` remains accepted as the legacy spelling. `raw` shows full addresses. Use `anonymized` in regulated environments. Implies `--ownership`. Configure default via `health.ownership.emailMode`. |
385
393
  | `--targets` | `bool` | `false` | Show only refactoring targets: ranked recommendations based on complexity, coupling, churn, and dead code signals. Categories: churn+complexity, circular dep, high impact, dead code, complexity, coupling. When no section flags are set, all sections are shown by default. Each target's JSON can include `direct_callers[]` (direct importers with the symbols they import) and `clone_siblings[]` (duplicate-code siblings with stable `dup:<8hex>` fingerprints for `fallow dupes --trace`); both omitted when empty. Human output adds `importers:` / `clones:` lines only when that evidence is present. |
394
+ | `--css` | `bool` | `false` | Add structural CSS analytics: specificity hotspots, !important density, over-complex selectors, deep nesting, and conservative cleanup candidates. Standard CSS is parsed structurally; preprocessor sources are scanned only where fallow can avoid expanding Sass/Less semantics. |
386
395
  | `--effort` | `low\|medium\|high` | - | Filter refactoring targets by effort level. Implies `--targets`. |
387
396
  | `--score` | `bool` | `false` | Show only the project health score (0-100) with letter grade (A/B/C/D/F). The score is included by default when no section flags are set. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown. As of v2.55.0, plain `--score` skips the churn-backed hotspot penalty so it does not run a `git log` shell-out per invocation; pass `--hotspots` (or `--targets` with `--score`) to include the hotspot penalty. Snapshot (`--save-snapshot`) and trend (`--trend`) flows still trigger hotspot vital signs so saved data stays complete. |
388
397
  | `--min-score` | `string` | - | Fail (exit 1) only when the health score is below this threshold. Implies `--score`. Authoritative CI quality gate: when set, complexity findings are demoted to informational and the exit code is driven solely by the score, so `--min-score 0` always exits 0. Composes with `--min-severity`. |
@@ -492,7 +501,7 @@ fallow health --format json --quiet --trend
492
501
  {
493
502
  "kind": "health",
494
503
  "schema_version": 7,
495
- "version": "2.95.0",
504
+ "version": "2.97.0",
496
505
  "elapsed_ms": 32,
497
506
  "summary": {
498
507
  "files_analyzed": 482,
@@ -879,7 +888,7 @@ fallow audit \
879
888
  {
880
889
  "kind": "audit",
881
890
  "schema_version": 7,
882
- "version": "2.95.0",
891
+ "version": "2.97.0",
883
892
  "command": "audit",
884
893
  "verdict": "fail",
885
894
  "changed_files_count": 12,
@@ -954,7 +963,7 @@ fallow flags --format json --quiet --workspace my-package
954
963
  ```json
955
964
  {
956
965
  "schema_version": 7,
957
- "version": "2.95.0",
966
+ "version": "2.97.0",
958
967
  "elapsed_ms": 116,
959
968
  "feature_flags": [],
960
969
  "total_flags": 0
@@ -1054,7 +1063,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1054
1063
  {
1055
1064
  "kind": "security",
1056
1065
  "schema_version": "4",
1057
- "version": "2.95.0",
1066
+ "version": "2.97.0",
1058
1067
  "elapsed_ms": 42,
1059
1068
  "config": {
1060
1069
  "rules": {
@@ -1083,7 +1092,7 @@ fallow security --gate newly-reachable --changed-since origin/main
1083
1092
  {
1084
1093
  "kind": "security",
1085
1094
  "schema_version": "4",
1086
- "version": "2.95.0",
1095
+ "version": "2.97.0",
1087
1096
  "elapsed_ms": 42,
1088
1097
  "config": {
1089
1098
  "rules": {
@@ -1544,7 +1553,8 @@ Available on all commands:
1544
1553
  | `--dupes-min-occurrences` | `string` | - | Override the minimum clone occurrences in combined mode (must be >= 2) |
1545
1554
  | `--dupes-skip-local` | `bool` | `false` | Only report cross-directory duplicates in combined mode |
1546
1555
  | `--dupes-cross-language` | `bool` | `false` | Enable cross-language duplicate detection in combined mode |
1547
- | `--dupes-ignore-imports` | `bool` | `false` | Exclude import declarations from duplicate detection in combined mode |
1556
+ | `--dupes-ignore-imports` | `bool` | `false` | Exclude module wiring from duplicate detection in combined mode |
1557
+ | `--dupes-no-ignore-imports` | `bool` | `false` | Count module wiring as clone candidates in combined mode (opt out of the default exclusion) |
1548
1558
  | `--score` | `bool` | `false` | Compute health score (0-100 with letter grade) in combined mode. Enables the health delta header in PR comments. JSON includes `health_score` object with `score`, `grade`, and `penalties` breakdown |
1549
1559
  | `--trend` | `bool` | `false` | Compare current health metrics against saved snapshot. Implies `--score`. Shows per-metric deltas with directional indicators. Requires at least one saved snapshot in `.fallow/snapshots/` |
1550
1560
  | `--save-snapshot` | `string` | - | Save vital signs snapshot for trend tracking. Default path: `.fallow/snapshots/<timestamp>.json`. Forces file-scores + hotspot computation |
@@ -1572,7 +1582,7 @@ Available on all commands:
1572
1582
  | `--dupes-min-occurrences` | `string` | - | Override the minimum clone occurrences in combined mode (must be >= 2) |
1573
1583
  | `--dupes-skip-local` | `bool` | `false` | Only report cross-directory duplicates in combined mode |
1574
1584
  | `--dupes-cross-language` | `bool` | `false` | Enable cross-language duplicate detection in combined mode |
1575
- | `--dupes-ignore-imports` | `bool` | `false` | Exclude import declarations from duplicate detection in combined mode |
1585
+ | `--dupes-ignore-imports` | `bool` | `false` | Exclude module wiring from duplicate detection in combined mode |
1576
1586
  | `--score` | `bool` | `false` | Compute health score in combined mode |
1577
1587
  | `--trend` | `bool` | `false` | Compare current health metrics against the most recent saved snapshot |
1578
1588
  | `--save-snapshot` | `string` | - | Save a vital signs snapshot for trend tracking in combined mode. Provide a path or omit for the default `.fallow/snapshots/` location |
@@ -1699,7 +1709,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
1699
1709
  {
1700
1710
  "kind": "dead-code",
1701
1711
  "schema_version": 7,
1702
- "version": "2.95.0",
1712
+ "version": "2.97.0",
1703
1713
  "elapsed_ms": 45,
1704
1714
  "total_issues": 12,
1705
1715
  "entry_points": {
@@ -1859,7 +1869,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
1859
1869
  {
1860
1870
  "kind": "dupes",
1861
1871
  "schema_version": 7,
1862
- "version": "2.95.0",
1872
+ "version": "2.97.0",
1863
1873
  "elapsed_ms": 82,
1864
1874
  "total_clones": 15,
1865
1875
  "total_lines_duplicated": 230,
@@ -1903,11 +1913,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
1903
1913
  {
1904
1914
  "kind": "combined",
1905
1915
  "schema_version": 7,
1906
- "version": "2.95.0",
1916
+ "version": "2.97.0",
1907
1917
  "elapsed_ms": 159,
1908
1918
  "check": {
1909
1919
  "schema_version": 7,
1910
- "version": "2.95.0",
1920
+ "version": "2.97.0",
1911
1921
  "elapsed_ms": 45,
1912
1922
  "total_issues": 12,
1913
1923
  "unused_files": [],
@@ -2129,4 +2139,4 @@ preset = "bulletproof"
2129
2139
 
2130
2140
  ### Valid Issue Type Tokens
2131
2141
 
2132
- `unused-file`, `unused-export`, `unused-type`, `unused-dependency`, `unused-dev-dependency`, `unused-enum-member`, `unused-class-member`, `unresolved-import`, `unlisted-dependency`, `duplicate-export`, `circular-dependency`, `re-export-cycle`, `boundary-violation`, `policy-violation`, `unused-optional-dependency`, `type-only-dependency`, `test-only-dependency`, `code-duplication`
2142
+ `unused-file`, `unused-export`, `unused-type`, `unused-dependency`, `unused-dev-dependency`, `unused-enum-member`, `unused-class-member`, `unused-store-member`, `unresolved-import`, `unlisted-dependency`, `duplicate-export`, `circular-dependency`, `re-export-cycle`, `boundary-violation`, `policy-violation`, `unused-optional-dependency`, `type-only-dependency`, `test-only-dependency`, `code-duplication`
@@ -462,6 +462,18 @@ Fallow marks `src/fragments/user-fields.graphql` or `src/fragments/user-fields.g
462
462
 
463
463
  ---
464
464
 
465
+ ## Tailwind v4 `@theme` Tokens Are Conservative Cleanup Candidates
466
+
467
+ When `fallow health --css` reports `css_analytics.unused_theme_tokens`, treat the rows as dead-design-token candidates, not as auto-fix instructions. A Tailwind v4 `@theme` token such as `--color-brand` is considered used when fallow sees a generated utility suffix such as `bg-brand` or `text-brand`, a `var(--color-brand)` read, an `@apply` utility, a Tailwind arbitrary value such as `rounded-[--radius-card]`, or another `@theme` token that references it.
468
+
469
+ The detector intentionally abstains when a Tailwind plugin or published CSS surface could consume tokens invisibly. Always run the row's `actions[].command` verification before deleting a token, and do not run `fallow fix` for these rows.
470
+
471
+ ## CSS Health Candidates Are Advisory
472
+
473
+ `fallow health --css` also emits advisory cleanup and typo candidates in `css_analytics.unreferenced_css_classes` (a plain-CSS class defined but matched by no `class`/`className` in project markup), `css_analytics.unresolved_class_references` (the reverse: a markup class one edit away from a defined class, a likely typo), `css_analytics.unused_font_faces`, `css_analytics.undefined_keyframes`, and `css_analytics.font_size_unit_mix`. Treat them like review prompts, not confirmed defects. Run each row's `actions[].command` before changing CSS, because fonts, classes, animations, and type scales can be driven by inline styles, JavaScript, CMS templates, or preprocessor expansion that static analysis intentionally does not execute.
474
+
475
+ ---
476
+
465
477
  ## Library Packages: Use `publicPackages` Instead of Visibility Tags
466
478
 
467
479
  In monorepos, shared library packages have exported APIs consumed by external consumers not visible to fallow. Instead of annotating every export with `/** @public */` (or `@internal`, `@beta`, `@alpha`), use the `publicPackages` config to mark entire workspace packages as public libraries. Exports and exported enum/class members from these packages are excluded from unused API detection.