Counsel first
Judge remove (usually scan block) is the highest blast radius. The model may confirm, escalate to verify, or overturn to keep. It cannot invent files.
deadpath workflow / MCP deadpath.workflow turns findings into an ordered checklist shaped by the repository's languages, frameworks and history. The first verify step is the judge's next check — the one artifact that would settle a hidden live path. It is data an agent executes, not prose it interprets. The model, if a key is set, is counsel for the defense over that packet — never a second scanner.
Targeted grep and bounded reads. Never "read the repo".
Propose a reviewable patch. Deletion is proposed, never performed.
Compiler, type checker, tests for the detected stack; then re-scan.
Record keep / false_positive / resolved so the next session starts warm.
Putting a model in the graph or the judge looks like “more reasoning.” Buyers who have been burned by AI dead-code tools will not buy it:
block without a network round-trip or a model version bump.file:line evidence.Stage four is where a model does add value: reading the judge's packet and trying to save code that is about to be proposed for deletion. Skipping block/remove used to look cheaper. That was the wrong safety story — those are the deletions that hurt if the regex judge missed a Temporal workflow or a house-style entry.
Most "AI dead-code" tools stream the whole finding list — or the whole repository — through a model. Deadpath inverts that. The deterministic engine builds the case file; the model is a veto-only second devil's advocate over that file, asked once, remembered.
Judge remove (usually scan block) is the highest blast radius. The model may confirm, escalate to verify, or overturn to keep. It cannot invent files.
Ambiguous findings go in the same call, at most 8 per run, as compact packets: id · kind · path · symbol · confidence · signals · why · judge. No file bodies. The model cannot upgrade these to likely_dead.
keep already has file:line evidence. note is too thin for a model to add anything but confabulation. Both stay in the report for humans.
Cached by evidence digest. Every verdict is stored in .deadpath/memory.json under a hash of the finding's path, symbol, signals, confidence and judge verdict. If nothing about the evidence changed, the model is not asked again — across sessions, agents and machines that share the memory file.
Offline identical. Without DEADPATH_API_KEY, triage returns deterministic heuristic verdicts from the same signals (framework/entry signal → keep; string/dynamic signal → verify; clean graph → likely_dead). Workflows have the same shape either way.
| Verdict | Ordering | Budget hint given to the agent |
|---|---|---|
likely_dead | First (confirmed remove, after security_first) | "A single grep is enough; skip reading the file unless the grep hits." |
verify | After likely_dead | "Read the grep hits, not the whole file." |
keep | Removed from selected_findings, listed in kept_by_triage | "Skip these; record them with deadpath.remember if you agree." |
| Detected | Workflow changes |
|---|---|
| Python | Import-check touched packages with python -c "import pkg"; run pytest; run mypy/pyright if configured in pyproject.toml. |
| Python + framework (Django, Flask, FastAPI, Celery, SQLAlchemy, Click, Airflow, pytest) | Adds verify steps for framework wiring (INSTALLED_APPS, router includes, autodiscover, entry points) and decorator registration. |
| TypeScript / JavaScript | Reads package.json main/exports/bin and tsconfig.json; runs npx tsc --noEmit when TypeScript is a dependency; runs vitest or jest if present. |
| Go · Rust · Java · Kotlin · Scala · C# · Ruby · PHP · Swift · Dart · Elixir · C/C++ · Lua · Perl | Adds a verify step to check build wiring and DI/reflection registration, and language-specific validation: go build ./... && go test ./..., cargo check && cargo test, ./gradlew test, dotnet build, bundle exec rspec, phpunit, swift test, flutter test, mix test, ctest, busted, prove… |
| Monorepo | profile.monorepo: true so the agent scopes verification to the workspace and checks cross-package imports. |
| Memory has previous runs | New findings first. The context step states how many findings were already triaged so the agent does not re-read them. |
{
"auto_delete": false,
"profile": { "primary": "py", "frameworks": ["fastapi", "pytest"], "monorepo": false, ... },
"policy": { "block_threshold": 0.85, "warn_threshold": 0.55,
"delete_requires": "explicit user approval after validation steps pass" },
"llm": { "policy": "model is a veto-only counsel on judge remove (first) and verify/warn packets; cannot strengthen verify to likely_dead; keep and note are never sent; verdicts cached by evidence digest; never file bodies",
"enabled": true, "called": true, "asked": 4, "cached": 0, "heuristic": 0, "skipped_keep": 1, "skipped_note": 0, "reviewed_remove": 3, "reviewed_verify": 1 },
"selected_findings": ["orphan_file:pkg/orphan.py", "unused_export:pkg/exports.py:dead_symbol", "unused_export:pkg/hooks.py:maybe_dead"],
"kept_by_triage": [],
"steps": [
{ "id": "ctx-01", "phase": "verify", "action": "Read only the files named in this workflow...", "budget_hint": "First run for this repository; all findings are new." },
{ "id": "verify-02", "phase": "verify", "finding_id": "orphan_file:pkg/orphan.py", "grep": "pkg.orphan", "read": ["pkg/orphan.py"] },
{ "id": "verify-06", "phase": "verify", "finding_id": "unused_export:pkg/hooks.py:maybe_dead", "grep": "maybe_dead",
"triage": "verify: module imported whole; grep attribute access before acting",
"budget_hint": "Triage flagged a dynamic/string reference: read the grep hits, not the whole file." },
{ "id": "edit-03", "phase": "edit", "finding_id": "orphan_file:pkg/orphan.py", "action": "If verified: propose deleting ... Do not delete without user approval." },
{ "id": "validate-08","phase": "validate", "command": "python -c \"import pkg\"" },
{ "id": "validate-09","phase": "validate", "command": "pytest -q" },
{ "id": "validate-10","phase": "validate", "tool": "deadpath.scan" },
{ "id": "mem-11", "phase": "remember", "tool": "deadpath.remember" }
]
}
deadpath workflow [PATH] [--format json|md|table] [--max 12] [--no-triage] [--no-llm]
deadpath triage [PATH] [--format json|md|table] [--max-items 8] [--no-llm]
deadpath judge [PATH] [--format table|md|json]