8 min read Rocky Elsalaymeh
3,640 lines of code nobody could reach
Compiling and passing tests is not done. Done means reachable from an entry point. Team-X carried 3,640 lines of renderer code that was not, including install dialogs that invented the permissions a user would approve.
Your build is green, your suite is green, and part of a feature you believe you shipped does not exist. That was the state of parts of Team-X in August 2026.
I ran an audit and deleted what I found. The changelog records the headline number: 3,640 lines of renderer code that nothing could reach.
Team-X, an open-source, local-first desktop app for running AI-agent organizations, found out the hard way that compiling and passing tests is not a definition of done. Code is done when an import chain connects it to a real entry point. Anything else is an orphan: it costs reading time, carries dependencies, and can lie to the next person who trusts it.
This work is on main in the repo. It was not in a tagged release when I wrote this; the latest tag is v3.4.0.
What does “done” mean when the build is green?
Done means reachable. A compiler checks that a file is well formed. A test checks that a function does what its author expected. Neither checks that anything calls the function.
That gap is where orphans live. A module can be typed correctly, linted cleanly, and covered by a test, and still never execute in the product. The test passes because it calls the code directly, which is exactly the call the product never makes.
The test of reachability is mechanical. Pick the entry points. In Team-X the packaged main process is built from main/index.ts, and the renderer starts at main.tsx, which renders App. Walk the imports outward. If a file is not on any chain, it is not part of the product, whatever its header says.
What did the audit actually find?
It found a body of code that looked finished and was not connected to anything. The commit that deleted the renderer half says an import-graph sweep found twelve renderer modules with zero reachable importers. None were behind a feature flag or a lazy route.
The changelog entry lists them: the skills and MCP marketplaces, the custom skill and MCP install dialogs, a simplified-permissions panel, three catalog data modules that only they imported, an environment helper orphaned with them, a retired CardsView, an unmounted grant-authority dialog, and an unused avatar primitive. A later commit removed more, including the two files below.
| Orphan | Why it looked real | What the repo shows |
|---|---|---|
| Skill and MCP install dialogs | A “Skill Preview” with “Included Tools” | Preview invented client-side; a test asserted the live settings section never mounted them |
orchestrator/queue.ts | Header calls it the orchestrator’s only scheduler primitive | orchestrator/index.ts never imported it; only its own test did |
db/vec-init.ts | Creates the vector table | Created vec_embeddings; the repo queried embeddings_vec; no caller |
| Four renderer components | Survived a UI sweep | employee-card.tsx, ui/alert.tsx, ui/collapsible.tsx, ui/tabs.tsx had zero importers |
Each row has a different failure mode. The next sections take them in order of how much damage they could have done.
How did dead code end up fabricating a permission preview?
The install dialogs did not just sit idle. They would have shown a user made-up information. The commit message is blunt: both dialogs rendered a “manifest preview” with tool names, capability grants, and permission scopes invented client-side from the URL the user typed, with no manifest ever fetched or parsed.
Here is the code, copied from the skill dialog just before deletion:
// Generate mock preview (in real implementation, this would fetch the actual manifest)
try {
const mockPreview: SkillPreview = {
name: 'Custom Skill',
description: 'A custom skill from the provided URL',
version: '1.0.0',
author: 'Unknown',
tools: ['custom_tool_1', 'custom_tool_2', 'custom_tool_3'],
capabilities: ['network'],
The comment admits it is a mock. The rendered dialog did not. It put the mock under a heading that read “Skill Preview” and a sub-heading that read “Included Tools”. A user would have approved an install against a preview the app made up.
The changelog adds that the real, security-hardened manifest loader sat unused behind the live dialogs. I want to be precise about the damage: nothing in the repo shows a user ever saw these dialogs, because nothing could reach them. That is the point. The risk was not an incident. It was a trap left for the next person who wired a button to the nearest dialog that looked finished.
The same reasoning applies to the permission catalog. A file of permission presets that nothing consumes is a file that someone will eventually consume, trusting it.
How do you prove a file is unreachable?
You prove it with two checks: an import search and a look at what is allowed to import it. For each suspect I asked what imports it, and whether the importer is itself reachable.
Take orchestrator/queue.ts. Its header said:
* This is the orchestrator's only scheduler primitive (CLAUDE.md
* invariant #2: "Orchestrator is the only scheduler. If the orchestrator
* says pause, nothing new dispatches."). Every agent execution, every
* meeting turn, every background MCP call funnels through one of these.
That is a confident, specific, load-bearing claim. A reader who trusted it would believe pausing the queue paused the orchestrator. The changelog records the reality: orchestrator/index.ts never imported it. The real dispatch is a closure in index.ts built from pending and scheduleDispatch, and admission there depends on per-thread, per-provider, and per-company accounting plus budget admission that a generic semaphore could not replace.
A search for the factory name createWorkQueue before deletion found one importer: queue.test.ts. A test is a reference, but it is not a chain to an entry point. Under the rule that a reference from an orphan is still an orphan, the file was dead.
The vector initializer failed the same way. db/vec-init.ts created a table named vec_embeddings. The repo’s queries used embeddings_vec, the opposite word order. And unlike its sibling initFts5, which main/index.ts calls, initVec had no caller. Our vector database never ran covers the retrieval path around it.
Why is dead code not neutral?
Dead code is a liability that looks like an asset. It does harm in five ways, and the first four have an outside authority behind them.
First, it can run when nobody means it to. The most expensive documented case is Knight Capital. The SEC’s account of the August 2012 incident says: “Although this function was not meant to be used, Knight left it in the router.” The same release says Knight “eventually suffered a loss of more than $460 million,” and it places the damage in “the first 45 minutes after the market opened on August 1.” Code nobody meant to run is still code that can run.
Second, dead code keeps costing money after it stops mattering. Google’s engineers wrote that while dead code sits undeleted it keeps incurring cost, and described the system they built to remove it. Their method is the one I used by hand: “This allows us to find libraries that are not linked into any binary, and propose their deletion.” They report that the project “submits over 1000 deletion changelists per week, and has so far deleted nearly 5% of all C++ at Google.”
Third, it ships dependencies. OWASP’s guidance on vulnerable and outdated components tells teams to “Remove unused dependencies, unnecessary features, components, files, and documentation.” The audit followed that line. The deletion dropped @radix-ui/react-collapsible and @radix-ui/react-tabs, which only the orphaned components used, and the unused sqlite-vec dependency.
Fourth, it has a runtime price. A 2023 study of JavaScript dead code states: “The costs for downloading and parsing dead code can negatively contribute to the loading time and resource usage of web apps.” That study measured mobile web apps, so I will not claim a number for an Electron renderer. I will claim the direction.
Fifth, it is getting cheaper to produce, and the evidence on that is indirect, so I will keep the claim narrow. The repo does not record who or what wrote this dead code, and I will not guess. The question is what the incentives do.
Writing a complete-looking dialog is now cheap. Reading it and finding it plausible is cheaper. GitClear’s 2025 research examined 211 million changed lines and reports: “We observe a spike in the prevalence of duplicate code blocks, along with increases in short-term churn code, and the continued decline of moved lines (code reuse).”
That study measures duplication and churn, not dead code. It does not show that assisted coding creates orphans. It shows that the habits which guard against them, such as moving and reusing code rather than adding more, are declining in the data it analyzed.
A module is not done when it compiles. It is done when something can reach it.
The practical consequence is simple. Volume of plausible code goes up, and the review that catches “nothing calls this” has to become a tool rather than an opinion.
What keeps a deletion deleted?
A cheap guard that fails the build if the file returns. Deleting is half the job. The other half is making resurrection loud.
The audit commit turned three tests that read dead files as source strings into tests that assert the files are gone. Before, a settings test read data/permission-presets.ts and lib/renderer-environment.ts and asserted on their contents, which kept those files looking tested. After, it asserts absence:
expect(existsSync(join(rendererRoot, relative))).toBe(false);
The top bar got a guard too, for a “Coming soon” disabled state no tab ever set:
expect(src).not.toContain('Coming soon');
These guards are blunt. They do not detect new orphans; they prevent known ones from coming back. For detection, the technique is entry-point analysis, which tools such as Knip describe as “Advanced analysis starting from fine-grained entry points based on the actual frameworks and tooling in (mono)repos for accurate and actionable results.” The repo does not run Knip at the pinned commit. I found no mention of it in the root or desktop package.json.
What can you do on Monday?
- List your real entry points. Main process, renderer, workers, scripts, CI.
- Walk the import graph from them and print every file with no inbound chain. A tool such as Knip does this; a hand-rolled script does too.
- For each orphan, read its header and tests. Ask whether either makes a claim the product does not honor.
- Delete, then pin the absence with a test. An
existsSyncassertion is enough. - Drop the dependencies only the orphans used, and rerun your lockfile audit.
Team-X is MIT-licensed and the audit commits are in the repo. If you want notes from the shop floor as this work continues, Field Notes is where they go.
Frequently asked questions
What is unreachable code and why does it matter?
Unreachable code is code that compiles and may even have passing tests, but that no entry point can ever call. In Team-X, an open-source, local-first desktop app for running AI-agent organizations, an audit deleted 3,640 lines of it from the renderer because it misled readers and carried dependencies.
How do you find dead code in a TypeScript project?
Start from the real entry points and walk the import graph. Anything with no inbound chain is an orphan. Team-X's audit used an import-graph sweep to find twelve renderer modules with zero reachable importers. Tools such as Knip automate this kind of entry-point analysis.
Can passing tests hide dead code?
Yes. In Team-X, tests read dead files as source strings and asserted on their contents, so the files looked covered while nothing in the running app imported them. One work queue file had its own test file but no importer in the orchestrator.
A module is not done when it compiles. It is done when something can reach it.