openhermes 4.3.0 → 4.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTEXT.md +10 -1
- package/README.md +54 -42
- package/bootstrap.ts +396 -142
- package/harness/agents/oh-browser.md +97 -0
- package/harness/agents/oh-builder.md +78 -0
- package/harness/agents/oh-facade.md +75 -0
- package/harness/agents/oh-fusion.md +45 -0
- package/harness/agents/oh-gauntlet.md +71 -0
- package/harness/agents/oh-grill.md +71 -0
- package/harness/agents/oh-investigate.md +60 -0
- package/harness/agents/oh-manifest.md +95 -0
- package/harness/agents/oh-plan-review.md +40 -0
- package/harness/agents/oh-planner.md +50 -0
- package/harness/agents/oh-refactor.md +37 -0
- package/harness/agents/oh-retro.md +46 -0
- package/harness/agents/oh-review.md +85 -0
- package/harness/agents/oh-security.md +83 -0
- package/harness/agents/oh-ship.md +76 -0
- package/harness/agents/oh-skill-craft.md +38 -0
- package/harness/agents/openhermes.md +28 -73
- package/harness/codex/AUTOPILOT.md +235 -87
- package/harness/codex/CHARTER.md +80 -0
- package/harness/instructions/SHELL.md +76 -0
- package/harness/lib/background/background.test.ts +197 -0
- package/harness/lib/background/index.ts +7 -0
- package/harness/lib/background/interfaces.ts +31 -0
- package/harness/lib/background/manager.ts +320 -0
- package/harness/lib/composer/compose.test.ts +168 -0
- package/harness/lib/composer/compose.ts +65 -0
- package/harness/lib/composer/fragments/01-identity.md +1 -0
- package/harness/lib/composer/fragments/02-delegation.md +6 -0
- package/harness/lib/composer/fragments/03-permissions.md +13 -0
- package/harness/lib/composer/fragments/04-task-flow.md +15 -0
- package/harness/lib/composer/fragments/05-confidence.md +5 -0
- package/harness/lib/composer/fragments/06-parallelization.md +17 -0
- package/harness/lib/composer/fragments/07-shell.md +41 -0
- package/harness/lib/composer/fragments/08-routing.md +8 -0
- package/harness/lib/composer/fragments/09-guardrails.md +12 -0
- package/harness/lib/composer/index.ts +1 -0
- package/harness/lib/hooks/builtins/confidence-gate-hook.ts +70 -0
- package/harness/lib/hooks/builtins/delegation-depth-hook.ts +59 -0
- package/harness/lib/hooks/builtins/error-recovery-hook.ts +107 -0
- package/harness/lib/hooks/builtins/memory-sync-hook.ts +73 -0
- package/harness/lib/hooks/builtins/plan-check-hook.ts +43 -0
- package/harness/lib/hooks/builtins/route-tracking-hook.ts +147 -0
- package/harness/lib/hooks/builtins/sanity-check-hook.ts +52 -0
- package/harness/lib/hooks/builtins/shell-detect-hook.ts +96 -0
- package/harness/lib/hooks/hooks.test.ts +1016 -0
- package/harness/lib/hooks/index.ts +30 -0
- package/harness/lib/hooks/registry.ts +416 -0
- package/harness/lib/hooks/types.ts +71 -0
- package/harness/lib/memory/index.ts +18 -0
- package/harness/lib/memory/interfaces.ts +53 -0
- package/harness/lib/memory/memory-manager.ts +205 -0
- package/harness/lib/memory/memory.test.ts +491 -0
- package/harness/lib/memory/plan-store.ts +366 -0
- package/harness/lib/recovery/handler.ts +243 -0
- package/harness/lib/recovery/index.ts +14 -0
- package/harness/lib/recovery/interfaces.ts +48 -0
- package/harness/lib/recovery/patterns.ts +149 -0
- package/harness/lib/recovery/recovery.test.ts +312 -0
- package/harness/lib/sanity/anomaly-tracker.ts +127 -0
- package/harness/lib/sanity/checker.ts +178 -0
- package/harness/lib/sanity/index.ts +13 -0
- package/harness/lib/sanity/interfaces.ts +24 -0
- package/harness/lib/sanity/sanity.test.ts +472 -0
- package/harness/lib/sync/file-watcher.ts +174 -0
- package/harness/lib/sync/index.ts +11 -0
- package/harness/lib/sync/interfaces.ts +27 -0
- package/harness/lib/sync/plan-sync.ts +536 -0
- package/harness/lib/sync/sync.test.ts +832 -0
- package/harness/skills/oh-ascii/DEEP.md +292 -0
- package/harness/skills/oh-ascii/SKILL.md +31 -0
- package/harness/skills/oh-ascii/scripts/check_ascii_alignment.py +596 -0
- package/harness/skills/oh-browser/DEEP.md +54 -0
- package/harness/skills/oh-browser/SKILL.md +30 -0
- package/harness/skills/oh-builder/DEEP.md +63 -0
- package/harness/skills/oh-builder/SKILL.md +12 -90
- package/harness/skills/oh-expert/DEEP.md +85 -0
- package/harness/skills/oh-expert/SKILL.md +13 -106
- package/harness/skills/oh-facade/DEEP.md +182 -0
- package/harness/skills/oh-facade/SKILL.md +15 -279
- package/harness/skills/oh-freeze/DEEP.md +18 -0
- package/harness/skills/oh-freeze/SKILL.md +10 -19
- package/harness/skills/oh-full-output/DEEP.md +25 -0
- package/harness/skills/oh-full-output/SKILL.md +12 -65
- package/harness/skills/oh-fusion/DEEP.md +120 -0
- package/harness/skills/oh-fusion/SKILL.md +17 -295
- package/harness/skills/oh-gauntlet/DEEP.md +77 -0
- package/harness/skills/oh-gauntlet/SKILL.md +13 -105
- package/harness/skills/oh-grill/DEEP.md +51 -0
- package/harness/skills/oh-grill/SKILL.md +12 -63
- package/harness/skills/oh-guard/DEEP.md +19 -0
- package/harness/skills/oh-guard/SKILL.md +10 -24
- package/harness/skills/oh-handoff/DEEP.md +48 -0
- package/harness/skills/oh-handoff/SKILL.md +13 -23
- package/harness/skills/oh-health/DEEP.md +74 -0
- package/harness/skills/oh-health/SKILL.md +13 -76
- package/harness/skills/oh-init/DEEP.md +85 -0
- package/harness/skills/oh-init/SKILL.md +13 -127
- package/harness/skills/oh-investigate/DEEP.md +171 -0
- package/harness/skills/oh-investigate/SKILL.md +13 -66
- package/harness/skills/oh-issue/DEEP.md +21 -0
- package/harness/skills/oh-issue/SKILL.md +11 -27
- package/harness/skills/oh-manifest/DEEP.md +92 -0
- package/harness/skills/oh-manifest/SKILL.md +12 -109
- package/harness/skills/oh-plan-review/DEEP.md +90 -0
- package/harness/skills/oh-plan-review/SKILL.md +13 -115
- package/harness/skills/oh-planner/DEEP.md +172 -0
- package/harness/skills/oh-planner/SKILL.md +12 -149
- package/harness/skills/oh-prd/DEEP.md +45 -0
- package/harness/skills/oh-prd/SKILL.md +10 -26
- package/harness/skills/oh-refactor/DEEP.md +122 -0
- package/harness/skills/oh-refactor/SKILL.md +17 -410
- package/harness/skills/oh-retro/DEEP.md +26 -0
- package/harness/skills/oh-retro/SKILL.md +12 -24
- package/harness/skills/oh-review/DEEP.md +87 -0
- package/harness/skills/oh-review/SKILL.md +11 -97
- package/harness/skills/oh-security/DEEP.md +83 -0
- package/harness/skills/oh-security/SKILL.md +14 -96
- package/harness/skills/oh-ship/DEEP.md +141 -0
- package/harness/skills/oh-ship/SKILL.md +14 -32
- package/harness/skills/oh-skill-craft/DEEP.md +369 -0
- package/harness/skills/oh-skill-craft/SKILL.md +13 -177
- package/harness/skills/oh-skills-link/DEEP.md +16 -0
- package/harness/skills/oh-skills-link/SKILL.md +10 -20
- package/harness/skills/oh-skills-list/DEEP.md +20 -0
- package/harness/skills/oh-skills-list/SKILL.md +9 -22
- package/harness/skills/oh-triage/DEEP.md +23 -0
- package/harness/skills/oh-triage/SKILL.md +8 -24
- package/harness/skills/oh-worktree/DEEP.md +169 -0
- package/harness/skills/oh-worktree/SKILL.md +32 -0
- package/lib/harness-resolver.ts +8 -10
- package/package.json +7 -5
- package/tsconfig.json +1 -1
- package/harness/codex/CONSTITUTION.md +0 -73
- package/harness/codex/ROUTING.md +0 -92
- package/harness/commands/oh-doctor.md +0 -26
- package/harness/commands/oh-log.md +0 -18
- package/harness/instructions/RUNTIME.md +0 -30
- package/harness/skills/oh-caveman/SKILL.md +0 -42
- package/harness/skills/oh-learn/SKILL.md +0 -101
- package/lib/logger.ts +0 -75
|
@@ -1,426 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oh-refactor
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use when code is hard to maintain, functions are too long, code smells accumulate, or the user asks to clean up, improve, or refactor code. Behavior-preserving refactoring — extract, deduplicate, simplify, improve types."
|
|
4
4
|
tier: 3
|
|
5
|
-
benefits-from: [oh-investigate, oh-review]
|
|
6
|
-
triggers:
|
|
7
|
-
- "refactor"
|
|
8
|
-
- "clean up"
|
|
9
|
-
- "improve this code"
|
|
10
|
-
- "code smell"
|
|
11
|
-
- "make this better"
|
|
12
|
-
- "extract method"
|
|
13
|
-
- "reduce duplication"
|
|
14
|
-
- "fix this mess"
|
|
15
|
-
- "technical debt"
|
|
16
|
-
- "god function"
|
|
17
|
-
- "long method"
|
|
18
|
-
- "nested conditionals"
|
|
19
5
|
route:
|
|
20
6
|
pass: oh-gauntlet
|
|
21
|
-
fail:
|
|
7
|
+
fail:
|
|
8
|
+
- oh-planner
|
|
9
|
+
- oh-investigate
|
|
10
|
+
- oh-builder
|
|
22
11
|
blocker: surface
|
|
23
12
|
---
|
|
24
13
|
|
|
25
14
|
# oh-refactor
|
|
26
15
|
|
|
27
|
-
Improve code structure
|
|
16
|
+
Improve code structure without changing external behavior.
|
|
28
17
|
|
|
29
|
-
##
|
|
18
|
+
## Steps
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- Technical debt has accumulated to the point it slows development
|
|
37
|
-
|
|
38
|
-
## Refactoring Principles
|
|
39
|
-
|
|
40
|
-
### Golden Rules
|
|
41
|
-
|
|
42
|
-
1. **Behavior is preserved** — Refactoring doesn't change what the code does, only how. If the goal changes behavior, that's a feature, not a refactor.
|
|
43
|
-
2. **Small steps** — Make one change, verify, commit, repeat. Never batch refactoring changes.
|
|
44
|
-
3. **Tests are essential** — Without a fast, reliable test, you're not refactoring, you're editing blind. Write tests first if they don't exist.
|
|
45
|
-
4. **One thing at a time** — Never mix refactoring with feature changes in the same commit.
|
|
46
|
-
5. **Commit between safe states** — Commit before starting, commit after each green test run.
|
|
47
|
-
|
|
48
|
-
### When NOT to Refactor
|
|
49
|
-
|
|
50
|
-
- Code that works and will never change again
|
|
51
|
-
- Critical production code without tests (add tests first)
|
|
52
|
-
- Under a tight deadline with no test safety net
|
|
53
|
-
- "Just because" — every refactor needs a clear purpose
|
|
54
|
-
|
|
55
|
-
## Workflow
|
|
56
|
-
|
|
57
|
-
### Phase 1: Prepare
|
|
58
|
-
|
|
59
|
-
1. **Check test coverage** — run existing tests. If coverage is thin, write characterization tests that lock down current behavior before touching anything.
|
|
60
|
-
2. **Commit current state** — `git commit` so you can diff and revert cleanly.
|
|
61
|
-
3. **Create a feature branch** — isolate refactoring work from other changes.
|
|
62
|
-
|
|
63
|
-
### Phase 2: Identify
|
|
64
|
-
|
|
65
|
-
1. Find the code smell to address (see [Code Smells](#common-code-smells--fixes) below).
|
|
66
|
-
2. Understand what the code actually does — trace all code paths.
|
|
67
|
-
3. Plan the smallest refactoring that makes the problem better.
|
|
68
|
-
4. If behavior is unclear, delegate to `oh-investigate` before refactoring.
|
|
69
|
-
|
|
70
|
-
### Phase 3: Refactor (small steps)
|
|
71
|
-
|
|
72
|
-
1. Make one small change.
|
|
73
|
-
2. Run tests.
|
|
74
|
-
3. Commit if tests pass.
|
|
75
|
-
4. Repeat until the smell is gone.
|
|
76
|
-
|
|
77
|
-
### Phase 4: Verify
|
|
78
|
-
|
|
79
|
-
1. All tests pass.
|
|
80
|
-
2. Manual smoke test if full coverage is missing.
|
|
81
|
-
3. Performance unchanged or improved.
|
|
82
|
-
4. Diff shows only structural changes — no logic changes.
|
|
83
|
-
|
|
84
|
-
### Phase 5: Clean Up
|
|
85
|
-
|
|
86
|
-
1. Remove commented-out code, stale imports, dead paths.
|
|
87
|
-
2. Update inline docs only if behavior semantics changed.
|
|
88
|
-
3. Final commit.
|
|
89
|
-
4. Optionally route to `oh-review` for post-refactor quality gate.
|
|
90
|
-
|
|
91
|
-
## Common Code Smells & Fixes
|
|
92
|
-
|
|
93
|
-
### 1. Long Method/Function
|
|
94
|
-
|
|
95
|
-
```diff
|
|
96
|
-
# BAD: 200-line function that does everything
|
|
97
|
-
- async function processOrder(orderId) {
|
|
98
|
-
- // 50 lines: fetch order
|
|
99
|
-
- // 30 lines: validate order
|
|
100
|
-
- // 40 lines: calculate pricing
|
|
101
|
-
- // 30 lines: update inventory
|
|
102
|
-
- // 20 lines: create shipment
|
|
103
|
-
- // 30 lines: send notifications
|
|
104
|
-
- }
|
|
105
|
-
|
|
106
|
-
# GOOD: Broken into focused functions
|
|
107
|
-
+ async function processOrder(orderId) {
|
|
108
|
-
+ const order = await fetchOrder(orderId);
|
|
109
|
-
+ validateOrder(order);
|
|
110
|
-
+ const pricing = calculatePricing(order);
|
|
111
|
-
+ await updateInventory(order);
|
|
112
|
-
+ const shipment = await createShipment(order);
|
|
113
|
-
+ await sendNotifications(order, pricing, shipment);
|
|
114
|
-
+ return { order, pricing, shipment };
|
|
115
|
-
+ }
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### 2. Duplicated Code
|
|
119
|
-
|
|
120
|
-
```diff
|
|
121
|
-
# BAD: Same logic in multiple places
|
|
122
|
-
- function calculateUserDiscount(user) {
|
|
123
|
-
- if (user.membership === 'gold') return user.total * 0.2;
|
|
124
|
-
- if (user.membership === 'silver') return user.total * 0.1;
|
|
125
|
-
- return 0;
|
|
126
|
-
- }
|
|
127
|
-
- function calculateOrderDiscount(order) {
|
|
128
|
-
- if (order.user.membership === 'gold') return order.total * 0.2;
|
|
129
|
-
- if (order.user.membership === 'silver') return order.total * 0.1;
|
|
130
|
-
- return 0;
|
|
131
|
-
- }
|
|
132
|
-
|
|
133
|
-
# GOOD: Extract common logic
|
|
134
|
-
+ function getMembershipDiscountRate(membership) {
|
|
135
|
-
+ const rates = { gold: 0.2, silver: 0.1 };
|
|
136
|
-
+ return rates[membership] || 0;
|
|
137
|
-
+ }
|
|
138
|
-
+ function calculateUserDiscount(user) {
|
|
139
|
-
+ return user.total * getMembershipDiscountRate(user.membership);
|
|
140
|
-
+ }
|
|
141
|
-
+ function calculateOrderDiscount(order) {
|
|
142
|
-
+ return order.total * getMembershipDiscountRate(order.user.membership);
|
|
143
|
-
+ }
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### 3. Large Class/Module (God Object)
|
|
147
|
-
|
|
148
|
-
```diff
|
|
149
|
-
# BAD: God object that knows too much
|
|
150
|
-
- class UserManager {
|
|
151
|
-
- createUser() { /* ... */ }
|
|
152
|
-
- updateUser() { /* ... */ }
|
|
153
|
-
- deleteUser() { /* ... */ }
|
|
154
|
-
- sendEmail() { /* ... */ }
|
|
155
|
-
- generateReport() { /* ... */ }
|
|
156
|
-
- handlePayment() { /* ... */ }
|
|
157
|
-
- validateAddress() { /* ... */ }
|
|
158
|
-
- }
|
|
159
|
-
|
|
160
|
-
# GOOD: Single responsibility per class
|
|
161
|
-
+ class UserService {
|
|
162
|
-
+ create(data) { /* ... */ }
|
|
163
|
-
+ update(id, data) { /* ... */ }
|
|
164
|
-
+ delete(id) { /* ... */ }
|
|
165
|
-
+ }
|
|
166
|
-
+ class EmailService {
|
|
167
|
-
+ send(to, subject, body) { /* ... */ }
|
|
168
|
-
+ }
|
|
169
|
-
+ class ReportService {
|
|
170
|
-
+ generate(type, params) { /* ... */ }
|
|
171
|
-
+ }
|
|
172
|
-
+ class PaymentService {
|
|
173
|
-
+ process(amount, method) { /* ... */ }
|
|
174
|
-
+ }
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### 4. Long Parameter List
|
|
178
|
-
|
|
179
|
-
```diff
|
|
180
|
-
# BAD: Too many parameters
|
|
181
|
-
- function createUser(email, password, name, age, address, city, country, phone) { }
|
|
182
|
-
|
|
183
|
-
# GOOD: Group related parameters
|
|
184
|
-
+ interface UserData {
|
|
185
|
-
+ email: string;
|
|
186
|
-
+ password: string;
|
|
187
|
-
+ name: string;
|
|
188
|
-
+ age?: number;
|
|
189
|
-
+ address?: Address;
|
|
190
|
-
+ phone?: string;
|
|
191
|
-
+ }
|
|
192
|
-
+ function createUser(data: UserData) { }
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### 5. Feature Envy
|
|
196
|
-
|
|
197
|
-
```diff
|
|
198
|
-
# BAD: Method uses another object's data more than its own
|
|
199
|
-
- class Order {
|
|
200
|
-
- calculateDiscount(user) {
|
|
201
|
-
- if (user.membershipLevel === 'gold') return this.total * 0.2;
|
|
202
|
-
- if (user.accountAge > 365) return this.total * 0.1;
|
|
203
|
-
- return 0;
|
|
204
|
-
- }
|
|
205
|
-
- }
|
|
206
|
-
|
|
207
|
-
# GOOD: Move logic to the object that owns the data
|
|
208
|
-
+ class User {
|
|
209
|
-
+ getDiscountRate(orderTotal) {
|
|
210
|
-
+ if (this.membershipLevel === 'gold') return 0.2;
|
|
211
|
-
+ if (this.accountAge > 365) return 0.1;
|
|
212
|
-
+ return 0;
|
|
213
|
-
+ }
|
|
214
|
-
+ }
|
|
215
|
-
+ class Order {
|
|
216
|
-
+ calculateDiscount(user) {
|
|
217
|
-
+ return this.total * user.getDiscountRate(this.total);
|
|
218
|
-
+ }
|
|
219
|
-
+ }
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### 6. Primitive Obsession
|
|
223
|
-
|
|
224
|
-
```diff
|
|
225
|
-
# BAD: Using primitives for domain concepts
|
|
226
|
-
- function sendEmail(to, subject, body) { }
|
|
227
|
-
- sendEmail('user@example.com', 'Hello', '...');
|
|
228
|
-
|
|
229
|
-
# GOOD: Use domain types
|
|
230
|
-
+ class Email {
|
|
231
|
-
+ private constructor(public readonly value: string) {
|
|
232
|
-
+ if (!Email.isValid(value)) throw new Error('Invalid email');
|
|
233
|
-
+ }
|
|
234
|
-
+ static create(value: string) { return new Email(value); }
|
|
235
|
-
+ static isValid(email: string) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }
|
|
236
|
-
+ }
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### 7. Magic Numbers/Strings
|
|
240
|
-
|
|
241
|
-
```diff
|
|
242
|
-
# BAD: Unexplained values
|
|
243
|
-
- if (user.status === 2) { }
|
|
244
|
-
- const discount = total * 0.15;
|
|
245
|
-
|
|
246
|
-
# GOOD: Named constants
|
|
247
|
-
+ const UserStatus = { ACTIVE: 1, INACTIVE: 2, SUSPENDED: 3 } as const;
|
|
248
|
-
+ const DISCOUNT_RATES = { STANDARD: 0.1, PREMIUM: 0.15, VIP: 0.2 } as const;
|
|
249
|
-
+ if (user.status === UserStatus.INACTIVE) { }
|
|
250
|
-
+ const discount = total * DISCOUNT_RATES.PREMIUM;
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### 8. Nested Conditionals (Arrow Code)
|
|
254
|
-
|
|
255
|
-
```diff
|
|
256
|
-
# BAD: Arrow code
|
|
257
|
-
- function process(order) {
|
|
258
|
-
- if (order) {
|
|
259
|
-
- if (order.user) {
|
|
260
|
-
- if (order.user.isActive) {
|
|
261
|
-
- if (order.total > 0) {
|
|
262
|
-
- return processOrder(order);
|
|
263
|
-
- } else { return { error: 'Invalid total' }; }
|
|
264
|
-
- } else { return { error: 'User inactive' }; }
|
|
265
|
-
- } else { return { error: 'No user' }; }
|
|
266
|
-
- } else { return { error: 'No order' }; }
|
|
267
|
-
- }
|
|
268
|
-
|
|
269
|
-
# GOOD: Guard clauses / early returns
|
|
270
|
-
+ function process(order) {
|
|
271
|
-
+ if (!order) return { error: 'No order' };
|
|
272
|
-
+ if (!order.user) return { error: 'No user' };
|
|
273
|
-
+ if (!order.user.isActive) return { error: 'User inactive' };
|
|
274
|
-
+ if (order.total <= 0) return { error: 'Invalid total' };
|
|
275
|
-
+ return processOrder(order);
|
|
276
|
-
+ }
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### 9. Dead Code
|
|
280
|
-
|
|
281
|
-
```diff
|
|
282
|
-
# BAD: Unused code lingers
|
|
283
|
-
- function oldImplementation() { }
|
|
284
|
-
- const DEPRECATED_VALUE = 5;
|
|
285
|
-
- import { unusedThing } from './somewhere';
|
|
286
|
-
|
|
287
|
-
# GOOD: Remove it
|
|
288
|
-
+ // Delete unused functions, imports, commented-out code
|
|
289
|
-
+ // Git history has everything you need
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### 10. Inappropriate Intimacy
|
|
293
|
-
|
|
294
|
-
```diff
|
|
295
|
-
# BAD: One class reaches deep into another
|
|
296
|
-
- class OrderProcessor {
|
|
297
|
-
- process(order) {
|
|
298
|
-
- order.user.profile.address.street; // Too intimate
|
|
299
|
-
- }
|
|
300
|
-
- }
|
|
301
|
-
|
|
302
|
-
# GOOD: Ask, don't tell
|
|
303
|
-
+ class OrderProcessor {
|
|
304
|
-
+ process(order) {
|
|
305
|
-
+ order.getShippingAddress(); // Order knows how to get it
|
|
306
|
-
+ order.save();
|
|
307
|
-
+ }
|
|
308
|
-
+ }
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
## Extract Method Refactoring
|
|
312
|
-
|
|
313
|
-
```diff
|
|
314
|
-
# Before: One long function
|
|
315
|
-
- function printReport(users) {
|
|
316
|
-
- console.log('USER REPORT');
|
|
317
|
-
- console.log('============');
|
|
318
|
-
- console.log(`Total users: ${users.length}`);
|
|
319
|
-
- console.log('ACTIVE USERS');
|
|
320
|
-
- const active = users.filter(u => u.isActive);
|
|
321
|
-
- active.forEach(u => console.log(`- ${u.name} (${u.email})`));
|
|
322
|
-
- console.log(`Active: ${active.length}`);
|
|
323
|
-
- console.log('INACTIVE USERS');
|
|
324
|
-
- const inactive = users.filter(u => !u.isActive);
|
|
325
|
-
- inactive.forEach(u => console.log(`- ${u.name} (${u.email})`));
|
|
326
|
-
- console.log(`Inactive: ${inactive.length}`);
|
|
327
|
-
- }
|
|
328
|
-
|
|
329
|
-
# After: Extracted methods
|
|
330
|
-
+ function printReport(users) {
|
|
331
|
-
+ printHeader('USER REPORT');
|
|
332
|
-
+ console.log(`Total users: ${users.length}\n`);
|
|
333
|
-
+ printUserSection('ACTIVE USERS', users.filter(u => u.isActive));
|
|
334
|
-
+ printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));
|
|
335
|
-
+ }
|
|
336
|
-
+ function printHeader(title) {
|
|
337
|
-
+ const line = '='.repeat(title.length);
|
|
338
|
-
+ console.log(title); console.log(line); console.log('');
|
|
339
|
-
+ }
|
|
340
|
-
+ function printUserSection(title, users) {
|
|
341
|
-
+ console.log(title);
|
|
342
|
-
+ console.log('-'.repeat(title.length));
|
|
343
|
-
+ users.forEach(u => console.log(`- ${u.name} (${u.email})`));
|
|
344
|
-
+ console.log(`${title.split(' ')[0]}: ${users.length}`);
|
|
345
|
-
+ }
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
## Design Patterns for Refactoring
|
|
349
|
-
|
|
350
|
-
### Strategy Pattern
|
|
351
|
-
|
|
352
|
-
Replace conditional branching with composable strategies:
|
|
353
|
-
|
|
354
|
-
```diff
|
|
355
|
-
- function calculateShipping(order, method) {
|
|
356
|
-
- if (method === 'standard') return order.total > 50 ? 0 : 5.99;
|
|
357
|
-
- else if (method === 'express') return order.total > 100 ? 9.99 : 14.99;
|
|
358
|
-
- else if (method === 'overnight') return 29.99;
|
|
359
|
-
- }
|
|
360
|
-
|
|
361
|
-
+ interface ShippingStrategy { calculate(order: Order): number; }
|
|
362
|
-
+ class StandardShipping implements ShippingStrategy {
|
|
363
|
-
+ calculate(order: Order) { return order.total > 50 ? 0 : 5.99; }
|
|
364
|
-
+ }
|
|
365
|
-
+ class ExpressShipping implements ShippingStrategy {
|
|
366
|
-
+ calculate(order: Order) { return order.total > 100 ? 9.99 : 14.99; }
|
|
367
|
-
+ }
|
|
368
|
-
+ function calculateShipping(order: Order, strategy: ShippingStrategy) {
|
|
369
|
-
+ return strategy.calculate(order);
|
|
370
|
-
+ }
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Guard Clauses
|
|
374
|
-
|
|
375
|
-
Replace nested conditions with early returns. This is the single highest-ROI refactoring pattern — it flattens deeply nested code immediately.
|
|
376
|
-
|
|
377
|
-
## Common Refactoring Operations
|
|
378
|
-
|
|
379
|
-
| Operation | Description |
|
|
380
|
-
|---|---|
|
|
381
|
-
| Extract Method | Turn code fragment into named function |
|
|
382
|
-
| Extract Class | Move related behavior to new class |
|
|
383
|
-
| Inline Method | Move method body back to single caller |
|
|
384
|
-
| Rename Method/Variable | Improve clarity |
|
|
385
|
-
| Introduce Parameter Object | Group related parameters |
|
|
386
|
-
| Replace Conditional with Polymorphism | Dispatch by type instead of if/switch |
|
|
387
|
-
| Replace Magic Number with Constant | Named constants for literals |
|
|
388
|
-
| Decompose Conditional | Break complex conditions into named predicates |
|
|
389
|
-
| Consolidate Conditional | Combine duplicate conditions |
|
|
390
|
-
| Replace Nested Conditional with Guard Clauses | Early returns |
|
|
391
|
-
| Replace Inheritance with Delegation | Composition over inheritance |
|
|
392
|
-
|
|
393
|
-
## Refactoring Checklist
|
|
394
|
-
|
|
395
|
-
### Code Quality
|
|
396
|
-
- [ ] Functions are small (< 50 lines)
|
|
397
|
-
- [ ] Functions do one thing
|
|
398
|
-
- [ ] No duplicated code
|
|
399
|
-
- [ ] Descriptive names (variables, functions, classes)
|
|
400
|
-
- [ ] No magic numbers/strings
|
|
401
|
-
- [ ] Dead code removed
|
|
402
|
-
|
|
403
|
-
### Structure
|
|
404
|
-
- [ ] Related code is together
|
|
405
|
-
- [ ] Clear module boundaries
|
|
406
|
-
- [ ] Dependencies flow in one direction
|
|
407
|
-
- [ ] No circular dependencies
|
|
408
|
-
|
|
409
|
-
### Type Safety
|
|
410
|
-
- [ ] Types defined for all public APIs
|
|
411
|
-
- [ ] No `any` types without justification
|
|
412
|
-
- [ ] Nullable types explicitly marked
|
|
413
|
-
|
|
414
|
-
### Testing
|
|
415
|
-
- [ ] Refactored code is tested
|
|
416
|
-
- [ ] Tests cover edge cases
|
|
417
|
-
- [ ] All tests pass
|
|
20
|
+
1. Prepare — check test coverage. Write characterization tests if thin. Commit current state. Create feature branch.
|
|
21
|
+
2. Identify — find code smell. Understand what the code does. Plan the smallest fix.
|
|
22
|
+
3. Refactor in small steps — one change, run tests, commit. Repeat until smell is gone.
|
|
23
|
+
4. Verify — all tests pass, manual smoke test if coverage missing, performance unchanged, diff shows structural changes only.
|
|
24
|
+
5. Clean up — remove commented-out code, stale imports, dead paths. Update docs only if semantics changed.
|
|
418
25
|
|
|
419
26
|
## Routing
|
|
420
27
|
|
|
421
28
|
| Outcome | Route |
|
|
422
|
-
|
|
423
|
-
| pass |
|
|
424
|
-
| behavior unclear |
|
|
425
|
-
| test gap found |
|
|
426
|
-
| blocker |
|
|
29
|
+
|---------|-------|
|
|
30
|
+
| pass | → oh-gauntlet (test integrity) |
|
|
31
|
+
| behavior unclear | → oh-investigate |
|
|
32
|
+
| test gap found | → oh-builder (TDD mode) |
|
|
33
|
+
| blocker | → surface |
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# oh-retro — Deep Reference
|
|
2
|
+
|
|
3
|
+
## When to Use
|
|
4
|
+
|
|
5
|
+
End of sprint or work week. Analyze shipped work, how it went, what to improve.
|
|
6
|
+
|
|
7
|
+
## Workflow
|
|
8
|
+
|
|
9
|
+
1. Read git log since last retro
|
|
10
|
+
2. Categorize: features, fixes, refactors, docs, chores
|
|
11
|
+
3. Pattern analysis: recurring themes, bottlenecks, bug types
|
|
12
|
+
4. Praise: good work, patterns, decisions
|
|
13
|
+
5. Growth areas: specific suggestions for improvement
|
|
14
|
+
6. Trend tracking: compare to previous retros
|
|
15
|
+
|
|
16
|
+
## Output
|
|
17
|
+
|
|
18
|
+
Structured retro: shipped items, metrics, praise, growth areas, action items.
|
|
19
|
+
|
|
20
|
+
**Example:** End of sprint. Read git log → categorize (features, fixes, refactors) → pattern analysis → praise → growth areas → action items.
|
|
21
|
+
|
|
22
|
+
## Anti-patterns
|
|
23
|
+
|
|
24
|
+
- Blame-focused (process, not people)
|
|
25
|
+
- Action items without owners
|
|
26
|
+
- Same retro every week (nothing changed → why?)
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oh-retro
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use at the end of a sprint or milestone to analyze commit history, work patterns, and extract actionable insights for the next cycle."
|
|
4
4
|
tier: 3
|
|
5
|
-
triggers:
|
|
6
|
-
- "retrospective"
|
|
7
|
-
- "retro for"
|
|
8
|
-
- "post-ship review"
|
|
9
5
|
route:
|
|
10
6
|
pass: oh-planner
|
|
11
7
|
fail: oh-handoff
|
|
@@ -14,29 +10,21 @@ route:
|
|
|
14
10
|
|
|
15
11
|
# oh-retro
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
At the end of a sprint or work week. Analyzes what was shipped, how it went, and what to improve.
|
|
13
|
+
Analyze shipped work and extract actionable insights for the next cycle.
|
|
19
14
|
|
|
20
|
-
##
|
|
21
|
-
1. **Analyze commits** — read git log since last retro
|
|
22
|
-
2. **Categorize work** — features, fixes, refactors, docs, chores
|
|
23
|
-
3. **Pattern analysis** — recurring themes, bottlenecks, types of bugs
|
|
24
|
-
4. **Praise** — call out good work, good patterns, good decisions
|
|
25
|
-
5. **Growth areas** — what could be better, with specific suggestions
|
|
26
|
-
6. **Trend tracking** — compare against previous retros
|
|
15
|
+
## Steps
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- Same retro every week (if nothing changed, why?)
|
|
17
|
+
1. Read git log since last retro
|
|
18
|
+
2. Categorize commits: features, fixes, refactors, docs, chores
|
|
19
|
+
3. Analyze recurring themes, bottlenecks, and bug types
|
|
20
|
+
4. Document praise: good work, patterns, decisions
|
|
21
|
+
5. Identify growth areas with specific improvement suggestions
|
|
22
|
+
6. Track trends against previous retros
|
|
35
23
|
|
|
36
24
|
## Routing
|
|
37
25
|
|
|
38
26
|
| Outcome | Route |
|
|
39
27
|
|---------|-------|
|
|
40
|
-
| pass | → oh-planner
|
|
41
|
-
| fail | → oh-handoff
|
|
42
|
-
| blocker | → surface
|
|
28
|
+
| pass | → oh-planner |
|
|
29
|
+
| fail | → oh-handoff |
|
|
30
|
+
| blocker | → surface |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# oh-review — Deep Reference
|
|
2
|
+
|
|
3
|
+
## Mode A: Diff Review
|
|
4
|
+
|
|
5
|
+
### 1. Pin Fixed Point
|
|
6
|
+
User provides branch/commit/tag. Capture `git diff <fixed>...HEAD` + `git log <fixed>..HEAD --oneline`.
|
|
7
|
+
|
|
8
|
+
### 2. Find Spec Source (order)
|
|
9
|
+
1. Issue refs in commit messages (`#123`, `Closes #45`)
|
|
10
|
+
2. User-provided path
|
|
11
|
+
3. `docs/`, `specs/`, `.scratch/` files
|
|
12
|
+
4. Ask user
|
|
13
|
+
|
|
14
|
+
No spec found → spec sub-agent reports "no spec available."
|
|
15
|
+
|
|
16
|
+
### 3. Find Standards Sources
|
|
17
|
+
AGENTS.md, CLAUDE.md, CONTRIBUTING.md, CONTEXT.md, ADRs, eslint/biome/prettier config (note tool-enforced — don't re-check).
|
|
18
|
+
|
|
19
|
+
### 4. Spawn Sub-Agents (parallel)
|
|
20
|
+
- **Standards** — Read standards + diff. Per-file/hunk: violations citing standard + rule. Distinguish hard violations from judgment calls. Skip tool-enforced.
|
|
21
|
+
- **Spec** — Read spec + diff. Report: missing/partial requirements, scope creep, wrong implementations. Quote spec line.
|
|
22
|
+
|
|
23
|
+
### 5. Aggregate
|
|
24
|
+
Present under `## Standards` / `## Spec`. Do not merge. End with total + worst issue.
|
|
25
|
+
|
|
26
|
+
### Safety Check (inline before spawning)
|
|
27
|
+
- SQL injection, LLM trust boundary violations, conditional side effects (test vs prod), hardcoded secrets
|
|
28
|
+
- Block immediately if critical — do not spawn sub-agents.
|
|
29
|
+
|
|
30
|
+
## Mode B: Architecture Deepening
|
|
31
|
+
|
|
32
|
+
Surface refactoring opportunities using the **deletion test**: deleting a shallow module concentrates complexity; a deep module's complexity vanishes.
|
|
33
|
+
|
|
34
|
+
### Vocabulary
|
|
35
|
+
- **Module** — interface + implementation
|
|
36
|
+
- **Depth** — leverage at interface (lots of behavior, small interface)
|
|
37
|
+
- **Seam** — where interface lives; place to alter behavior without in-place edit
|
|
38
|
+
- **Leverage** — what callers get from depth
|
|
39
|
+
- **Locality** — change concentrated in one place
|
|
40
|
+
|
|
41
|
+
### Process
|
|
42
|
+
1. **Explore** — Read CONTEXT.md, ADRs. Walk codebase for friction (bouncing between modules, shallow interfaces, deletion test candidates).
|
|
43
|
+
2. **Present candidates** — Numbered. Files, problem, solution, locality/leverage benefits. Flag ADR conflicts.
|
|
44
|
+
3. **Grilling loop** — Walk design tree. Update CONTEXT.md for new terms. Offer ADRs for rejected candidates.
|
|
45
|
+
4. **Output** — Ranked refactoring candidates with collision warnings.
|
|
46
|
+
|
|
47
|
+
## Mode C: Receiving Review Feedback
|
|
48
|
+
|
|
49
|
+
**Pattern:** READ → UNDERSTAND → VERIFY → EVALUATE → RESPOND → IMPLEMENT
|
|
50
|
+
|
|
51
|
+
### Banned Responses
|
|
52
|
+
Never: "You're absolutely right!", "Great point!", "Excellent feedback!", any gratitude. Instead: restate technical requirement, ask clarifying questions, or just implement.
|
|
53
|
+
|
|
54
|
+
### Source-Specific Handling
|
|
55
|
+
- **Partner (trusted):** Still verify. No performative agreement. Skip to action or technical acknowledgment.
|
|
56
|
+
- **External reviewer (skeptical):** Check 5 things before implementing — technically correct? Breaks existing? Full context? Cross-platform? Conflicts with prior decisions?
|
|
57
|
+
|
|
58
|
+
### YAGNI Check
|
|
59
|
+
If reviewer says "implement properly", grep for actual usage. Unused → propose removal. Used → implement.
|
|
60
|
+
|
|
61
|
+
### Implementation Order
|
|
62
|
+
1. Clarify unclear items FIRST (partial understanding = wrong implementation)
|
|
63
|
+
2. Blocker fixes (breaks, security)
|
|
64
|
+
3. Simple fixes (typos, imports)
|
|
65
|
+
4. Complex fixes (refactoring, logic)
|
|
66
|
+
5. Test each individually, verify no regressions
|
|
67
|
+
|
|
68
|
+
### When to Push Back
|
|
69
|
+
Suggestion breaks existing functionality, reviewer lacks context, violates YAGNI, technically incorrect for this stack, conflicts with architecture decisions. Use technical reasoning, not defensiveness.
|
|
70
|
+
|
|
71
|
+
### Graceful Correction
|
|
72
|
+
If you pushed back and were wrong: state factually — "You were right, checked [X], it does [Y]. Fixing now." No long apologies, no defending, no over-explaining.
|
|
73
|
+
|
|
74
|
+
## Scoring
|
|
75
|
+
- Critical safety → block before sub-agents
|
|
76
|
+
- Structural concern / spec deviation → changes requested
|
|
77
|
+
- Style/nit → follow-up note
|
|
78
|
+
|
|
79
|
+
## Anti-patterns
|
|
80
|
+
- Style before safety
|
|
81
|
+
- Rubber-stamping without reading diff
|
|
82
|
+
- Subjective preference changes
|
|
83
|
+
- Merging Standards + Spec findings (one axis masks the other)
|
|
84
|
+
- Proposing interfaces before user picks a candidate
|
|
85
|
+
- Performative agreement (thanking reviewer before verifying)
|
|
86
|
+
- Blind implementation of reviewer suggestions
|
|
87
|
+
- Mixing feedback handling modes
|