September 12, 2026
CLEANUP IS ALSO DEPENDENCIES, DOCUMENTATION, AND OWNERSHIP

Lessons 53.1 and 53.2 handled the code itself: map the debt, then move one seam without changing behavior. But ask any maintainer what actually sank their AI-built project and they will point beside the source files — a dependency nobody dares remove, a feature flag from a canceled experiment, a stale test suite nobody trusts, a credential that outlived its demo, a diagram that lies about the architecture. Source cleanup without this surrounding cleanup is mopping the floor while the sink overflows.
The six piles beside the code
Work through these in order of blast radius, smallest first:
1. Packages. Every dependency is code you own but did not write (Class 48.4). Before removing anything, answer: what imports it, what breaks without it, and what replaces its job? Never let an AI delete "unused" code on a shallow text search — dynamic imports, worker entry points, and build plugins all hide from naive grep. 2. Flags and configuration. Retire obsolete feature flags, dead environment samples, and prototype config. Each leftover flag doubles the states a future test must cover. Confirm the flag is off in every environment, remove its branches, then remove its config — in that order. 3. Stale tests. Delete a stale test only after confirming replacement coverage. A skipped browser journey with no successor is not clutter; it is an uncovered user path. Map old test → new test explicitly, or keep the old one. 4. Credentials. Rotate or disable unused keys, demo tokens, and test accounts with production access. Recall Class 48.2: deleting a committed key from the current files does not erase its history — rotation, not deletion, is the fix. Never paste a secret into a prompt or log while auditing. 5. Docs and diagrams. Update ARCHITECTURE.md, API-CONTRACT.md, and the request-flow diagram whenever a boundary actually moved. A diagram that disagrees with the code is worse than no diagram, because agents will follow the diagram. 6. Ownership. Make clear who owns each boundary going forward: who approves adapter changes, who owns the watchlist policy, who rotates the provider key. Unowned code becomes neglected debt within weeks.
None of these belongs inside a feature PR. Each gets the Part X treatment — its own task card, branch, tests or evidence, and review — so a reviewer can approve removing a library without also approving a UI redesign they did not ask for.
Lockfile discipline
Your lockfile (package-lock.json, pnpm-lock.yaml, or equivalent) pins the exact versions of every direct and transitive dependency so every install reproduces the same tree. Treat it as a contract, not noise:
- Install and update through the project's package manager; never hand-edit the lockfile.
- Update intentionally: one dependency or one related group at a time, with tests run and the dependency diff inspected before committing.
- Commit the lockfile with the change it belongs to. A lockfile change smuggled into an unrelated refactor makes both unreviewable.
- When AI proposes an upgrade, require it to state *why now*: a security advisory, a needed capability, or a blocking incompatibility — with the advisory or error cited. "Latest is safer" is not a reason (Class 48.4).
A clean upgrade PR is small and boring: one library, its lockfile diff, test evidence, and a rollback note ("revert this commit; previous lockfile restores exact tree"). Boring is the goal.
The independent review: don't let the model grade its own homework
The agent that wrote the refactor is the worst judge of whether behavior changed — it shares its own wrong assumptions (Class 50.4). Require an independent read: a different model session, or better a human, that receives only the original task card plus the diff and answers three questions:
1. What behavior could have changed? List every user-visible, API-level, or policy-level difference the diff could plausibly cause — including ones the tests might miss. 2. Which tests actually cover it? For each risk, name the test that would fail if the risk materialized. "The suite passed" is not an answer; test names and assertions are. 3. What remains unproven? Name the residual risk and who accepts it: needs a browser pass, needs a staging check, needs a second reviewer on the policy file.
Run this as a prompt like: "You did not write this change. Read only the attached card and diff. List behavior that could have changed, the test covering each, and anything unproven. Cite files and lines. Separate evidence from guesses." File the review note with the PR — it becomes part of the handoff.
For Neighborhood Events, this catches the classic: the cleanup "simplified" the event-edit route and its test still passes — because the test mocks the ownership helper to always return true. The independent reader, asked what would fail if User A edited User B's event, finds no two-identity test and blocks the merge. That is the whole technique working.
The monthly 30-minute review
Cleanup is a cadence, not a heroic weekend. Once a month, spend 30 minutes with the debt map and this checklist:
Before (5 min): open TECH-DEBT.md + dependency/config diff since last review
Scan (15 min): packages → flags/config → tests → creds → docs → ownership
Decide (10 min): pick ONE high-value safe seam → write its card,
or document why every candidate waits
Ask of each candidate: Is the evidence still true? Did a trigger fire (second provider added, flag experiment ended, advisory published)? Is the blast radius still small? Then either create the card with owner and trigger, or write one line explaining the deferral. "Deferred: image library still unused but removal breaks preview plugin; revisit after plugin migration" is a decision. Silence is neglect.
Done means: an updated TECH-DEBT.md (re-ranked, triggers checked), plus either one intentional cleanup PR with its independent review note, or a dated deferral line — and an architecture or ownership record that matches the current code. Verify: git log --oneline -5 shows cleanup on its own branch and commit, and a teammate can state the current owner of each changed boundary. Common failure: a feature PR with "also cleaned up" commits hidden inside — split them out, always.
Exercise: run the review for real
1. Open your TECH-DEBT.md and your package manager's outdated/audit output side by side. 2. Walk the six piles. For each candidate removal, confirm with an import search *plus* a test or preview run — never the search alone. 3. Ship or defer exactly one item following the card → branch → PR → independent review path.
Check your understanding
- Why must stale tests, credentials, and docs each get their own card rather than riding inside a feature PR?
- What three questions does the independent reviewer answer, and why can't the original model answer them alone?
- What does a monthly review produce even when it defers everything?
You now have the full cleanup discipline: map cost, move one seam, sweep the surroundings, and prove it all. The capstone pulls every Part XI skill together into one controlled, deployable slice.
ARTICLE DISCUSSION
JOIN THE
CONVERSATION.
Got a question, a take, or a better way to do this? Log in and leave a comment.
