Compass Method Refactoring

Table of Contents

1. When to use this skill

Structure changes and behaviour does not: a rename, an extraction, a collapse of duplicates, a move across a boundary. The deliverable is the same system in a better shape, plus the evidence that it is the same.

Not this method if behaviour changes, however slightly. A refactor that "also fixes" something is two changes wearing one commit, and the fix loses its reproduction while the refactor loses its guarantee.

2. How to use this skill

2.1. 1. Establish the invariant first

Before moving anything, name what must still be true afterwards and find what checks it. A refactor without that is indistinguishable from a rewrite with optimism.

Where nothing checks it, the first unit of work is the check, not the move. That check is also the deliverable's proof, so it is never wasted.

2.2. 2. Ground and map the blast radius

Resolve the concepts (Grounding), then find everything that references what you are about to change, including archived documents and generated output. The cost of a refactor is dominated by the references nobody remembered, and finding them is mechanical.

2.3. 3. Subtract before restructuring

Ask what can be deleted outright before deciding where the rest should live (principle-subtract-before-you-add). Code that no longer needs to exist is the cheapest thing to move, because it does not get moved.

Ask also whether the shape is right rather than merely tidier (principle-redesign-from-first-principles). A refactor that preserves a structure nobody would choose today has spent effort to keep a decision that should have been revisited.

2.4. 4. Write the change as a script where it repeats

A change across many files is a script, not an afternoon (principle-build-the-lever). The script is what a reviewer re-runs, it is idempotent so a partial run is recoverable, and it is what makes the next change of the same shape cheap.

Give it a --check mode where the new state is something that could drift back, and wire that into CI (principle-encode-lessons-in-structure). A refactor whose result nothing enforces is a shape that decays.

2.5. 5. Move, in verifiable units

Sequence the change so each step ends in a system that builds and passes (principle-sequence-verifiable-units). Where an old and a new form must coexist, migrate the callers and delete the old one in the same wave rather than leaving both: two ways to do one thing is the debt the refactor was meant to remove (principle-migrate-callers-then-delete-legacy-apis).

2.6. 6. Prove behaviour survived

Run the invariant from phase 1 (principle-prove-it-works), then the class checks for what you touched via compass-code-run-build. For generated code, the proof is byte-identical regeneration (compass-codegen-fix-drift).

A green build is necessary and not sufficient: it says nothing about the references that live in documentation, and those break silently.

2.7. 7. Land

Close with compass-agile-close-task and raise with compass-pr-raise. Keep the script in the tree: it is the artefact that makes the change reviewable and repeatable.

3. When this method is the wrong one

Re-match if phase 1 shows the behaviour is not currently correct, which makes it compass-method-bug-fix first and a refactor afterwards; or if the restructuring turns out to require new behaviour, which is compass-method-feature.

4. Recipes

5. Reference

Emacs 29.3 (Org mode 9.6.15)