openhermes 4.1.0 → 4.3.0

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.
Files changed (42) hide show
  1. package/ETHOS.md +6 -3
  2. package/LICENSE +21 -21
  3. package/README.md +109 -79
  4. package/bootstrap.ts +214 -8
  5. package/harness/agents/openhermes.md +45 -55
  6. package/harness/codex/AUTOPILOT.md +126 -0
  7. package/harness/codex/CONSTITUTION.md +14 -11
  8. package/harness/codex/ROUTING.md +35 -70
  9. package/harness/commands/oh-log.md +18 -0
  10. package/harness/instructions/RUNTIME.md +27 -52
  11. package/harness/skills/oh-builder/SKILL.md +13 -8
  12. package/harness/skills/oh-caveman/SKILL.md +9 -0
  13. package/harness/skills/oh-expert/SKILL.md +6 -0
  14. package/harness/skills/oh-facade/SKILL.md +298 -0
  15. package/harness/skills/oh-freeze/SKILL.md +9 -0
  16. package/harness/skills/oh-full-output/SKILL.md +81 -0
  17. package/harness/skills/oh-fusion/SKILL.md +314 -0
  18. package/harness/skills/oh-gauntlet/SKILL.md +9 -5
  19. package/harness/skills/oh-grill/SKILL.md +9 -5
  20. package/harness/skills/oh-guard/SKILL.md +9 -0
  21. package/harness/skills/oh-handoff/SKILL.md +9 -0
  22. package/harness/skills/oh-health/SKILL.md +8 -4
  23. package/harness/skills/oh-init/SKILL.md +28 -94
  24. package/harness/skills/oh-investigate/SKILL.md +10 -0
  25. package/harness/skills/oh-issue/SKILL.md +9 -0
  26. package/harness/skills/oh-learn/SKILL.md +13 -4
  27. package/harness/skills/oh-manifest/SKILL.md +15 -10
  28. package/harness/skills/oh-plan-review/SKILL.md +15 -8
  29. package/harness/skills/oh-planner/SKILL.md +18 -8
  30. package/harness/skills/oh-prd/SKILL.md +9 -0
  31. package/harness/skills/oh-refactor/SKILL.md +426 -0
  32. package/harness/skills/oh-retro/SKILL.md +9 -0
  33. package/harness/skills/oh-review/SKILL.md +11 -4
  34. package/harness/skills/oh-security/SKILL.md +4 -0
  35. package/harness/skills/oh-ship/SKILL.md +10 -0
  36. package/harness/skills/oh-skill-craft/SKILL.md +88 -0
  37. package/harness/skills/oh-skills-link/SKILL.md +9 -0
  38. package/harness/skills/oh-skills-list/SKILL.md +9 -0
  39. package/harness/skills/oh-triage/SKILL.md +11 -0
  40. package/lib/harness-resolver.ts +2 -2
  41. package/lib/logger.ts +7 -1
  42. package/package.json +6 -3
@@ -1,6 +1,15 @@
1
1
  ---
2
2
  name: oh-learn
3
3
  description: "Extract, evolve, and promote session learnings as instincts. Review, search, prune, export."
4
+ tier: 2
5
+ triggers:
6
+ - "learn from session"
7
+ - "extract patterns"
8
+ - "run oh-learn"
9
+ route:
10
+ pass: done
11
+ fail: surface
12
+ blocker: surface
4
13
  ---
5
14
 
6
15
  # oh-learn
@@ -9,7 +18,7 @@ Learning engine for the harness. Distills patterns from sessions into **instinct
9
18
 
10
19
  ## Instinct Data Model
11
20
 
12
- Every learning stored as one JSONL line in `.opencode/instincts.jsonl`:
21
+ Every learning stored as one JSONL line in `~/.local/share/opencode/openhermes/plans/<project-name>-instincts.jsonl`:
13
22
 
