How the dead code agent works
Learn about call graphs, dead paths, confidence scoring, and the pull request pipeline.
Call graph construction
YAGNI creates a complete interprocedural call graph from your source using several static analysis techniques:
- Import resolution: follows all import and require statements to map module dependencies
- Function call extraction: identifies every direct call site, including method chains
- Type-flow analysis: follows constructor patterns, class instantiation, and interface implementations
- Dynamic dispatch estimation: flags calls through interfaces and reflection as uncertain
The graph connects every function and module to the callers able to reach it from any entry point, including HTTP handlers, CLI commands, cron jobs, event listeners, and queue consumers.
Dead path detection
A path qualifies as dead only when both criteria are met:
- No reachable caller exists in the static call graph starting from any known entry point
- No runtime trace data shows the path being exercised (when runtime traces are available)
Paths failing only the static criterion but passing the runtime criterion go to review, not automatic removal, handling dynamic dispatch that static analysis cannot fully resolve.
Confidence scoring
Each detected dead path gets a confidence score from 0 to 100. Scores above 85 create automated pull requests, while scores from 60-85 appear in the dashboard as manual review candidates.
| Score range | Signal | Action |
|---|---|---|
| 85 to 100 | No callers, no runtime hits, no dynamic dispatch | Automated PR opened |
| 60 to 84 | No callers, runtime inconclusive or absent | Surfaced in dashboard for manual review |
| 40 to 59 | No callers, some dynamic dispatch detected | Flagged with caution label, awaits team decision |
| Below 40 | Ambiguous caller chain or reflection-heavy path | Logged only, no action taken |
PR pipeline
When a dead path exceeds the automated threshold, YAGNI:
- Removes the dead modules from a working copy of your branch
- Runs your configured test command in an isolated container
- If tests pass: opens a pull request against your target branch with a summary of what was removed and why
- If tests fail: logs the failure and defers the removal until the next analysis cycle
.yagniignore
Add a .yagniignore file at the repository root to omit paths from analysis. It follows .gitignore-style syntax:
# Vendor code
vendor/
node_modules/
# Deprecated but stable APIs
src/api/v1/legacy/
# Migration helpers
scripts/migrations/
# Test fixtures
__fixtures__/
Entries in .yagniignore stay out of the call graph entirely. They will not appear in dead path reports or qualify for automated removal.