File size: 5,889 Bytes
b6e19c7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# Workflow β€” Refactoring Code

## Purpose
Read this file every time you need to refactor existing code.
Refactoring means improving structure without changing behaviour.
If behaviour changes β€” that is a feature, not a refactor.

---

## Core Principle
**Tests must pass before AND after every refactor.**
If tests fail after refactor β€” you changed behaviour. Revert and retry.
Never refactor and fix a bug in the same commit.

---

## Step 1 β€” Confirm Refactor Scope
Before touching any code, state this out loud:

Refactor target: [file or function]
Reason for refactor: [why this needs to change]
Behaviour change: none
Files I will touch: [exact list]
Files I will NOT touch: [everything else]

- [ ] Confirm with user that this refactor is needed now
- [ ] Confirm all current tests pass before starting:
```bash
bash scripts/test.sh
```
- [ ] Do not proceed if any test is currently failing

---

## Step 2 β€” Identify What to Refactor
Valid reasons to refactor:
- [ ] Duplicate logic across multiple functions
- [ ] Function doing more than one thing
- [ ] Deeply nested conditionals reducing readability
- [ ] Magic numbers or hardcoded strings
- [ ] Missing or inconsistent error handling format
- [ ] Inconsistent naming conventions
- [ ] Dead code or unused imports

Not valid reasons:
- "It looks messy" without a specific structural problem
- Preference for a different syntax that does the same thing
- Rewriting working code during a bug fix session

---

## Step 3 β€” Refactor in Small Steps
- [ ] Change one thing at a time
- [ ] Run tests after each individual change
- [ ] Do not batch multiple refactors into one step
- [ ] Keep original logic visible until new logic is confirmed working

### Order of operations:

Extract repeated logic into a shared utility function
Simplify conditionals (early returns over nested if/else)
Rename for clarity (variables, functions)
Remove dead code and unused imports
Standardise error handling format per docs/debugging.md

---

## Step 4 β€” Run Tests After Every Change
```bash
# After each individual change
npm test -- tests/unit/[affected-file].test.ts 2>&1 | tee logs/test.log

# After all changes complete
bash scripts/test.sh
```
- [ ] Every test that passed before must still pass
- [ ] If a test fails β†’ revert the last change, do not chain fixes

---

## Step 5 β€” Update Tests if Needed
Refactoring may require test updates only in these cases:
- [ ] A function was renamed β†’ update test description and import
- [ ] A function was split into two β†’ write tests for both
- [ ] A utility was extracted β†’ write a unit test for the utility

Do NOT update tests to make them pass after a refactor.
If a test fails after refactor β†’ the refactor changed behaviour β†’ revert.

---

## Step 6 β€” Self Review Checklist
Before declaring refactor done:
- [ ] Behaviour is identical before and after
- [ ] All tests pass
- [ ] No new files created outside the plan in Step 1
- [ ] Error handling format matches `docs/debugging.md`
- [ ] No console.log left in code
- [ ] No dead code or unused imports remain
- [ ] No hardcoded values introduced

---

## Step 7 β€” Update Docs
- [ ] Update `docs/architecture.md` if structure changed
- [ ] Add one-liner to `docs/progress.md`
- [ ] Append one line to `session/phase-log.md`
- [ ] Update `session/summary.md`
- [ ] If a pattern was discovered that saves time β†’ add to `docs/learnings.md`

---

## Step 8 β€” Git Commit Message
Provide one-liner commit message in this format:

refactor([scope]): [what was improved and how]
Examples:
refactor(auth): extract session validation into shared utility
refactor(dashboard): replace nested conditionals with early returns
refactor(db): standardise error handling across all supabase queries
refactor(utils): remove dead code and unused imports from helpers

**Do NOT push to GitHub. Hand the message to the user.**

---

## Step 9 β€” Confirm with User
- [ ] Show exactly what changed and in which files
- [ ] Show before/after for key changes
- [ ] Show test results confirming no behaviour change
- [ ] Show commit message
- [ ] Ask: "Refactor complete β€” ready to continue?"
- [ ] Do NOT proceed until user confirms

---

## Refactor Decision Tree

Refactor needed?
β”‚
β–Ό
All tests passing?
β”‚
β”œβ”€β”€ No β†’ fix failing tests first, then refactor
β”‚
└── Yes β†’ confirm scope β†’ refactor one thing at a time
β”‚
β–Ό
Run tests after each change
β”‚
β”œβ”€β”€ Pass β†’ continue next change
β”‚
└── Fail β†’ revert last change
β†’ reassess scope
β†’ do not chain fixes

---

## Refactor Patterns

### Extract repeated logic
```typescript
// Before β€” same null check in 3 functions
if (!userId || userId === '') return null

// After β€” shared utility
function isValidId(id: string | null | undefined): boolean {
  return !!id && id.trim() !== ''
}
```

### Early returns over nested conditionals
```typescript
// Before
function processUser(user: User | null) {
  if (user) {
    if (user.isActive) {
      if (user.hasProfile) {
        return user.profile
      }
    }
  }
  return null
}

// After
function processUser(user: User | null) {
  if (!user) return null
  if (!user.isActive) return null
  if (!user.hasProfile) return null
  return user.profile
}
```

### Standardise error handling
```typescript
// Before β€” inconsistent
try {
  ...
} catch (e) {
  console.log(e)  // wrong
}

// After β€” per docs/debugging.md
try {
  ...
} catch (err) {
  handleError(err, 'lib/users.ts', 'processUser')
  return null
}
```

---

## What NOT to Do
- Do not refactor and fix a bug in the same commit
- Do not refactor files not listed in Step 1
- Do not update tests to force them to pass after refactor
- Do not batch all refactors into one large change
- Do not refactor during a feature build session
- Do not push to GitHub
- Do not start a refactor if any test is currently failing