14
23
  ```json
15
24
  { "trigger": "situation pattern", "action": "recommended response", "confidence": 0.5, "applications": 1, "successes": 1, "category": "coding", "source": "oh-learn:extract", "ts": "2026-05-15T12:00:00Z" }
@@ -32,7 +41,7 @@ Mine the current session for reusable patterns.
32
41
 
33
42
  1. Scan recent conversation + code changes for repeated decision patterns
34
43
  2. For each distinct pattern write an instinct: trigger, action, confidence=0.5, category
35
- 3. Read existing `.opencode/instincts.jsonl`, check for near-duplicate triggers
44
+ 3. Read existing `~/.local/share/opencode/openhermes/plans/<project-name>-instincts.jsonl`, check for near-duplicate triggers
36
45
  4. If duplicate found: merge — `confidence = max(existing, 0.8 × new)`, increment applications
37
46
  5. If new: append line to file
38
47
 
@@ -43,7 +52,7 @@ Mine the current session for reusable patterns.
43
52
  ### Evolve
44
53
  Cluster related instincts into skill/command/agent candidates.
45
54
 
46
- 1. Read all instincts from `.opencode/instincts.jsonl`
55
+ 1. Read all instincts from `~/.local/share/opencode/openhermes/plans/<project-name>-instincts.jsonl`
47
56
  2. Group by `category`, then by trigger topic similarity
48
57
  3. **If cluster ≥ 5 instincts AND avg confidence ≥ 0.7** → generate `oh-skill-craft` spec for a new skill
49
58
  4. **If cluster 3-4 instincts with confidence ≥ 0.8** → suggest update to existing skill
@@ -52,7 +61,7 @@ Cluster related instincts into skill/command/agent candidates.
52
61
  ### Promote
53
62
  Graduate high-confidence instincts from project to global scope.
54
63
 
55
- 1. Scan `.opencode/instincts.jsonl` for instincts with `confidence >= 0.85 AND applications >= 10`
64
+ 1. Scan `~/.local/share/opencode/openhermes/plans/<project-name>-instincts.jsonl` for instincts with `confidence >= 0.85 AND applications >= 10`
56
65
  2. Filter out project-specific patterns (reference paths, local APIs, domain terms)
57
66
  3. Append filtered candidates to `%USERPROFILE%\.config\opencode\instincts.jsonl` (global)
58
67
  4. Tag promoted instincts with `"promoted": true` in project file
@@ -4,13 +4,18 @@ description: "Full build loop: plan → build → verify → loop until done or
4
4
  tier: 4
5
5
  benefits-from: [oh-planner, oh-builder, oh-expert]
6
6
  triggers:
7
- - "manifest"
8
- - "full build"
7
+ - "run the full build"
8
+ - "full build pipeline"
9
9
  - "build loop"
10
10
  - "build until done"
11
- - "orchestrate"
12
- - "pipeline"
11
+ - "orchestrate this build"
12
+ - "pipeline from plan"
13
13
  - "run the plan"
14
+ - "manifest this"
15
+ route:
16
+ pass: oh-planner
17
+ fail: oh-expert
18
+ blocker: surface
14
19
  ---
15
20
 
16
21
  # oh-manifest
@@ -31,21 +36,21 @@ Before any work begins, ALL of these MUST pass:
31
36
  If any check fails → **STOP**. Report which check failed and why. Do not proceed to Phase 1 until the blocker is resolved.
32
37
 
33
38
  ### Step 1: Plan
34
- - If `.opencode/plan.md` exists, load and verify it is current
39
+ - If a plan file (`~/.local/share/opencode/openhermes/plans/<project-name>-plan-<nnn>.md`) exists, load and verify it is current
35
40
  - If not, run `oh-planner` (Mode A, B, or C depending on context)
36
41
  - Auto-decide minor scope decisions using decision principles
37
42
  - Surface only: premises that need human judgment, or plan/alternative conflicts
38
43
 
39
44
  ### Step 2: Build
40
- - For each phase in plan.md, run `oh-builder` (Mode D: From Plan)
45
+ - For each phase in the plan file, run `oh-builder` (Mode D: From Plan)
41
46
  - Implements phases in dependency order
42
47
  - Parallelizable phases may be delegated to sub-agents
43
48
  - Auto-decide implementation choices using decision principles
44
49
 
45
50
  ### Step 3: Verify
46
- - Check each phase against its verification criteria in plan.md
51
+ - Check each phase against its verification criteria in the plan file
47
52
  - Run tests if they exist
48
- - If phase passes: mark complete in plan.md, proceed to next
53
+ - If phase passes: mark complete in plan file, proceed to next
49
54
  - If phase fails: diagnose (use oh-expert self-diagnosis), fix, re-verify
50
55
  - If fix is impossible within scope: surface blocker
51
56
 
@@ -110,8 +115,8 @@ When a blocker is encountered:
110
115
  - Auto-deciding premises (fundamental assumptions need user input)
111
116
  - Pushing through blockers (surface immediately, don't try 5 workarounds silently)
112
117
  - Skipping verification (verify every phase, not just the final result)
113
- - Parallelizing dependent phases (respect the dependency order in plan.md)
114
- - Forgetting to update plan.md with completion status
118
+ - Parallelizing dependent phases (respect the dependency order in the plan file)
119
+ - Forgetting to update the plan file with completion status
115
120
  - Ignoring escalation triggers (stall means pause, not try harder)
116
121
 
117
122
  ## Routing
@@ -4,15 +4,22 @@ description: "Multi-lens plan review: 4 perspectives in one skill. Choose Engine
4
4
  tier: 3
5
5
  benefits-from: [oh-planner, oh-expert]
6
6
  triggers:
7
- - "plan review"
8
- - "review the plan"
9
- - "architecture review"
10
- - "design review"
11
- - "ux review"
12
- - "dx review"
7
+ - "review this plan"
8
+ - "review the plan file"
9
+ - "architecture review of"
10
+ - "design review the plan"
11
+ - "ux review this plan"
12
+ - "dx review the plan"
13
13
  - "strategy review"
14
- - "eng review"
14
+ - "engineering review"
15
15
  - "ceo review"
16
+ - "review plan from"
17
+ route:
18
+ pass:
19
+ - oh-grill
20
+ - oh-manifest
21
+ fail: oh-planner
22
+ blocker: surface
16
23
  ---
17
24
 
18
25
  # oh-plan-review
@@ -110,7 +117,7 @@ Product/CEO review with 4 scope modes.
110
117
 
111
118
  ## Output
112
119
 
113
- After each lens, the plan file (`/.opencode/plan.md`) is updated with findings and decisions. The user reviews and accepts changes interactively.
120
+ After each lens, the plan file (`~/.local/share/opencode/openhermes/plans/<project-name>-plan-<nnn>.md`) is updated with findings and decisions. The user reviews and accepts changes interactively.
114
121
 
115
122
  ## Rules
116
123
 
@@ -6,17 +6,23 @@ benefits-from: [oh-expert, oh-grill]
6
6
  triggers:
7
7
  - "plan this"
8
8
  - "how should I build"
9
- - "architecture"
9
+ - "plan the architecture for"
10
10
  - "design this feature"
11
11
  - "brainstorm"
12
12
  - "autoplan"
13
- - "strategy"
14
- - "scope this"
13
+ - "strategy for this feature"
14
+ - "scope this feature"
15
+ - "create a plan for"
16
+ - "whats the plan for"
17
+ route:
18
+ pass: oh-grill
19
+ fail: oh-planner
20
+ blocker: surface
15
21
  ---
16
22
 
17
23
  # oh-planner
18
24
 
19
- The ALL-arounder planner. Merges brainstorm, architecture analysis, strategy review, and automatic plan review into one skill. Produces `.opencode/plan.md` that oh-builder consumes.
25
+ The ALL-arounder planner. Merges brainstorm, architecture analysis, strategy review, and automatic plan review into one skill. Produces a plan file in OpenCode's canonical storage at `~/.local/share/opencode/openhermes/plans/`.
20
26
 
21
27
  ## Entry Modes
22
28
 
@@ -80,9 +86,7 @@ Never auto-decide: premises (need human judgment) or cases where both the plan a
80
86
 
81
87
  ## Plan Artifact
82
88
 
83
- Output goes in `.opencode/plan.md` (per-project, overwritten each session) with this structure (matching the global AGENTS.md schema).
84
-
85
- **Then save a copy** to `%USERPROFILE%/.config/opencode/task/<project-name>-plan-<nnn>.md` (global, incrementing, persistent) per AGENTS.md persistent plan rules.
89
+ Output goes in `~/.local/share/opencode/openhermes/plans/<project-name>-plan-<nnn>.md` (OpenCode's canonical storage, sequence-numbered per-session/project). The plan ID matches the filename.
86
90
 
87
91
  ```markdown
