Simplify And Refactor Code Isomorphically
Make code simpler without changing what callers, users, persisted data, or
integrations can observe. Treat every edit as a behavior-preserving
transformation until evidence proves otherwise.
Operating Rules
- Start by naming the behavior surface: public APIs, CLI flags, wire formats,
database effects, files, environment variables, logs that tests assert, and
user-visible UI states.
- Establish characterization tests before changing unclear or under-tested
behavior. Prefer narrow tests that lock down current outputs, side effects,
ordering, and error cases.
- Write down invariants that must remain true after the refactor. Include both
domain invariants and mechanical invariants such as idempotence, ordering,
resource cleanup, and concurrency assumptions.
- Make one reversible transformation at a time. Keep each diff small enough to
review and roll back without losing unrelated work.
- Verify after each meaningful step with the smallest relevant test command.
Broaden verification when the refactor crosses module boundaries.
- Do not combine behavior changes with simplification. If a bug is discovered,
capture it separately unless the user explicitly asks to fix it now.
Workflow
- Inspect the target code and its call sites. Identify the observable contract,
risky dependencies, and the smallest safe scope for the first change.
- Build a behavior baseline. Run existing tests and add characterization tests
for unprotected behavior before structural edits.
- State invariants in the work notes or final report. Make the intended
preservation target explicit enough for another engineer to audit.
- Apply a single isomorphic transformation, such as extracting a pure helper,
replacing duplicated branches with a shared path, simplifying conditionals,
renaming for clarity, or moving code behind an equivalent interface.
- Compare the diff against the invariants. Remove incidental churn, formatting
noise, and unrelated cleanup.
- Run targeted verification. If verification fails, rollback the latest
transformation or isolate the behavioral difference before continuing.
- Repeat only while the next simplification remains clearly valuable and low
risk. Stop when additional cleanup would outgrow the evidence available.
Characterization Tests
Good characterization tests describe what the current system does, not what the
system should ideally do. Cover representative success paths, boundary inputs,
known odd behavior, failure modes, and side effects. Use fixtures or golden
outputs only when they make behavioral drift easier to detect than assertions.
When tests are expensive, add a narrow harness around the refactor target and
keep the full suite for final confirmation. When tests cannot be added, document
the manual or command-line probes used as the baseline and keep the refactor
smaller.
Diff Discipline
- Avoid broad reformatting unless the formatter is already the local standard
and the target file is expected to be formatted.
- Preserve names, exported symbols, error text, and ordering unless the baseline
proves they are not part of the contract.
- Prefer mechanical moves and extraction before semantic rewrites.
- Keep generated files, lockfiles, and unrelated dependency changes out of the
refactor unless they are required for verification.
- Re-read the final diff as a reviewer looking for hidden behavior changes.
Rollback
Every step needs a clear rollback point. If a transformation becomes tangled,
revert that step and choose a smaller path. If the baseline is too weak to prove
equivalence, stop and report the missing evidence instead of pushing through on
intuition.
Output
Report the behavior baseline, invariants, changed files, verification commands,
and any residual risk. If rollback was needed, say what was rolled back and why.
1---2name: behavior-preserving-simplification-23description: Use when simplifying code, reducing duplication, or clarifying flow while preserving behavior with tests. Triggers:4---5# Simplify And Refactor Code Isomorphically
6
7Make code simpler without changing what callers, users, persisted data, or
8integrations can observe. Treat every edit as a behavior-preserving
9transformation until evidence proves otherwise.
10
11## Operating Rules
12
13- Start by naming the behavior surface: public APIs, CLI flags, wire formats,
14 database effects, files, environment variables, logs that tests assert, and
15 user-visible UI states.
16- Establish characterization tests before changing unclear or under-tested
17 behavior. Prefer narrow tests that lock down current outputs, side effects,
18 ordering, and error cases.
19- Write down invariants that must remain true after the refactor. Include both
20 domain invariants and mechanical invariants such as idempotence, ordering,
21 resource cleanup, and concurrency assumptions.
22- Make one reversible transformation at a time. Keep each diff small enough to
23 review and roll back without losing unrelated work.
24- Verify after each meaningful step with the smallest relevant test command.
25 Broaden verification when the refactor crosses module boundaries.
26- Do not combine behavior changes with simplification. If a bug is discovered,
27 capture it separately unless the user explicitly asks to fix it now.
28
29## Workflow
30
311. Inspect the target code and its call sites. Identify the observable contract,
32 risky dependencies, and the smallest safe scope for the first change.
332. Build a behavior baseline. Run existing tests and add characterization tests
34 for unprotected behavior before structural edits.
353. State invariants in the work notes or final report. Make the intended
36 preservation target explicit enough for another engineer to audit.
374. Apply a single isomorphic transformation, such as extracting a pure helper,
38 replacing duplicated branches with a shared path, simplifying conditionals,
39 renaming for clarity, or moving code behind an equivalent interface.
405. Compare the diff against the invariants. Remove incidental churn, formatting
41 noise, and unrelated cleanup.
426. Run targeted verification. If verification fails, rollback the latest
43 transformation or isolate the behavioral difference before continuing.
447. Repeat only while the next simplification remains clearly valuable and low
45 risk. Stop when additional cleanup would outgrow the evidence available.
46
47## Characterization Tests
48
49Good characterization tests describe what the current system does, not what the
50system should ideally do. Cover representative success paths, boundary inputs,
51known odd behavior, failure modes, and side effects. Use fixtures or golden
52outputs only when they make behavioral drift easier to detect than assertions.
53
54When tests are expensive, add a narrow harness around the refactor target and
55keep the full suite for final confirmation. When tests cannot be added, document
56the manual or command-line probes used as the baseline and keep the refactor
57smaller.
58
59## Diff Discipline
60
61- Avoid broad reformatting unless the formatter is already the local standard
62 and the target file is expected to be formatted.
63- Preserve names, exported symbols, error text, and ordering unless the baseline
64 proves they are not part of the contract.
65- Prefer mechanical moves and extraction before semantic rewrites.
66- Keep generated files, lockfiles, and unrelated dependency changes out of the
67 refactor unless they are required for verification.
68- Re-read the final diff as a reviewer looking for hidden behavior changes.
69
70## Rollback
71
72Every step needs a clear rollback point. If a transformation becomes tangled,
73revert that step and choose a smaller path. If the baseline is too weak to prove
74equivalence, stop and report the missing evidence instead of pushing through on
75intuition.
76
77## Output
78
79Report the behavior baseline, invariants, changed files, verification commands,
80and any residual risk. If rollback was needed, say what was rolled back and why.