Step 3 · Execute

Goal

Execute the refactoring plan one step at a time, verifying tests pass after every single step. Ship a codebase that is measurably better, with zero behaviour change.

Instructions

You are in workflow step 3 of the refactor-cycle. The plan is in TODO.md. Now execute it with discipline.


The Refactoring Loop

For each step in TODO.md, repeat this exactly:

READ the step
  ↓
CONFIRM tests are currently passing before starting
  ↓
MAKE the one atomic change described in the step
  ↓
RUN the test suite — must still be fully green
  ↓
IF tests fail:
  → Do NOT continue
  → Do NOT make more changes to try to fix it
  → Understand why the test failed
  → Revert if the failure can't be fixed in one small targeted change
  → Document what went wrong
  ↓
IF tests pass:
  → COMMIT with message: "refactor: [what you did]"
  ↓
MARK the step DONE in TODO.md
  ↓
REPEAT for next step

Every step gets its own commit. No bundling.


Tasks to Perform

0. Pre-execution baseline

[full test runner command]
# All tests must be passing before you begin

1. Execute Step-by-Step

Pick the first undone task from TODO.md. Do exactly what it says. Nothing more.

After each step:

# Run tests — must be 100% green
[test runner command]

# Confirm no debug output accidentally left in
grep -rn "var_dump\|console\.log\|dd(\|print_r\|debugger\|die(" src/ | grep -v test

# Commit
git add -p  # stage only the refactoring change (not any unrelated edits)
git commit -m "refactor: [description of what was extracted/moved/renamed]"

2. Rename Protocol

When renaming a symbol (function, class, variable):

# Find all usages first
grep -rn "OldName" --include="*.{php,js,ts,py,go,rb}" . | grep -v node_modules | grep -v vendor

# After renaming, verify you got all of them
grep -rn "OldName" --include="*.{php,js,ts,py,go,rb}" . | grep -v node_modules | grep -v vendor
# Expected: no results

3. Move Protocol

When moving a function from Class A to Class B:

  1. Add the function to Class B (don't remove from Class A yet)
  2. Run tests — pass
  3. Update Class A to delegate to Class B
  4. Run tests — pass
  5. Remove function body from Class A
  6. Run tests — pass
  7. Commit

4. Extract Protocol

When extracting a block of code into a new function:

  1. Write the new function (copy, don't cut)
  2. Run tests — pass
  3. Replace the original block with a call to the new function
  4. Run tests — pass
  5. Remove the copied code from the original location
  6. Run tests — pass
  7. Commit

5. Do Not Mix Changes

If you notice a bug or want to add a feature during a refactoring:

  • Stop
  • Note it in TODO.md as a separate task using - [ ] [prefix]: [description] _(ref: workflows/refactor-cycle/03-execute.md)_
  • Complete the refactoring step you are on
  • Then address the bug/feature in a separate commit

Status rules: [ ] = not started · [~] = in progress (one at a time) · [x] = done (prefix the date: - [x] YYYY-MM-DD refactor: …)


Quality Gate (after all steps complete)

When all refactoring tasks are done, verify the success criteria:

# Run the full test suite — must pass
[full test runner]

# Compare metrics before and after
wc -l [refactored files]   # should be smaller or better organised

# Optional: run complexity analysis
[complexity tool if available]

# Check that the public interface is unchanged
git diff [first-refactor-commit]^..HEAD -- [public API files]

Check every item from the success criteria defined in Step 2.


Commit the Final Summary

After all steps are done:

git log [start-commit]..[HEAD] --oneline   # shows all the refactoring commits

A good refactoring history looks like:

refactor: add PasswordService with hash/verify methods
refactor: inject PasswordService into UserService, update all callers
refactor: remove hash/verify from UserService (now in PasswordService)
refactor: add UserValidator with password policy checks
refactor: delegate UserService.validatePasswordPolicy to UserValidator
refactor: remove duplicate password validation from UserService
test: add isolated tests for PasswordService
test: add isolated tests for UserValidator

Closing

Update docs/refactoring/REFACTOR-MODULE-NAME.md:

## Status: Completed YYYY-MM-DD

### Outcome
[What improved]

### Metrics
| Metric | Before | After |
|---|---|---|
| Lines in largest class | 450 | 120 |
| Test count | 24 | 31 |
| Cyclomatic complexity | 18 | 6 |

Exit Criteria

This step is complete when:

  • [ ] All refactoring steps in TODO.md are marked done
  • [ ] Full test suite passes
  • [ ] Every success criterion is met
  • [ ] Refactoring doc updated with outcome
  • [ ] No mixed commits (every commit is either refactor, test, or fix — not combined)