88
92
  # PLAN: <project-name>
@@ -93,7 +97,7 @@ Status: active
93
97
  Created: <local-date-time>
94
98
  Updated: <local-date-time>
95
99
  Project Path: <absolute-project-path>
96
- Plan Path: .opencode/plan.md
100
+ Plan Path: ~/.local/share/opencode/openhermes/plans/<project-name>-plan-<nnn>.md
97
101
  Objective: <short objective>
98
102
 
99
103
  ## Current State
@@ -123,6 +127,10 @@ Objective: <short objective>
123
127
 
124
128
  - <what's done>
125
129
 
130
+ ## Work Log
131
+
132
+ <timestamped entries for subagent handoffs>
133
+
126
134
  ## Blockers
127
135
 
128
136
  - None
@@ -142,6 +150,8 @@ Objective: <short objective>
142
150
  <anything else>
143
151
  ```
144
152
 
153
+ The plan file is self-contained — Tasks, Completed, Subagents, and Work Log sections eliminate the need for separate todo.md or work-log.md files.
154
+
145
155
  ## Anti-patterns
146
156
  - Skipping strategy review for complex features (architecture mistakes compound)
147
157
  - Plans at wrong granularity — too vague to execute or too detailed to read
@@ -1,6 +1,15 @@
1
1
  ---
2
2
  name: oh-prd
3
3
  description: "Turn conversation context into a PRD and publish as GitHub issue"
4
+ tier: 2
5
+ triggers:
6
+ - "write a prd"
7
+ - "product requirements"
8
+ - "prd for"
9
+ route:
10
+ pass: oh-issue
11
+ fail: oh-grill
12
+ blocker: surface
4
13
  ---
5
14
 
6
15
  # oh-prd
@@ -0,0 +1,426 @@
1
+ ---
2
+ name: oh-refactor
3
+ description: "Surgical, behavior-preserving code refactoring. Extract functions, eliminate duplication, improve type safety, remove dead code, simplify conditionals. Use when code is hard to maintain, functions are too long, code smells accumulate, or user asks to clean up/improve/refactor code."
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
+ route:
20
+ pass: oh-gauntlet
21
+ fail: oh-planner
22
+ blocker: surface
23
+ ---
24
+
25
+ # oh-refactor
26
+
27
+ Improve code structure and readability **without changing external behavior**. Refactoring is gradual evolution, not revolution.
28
+
29
+ ## When to Use
30
+
31
+ - Code is hard to understand or maintain
32
+ - Functions/classes are too large
33
+ - Code smells need addressing
34
+ - Adding features is difficult due to code structure
35
+ - User asks "clean up this code", "refactor this", "improve this"
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
418
+
419
+ ## Routing
420
+
421
+ | Outcome | Route |
422
+ |---|---|
423
+ | pass | -> oh-review (post-refactor quality gate) |
424
+ | behavior unclear | -> oh-investigate (diagnose before refactoring) |
425
+ | test gap found | -> oh-builder TDD mode (add characterization tests first) |
426
+ | blocker | -> surface to user |
@@ -1,6 +1,15 @@
1
1
  ---
2
2
  name: oh-retro
3
3
  description: "Weekly engineering retrospective — analyze commit history and work patterns"
4
+ tier: 3
5
+ triggers:
6
+ - "retrospective"
7
+ - "retro for"
8
+ - "post-ship review"
9
+ route:
10
+ pass: oh-planner
11
+ fail: oh-handoff
12
+ blocker: surface
4
13
  ---
5
14
 
6
15
  # oh-retro