The Flag That Outlived Its Reason
The vendor shipped a bug in version 4.3: pagination responses corrupted under load. You added a flag. When the vendor was detected, fall back to single-page fetches. The workaround was correct. Tests covered it. It shipped.
Version 4.7 fixed the bug. You updated the dependency. The flag kept running. Tests kept passing.
This is the category of debt that no quality report finds.
Worth separating from the other kinds. Bad code fails a test or produces wrong output. Drifted specs mean requirements changed and code didn't. Dead premise code looks like neither.
The spec is intact. The behavior is correct. The code does exactly what it says. The only thing gone is the reason the spec existed.
The test asks: does the fallback execute when the vendor is detected? Yes. That's what the test should check. It has no mechanism to ask whether the vendor still needs detecting. That's not a behavioral question. It lives outside what tests can see.
Code review doesn't catch it either. The reviewer reads the flag, sees a plausible name, sees tests, sees a clear code path. Nothing is wrong. The reviewer wasn't in the room when someone said "this vendor is melting our prod traffic." The context that made the code sensible is gone, and nothing in the artifact points to it.
What's left is archaeology. Git blame to the original commit, the message if it says anything useful (unlikely), the ticket it references if tickets still exist and the system is still running (optimistic), someone's memory of what was happening when 4.3 shipped. That chain breaks fast. Two or three years in, the person who remembers has moved on or forgotten the detail. The flag just runs.
The underlying problem: code captures what to do. It rarely captures "and stop doing this when X." There's no test for "is the vendor still broken." No scheduled question. No alarm. The condition that would invalidate the premise isn't tracked, because tracking it requires predicting, at the moment of writing, which premises might expire and when.
So this is outside what testing can fix. It's a reasoning artifact problem. The useful comment captures the decision and the expiration condition. That's a harder discipline at the moment of writing. You're under pressure, the bug is live, you write the workaround, and writing the invalidation condition costs effort with deferred payoff.
Architecture Decision Records, ADRs, are the formal version: a short doc per decision capturing the call, the context, and the conditions under which it should be reconsidered. Most codebases don't have them. Most that do don't write them with enough specificity to matter three years out.
The honest position: most codebases accumulate dead premise code continuously. The cost is diffuse. The flag adds a millisecond. The shim fires and returns immediately. Nothing breaks, so nothing changes.
The category name matters because naming it precedes having a policy about it. "Technical debt" covers too much. Dead premise code has a specific shape: correct behavior, current spec, gone premise, no automated detection. The only detection method is someone asking "why does this exist?" and having somewhere to look. That requires the answer to have been written down when the premise was alive.
Nothing fails. That's the problem.