.fallowrc.json (validated against official docs)
Note (script rename): the raw-fallowcheck:dead-code*npm scripts referenced below were removed and superseded by the unified orchestrator — usenpm run deadcode(andnpm run deadcode:cifor the CI gate). The Fallow flags/config described here are unchanged; only the npm entry points were consolidated.
Canonical accuracy mode: production
As of 2026-05-08 the canonical accuracy gate is production mode (fallow dead-code --production). This excludes test/story/dev files so “used by tests only” code is correctly flagged. Dev-inclusive runs remain available as check:dead-code:dev for investigating false-positive routes through test fixtures.
Production-mode baseline (2026-05-08)
Stored in:
regression.baselineinside.fallowrc.json(used by--fail-on-regression).fallow-baseline.json(snapshot used by--baselinefor added/removed/unchanged diffs).fallow-baseline.dev.legacy.json— prior dev-mode snapshot, retained for historical reference
Script wiring
npm run check:dead-code→fallow dead-code --production(default audit)npm run check:dead-code:dev→ dev-inclusive (test files count as consumers)npm run check:dead-code:baseline→ production-mode compact diff vs snapshot baselinenpm run check:dead-code:regression→ JSON-parsed gate; exit 0 only whenregression.exceeded == falsenpm run check:dead-code:ci→ alias for:regression
Why two baselines?
Barrel-noise / Public-API suppression policy
Mass-suppressing barrel re-exports hides genuine debt and is therefore forbidden. The policy below governs when and how to mark exports as intentionally retained.Default position
Unused exports are debt. The default action for aunused-export finding is to delete the export (or its source file) after consumer verification. Do not add suppression comments or ignoreExports entries to silence a finding you don’t intend to fix.
When suppression is justified
Suppression is allowed only for exports that are part of a documented public API contract (perdocs/architecture/integrations/PLATFORM_INTEGRATION_LAYERS.md) and that exist intentionally to be consumed externally — even when no current consumer exists.
Currently suppressed surfaces (forward-protection only)
The following barrels carry zero unused-export findings today, are documented as Platform Integration Layer public contracts, and are pre-marked to prevent future regressions from being masked behind “we’ll consume it later”:src/platform/types/index.ts— sharedEncounterContext,ChargeContext,DiagnosisReferencetypes (cross-core)src/platform/csv/index.ts— shared CSV parsing primitives for bulk importssrc/platform/scheduling/index.ts— encounter/appointment context (CL-04, CL-14, CL-24)src/platform/email-signatures/index.ts— PF-86 org/user signature servicesrc/platform/quota/index.ts— PF-43 tenant resource quotas
- The barrel must be listed in
docs/architecture/integrations/PLATFORM_INTEGRATION_LAYERS.mdwith a status of✅ Complete. - The barrel must currently have zero unused-export findings (otherwise pre-existing debt would be masked).
- The PR adding it must call out the rationale and link to the layer’s documentation.
How to expand the suppression set responsibly
If a documented PIL barrel currently has unused exports (e.g.@/platform/forms, @/platform/telephony, @/platform/gestures), do not add it to ignoreExports wholesale. Instead:
- Triage each unused export: is it documented in the layer’s README/integration doc?
- If yes → annotate with
/** @expected-unused */+ a one-line note pointing to the doc. - If no → delete the export.
ignoreExports forward-protection list above.
Why unused-types is off
Type aliases and interfaces are frequently re-exported as part of API contracts and are erased at runtime. Tracking them per export creates noise without bundle-impact value. The unused-types rule remains off and should not be re-enabled without a separate proposal.
Current production findings (2026-05-08)
This plan is based on the production-mode run (fallow dead-code --production --format json --quiet) revalidated on 2026-05-08 and triaged in reports/active/fallow-production-baseline-triage-2026-05-08.md.
False-positive patterns to verify before deletion
Before removing any file, confirm it is not:- A
React.lazy()target — route files commonly uselazy(() => import('@/cores/.../PageName')). - A barrel re-export target — files re-exported from
src/cores/*/index.tsandsrc/platform/**/index.ts. - A Supabase Edge Function entry/shared module — keep
supabase/functions/*/index.tsand validate non-_sharedhelpers. - A fixture/mock/factory — especially under
tests/mocks/**,tests/e2e/fixtures/**, andtests/utils/mock-factories.ts. - A script invoked by npm or CI — verify
package.jsonscripts and workflow usage. - A runtime dynamic asset — service worker (
public/sw-push.js) and chatbot embed assets.
Phased remediation timeline
Phase 1: Dependencies (lowest risk)
Goal: Resolve the 5 dependency findings first (fastest low-risk reduction).1a) Unused dependencies (3)
1b) Type-only dependencies (2)
Phase 1 exit criteria:
unusedDependencies: 0 and typeOnlyDependencies: 0 in .fallowrc.json regression.baseline.
Verification
Phase 2: Circular dependencies (single high-leverage fix)
Goal: Eliminate all 20 cycles with one import-path change. All 20 cycles follow this path: Fix insrc/platform/table-v2/index.ts:
circularDependencies: 0.
Verification
Phase 3: Duplicate exports (37 pairs)
Goal: Consolidate duplicate symbols into a single canonical source per concept.Pattern A: type duplicated between consumer and type barrel
Pattern B: same concept defined across multiple type files
Pattern C: utility exports duplicated across modules
Phase 3 exit criteria:
duplicateExports: 0.
Verification
Phase 4: Long-tail cleanup (unused exports + unused files)
Goal: Burn down the largest barrel-heavy export noise first, then trim true unused files in small verified batches.4a) Top unused-export concentrations (production mode)
Use the suppression policy above: only keep truly documented public API exports (
@expected-unused or qualified ignoreExports), delete the rest.
4b) Unused files by highest-volume module (production mode, 663 total)
Batch workflow
- Select one module or barrel.
- Classify each item as remove, investigate, or keep.
- Apply small batches (10-20 files or one barrel at a time).
- Re-run verification and baseline update.
unusedFiles <= 200, unusedExports <= 800.
Config changes made
The.fallowrc.json was updated during this audit with the following improvements:
- Added explicit entry points:
src/routes/**/lazy-pages.tsandsrc/main.tsx. - Added Deno
npm:*/jsr:*specifiers toignoreDependenciesfor Supabase function imports. - Added
ignoreExportsUsedInFile: trueto reduce same-file export noise. - Expanded rule severities (
unused-dependencies,duplicate-exports,circular-dependencies,boundary-violation,stale-suppressions, etc.).
CI promotion path
Current state:.github/workflows/build.yml runs npm run check:dead-code:ci in non-blocking-analysis with continue-on-error: true.
- After Phase 1 + Phase 2 land (deps/type-only clean, cycles eliminated), make dead-code regression blocking by removing
continue-on-error: truefrom the dead-code step. - After Phase 3 duplicate-export consolidation, remove
continue-on-errorfrom thenon-blocking-analysisjob and enforce dead-code gating in CI.
Re-baseline workflow (after each phase)
.fallow-baseline.dev.legacy.json remains historical reference only (gitignored).
References
- Fallow documentation
- Fallow configuration overview
- Fallow adoption guide
- Dead code analysis explanation
- Rules & severity
- Architecture boundaries
- Skill file:
.cursor/skills/dead-code-audit/SKILL.md - Config:
.fallowrc.json