Skip to main content
A unified pipeline at scripts/deadcode/ that wraps Fallow and adds detectors for routes, Edge Functions, feature flags, and i18n. Replaces the bespoke audit-unused-* scripts.

Commands

What it detects

Classification

Every issue is labeled auto-drop | review | keep per the spec at docs/superpowers/specs/2026-05-23-dead-code-cleanup-design.md. Auto-drop requires:
  • No spec with a LAUNCH_READY or PROTECTING signal (see Spec↔code linkage below) governs the file/symbol
  • Detector marks the surface dead
  • Age ≥ 6 months (or 3 months for flags). Age is computed from the most recent commit that is neither format-only nor a bulk reconcile/merge/sync commit, so a repo-wide reconcile does not reset every file’s age to ~0.
  • Not in a regulated core (CL/PM/HR/RH/GR/FA)
  • Not in .deadcode-allowlist.json
  • Not structurally-protected (auto-generated files, migrations, spec templates)
Barrel reclassification: a re-export index.ts flagged unused-file is reclassified to keep (barrel re-exports live modules — not actionable) when it fronts ≥1 live module — i.e. a re-export target that is not itself in the run’s unused-file set (consumers just import the sub-modules by direct path, not the barrel). A barrel whose every target is also unused stays flagged (it’s a genuinely-dead cluster). See scripts/deadcode/barrel.ts. Everything else falls to review (human triage) or keep (protected). Page-less features: finished components/hooks for LAUNCH_READY specs that the report shows unwired can’t be wired mechanically (no host page exists) — they’re collected into docs/development/PAGELESS_FEATURE_BACKLOG.md via npm run deadcode:pageless as product-prioritized feature work, not deadcode noise.

Spec↔code linkage

The triage engine (scripts/deadcode/triage.ts) uses a spec signal to determine whether a file is protected by a governing specification. The signal is derived from whichever frontmatter key is present — status: or pipeline_status: — mapped as follows: LAUNCH_READY items produce WIRE_DIRECT triage; PROTECTING (or PHI-flagged) items produce WIRE_FLAG; NONE allows DELETE/DEFER.

affected_files — declaring code ownership

A spec declares the code it governs via the affected_files frontmatter array of path globs, e.g.:
Globs are matched with minimatch by governingSpecsForPath(idx, path) in scripts/deadcode/spec-index.ts. Any file matched by a spec with a LAUNCH_READY or PROTECTING signal is protected from auto-drop.

Extending coverage for a core

High-confidence matches are applied automatically; lower-confidence suggestions remain in the worksheet for manual review.

Allowlist

Add entries to .deadcode-allowlist.json to protect a file from auto-drop:
path can be exact or a glob. reason and spec_ref are required.

Feature-flag registry snapshot

The flags detector cross-references in-repo call sites against the pf_feature_flags table. In v1, supply a JSON snapshot at .deadcode-cache/feature-flags-registry.json (array of flag-key strings). A future task will automate the snapshot via a CI step or admin tool export.

CI behavior

.github/workflows/deadcode.yml runs deadcode:ci on every PR to development / main, fails on regression vs the baseline total, uploads the full report as an artifact, and posts an excerpt as a PR comment.

Regression baseline (.deadcode-baseline.json)

deadcode:ci fails when the orchestrator’s total issue count exceeds totalIssues in .deadcode-baseline.json. This is the orchestrator’s own gate, distinct from Fallow’s .fallow-baseline.json (which gates the fallow tool itself). Refresh .deadcode-baseline.json — and re-run npm run deadcode — only when intentionally accepting new findings.

Cache

The orchestrator caches under .deadcode-cache/ (gitignored). Invalidated automatically when input files change. Delete the directory to force a full rebuild.

Adding a new detector

  1. Create scripts/deadcode/detectors/<name>.ts exporting a Detector (matches { name, run(ctx) }).
  2. Add it to the detectors: array in scripts/deadcode/run.ts.
  3. Write unit tests at tests/unit/deadcode/detectors/<name>.test.ts.
  4. Update this doc.

Migrating from the old scripts

The retired scripts and their replacements: