Architecture Cleanup
Analyse an architecture-map (map.js) to find what can be safely removed, prove each
candidate statically, and paint the findings back onto the map as a red removable overlay.
Core principle — advisor by default. Step 1 only reads code and annotates the map. It
NEVER edits source. Removal happens only in Step 2, after the user's explicit approval, as a
branch + PR. No runtime telemetry exists, so claims are "no static references found" — never
"unused in production".
When to use
- "Clean up / debloat the architecture", "find dead code", "what can I delete".
- After mapping a repo and wanting to shrink it before adding features.
- Not for line-level perf or refactor proposals — that's
architecture-improve.
- Recommended order: cleanup → improve (don't optimise code you're about to delete).
Input — map.js (ADR-010)
The input is <repo>/architecture-map/map.js (window.MAP_DATA). If it doesn't exist, build
it first with the architecture-map skill, then run cleanup on the result. Node file-refs
(path:line) and the status field are what cleanup cross-checks against the live code.
Step 1 — advisory pass (default)
- Ensure the map exists & is fresh. No
map.js → build via architecture-map. A stale
map gives stale findings, so re-map if the repo moved since it was generated.
- Git-snapshot the map FIRST (ADR-011). Before annotating, make sure
map.js is committed
(or git stash-clean), so backout is one git restore. The overlay is additive — original
node data is only augmented, never overwritten — but the snapshot is the undo guarantee.
- Topology layer (deterministic). Run the helper to get the per-node worklist — inbound/
outbound edge counts,
isolated flag, inboundFrom, blast-radius, the proposed-node list,
and duplicate-tech groups:node <SKILL_DIR>/analyze-map.mjs <repo>/architecture-map/map.js > /tmp/worklist.json
- Static cross-check (judgment). For each candidate, grep its
path:line refs in the real
code and assign a confidence tier (table below). The helper gives topology; grep gives the
code half. Dynamic/string-based calls grep can't follow → 🟡, never 🔴.
- Bucket into the 7-category taxonomy. Every finding =
category + tier + evidence (path:line + ref-count) + blastRadius. Build a findings.json array (one object per node
or edge — see helper --selftest for the shape). ⚫️ guesses are NOT surfaced.
- Write the overlay (additive). Flag the map's nodes/edges
removable without touching
their data:node <SKILL_DIR>/apply-overlay.mjs <repo>/architecture-map/map.js /tmp/findings.json > /tmp/map.js \
&& mv /tmp/map.js <repo>/architecture-map/map.js
If the repo's viewer predates the overlay, refresh it so the red toggle appears:
cp <ARCH_MAP_SKILL_DIR>/assets/index.html <repo>/architecture-map/.
- Report — plain-language finding cards. Hand the user one plain-language card per finding
(format:
references/finding-card-and-issues.md — What it is / Why / What you gain /
Risk, with the technical evidence folded at the bottom). Grouped by category, then tier.
Plus the open command: open <repo>/architecture-map/index.html shows a 🔴 Removable
toggle (on by default); clicking a node shows tier + evidence + blast-radius.
Step 1b — PRD-ready tracker issues (on approval)
When the user approves findings (per finding, per category, or "all 🔴"), convert them to
issues in the project's tracker (Linear, GitHub Issues, Jira — via its workflow skill if you
have one). Structure, sub-issue PRD template (Background/Solution/Acceptance criteria/Risk/
Evidence), estimate/label/priority mapping: all in references/finding-card-and-issues.md. Parent Cleanup: <repo> (<date>) +
one sub-issue per approved finding. Draft the whole batch, show the user titles + estimates,
ONE go creates them. Unapproved findings stay on the map only.
Step 2 (removal) can then execute against the sub-issues with normal status discipline.
Confidence tiers (static only)
| Tier |
Meaning |
Condition |
| 🔴 sure |
both signals agree |
node isolated (no inbound edges) AND grep at its path:line finds zero references |
| 🟡 check-yourself |
can't prove it |
refs exist but only from other dead code, OR the call is dynamic (string/reflection/route table) grep can't follow — "you decide" |
| ⚫️ silent |
pure guess |
not surfaced at all |
Taxonomy (7 fixed categories, D5)
| # |
Category |
How to detect |
| 1 |
dead functions |
isolated node + 0 grep refs |
| 2 |
unused endpoints/routes |
route node with no caller edge + no client ref |
| 3 |
stale data-streams |
edge whose target node is gone from code (flag the edge) |
| 4 |
unreferenced files/modules |
file-ref node nothing imports |
| 5 |
stale config/feature-flags/env |
config node not read anywhere |
| 6 |
unbuilt proposed-nodes |
still proposed/status:proposed, never shipped (proposedNodes list) |
| 7 |
duplicate/superseded |
nodes sharing tech/files (duplicateGroups) where one supersedes |
Step 2 — removal (only on explicit approval, ADR-012)
Triggered only when the user says yes (per finding or per category). Ask first — this edits source.
- Emit a Cleanup-PLAN, then execute it via an orchestrator ("Lead-dev") + subagents.
Use your plan-execution + subagent tooling (e.g. the superpowers plugin's executing-plans /
subagent-driven-development skills, or the Workflow tool) — do NOT build new transport.
- Lead-dev holds only the plan + task results, never all file contents (avoids context-bloat).
- Work-unit = one file/module cluster, each subagent in its own git worktree
→ no two agents touch the same file.
- Dependency graph from blast-radius: independent removals run as a parallel batch; dependent
ones are removed together by one agent or serialised.
- Verify per task: each subagent runs build/tsc/relevant tests + greps "symbol gone" AFTER its
removal; a break rolls back that task and flags it for the user without blocking the others.
- Only 🔴 findings are auto-eligible. 🟡 stays human-only.
- Branch + PR, never on main, never force, move-don't-destroy convention where it
fits. The user reviews the PR before merge.
Cost (C3)
Step 1 is static and cheap — no gate. Step 2's subagent fan-out warns on scale (finding/agent
count) before firing.
Helpers
analyze-map.mjs <map.js> — deterministic topology worklist. --selftest to verify.
apply-overlay.mjs <map.js> <findings.json> — additive removable write-back (ADR-011).
--selftest to verify. <SKILL_DIR> = this skill's canonical dir skills/architecture-cleanup/.
Red flags — STOP
- About to edit source in Step 1 → don't. Step 1 is advisory-only.
- About to remove anything without the user's explicit yes → stop, ask.
- About to auto-remove a 🟡 finding → don't. 🟡 is human-only.
- About to overwrite a node's data instead of adding a flag → wrong; the overlay is additive.
- About to work on main → wrong; Step 2 is always a branch + PR.
- About to create tracker issues without the batch-go → stop (Step 1b).
- Report card leads with function names/paths instead of plain language → wrong; evidence goes in the folded block.
1---2name: architecture-cleanup3description: Use when you want to find and remove dead/legacy code, unused endpoints, orphaned data-streams, stale config, or unbuilt proposed-nodes that bloat a repo — a static debloat/cleanup pass over an existing architecture-map. Findings arrive as plain-language cards a non-developer can decide on, and approved findings convert to PRD-ready tracker issues. Triggers — "architecture cleanup", "find dead code from the map", "what can I delete", "debloat this repo", "remove unused endpoints", "clean up the architecture". Default is advisory-only; it touches no source code until you explicitly approve a removal.4---56# Architecture Cleanup78Analyse an architecture-map (`map.js`) to find what can be safely **removed**, prove each9candidate statically, and paint the findings back onto the map as a red `removable` overlay.1011**Core principle — advisor by default.** Step 1 only reads code and annotates the map. It12NEVER edits source. Removal happens only in Step 2, after the user's explicit approval, as a13branch + PR. No runtime telemetry exists, so claims are "no static references found" — never14"unused in production".1516## When to use1718- "Clean up / debloat the architecture", "find dead code", "what can I delete".19- After mapping a repo and wanting to shrink it before adding features.20- **Not** for line-level perf or refactor proposals — that's `architecture-improve`.21- Recommended order: cleanup → improve (don't optimise code you're about to delete).2223## Input — map.js (ADR-010)2425The input is `<repo>/architecture-map/map.js` (`window.MAP_DATA`). If it doesn't exist, build26it first with the `architecture-map` skill, then run cleanup on the result. Node file-refs27(`path:line`) and the `status` field are what cleanup cross-checks against the live code.2829## Step 1 — advisory pass (default)30311. **Ensure the map exists & is fresh.** No `map.js` → build via `architecture-map`. A stale32 map gives stale findings, so re-map if the repo moved since it was generated.332. **Git-snapshot the map FIRST (ADR-011).** Before annotating, make sure `map.js` is committed34 (or `git stash`-clean), so backout is one `git restore`. The overlay is additive — original35 node data is only augmented, never overwritten — but the snapshot is the undo guarantee.363. **Topology layer (deterministic).** Run the helper to get the per-node worklist — inbound/37 outbound edge counts, `isolated` flag, `inboundFrom`, blast-radius, the proposed-node list,38 and duplicate-tech groups:39 ```bash40 node <SKILL_DIR>/analyze-map.mjs <repo>/architecture-map/map.js > /tmp/worklist.json41 ```424. **Static cross-check (judgment).** For each candidate, grep its `path:line` refs in the real43 code and assign a confidence tier (table below). The helper gives topology; grep gives the44 code half. Dynamic/string-based calls grep can't follow → 🟡, never 🔴.455. **Bucket into the 7-category taxonomy.** Every finding = `category + tier + evidence46 (path:line + ref-count) + blastRadius`. Build a `findings.json` array (one object per node47 or edge — see helper `--selftest` for the shape). ⚫️ guesses are NOT surfaced.486. **Write the overlay (additive).** Flag the map's nodes/edges `removable` without touching49 their data:50 ```bash51 node <SKILL_DIR>/apply-overlay.mjs <repo>/architecture-map/map.js /tmp/findings.json > /tmp/map.js \52 && mv /tmp/map.js <repo>/architecture-map/map.js53 ```54 If the repo's viewer predates the overlay, refresh it so the red toggle appears:55 `cp <ARCH_MAP_SKILL_DIR>/assets/index.html <repo>/architecture-map/`.567. **Report — plain-language finding cards.** Hand the user one plain-language card per finding57 (format: `references/finding-card-and-issues.md` — What it is / Why / What you gain /58 Risk, with the technical evidence folded at the bottom). Grouped by category, then tier.59 Plus the open command: `open <repo>/architecture-map/index.html` shows a 🔴 **Removable**60 toggle (on by default); clicking a node shows tier + evidence + blast-radius.6162## Step 1b — PRD-ready tracker issues (on approval)6364When the user approves findings (per finding, per category, or "all 🔴"), convert them to65issues in the project's tracker (Linear, GitHub Issues, Jira — via its workflow skill if you66have one). Structure, sub-issue PRD template (Background/Solution/Acceptance criteria/Risk/67Evidence), estimate/label/priority mapping: all in `references/finding-card-and-issues.md`. Parent `Cleanup: <repo> (<date>)` +68one sub-issue per approved finding. Draft the whole batch, show the user titles + estimates,69ONE go creates them. Unapproved findings stay on the map only.70Step 2 (removal) can then execute against the sub-issues with normal status discipline.7172## Confidence tiers (static only)7374| Tier | Meaning | Condition |75|------|---------|-----------|76| 🔴 **sure** | both signals agree | node `isolated` (no inbound edges) AND grep at its `path:line` finds zero references |77| 🟡 **check-yourself** | can't prove it | refs exist but only from other dead code, OR the call is dynamic (string/reflection/route table) grep can't follow — "you decide" |78| ⚫️ **silent** | pure guess | not surfaced at all |7980## Taxonomy (7 fixed categories, D5)8182| # | Category | How to detect |83|---|----------|---------------|84| 1 | dead functions | isolated node + 0 grep refs |85| 2 | unused endpoints/routes | route node with no caller edge + no client ref |86| 3 | stale data-streams | edge whose target node is gone from code (flag the **edge**) |87| 4 | unreferenced files/modules | file-ref node nothing imports |88| 5 | stale config/feature-flags/env | config node not read anywhere |89| 6 | unbuilt proposed-nodes | still `proposed`/`status:proposed`, never shipped (`proposedNodes` list) |90| 7 | duplicate/superseded | nodes sharing `tech`/files (`duplicateGroups`) where one supersedes |9192## Step 2 — removal (only on explicit approval, ADR-012)9394Triggered only when the user says yes (per finding or per category). Ask first — this edits source.9596- Emit a **Cleanup-PLAN**, then execute it via an orchestrator ("Lead-dev") + subagents.97 Use your plan-execution + subagent tooling (e.g. the superpowers plugin's executing-plans /98 subagent-driven-development skills, or the Workflow tool) — do NOT build new transport.99- **Lead-dev holds only the plan + task results**, never all file contents (avoids context-bloat).100- **Work-unit = one file/module cluster**, each subagent in its own git worktree101 → no two agents touch the same file.102- **Dependency graph from blast-radius:** independent removals run as a parallel batch; dependent103 ones are removed together by one agent or serialised.104- **Verify per task:** each subagent runs build/tsc/relevant tests + greps "symbol gone" AFTER its105 removal; a break rolls back that task and flags it for the user without blocking the others.106- **Only 🔴 findings are auto-eligible.** 🟡 stays human-only.107- Branch + PR, **never on main, never force**, move-don't-destroy convention where it108 fits. The user reviews the PR before merge.109110## Cost (C3)111112Step 1 is static and cheap — no gate. Step 2's subagent fan-out warns on scale (finding/agent113count) before firing.114115## Helpers116117- `analyze-map.mjs <map.js>` — deterministic topology worklist. `--selftest` to verify.118- `apply-overlay.mjs <map.js> <findings.json>` — additive `removable` write-back (ADR-011).119 `--selftest` to verify. `<SKILL_DIR>` = this skill's canonical dir `skills/architecture-cleanup/`.120121## Red flags — STOP122123- About to edit source in Step 1 → don't. Step 1 is advisory-only.124- About to remove anything without the user's explicit yes → stop, ask.125- About to auto-remove a 🟡 finding → don't. 🟡 is human-only.126- About to overwrite a node's data instead of adding a flag → wrong; the overlay is additive.127- About to work on main → wrong; Step 2 is always a branch + PR.128- About to create tracker issues without the batch-go → stop (Step 1b).129- Report card leads with function names/paths instead of plain language → wrong; evidence goes in the folded block.