The Two-Model Pruning Cycle: How to Simplify an AI-Assisted Codebase Safely
Revised October 9, 2026 for material factual and workflow corrections.
A feature can work correctly and still leave the repository harder to understand.
Consider a service with a function that normalizes customer addresses. You ask an AI coding agent to add regional formatting. The feature ships, the tests pass, and customers receive the expected result.
But the agent has added a second normalization path beside the first. One endpoint calls the old path. Another reaches the new one through a wrapper. A compatibility test still describes behavior nobody intends to support. Repository instructions tell future contributors to use a helper that the new code bypasses.
The example is hypothetical, but I recognize the pattern from my own AI-assisted development. Repeated feature work can leave extra implementations, wrappers, tests, and instructions behind. I have not measured a universal rate of code growth, and I do not assume that every model or feature produces this result. I am describing residue I have found while maintaining real projects.
Feature completion and repository simplification are separate jobs. A pruning pass needs its own evidence and decision boundary.
The cycle is:
- establish one revision and its retained requirements;
- obtain isolated Model A and Model B analyses;
- reconcile candidates using observable evidence;
- defer unresolved cases;
- implement one small reversible batch through one writer;
- audit the actual diff and validation results.
The decision is not whether a model suggested deletion. It is whether the repository contains enough evidence to preserve required behavior after the change.
One pruning cycle, two independent views
1. Establish what must remain
Input: one exact repository revision, the retained requirements, the validation commands, and any explicitly approved retirements. Prefer an immutable commit identifier. Record supported behavior, public interfaces, exports, entry points, platforms, compatibility requirements, configuration, automation, and active guidance that must remain aligned.
Output: a preservation boundary that another person can inspect. In the address-formatting example, it should identify the endpoints and regional formats that still have to work, along with the checks that cover them.
Consequence: both reviewers evaluate the same problem. They are not asked to decide silently which requirements matter. If the retained behavior or retirement scope is unclear, narrow the pass or establish that information first.
2. Obtain isolated analyses
Input: the same revision and preservation boundary for Model A and Model B. Each reviewer receives the material independently and completes an initial analysis before seeing the other report.
Output: two evidence reports. Each should identify exact candidate locations, apparent purpose, usage or non-usage evidence, inspection scope, possible indirect dependencies, affected tests and guidance, proposed validation, and uncertainty.
Consequence: the reports show what each reviewer actually examined. Disconnected sessions do not share reports, repository state, diffs, or validation output automatically, so the inputs must be transferred explicitly.
A missing result from a text search remains limited evidence. An incomplete inspection is still incomplete when both reviewers sound confident. Agreement can identify an observation worth investigating, but it does not establish that deletion is safe.
3. Reconcile candidates using evidence
Input: the two independent reports and the exact candidate locations they describe.
Output: a candidate-by-candidate record. For each item, align the reports on the file, symbol, rule, or test. List evidence supporting retirement and retention, compare search scope and assumptions, identify the behavior that could be affected, and choose one status: supported for a small reversible batch, retain, or defer pending named evidence.
Consequence: the decision is tied to observable repository facts rather than to reviewer confidence. For a function with no visible callers, investigate imports, exports, package fields, configuration, scripts, plugins, dynamic imports, workers, process launches, generated registries, automation, and external consumers. A missing text-search result makes the function a candidate, not a safe deletion.
The Knip entry-file documentation shows why applicable entry points matter in JavaScript and TypeScript unused-code analysis. Knip is an example for that ecosystem, not a universal proof system.
For a test, identify the supported behavior it protects. For a repository rule, recover why it existed and whether that purpose still applies. For competing implementations, establish which path is authoritative. Finding a newer helper is not enough to retire an older path if the older one still serves a supported endpoint.
4. Defer unresolved cases
Input: a candidate whose purpose, dependency, test coverage, external contract, or retirement condition remains uncertain.
Output: a named deferral record containing the candidate, the evidence already checked, the disagreement or missing fact, and what would settle it. The missing fact might be an external contract, a dynamic loading path, migration status, or the purpose of a test.
Consequence: uncertainty stays visible and outside the current batch. Do not convert disagreement about a live dependency into forced consensus.
A research preprint on multi-agent debate cautions that consensus-seeking protocols can filter out informative disagreement. It does not evaluate Claude and Codex pruning repositories. Its relevance here is narrower: agreement cannot replace repository evidence. Preserve disagreement until a specific fact resolves it.
Leaving the address wrapper in place until its consumer is understood is a useful outcome. The record tells the next cycle why it stayed and what evidence would make another review worthwhile.
5. Implement one small reversible batch
Input: the supported candidate set, the deferrals, the preservation boundary, and baseline validation results.
Output: one scoped diff made by one writer. Keep related code, tests, exports, configuration, automation, and active guidance changes together. Preserve public interfaces and current requirements unless their retirement was explicitly approved.
Consequence: the change remains inspectable and reversible. If implementation reaches a deferred candidate or requires a new retirement decision, narrow the batch or return that question to reconciliation. Permission to prune one path is not permission for a general cleanup.
Tests need the same care as production code. Evaluate each test by the behavior it protects. Keep relevant regression coverage and adapt useful tests after consolidation. Remove coverage only when the behavior is demonstrably retired or the coverage is redundant. A failing test is not a reason to delete it.
Before retiring a repository rule, check why it was introduced and whether its purpose still applies. When the architecture changes, update active guidance in the same batch. Otherwise the repository may teach the next contributor to recreate the structure just removed.
6. Audit the actual diff and validation
Input: the exact diff, the approved batch, the deferral record, the baseline results, and the relevant post-change results.
Output: an independent audit of every changed and deleted line, including affected dependency paths, entry points, exports, configuration, automation, tests, and repository guidance.
Consequence: keep the batch only when the actual change preserves the retained behavior and stays within scope. If the diff changes deferred behavior, removes required coverage, leaves a stale interface or instruction, or includes unrelated cleanup, narrow or revert it. Record unresolved findings for the next cycle.
Judge validation by its coverage. Green tests and clean static analysis are useful evidence, but they cannot by themselves show that every supported entry point was exercised or preserved. The audit must inspect what the checks actually cover.
Deferred candidates become input to a later cycle. They do not need to expand the current cleanup patch.
Why the delete-key explanation is incomplete
There is a memorable explanation for repository residue: language models generate tokens, deletion produces fewer tokens, and models therefore prefer adding code. Saying that a model “hates the delete key” is a playful metaphor, not a technical diagnosis.
Autoregressive language models generate successive tokens, or pieces of text, conditioned on the prompt and prior output. Decoding can use a next-token probability distribution rather than always selecting the single most probable token. The Hugging Face text-generation guide describes those mechanics.
Inference: those mechanics alone do not establish a motive to preserve repository code or an inability to propose deletion. A patch that removes a thousand lines is also generated text. Token generation explains how the patch is produced, not the repository objective by itself.
Historical instruction-following language models work describes demonstrations, ranked outputs, reward modeling, and reinforcement learning used to shape instruction-following behavior beyond a base next-word objective. That is historical InstructGPT evidence, not a disclosure of how every current system is trained. Instructions, tools, retrieved context, and task scope can also affect what gets inspected and proposed.
A 2026 observational study of merged GitHub pull requests found that 24,014 merged agentic pull requests in its sample tended to be smaller and more localized than 5,081 merged human comparison pull requests. The study did not establish intent, correctness, lifetime maintainability, or a causal token-generation effect. It does not show that every AI-assisted repository grows, and it does not remove the need to inspect a particular repository.
Why useful feature work can still leave residue
Repository access does not mean that every file is simultaneously present in context or understood. Coding agents can retrieve selected files, search symbols, inspect directories, and load more context as a task develops. Anthropic's discussion of context engineering for AI agents describes this incremental retrieval model. An agent may inspect a large portion of a repository when the task requires it, but access alone is not the same as a complete audit.
Inference: instructions such as “check first,” “reuse existing utilities,” “avoid duplication,” and “follow existing patterns” are useful starting points, not exhaustive repository audits unless their search scope and evidence are observable. A quick check can miss an indirect entry point, an older implementation with different terminology, or a rule stored outside the directory being searched.
That explains how a feature can be delivered while residue remains without claiming a universal model motive. If the request is regional address formatting, a narrow adapter may be the shortest supported route. The older path can remain because the feature task did not gather enough evidence to retire it.
Feature work asks how to make the requested behavior work. Pruning asks which implementation should remain, what still depends on it, and what can be retired without changing required behavior. Those objectives need separate attention.
What to keep after pruning
Pruning is behavior-preserving maintenance. Martin Fowler's definition of refactoring puts observable behavior at the center: internal structure changes so the software becomes easier to understand and modify.
In my own pruning passes, I look for competing implementations, code shown to be unused, obsolete or redundant tests, stale guidance, and workflows that still point to an older path. Each category can look disposable before its purpose is understood.
Inference: removing obsolete competing implementations and instructions can reduce the maintained surface that people and agents must reason about. I judge that result by preserved behavior, clear ownership, and understandable structure, not minimum line count.
I use Claude and Codex in cross-review, and that practice has helped me catch deletion mistakes and maintain a regularly pruned codebase. This is an account of my practice, not a guarantee of objectivity, permanent stability, or the same result for every repository.
Manual handoffs and paste-ready prompts
These prompts are provider-neutral. Replace the bracketed fields with facts from the repository.
When sessions or tools are not connected, neither reviewer can automatically see the other report, repository state, diff, or validation output. Supply the same revision and retained requirements to both reviewers, then transfer reports and diffs manually at each handoff.
Model A: independent analysis
You are Model A, the first independent reviewer in a behavior-preserving
repository-pruning cycle.
Repository revision:
[IMMUTABLE COMMIT OR REVISION]
Retained requirements:
[SUPPORTED BEHAVIOR, PUBLIC INTERFACES, PLATFORMS, AND CONSTRAINTS]
Explicitly approved retirements:
[ITEMS, OR "NONE"]
Available validation commands:
[COMMANDS AND WHAT EACH COMMAND COVERS]
Analyze only. Do not edit files.
Look for:
- duplicate or competing implementations;
- wrappers and compatibility paths that may no longer be needed;
- unreachable or unused code;
- obsolete or redundant tests;
- stale repository instructions, review rules, CI rules, and migration notes;
- workflows or automation that still reference an older path.
For every candidate, report:
1. exact files and symbols;
2. the candidate’s apparent purpose;
3. concrete evidence of usage or non-usage;
4. entry points and indirect references checked, including applicable
configuration, imports, exports, scripts, plugins, dynamic loading,
workers, automation, and external-interface risk;
5. retained behavior or public interfaces that could be affected;
6. tests and guidance that protect or describe the candidate;
7. proposed validation before and after a change;
8. uncertainty, missing evidence, and reasons to defer.
A missing text-search result is not sufficient evidence for deletion.
Do not optimize for line-count reduction.
Do not assume another reviewer will agree.
Return an evidence report, a clearly labeled candidate list, and explicit
deferrals.
Model B: independent analysis
You are Model B, the second independent reviewer in a behavior-preserving
repository-pruning cycle.
You must complete your initial analysis without seeing Model A's conclusions.
Repository revision:
[THE SAME IMMUTABLE COMMIT OR REVISION GIVEN TO MODEL A]
Retained requirements:
[THE SAME REQUIREMENTS GIVEN TO MODEL A]
Explicitly approved retirements:
[THE SAME RETIREMENT SCOPE GIVEN TO MODEL A]
Available validation commands:
[THE SAME COMMANDS AND COVERAGE NOTES GIVEN TO MODEL A]
Analyze only. Do not edit files.
Independently identify possible duplicate implementations, dead paths,
obsolete or redundant tests, stale governance, and outdated workflows.
For every candidate, provide:
- exact location and current purpose;
- observable supporting evidence;
- search and inspection scope;
- applicable entry points, configuration, imports, exports, scripts,
plugins, dynamic loading, workers, automation, and external consumers;
- behavior, tests, or instructions that could still depend on it;
- a safe validation plan;
- confidence and counterevidence;
- a clear deferral when evidence is incomplete.
Do not infer safety from a missing search result, test age, model confidence,
or expected line-count reduction.
Return your independent evidence report before reading Model A's report.
Evidence-based reconciliation
Reconcile the two independent pruning reports below.
Repository revision:
[SHARED IMMUTABLE REVISION]
Retained requirements:
[SHARED RETAINED REQUIREMENTS]
MODEL A REPORT:
[PASTE REPORT]
MODEL B REPORT:
[PASTE REPORT]
Do not force consensus and do not treat agreement as proof.
For each candidate:
1. align the two reports on the exact file, symbol, rule, or test;
2. list evidence supporting retirement;
3. list evidence supporting retention;
4. identify any difference in search scope or assumptions;
5. decide one of:
- supported for a small reversible batch;
- retain;
- defer pending named evidence;
6. specify baseline checks, post-change checks, and manual inspections;
7. identify code, tests, configuration, automation, and active guidance
that must change together.
Preserve unresolved disagreement in the record. Recommend the smallest
coherent batch whose safety is supported by observable evidence.
Model A: scoped implementation
You are the sole writer for this pruning batch.
Repository revision and working state:
[REVISION AND CLEAN/KNOWN WORKTREE STATUS]
Retained requirements:
[REQUIREMENTS]
Approved batch:
[PASTE ONLY THE RECONCILED, SUPPORTED CANDIDATES]
Deferred and prohibited items:
[PASTE DEFERRALS, PUBLIC INTERFACES, AND OUT-OF-SCOPE AREAS]
Baseline results:
[COMMANDS, OUTPUT SUMMARY, AND ANY KNOWN FAILURES]
Implement only the approved batch.
Requirements:
- preserve retained behavior and public interfaces unless retirement is
explicitly approved;
- keep the change small and reversible;
- update affected tests rather than deleting failures for convenience;
- remove tests only when the reconciled evidence shows they are obsolete
or redundant;
- update active repository guidance, configuration, and workflows in the
same change when their references become stale;
- do not act on deferred candidates.
After editing, run the approved validation. Return:
1. a concise diff summary;
2. exact files changed;
3. validation commands and results;
4. tests, rules, exports, or entry points removed or modified;
5. remaining uncertainty;
6. anything that should cause the batch to be reverted or narrowed.
Model B: post-change audit
You are the independent post-change auditor. Review the actual change, not
the implementation plan.
Base revision:
[BASE REVISION]
Retained requirements:
[REQUIREMENTS]
Approved batch and deferrals:
[RECONCILIATION RECORD]
Actual diff:
[PROVIDE THE DIFF OR ACCESS TO THE EXACT CHANGED REVISION]
Baseline and post-change validation:
[COMMANDS, COVERAGE NOTES, RESULTS, AND KNOWN FAILURES]
Audit:
- every changed and deleted line;
- retained behavior and public interfaces;
- applicable entry points, configuration, imports, exports, scripts,
plugins, dynamic loading, workers, and automation;
- removed or modified tests and the behavior they protected;
- repository instructions, review rules, CI rules, and migration notes;
- whether any deferred candidate was changed accidentally;
- whether validation actually covers the affected behavior.
Do not approve merely because tests pass, tools report no references, the
diff is smaller, or both reviewers previously agreed.
Return prioritized findings with concrete evidence. For each finding,
state whether to block, revise, revert, or investigate. If no blocking
issue is found, state the residual risks and why the available evidence
supports keeping this batch.
Keep, defer, or revert
Keep the batch when the actual diff preserves required behavior, dependency evidence covers the affected paths, related instructions and interfaces agree, and the independent audit finds no blocking issue. Understand the validation results rather than treating green output as sufficient.
Defer a candidate when its purpose or a live dependency remains unknown. Record the fact that would make the next review useful.
Revert or narrow a change that exceeds the approved scope, hides a failure by deleting coverage, or cannot be supported by the checks that ran. In the address-formatting example, keeping the batch requires evidence that regional formatting still works and that the retained path is clear. The number of deleted lines cannot answer either question.