---
requires: diff vs main
produces: simpler code
action_style: procedural
---
Leave the codebase simpler than you found it. Delete what isn't needed. Flatten unnecessary abstractions.
## Goal
The best reduction isn't deleting a function—it's reshaping a structure so three special cases become one.
Simplicity compounds. Every line removed is a line that can't break, can't confuse, can't slow down the next change.
The bar: could someone reading this code for the first time understand it faster after your changes?
## Workflow
1. **Reflect on the implementation**
What did building this reveal? Ask:
- Did the implementation fight the existing structure?
- Did we add workarounds that hint at a deeper problem?
- Is there a simpler design we only see now that it's built?
If yes: this is the reduction opportunity. Don't just clean up around the edges—reshape toward the simpler design you now see.
2. **Review the diff**
The diff against main is in your context. Identify what was added, what was
changed, and whether the current slice still moves toward the complete
reviewed design.
3. **Find reduction opportunities**
For each file touched, ask:
- What's unused now that this change landed?
- What abstraction exists only because the old code needed it?
- What duplication did this change create or reveal?
- Which old authority, type, writer, or path should now be unreachable?
- Did a locally convenient adapter leave two representations of one concept?
4. **Reduce**
Apply changes directly. Prefer reshaping over deleting—a better structure beats surgical removal.
5. **Verify**
If the reduction changed executable behavior, run the smallest existing
behavioral test that covers it. If only structure changed, do not rerun the
branch suite; gate owns that proof. If the focused test breaks, the
reduction went too far.
## What to reduce
**Reshape data structures.** A different representation can eliminate special cases.
Example: Three optional fields that are mutually exclusive → one enum with three variants.
**Rearrange APIs.** Change the interface so callers don't need conditionals.
Example: `process(item, mode)` where every caller passes the same mode → `process(item)` with mode baked in.
**Delete dead code.** Unused functions, unreachable branches, obsolete options.
Example: A feature flag that's been `true` for six months → delete the flag and the `false` branch.
**Collapse duplication.** Same pattern twice? Inline it or pick one location.
Example: Two functions that differ by one line → one function with a parameter, or inline both if they're only called once.
**Remove backwards-compatibility shims.** Old parameter names, deprecated re-exports, migration code for formats nothing uses anymore.
Example: `def foo(x, old_name=None): x = x or old_name` → just `def foo(x):` if nothing uses `old_name`.
## Scope
**Stay in the diff.** If a file wasn't changed or used by this branch, don't touch it.
**Reshape, don't layer.** Restructuring is good. Adding adapters, wrappers, or compatibility shims is not reducing—it's adding.
**Preserve behavior.** Reduction changes structure, not functionality. If tests break, you changed behavior.
**Be aggressive.** Question whether each abstraction earns its place. Question whether each option is used. Question whether the API surface is minimal. The default is "this can probably go"—make it prove otherwise.
## Output
Simpler code that passes tests. If nothing can be reduced, say so—not every diff has reduction opportunities.