Local only
Add .deadpath/ to .gitignore (the default in this repo). Each developer and agent builds their own cache.
.deadpath/memory.json lives next to the scanned root and makes every following iteration cheaper — in parse time, in model calls, and in the tokens your agent has to read.
Tokens per deadpath.scan packet, bundled fixture (≈4 chars/token)
MCP deadpath.scan returns full evidence only for new findings. Known findings come back as one-liners (id · severity · confidence); profile and memory summaries shrink to essentials.
After deadpath.remember with keep or false_positive, only a suppressed id list remains.
Model verdicts are cached by evidence digest. A repeat session pays zero model tokens for unchanged findings.
Steps carry read and grep targets so the agent does bounded reads instead of crawling.
| Section | Contents | Effect |
|---|---|---|
files | Per file: SHA-256 of content and extracted facts (exports, imports/references, decorators, bases, string literals, tokens). Never the source itself. | Unchanged files are not re-parsed, in any language. cache_hits / cache_misses are reported on every run. |
findings | Per finding id: first_seen, last_seen, seen_count, last confidence, status open/resolved. | Delta per run: new, persisting, resolved. stable_across_runs nudges confidence. |
decisions | Per finding id: keep | false_positive | resolved, note, timestamp. | keep and false_positive suppress the finding from output and the plan. Auto-flipped to resolved when the finding disappears. |
llm | Per finding id: counsel verdict, reason, model, evidence digest, timestamp. | Veto-only on remove then verify. Asked at most once per evidence state. Heuristic verdicts are upgraded when a key becomes available. |
runs | Last 50 runs: totals, delta counts, cache stats. | Trend line for the team; ratchet evidence in CI. |
profile | Last detected language/framework profile. | Lets an agent answer "what kind of repo is this" without a re-scan. |
# first session: 3 findings, full evidence
$ deadpath scan . --format json --compact | jq .delta.counts
{ "new": 3, "persisting": 0, "resolved": 0, "suppressed": 0 }
# workflow runs heuristic counsel on remove+verify (LLM if a key is set) and caches verdicts
$ deadpath workflow . --format json | jq .llm
{ "enabled": false, "called": false, "asked": 0, "cached": 0, "heuristic": 4, "skipped_keep": 1, "skipped_note": 0, ... }
# agent decides one finding is intentional public API
$ deadpath remember unused_export:pkg/exports.py:dead_symbol --decision keep --note "plugin API"
# next session: nothing new, one-liners only, one suppressed, verdict served from cache
$ deadpath scan . --format json --compact | jq '.delta.counts, .tokens_saved_estimate'
{ "new": 0, "persisting": 2, "resolved": 0, "suppressed": 1 }
269
deadpath memory [PATH] # summary + decisions
deadpath memory [PATH] --clear # delete .deadpath/memory.json
deadpath memory [PATH] --forget FINDING_ID # drop one decision
deadpath remember FINDING_ID --decision keep|false_positive|resolved [--note ...] [--path PATH]
deadpath scan --no-memory # stateless run
deadpath scan --only-new # CI ratchet: fail only on new block findings
MCP: deadpath.memory { path?, clear? }
MCP: deadpath.remember { id, decision, note?, path? }
MCP: deadpath.scan { only_new?, full?, memory? }
MCP: deadpath.triage { max_items?, llm? }
Add .deadpath/ to .gitignore (the default in this repo). Each developer and agent builds their own cache.
Commit .deadpath/memory.json. CI runs deadpath scan --only-new; decisions with notes become the audit trail; triage verdicts are shared, so the team pays for each model call once.
Set DEADPATH_MEMORY_DIR to keep memory outside the repository, e.g. in a CI cache.
Memory never contains source code or secrets: only hashes, symbol names, paths, tokens, and your notes. Deleting the file is always safe; the next scan rebuilds it. A leftover .unreach/ directory from the previous package name is renamed to .deadpath/ automatically.