deadwood-scan 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # deadwood-scan
2
+
3
+ [![npm version](https://img.shields.io/npm/v/deadwood-scan)](https://www.npmjs.com/package/deadwood-scan)
4
+
5
+ **Find the code your repo no longer calls — and prove it.** deadwood statically scans a
6
+ JS/TS repo for dead routes, unused exports, unused dependencies and unreachable files,
7
+ attaches **evidence** to every finding, and gives you a safe way to delete it.
8
+
9
+ ```bash
10
+ npx deadwood-scan .
11
+ ```
12
+
13
+ ```
14
+ ☠ 31% of your routes appear dead (9 of 29)
15
+ 7 unused exports · 2 unused dependencies
16
+
17
+ DELETE /api/legacy/export legacy.ts:87 70% │ capped
18
+ ├─ no client path matches this route
19
+ ├─ marked @deprecated
20
+ ├─ last commit touching this file: 14 months ago
21
+ └─ no runtime evidence — connect telemetry
22
+
23
+ export draftCheckout pay.ts:12 50% │ demoted
24
+ └─ modified 3 days ago — likely work in progress
25
+
26
+ → deadwood clean — review & remove these interactively (one revertable commit each)
27
+ ```
28
+
29
+ Zero network calls. Zero telemetry. Nothing leaves your machine.
30
+
31
+ ## Why it's different
32
+
33
+ - **Evidence, not verdicts.** Every finding carries the signals that produced it, with
34
+ signed weights. Anything the analyzer can't resolve _lowers_ confidence instead of
35
+ being ignored — so hidden callers (dynamic imports, string dispatch, cron manifests)
36
+ demote a finding rather than causing a false positive.
37
+ - **It says "appears dead", never "is dead".** Static confidence is hard-capped (70 for
38
+ routes, 85 for the rest). Only runtime evidence lifts the cap.
39
+ - **Your git history is evidence.** Code untouched for a year ranks up; code you touched
40
+ this week is demoted as work-in-progress. Works from your first commit, offline.
41
+
42
+ ## Commands
43
+
44
+ ### Scan
45
+
46
+ ```bash
47
+ deadwood [path] # the shock report
48
+ deadwood --json # machine-readable ScanResult (schemaVersion 1)
49
+ deadwood --md # markdown, for PR comments / Slack
50
+ deadwood --fail-on high # CI gate: exit 1 when tripped
51
+ ```
52
+
53
+ ### `--diff-base <ref>` — the PR delta gate
54
+
55
+ Report only what a change **introduces**, not the whole inventory. This is the loop that
56
+ stops AI-generated orphan code at the door:
57
+
58
+ ```bash
59
+ deadwood --diff-base main # "+2 introduced · −1 resolved"
60
+ deadwood --diff-base origin/main --fail-on medium # CI: you may not ADD dead code
61
+ ```
62
+
63
+ The base ref is scanned in a temporary git worktree; the diff is exact (finding ids are
64
+ stable across scans by design). `--fail-on` then gates the _delta_, not the backlog — so
65
+ a legacy repo can adopt the gate on day one without fixing everything first.
66
+
67
+ ### `deadwood clean` — guided deletion
68
+
69
+ ```bash
70
+ deadwood clean --dry-run # print the plan, touch nothing
71
+ deadwood clean # interactive: [d]elete / [s]kip / [a]ll / [q]uit
72
+ deadwood clean --yes # non-interactive, medium+ confidence
73
+ ```
74
+
75
+ Each accepted removal is applied **and committed on its own**, so `git revert <sha>` is
76
+ always the undo. It only offers removals it can _prove_ (whole unreachable files, unused
77
+ dependencies); routes and exports are listed for manual review, never auto-edited. It
78
+ refuses to run on a dirty working tree.
79
+
80
+ ### `deadwood explain <query>`
81
+
82
+ One finding, fully unpacked — every evidence line with its signed weight and source, the
83
+ confidence arithmetic including the active cap, and what would make the code live.
84
+
85
+ ### `deadwood mcp`
86
+
87
+ A [Model Context Protocol](https://modelcontextprotocol.io) server over stdio, so your
88
+ coding agents (Cursor, Claude Code, Copilot) can consult the dead-code map _before_
89
+ writing or deleting. Tools: `deadwood_scan`, `deadwood_findings`.
90
+
91
+ ```jsonc
92
+ // .cursor/mcp.json or claude_desktop_config.json
93
+ { "mcpServers": { "deadwood": { "command": "npx", "args": ["deadwood-scan", "mcp", "."] } } }
94
+ ```
95
+
96
+ ### `deadwood badge` · `--watch`
97
+
98
+ ```bash
99
+ deadwood badge --output deadwood-badge.svg # self-hosted status SVG (no external service)
100
+ deadwood --watch # re-scan on save: +introduced / −resolved
101
+ ```
102
+
103
+ ## Flags
104
+
105
+ | flag | |
106
+ | -------------------------------------------------------- | --------------------------------------------------------- |
107
+ | `--json` / `--md` | machine-readable / markdown output |
108
+ | `--fail-on <high\|medium\|high:N>` | CI gate (exit 1); with `--diff-base`, gates the delta |
109
+ | `--diff-base <ref>` | report only findings introduced since this git ref |
110
+ | `--watch` | re-scan on save, report the delta per change |
111
+ | `--min-confidence <low\|medium\|high>` | hide findings below this level (never affects the gate) |
112
+ | `--entry <file...>` | extra entry points — the false-positive escape hatch |
113
+ | `--category <…>` · `--workspace <…>` · `--framework <…>` | narrow the scan |
114
+ | `--include` / `--exclude <glob...>` | extra globs |
115
+ | `--no-default-excludes` | also report on `generated/`, `examples/`, fixtures, mocks |
116
+ | `--no-git` | skip git-history evidence |
117
+ | `--no-color` | plain output |
118
+
119
+ **Exit codes:** `0` clean · `1` `--fail-on` gate tripped · `2` scan error.
120
+
121
+ ## Configuration (in-repo, versioned with your code)
122
+
123
+ `deadwood.config.json`:
124
+
125
+ ```json
126
+ {
127
+ "entries": ["scripts/cron-job.ts"],
128
+ "exclude": ["legacy/**"],
129
+ "publicApi": ["src/index.ts"]
130
+ }
131
+ ```
132
+
133
+ `entries` = extra entry points. `exclude` = extra globs. **`publicApi`** = files whose
134
+ exports are your published API surface: external consumers are invisible to static
135
+ analysis, so their unused-export findings are demoted with spare evidence — kept visible,
136
+ never shouted.
137
+
138
+ ```
139
+ # .deadwoodignore (one glob per line, '#' comments)
140
+ vendor/**
141
+ ```
142
+
143
+ ## Evidence signals
144
+
145
+ Findings score as `clamp(0, cap, Σ evidence weights)`:
146
+
147
+ | | |
148
+ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
149
+ | **kill** (raise confidence) | route registered but nothing references its path · marked `@deprecated` · reachable only from tests · file untouched for a year · last author gone 6+ months · introduced once, never revisited |
150
+ | **spare** (lower confidence — a hidden caller may exist) | dynamic import may load this directory · symbol in a string-dispatch table · referenced by a package script, build config or CI/cron manifest · declared public API · **modified in the last 30 days (work in progress)** |
151
+ | **runtime** (lifts the cap — the paid tiers) | dev/staging/e2e traffic seen (→ 90) · production traffic seen, or coverage-guaranteed zero requests in 90 days (→ 100, _confirmed dead_) |
152
+
153
+ ## Beyond the CLI
154
+
155
+ - **GitHub App** — a shock report on every PR, findings that upgrade in place as evidence arrives.
156
+ - **[deadwood-express-probe](https://www.npmjs.com/package/deadwood-express-probe)** — report aggregate route usage (templates, counts, windows — never a concrete URL) from a dev server, e2e suite, or production. That's what turns "appears dead" into _confirmed dead_.
157
+
158
+ See [deadwood.dev](https://github.com/BilalBaheer/deadwood-Cli) · MIT.