@kata-sh/cli 0.1.0 → 0.1.1
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/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/app-paths.d.ts +4 -0
- package/dist/app-paths.js +6 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +56 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +95 -0
- package/dist/resource-loader.d.ts +18 -0
- package/dist/resource-loader.js +50 -0
- package/dist/wizard.d.ts +15 -0
- package/dist/wizard.js +159 -0
- package/package.json +50 -21
- package/pkg/dist/modes/interactive/theme/dark.json +85 -0
- package/pkg/dist/modes/interactive/theme/light.json +84 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.js +949 -0
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -0
- package/pkg/package.json +8 -0
- package/scripts/postinstall.js +45 -0
- package/src/resources/AGENTS.md +108 -0
- package/src/resources/KATA-WORKFLOW.md +661 -0
- package/src/resources/agents/researcher.md +29 -0
- package/src/resources/agents/scout.md +56 -0
- package/src/resources/agents/worker.md +31 -0
- package/src/resources/extensions/ask-user-questions.ts +200 -0
- package/src/resources/extensions/bg-shell/index.ts +2758 -0
- package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/src/resources/extensions/browser-tools/core.js +1057 -0
- package/src/resources/extensions/browser-tools/index.ts +4916 -0
- package/src/resources/extensions/browser-tools/package.json +20 -0
- package/src/resources/extensions/context7/index.ts +428 -0
- package/src/resources/extensions/context7/package.json +11 -0
- package/src/resources/extensions/get-secrets-from-user.ts +352 -0
- package/src/resources/extensions/github/formatters.ts +207 -0
- package/src/resources/extensions/github/gh-api.ts +537 -0
- package/src/resources/extensions/github/index.ts +778 -0
- package/src/resources/extensions/kata/activity-log.ts +88 -0
- package/src/resources/extensions/kata/auto.ts +2786 -0
- package/src/resources/extensions/kata/commands.ts +355 -0
- package/src/resources/extensions/kata/crash-recovery.ts +85 -0
- package/src/resources/extensions/kata/dashboard-overlay.ts +516 -0
- package/src/resources/extensions/kata/docs/preferences-reference.md +103 -0
- package/src/resources/extensions/kata/doctor.ts +683 -0
- package/src/resources/extensions/kata/files.ts +730 -0
- package/src/resources/extensions/kata/gitignore.ts +165 -0
- package/src/resources/extensions/kata/guided-flow.ts +976 -0
- package/src/resources/extensions/kata/index.ts +556 -0
- package/src/resources/extensions/kata/metrics.ts +397 -0
- package/src/resources/extensions/kata/observability-validator.ts +408 -0
- package/src/resources/extensions/kata/package.json +11 -0
- package/src/resources/extensions/kata/paths.ts +346 -0
- package/src/resources/extensions/kata/preferences.ts +695 -0
- package/src/resources/extensions/kata/prompt-loader.ts +50 -0
- package/src/resources/extensions/kata/prompts/complete-milestone.md +25 -0
- package/src/resources/extensions/kata/prompts/complete-slice.md +27 -0
- package/src/resources/extensions/kata/prompts/discuss.md +151 -0
- package/src/resources/extensions/kata/prompts/doctor-heal.md +29 -0
- package/src/resources/extensions/kata/prompts/execute-task.md +64 -0
- package/src/resources/extensions/kata/prompts/guided-complete-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-milestone.md +3 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-slice.md +59 -0
- package/src/resources/extensions/kata/prompts/guided-execute-task.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-plan-milestone.md +23 -0
- package/src/resources/extensions/kata/prompts/guided-plan-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-research-slice.md +11 -0
- package/src/resources/extensions/kata/prompts/guided-resume-task.md +1 -0
- package/src/resources/extensions/kata/prompts/plan-milestone.md +47 -0
- package/src/resources/extensions/kata/prompts/plan-slice.md +63 -0
- package/src/resources/extensions/kata/prompts/queue.md +85 -0
- package/src/resources/extensions/kata/prompts/reassess-roadmap.md +48 -0
- package/src/resources/extensions/kata/prompts/replan-slice.md +39 -0
- package/src/resources/extensions/kata/prompts/research-milestone.md +37 -0
- package/src/resources/extensions/kata/prompts/research-slice.md +28 -0
- package/src/resources/extensions/kata/prompts/run-uat.md +109 -0
- package/src/resources/extensions/kata/prompts/system.md +341 -0
- package/src/resources/extensions/kata/session-forensics.ts +550 -0
- package/src/resources/extensions/kata/skill-discovery.ts +137 -0
- package/src/resources/extensions/kata/state.ts +509 -0
- package/src/resources/extensions/kata/templates/context.md +76 -0
- package/src/resources/extensions/kata/templates/decisions.md +8 -0
- package/src/resources/extensions/kata/templates/milestone-summary.md +73 -0
- package/src/resources/extensions/kata/templates/plan.md +133 -0
- package/src/resources/extensions/kata/templates/preferences.md +15 -0
- package/src/resources/extensions/kata/templates/project.md +31 -0
- package/src/resources/extensions/kata/templates/reassessment.md +28 -0
- package/src/resources/extensions/kata/templates/requirements.md +81 -0
- package/src/resources/extensions/kata/templates/research.md +46 -0
- package/src/resources/extensions/kata/templates/roadmap.md +118 -0
- package/src/resources/extensions/kata/templates/slice-context.md +58 -0
- package/src/resources/extensions/kata/templates/slice-summary.md +99 -0
- package/src/resources/extensions/kata/templates/state.md +19 -0
- package/src/resources/extensions/kata/templates/task-plan.md +52 -0
- package/src/resources/extensions/kata/templates/task-summary.md +57 -0
- package/src/resources/extensions/kata/templates/uat.md +54 -0
- package/src/resources/extensions/kata/tests/activity-log-prune.test.ts +327 -0
- package/src/resources/extensions/kata/tests/auto-preflight.test.ts +97 -0
- package/src/resources/extensions/kata/tests/auto-supervisor.test.mjs +53 -0
- package/src/resources/extensions/kata/tests/complete-milestone.test.ts +317 -0
- package/src/resources/extensions/kata/tests/cost-projection.test.ts +160 -0
- package/src/resources/extensions/kata/tests/derive-state-deps.test.ts +477 -0
- package/src/resources/extensions/kata/tests/derive-state.test.ts +1013 -0
- package/src/resources/extensions/kata/tests/doctor.test.ts +718 -0
- package/src/resources/extensions/kata/tests/idle-recovery.test.ts +490 -0
- package/src/resources/extensions/kata/tests/metrics-io.test.ts +254 -0
- package/src/resources/extensions/kata/tests/metrics.test.ts +217 -0
- package/src/resources/extensions/kata/tests/must-have-parser.test.ts +309 -0
- package/src/resources/extensions/kata/tests/parsers.test.ts +1257 -0
- package/src/resources/extensions/kata/tests/plan-milestone.test.ts +185 -0
- package/src/resources/extensions/kata/tests/plan-quality-validator.test.ts +386 -0
- package/src/resources/extensions/kata/tests/reassess-prompt.test.ts +208 -0
- package/src/resources/extensions/kata/tests/replan-slice.test.ts +686 -0
- package/src/resources/extensions/kata/tests/requirements.test.ts +151 -0
- package/src/resources/extensions/kata/tests/resolve-ts-hooks.mjs +17 -0
- package/src/resources/extensions/kata/tests/resolve-ts.mjs +11 -0
- package/src/resources/extensions/kata/tests/run-uat.test.ts +383 -0
- package/src/resources/extensions/kata/tests/unit-runtime.test.ts +388 -0
- package/src/resources/extensions/kata/tests/workspace-index.test.ts +118 -0
- package/src/resources/extensions/kata/tests/worktree.test.ts +222 -0
- package/src/resources/extensions/kata/types.ts +159 -0
- package/src/resources/extensions/kata/unit-runtime.ts +163 -0
- package/src/resources/extensions/kata/workspace-index.ts +203 -0
- package/src/resources/extensions/kata/worktree.ts +182 -0
- package/src/resources/extensions/mac-tools/index.ts +852 -0
- package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/src/resources/extensions/search-the-web/cache.ts +78 -0
- package/src/resources/extensions/search-the-web/format.ts +258 -0
- package/src/resources/extensions/search-the-web/http.ts +238 -0
- package/src/resources/extensions/search-the-web/index.ts +68 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +519 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +404 -0
- package/src/resources/extensions/search-the-web/tool-search.ts +503 -0
- package/src/resources/extensions/search-the-web/url-utils.ts +91 -0
- package/src/resources/extensions/shared/confirm-ui.ts +126 -0
- package/src/resources/extensions/shared/interview-ui.ts +822 -0
- package/src/resources/extensions/shared/next-action-ui.ts +235 -0
- package/src/resources/extensions/shared/progress-widget.ts +282 -0
- package/src/resources/extensions/shared/thinking-widget.ts +107 -0
- package/src/resources/extensions/shared/ui.ts +400 -0
- package/src/resources/extensions/shared/wizard-ui.ts +551 -0
- package/src/resources/extensions/slash-commands/audit.ts +92 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +375 -0
- package/src/resources/extensions/slash-commands/create-slash-command.ts +280 -0
- package/src/resources/extensions/slash-commands/index.ts +12 -0
- package/src/resources/extensions/slash-commands/kata-run.ts +34 -0
- package/src/resources/extensions/subagent/agents.ts +126 -0
- package/src/resources/extensions/subagent/index.ts +1293 -0
- package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/src/resources/skills/frontend-design/SKILL.md +45 -0
- package/src/resources/skills/swiftui/SKILL.md +208 -0
- package/src/resources/skills/swiftui/references/animations.md +921 -0
- package/src/resources/skills/swiftui/references/architecture.md +1561 -0
- package/src/resources/skills/swiftui/references/layout-system.md +1186 -0
- package/src/resources/skills/swiftui/references/navigation.md +1492 -0
- package/src/resources/skills/swiftui/references/networking-async.md +214 -0
- package/src/resources/skills/swiftui/references/performance.md +1706 -0
- package/src/resources/skills/swiftui/references/platform-integration.md +204 -0
- package/src/resources/skills/swiftui/references/state-management.md +1443 -0
- package/src/resources/skills/swiftui/references/swiftdata.md +297 -0
- package/src/resources/skills/swiftui/references/testing-debugging.md +247 -0
- package/src/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
- package/src/resources/skills/swiftui/workflows/add-feature.md +191 -0
- package/src/resources/skills/swiftui/workflows/build-new-app.md +311 -0
- package/src/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
- package/src/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
- package/src/resources/skills/swiftui/workflows/ship-app.md +203 -0
- package/src/resources/skills/swiftui/workflows/write-tests.md +235 -0
- package/dist/commands/task.d.ts +0 -9
- package/dist/commands/task.d.ts.map +0 -1
- package/dist/commands/task.js +0 -129
- package/dist/commands/task.js.map +0 -1
- package/dist/commands/task.test.d.ts +0 -2
- package/dist/commands/task.test.d.ts.map +0 -1
- package/dist/commands/task.test.js +0 -169
- package/dist/commands/task.test.js.map +0 -1
- package/dist/e2e/task-e2e.test.d.ts +0 -2
- package/dist/e2e/task-e2e.test.d.ts.map +0 -1
- package/dist/e2e/task-e2e.test.js +0 -173
- package/dist/e2e/task-e2e.test.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -93
- package/dist/index.js.map +0 -1
- package/dist/slug.d.ts +0 -2
- package/dist/slug.d.ts.map +0 -1
- package/dist/slug.js +0 -12
- package/dist/slug.js.map +0 -1
- package/dist/slug.test.d.ts +0 -2
- package/dist/slug.test.d.ts.map +0 -1
- package/dist/slug.test.js +0 -32
- package/dist/slug.test.js.map +0 -1
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
|
|
2
|
+
<overview>
|
|
3
|
+
Debugging is applied scientific method. You observe a phenomenon (the bug), form hypotheses about its cause, design experiments to test those hypotheses, and revise based on evidence. This isn't metaphorical - it's literal experimental science.
|
|
4
|
+
</overview>
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
<principle name="falsifiability">
|
|
8
|
+
A good hypothesis can be proven wrong. If you can't design an experiment that could disprove it, it's not a useful hypothesis.
|
|
9
|
+
|
|
10
|
+
**Bad hypotheses** (unfalsifiable):
|
|
11
|
+
- "Something is wrong with the state"
|
|
12
|
+
- "The timing is off"
|
|
13
|
+
- "There's a race condition somewhere"
|
|
14
|
+
- "The library is buggy"
|
|
15
|
+
|
|
16
|
+
**Good hypotheses** (falsifiable):
|
|
17
|
+
- "The user state is being reset because the component remounts when the route changes"
|
|
18
|
+
- "The API call completes after the component unmounts, causing the state update on unmounted component warning"
|
|
19
|
+
- "Two async operations are modifying the same array without locking, causing data loss"
|
|
20
|
+
- "The library's caching mechanism is returning stale data because our cache key doesn't include the timestamp"
|
|
21
|
+
|
|
22
|
+
**The difference**: Specificity. Good hypotheses make specific, testable claims.
|
|
23
|
+
</principle>
|
|
24
|
+
|
|
25
|
+
<how_to_form>
|
|
26
|
+
**Process for forming hypotheses**:
|
|
27
|
+
|
|
28
|
+
1. **Observe the behavior precisely**
|
|
29
|
+
- Not "it's broken"
|
|
30
|
+
- But "the counter shows 3 when clicking once, should show 1"
|
|
31
|
+
|
|
32
|
+
2. **Ask "What could cause this?"**
|
|
33
|
+
- List every possible cause you can think of
|
|
34
|
+
- Don't judge them yet, just brainstorm
|
|
35
|
+
|
|
36
|
+
3. **Make each hypothesis specific**
|
|
37
|
+
- Not "state is wrong"
|
|
38
|
+
- But "state is being updated twice because handleClick is called twice"
|
|
39
|
+
|
|
40
|
+
4. **Identify what evidence would support/refute each**
|
|
41
|
+
- If hypothesis X is true, I should see Y
|
|
42
|
+
- If hypothesis X is false, I should see Z
|
|
43
|
+
|
|
44
|
+
<example>
|
|
45
|
+
**Observation**: Button click sometimes saves data, sometimes doesn't.
|
|
46
|
+
|
|
47
|
+
**Vague hypothesis**: "The save isn't working reliably"
|
|
48
|
+
❌ Unfalsifiable, not specific
|
|
49
|
+
|
|
50
|
+
**Specific hypotheses**:
|
|
51
|
+
1. "The save API call is timing out when network is slow"
|
|
52
|
+
- Testable: Check network tab for timeout errors
|
|
53
|
+
- Falsifiable: If all requests complete successfully, this is wrong
|
|
54
|
+
|
|
55
|
+
2. "The save button is being double-clicked, and the second request overwrites with stale data"
|
|
56
|
+
- Testable: Add logging to count clicks
|
|
57
|
+
- Falsifiable: If only one click is registered, this is wrong
|
|
58
|
+
|
|
59
|
+
3. "The save is successful but the UI doesn't update because the response is being ignored"
|
|
60
|
+
- Testable: Check if API returns success
|
|
61
|
+
- Falsifiable: If UI updates on successful response, this is wrong
|
|
62
|
+
</example>
|
|
63
|
+
</how_to_form>
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
<experimental_design>
|
|
67
|
+
An experiment is a test that produces evidence supporting or refuting a hypothesis.
|
|
68
|
+
|
|
69
|
+
**Good experiments**:
|
|
70
|
+
- Test one hypothesis at a time
|
|
71
|
+
- Have clear success/failure criteria
|
|
72
|
+
- Produce unambiguous results
|
|
73
|
+
- Are repeatable
|
|
74
|
+
|
|
75
|
+
**Bad experiments**:
|
|
76
|
+
- Test multiple things at once
|
|
77
|
+
- Have unclear outcomes ("maybe it works better?")
|
|
78
|
+
- Rely on subjective judgment
|
|
79
|
+
- Can't be reproduced
|
|
80
|
+
|
|
81
|
+
<framework>
|
|
82
|
+
For each hypothesis, design an experiment:
|
|
83
|
+
|
|
84
|
+
**1. Prediction**: If hypothesis H is true, then I will observe X
|
|
85
|
+
**2. Test setup**: What do I need to do to test this?
|
|
86
|
+
**3. Measurement**: What exactly am I measuring?
|
|
87
|
+
**4. Success criteria**: What result confirms H? What result refutes H?
|
|
88
|
+
**5. Run the experiment**: Execute the test
|
|
89
|
+
**6. Observe the result**: Record what actually happened
|
|
90
|
+
**7. Conclude**: Does this support or refute H?
|
|
91
|
+
|
|
92
|
+
</framework>
|
|
93
|
+
|
|
94
|
+
<example>
|
|
95
|
+
**Hypothesis**: "The component is re-rendering excessively because the parent is passing a new object reference on every render"
|
|
96
|
+
|
|
97
|
+
**1. Prediction**: If true, the component will re-render even when the object's values haven't changed
|
|
98
|
+
|
|
99
|
+
**2. Test setup**:
|
|
100
|
+
- Add console.log in component body to count renders
|
|
101
|
+
- Add console.log in parent to track when object is created
|
|
102
|
+
- Add useEffect with the object as dependency to log when it changes
|
|
103
|
+
|
|
104
|
+
**3. Measurement**: Count of renders and object creations
|
|
105
|
+
|
|
106
|
+
**4. Success criteria**:
|
|
107
|
+
- Confirms H: Component re-renders match parent renders, object reference changes each time
|
|
108
|
+
- Refutes H: Component only re-renders when object values actually change
|
|
109
|
+
|
|
110
|
+
**5. Run**: Execute the code with logging
|
|
111
|
+
|
|
112
|
+
**6. Observe**:
|
|
113
|
+
```
|
|
114
|
+
[Parent] Created user object
|
|
115
|
+
[Child] Rendering (1)
|
|
116
|
+
[Parent] Created user object
|
|
117
|
+
[Child] Rendering (2)
|
|
118
|
+
[Parent] Created user object
|
|
119
|
+
[Child] Rendering (3)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**7. Conclude**: CONFIRMED. New object every parent render → child re-renders
|
|
123
|
+
</example>
|
|
124
|
+
</experimental_design>
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
<evidence_quality>
|
|
128
|
+
Not all evidence is equal. Learn to distinguish strong from weak evidence.
|
|
129
|
+
|
|
130
|
+
**Strong evidence**:
|
|
131
|
+
- Directly observable ("I can see in the logs that X happens")
|
|
132
|
+
- Repeatable ("This fails every time I do Y")
|
|
133
|
+
- Unambiguous ("The value is definitely null, not undefined")
|
|
134
|
+
- Independent ("This happens even in a fresh browser with no cache")
|
|
135
|
+
|
|
136
|
+
**Weak evidence**:
|
|
137
|
+
- Hearsay ("I think I saw this fail once")
|
|
138
|
+
- Non-repeatable ("It failed that one time but I can't reproduce it")
|
|
139
|
+
- Ambiguous ("Something seems off")
|
|
140
|
+
- Confounded ("It works after I restarted the server and cleared the cache and updated the package")
|
|
141
|
+
|
|
142
|
+
<examples>
|
|
143
|
+
**Strong**:
|
|
144
|
+
```javascript
|
|
145
|
+
console.log('User ID:', userId); // Output: User ID: undefined
|
|
146
|
+
console.log('Type:', typeof userId); // Output: Type: undefined
|
|
147
|
+
```
|
|
148
|
+
✅ Direct observation, unambiguous
|
|
149
|
+
|
|
150
|
+
**Weak**:
|
|
151
|
+
"I think the user ID might not be set correctly sometimes"
|
|
152
|
+
❌ Vague, not verified, uncertain
|
|
153
|
+
|
|
154
|
+
**Strong**:
|
|
155
|
+
```javascript
|
|
156
|
+
for (let i = 0; i < 100; i++) {
|
|
157
|
+
const result = processData(testData);
|
|
158
|
+
if (result !== expected) {
|
|
159
|
+
console.log('Failed on iteration', i);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Output: Failed on iterations: 3, 7, 12, 23, 31...
|
|
163
|
+
```
|
|
164
|
+
✅ Repeatable, shows pattern
|
|
165
|
+
|
|
166
|
+
**Weak**:
|
|
167
|
+
"It usually works, but sometimes fails"
|
|
168
|
+
❌ Not quantified, no pattern identified
|
|
169
|
+
</examples>
|
|
170
|
+
</evidence_quality>
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
<decision_point>
|
|
174
|
+
Don't act too early (premature fix) or too late (analysis paralysis).
|
|
175
|
+
|
|
176
|
+
**Act when you can answer YES to all**:
|
|
177
|
+
|
|
178
|
+
1. **Do you understand the mechanism?**
|
|
179
|
+
- Not just "what fails" but "why it fails"
|
|
180
|
+
- Can you explain the chain of events that produces the bug?
|
|
181
|
+
|
|
182
|
+
2. **Can you reproduce it reliably?**
|
|
183
|
+
- Either always reproduces, or you understand the conditions that trigger it
|
|
184
|
+
- If you can't reproduce, you don't understand it yet
|
|
185
|
+
|
|
186
|
+
3. **Do you have evidence, not just theory?**
|
|
187
|
+
- You've observed the behavior directly
|
|
188
|
+
- You've logged the values, traced the execution
|
|
189
|
+
- You're not guessing
|
|
190
|
+
|
|
191
|
+
4. **Have you ruled out alternatives?**
|
|
192
|
+
- You've considered other hypotheses
|
|
193
|
+
- Evidence contradicts the alternatives
|
|
194
|
+
- This is the most likely cause, not just the first idea
|
|
195
|
+
|
|
196
|
+
**Don't act if**:
|
|
197
|
+
- "I think it might be X" - Too uncertain
|
|
198
|
+
- "This could be the issue" - Not confident enough
|
|
199
|
+
- "Let me try changing Y and see" - Random changes, not hypothesis-driven
|
|
200
|
+
- "I'll fix it and if it works, great" - Outcome-based, not understanding-based
|
|
201
|
+
|
|
202
|
+
<example>
|
|
203
|
+
**Too early** (don't act):
|
|
204
|
+
- Hypothesis: "Maybe the API is slow"
|
|
205
|
+
- Evidence: None, just a guess
|
|
206
|
+
- Action: Add caching
|
|
207
|
+
- Result: Bug persists, now you have caching to debug too
|
|
208
|
+
|
|
209
|
+
**Right time** (act):
|
|
210
|
+
- Hypothesis: "API response is missing the 'status' field when user is inactive, causing the app to crash"
|
|
211
|
+
- Evidence:
|
|
212
|
+
- Logged API response for active user: has 'status' field
|
|
213
|
+
- Logged API response for inactive user: missing 'status' field
|
|
214
|
+
- Logged app behavior: crashes on accessing undefined status
|
|
215
|
+
- Action: Add defensive check for missing status field
|
|
216
|
+
- Result: Bug fixed because you understood the cause
|
|
217
|
+
</example>
|
|
218
|
+
</decision_point>
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
<recovery>
|
|
222
|
+
You will be wrong sometimes. This is normal. The skill is recovering gracefully.
|
|
223
|
+
|
|
224
|
+
**When your hypothesis is disproven**:
|
|
225
|
+
|
|
226
|
+
1. **Acknowledge it explicitly**
|
|
227
|
+
- "This hypothesis was wrong because [evidence]"
|
|
228
|
+
- Don't gloss over it or rationalize
|
|
229
|
+
- Intellectual honesty with yourself
|
|
230
|
+
|
|
231
|
+
2. **Extract the learning**
|
|
232
|
+
- What did this experiment teach you?
|
|
233
|
+
- What did you rule out?
|
|
234
|
+
- What new information do you have?
|
|
235
|
+
|
|
236
|
+
3. **Revise your understanding**
|
|
237
|
+
- Update your mental model
|
|
238
|
+
- What does the evidence actually suggest?
|
|
239
|
+
|
|
240
|
+
4. **Form new hypotheses**
|
|
241
|
+
- Based on what you now know
|
|
242
|
+
- Avoid just moving to "second-guess" - use the evidence
|
|
243
|
+
|
|
244
|
+
5. **Don't get attached to hypotheses**
|
|
245
|
+
- You're not your ideas
|
|
246
|
+
- Being wrong quickly is better than being wrong slowly
|
|
247
|
+
|
|
248
|
+
<example>
|
|
249
|
+
**Initial hypothesis**: "The memory leak is caused by event listeners not being cleaned up"
|
|
250
|
+
|
|
251
|
+
**Experiment**: Check Chrome DevTools for listener counts
|
|
252
|
+
**Result**: Listener count stays stable, doesn't grow over time
|
|
253
|
+
|
|
254
|
+
**Recovery**:
|
|
255
|
+
1. ✅ "Event listeners are NOT the cause. The count doesn't increase."
|
|
256
|
+
2. ✅ "I've ruled out event listeners as the culprit"
|
|
257
|
+
3. ✅ "But the memory profile shows objects accumulating. What objects? Let me check the heap snapshot..."
|
|
258
|
+
4. ✅ "New hypothesis: Large arrays are being cached and never released. Let me test by checking the heap for array sizes..."
|
|
259
|
+
|
|
260
|
+
This is good debugging. Wrong hypothesis, quick recovery, better understanding.
|
|
261
|
+
</example>
|
|
262
|
+
</recovery>
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
<multiple_hypotheses>
|
|
266
|
+
Don't fall in love with your first hypothesis. Generate multiple alternatives.
|
|
267
|
+
|
|
268
|
+
**Strategy**: "Strong inference" - Design experiments that differentiate between competing hypotheses.
|
|
269
|
+
|
|
270
|
+
<example>
|
|
271
|
+
**Problem**: Form submission fails intermittently
|
|
272
|
+
|
|
273
|
+
**Competing hypotheses**:
|
|
274
|
+
1. Network timeout
|
|
275
|
+
2. Validation failure
|
|
276
|
+
3. Race condition with auto-save
|
|
277
|
+
4. Server-side rate limiting
|
|
278
|
+
|
|
279
|
+
**Design experiment that differentiates**:
|
|
280
|
+
|
|
281
|
+
Add logging at each stage:
|
|
282
|
+
```javascript
|
|
283
|
+
try {
|
|
284
|
+
console.log('[1] Starting validation');
|
|
285
|
+
const validation = await validate(formData);
|
|
286
|
+
console.log('[1] Validation passed:', validation);
|
|
287
|
+
|
|
288
|
+
console.log('[2] Starting submission');
|
|
289
|
+
const response = await api.submit(formData);
|
|
290
|
+
console.log('[2] Response received:', response.status);
|
|
291
|
+
|
|
292
|
+
console.log('[3] Updating UI');
|
|
293
|
+
updateUI(response);
|
|
294
|
+
console.log('[3] Complete');
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.log('[ERROR] Failed at stage:', error);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Observe results**:
|
|
301
|
+
- Fails at [2] with timeout error → Hypothesis 1
|
|
302
|
+
- Fails at [1] with validation error → Hypothesis 2
|
|
303
|
+
- Succeeds but [3] has wrong data → Hypothesis 3
|
|
304
|
+
- Fails at [2] with 429 status → Hypothesis 4
|
|
305
|
+
|
|
306
|
+
**One experiment, differentiates between four hypotheses.**
|
|
307
|
+
</example>
|
|
308
|
+
</multiple_hypotheses>
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
<workflow>
|
|
312
|
+
```
|
|
313
|
+
1. Observe unexpected behavior
|
|
314
|
+
↓
|
|
315
|
+
2. Form specific hypotheses (plural)
|
|
316
|
+
↓
|
|
317
|
+
3. For each hypothesis: What would prove/disprove?
|
|
318
|
+
↓
|
|
319
|
+
4. Design experiment to test
|
|
320
|
+
↓
|
|
321
|
+
5. Run experiment
|
|
322
|
+
↓
|
|
323
|
+
6. Observe results
|
|
324
|
+
↓
|
|
325
|
+
7. Evaluate: Confirmed, refuted, or inconclusive?
|
|
326
|
+
↓
|
|
327
|
+
8a. If CONFIRMED → Design fix based on understanding
|
|
328
|
+
8b. If REFUTED → Return to step 2 with new hypotheses
|
|
329
|
+
8c. If INCONCLUSIVE → Redesign experiment or gather more data
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Key insight**: This is a loop, not a line. You'll cycle through multiple times. That's expected.
|
|
333
|
+
</workflow>
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
<pitfalls>
|
|
337
|
+
|
|
338
|
+
**Pitfall: Testing multiple hypotheses at once**
|
|
339
|
+
- You change three things and it works
|
|
340
|
+
- Which one fixed it? You don't know
|
|
341
|
+
- Solution: Test one hypothesis at a time
|
|
342
|
+
|
|
343
|
+
**Pitfall: Confirmation bias in experiments**
|
|
344
|
+
- You only look for evidence that confirms your hypothesis
|
|
345
|
+
- You ignore evidence that contradicts it
|
|
346
|
+
- Solution: Actively seek disconfirming evidence
|
|
347
|
+
|
|
348
|
+
**Pitfall: Acting on weak evidence**
|
|
349
|
+
- "It seems like maybe this could be..."
|
|
350
|
+
- Solution: Wait for strong, unambiguous evidence
|
|
351
|
+
|
|
352
|
+
**Pitfall: Not documenting results**
|
|
353
|
+
- You forget what you tested
|
|
354
|
+
- You repeat the same experiments
|
|
355
|
+
- Solution: Write down each hypothesis and its result
|
|
356
|
+
|
|
357
|
+
**Pitfall: Giving up on the scientific method**
|
|
358
|
+
- Under pressure, you start making random changes
|
|
359
|
+
- "Let me just try this..."
|
|
360
|
+
- Solution: Double down on rigor when pressure increases
|
|
361
|
+
</pitfalls>
|
|
362
|
+
|
|
363
|
+
<excellence>
|
|
364
|
+
**Great debuggers**:
|
|
365
|
+
- Form multiple competing hypotheses
|
|
366
|
+
- Design clever experiments that differentiate between them
|
|
367
|
+
- Follow the evidence wherever it leads
|
|
368
|
+
- Revise their beliefs when proven wrong
|
|
369
|
+
- Act only when they have strong evidence
|
|
370
|
+
- Understand the mechanism, not just the symptom
|
|
371
|
+
|
|
372
|
+
This is the difference between guessing and debugging.
|
|
373
|
+
</excellence>
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
|
|
2
|
+
<overview>
|
|
3
|
+
These are systematic approaches to narrowing down bugs. Each technique is a tool in your debugging toolkit. The skill is knowing which tool to use when.
|
|
4
|
+
</overview>
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
<technique name="binary_search">
|
|
8
|
+
**When to use**: Large codebase, long execution path, or many possible failure points.
|
|
9
|
+
|
|
10
|
+
**How it works**: Cut the problem space in half repeatedly until you isolate the issue.
|
|
11
|
+
|
|
12
|
+
**In practice**:
|
|
13
|
+
|
|
14
|
+
1. **Identify the boundaries**: Where does it work? Where does it fail?
|
|
15
|
+
2. **Find the midpoint**: Add logging/testing at the middle of the execution path
|
|
16
|
+
3. **Determine which half**: Does the bug occur before or after the midpoint?
|
|
17
|
+
4. **Repeat**: Cut that half in half, test again
|
|
18
|
+
5. **Converge**: Keep halving until you find the exact line
|
|
19
|
+
|
|
20
|
+
<example>
|
|
21
|
+
Problem: API request returns wrong data
|
|
22
|
+
|
|
23
|
+
1. Test: Does the data leave the database correctly? YES
|
|
24
|
+
2. Test: Does the data reach the frontend correctly? NO
|
|
25
|
+
3. Test: Does the data leave the API route correctly? YES
|
|
26
|
+
4. Test: Does the data survive serialization? NO
|
|
27
|
+
5. **Found it**: Bug is in the serialization layer
|
|
28
|
+
|
|
29
|
+
You just eliminated 90% of the code in 4 tests.
|
|
30
|
+
</example>
|
|
31
|
+
</technique>
|
|
32
|
+
|
|
33
|
+
<technique name="comment_out_bisection">
|
|
34
|
+
**Variant**: Commenting out code to find the breaking change.
|
|
35
|
+
|
|
36
|
+
1. Comment out the second half of a function
|
|
37
|
+
2. Does it work now? The bug is in the commented section
|
|
38
|
+
3. Uncomment half of that, repeat
|
|
39
|
+
4. Converge on the problematic lines
|
|
40
|
+
|
|
41
|
+
**Warning**: Only works for code you can safely comment out. Don't use for initialization code.
|
|
42
|
+
</technique>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<technique name="rubber_duck">
|
|
46
|
+
**When to use**: You're stuck, confused, or your mental model doesn't match reality.
|
|
47
|
+
|
|
48
|
+
**How it works**: Explain the problem out loud (to a rubber duck, a colleague, or in writing) in complete detail.
|
|
49
|
+
|
|
50
|
+
**Why it works**: Articulating forces you to:
|
|
51
|
+
- Make assumptions explicit
|
|
52
|
+
- Notice gaps in your understanding
|
|
53
|
+
- Hear how convoluted your explanation sounds
|
|
54
|
+
- Realize what you haven't actually verified
|
|
55
|
+
|
|
56
|
+
**In practice**:
|
|
57
|
+
|
|
58
|
+
Write or say out loud:
|
|
59
|
+
1. "The system should do X"
|
|
60
|
+
2. "Instead it does Y"
|
|
61
|
+
3. "I think this is because Z"
|
|
62
|
+
4. "The code path is: A → B → C → D"
|
|
63
|
+
5. "I've verified that..." (List what you've actually tested)
|
|
64
|
+
6. "I'm assuming that..." (List assumptions)
|
|
65
|
+
|
|
66
|
+
Often you'll spot the bug mid-explanation: "Wait, I never actually verified that B returns what I think it does."
|
|
67
|
+
|
|
68
|
+
<example>
|
|
69
|
+
"So when the user clicks the button, it calls handleClick, which dispatches an action, which... wait, does the reducer actually handle this action type? Let me check... Oh. The reducer is looking for 'UPDATE_USER' but I'm dispatching 'USER_UPDATE'."
|
|
70
|
+
</example>
|
|
71
|
+
</technique>
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
<technique name="minimal_reproduction">
|
|
75
|
+
**When to use**: Complex system, many moving parts, unclear which part is failing.
|
|
76
|
+
|
|
77
|
+
**How it works**: Strip away everything until you have the smallest possible code that reproduces the bug.
|
|
78
|
+
|
|
79
|
+
**Why it works**:
|
|
80
|
+
- Removes distractions
|
|
81
|
+
- Isolates the actual issue
|
|
82
|
+
- Often reveals the bug during the stripping process
|
|
83
|
+
- Makes it easier to reason about
|
|
84
|
+
|
|
85
|
+
**Process**:
|
|
86
|
+
|
|
87
|
+
1. **Copy the failing code to a new file**
|
|
88
|
+
2. **Remove one piece** (a dependency, a function, a feature)
|
|
89
|
+
3. **Test**: Does it still reproduce?
|
|
90
|
+
- YES: Keep it removed, continue
|
|
91
|
+
- NO: Put it back, it's needed
|
|
92
|
+
4. **Repeat** until you have the bare minimum
|
|
93
|
+
5. **The bug is now obvious** in the stripped-down code
|
|
94
|
+
|
|
95
|
+
<example>
|
|
96
|
+
Start with: 500-line React component with 15 props, 8 hooks, 3 contexts
|
|
97
|
+
|
|
98
|
+
End with:
|
|
99
|
+
```jsx
|
|
100
|
+
function MinimalRepro() {
|
|
101
|
+
const [count, setCount] = useState(0);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
setCount(count + 1); // Bug: infinite loop, missing dependency array
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return <div>{count}</div>;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The bug was hidden in complexity. Minimal reproduction made it obvious.
|
|
112
|
+
</example>
|
|
113
|
+
</technique>
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
<technique name="working_backwards">
|
|
117
|
+
**When to use**: You know what the correct output should be, but don't know why you're not getting it.
|
|
118
|
+
|
|
119
|
+
**How it works**: Start from the desired end state and trace backwards through the execution path.
|
|
120
|
+
|
|
121
|
+
**Process**:
|
|
122
|
+
|
|
123
|
+
1. **Define the desired output precisely**
|
|
124
|
+
2. **Ask**: What function produces this output?
|
|
125
|
+
3. **Test that function**: Give it the input it should receive. Does it produce correct output?
|
|
126
|
+
- YES: The bug is earlier (wrong input to this function)
|
|
127
|
+
- NO: The bug is here
|
|
128
|
+
4. **Repeat backwards** through the call stack
|
|
129
|
+
5. **Find the divergence point**: Where does expected vs actual first differ?
|
|
130
|
+
|
|
131
|
+
<example>
|
|
132
|
+
Problem: UI shows "User not found" when user exists
|
|
133
|
+
|
|
134
|
+
Trace backwards:
|
|
135
|
+
1. UI displays: `user.error` → Is this the right value to display? YES
|
|
136
|
+
2. Component receives: `user.error = "User not found"` → Is this correct? NO, should be null
|
|
137
|
+
3. API returns: `{ error: "User not found" }` → Why?
|
|
138
|
+
4. Database query: `SELECT * FROM users WHERE id = 'undefined'` → AH!
|
|
139
|
+
5. **Found it**: The user ID is 'undefined' (string) instead of a number
|
|
140
|
+
|
|
141
|
+
Working backwards revealed the bug was in how the ID was passed to the query.
|
|
142
|
+
</example>
|
|
143
|
+
</technique>
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
<technique name="differential_debugging">
|
|
147
|
+
**When to use**: Something used to work and now doesn't. A feature works in one environment but not another.
|
|
148
|
+
|
|
149
|
+
**How it works**: Compare the working vs broken states to find what's different.
|
|
150
|
+
|
|
151
|
+
**Questions to ask**:
|
|
152
|
+
|
|
153
|
+
**Time-based** (it worked, now it doesn't):
|
|
154
|
+
- What changed in the code since it worked?
|
|
155
|
+
- What changed in the environment? (Node version, OS, dependencies)
|
|
156
|
+
- What changed in the data? (Database schema, API responses)
|
|
157
|
+
- What changed in the configuration?
|
|
158
|
+
|
|
159
|
+
**Environment-based** (works in dev, fails in prod):
|
|
160
|
+
- What's different between environments?
|
|
161
|
+
- Configuration values
|
|
162
|
+
- Environment variables
|
|
163
|
+
- Network conditions
|
|
164
|
+
- Data volume
|
|
165
|
+
- Third-party service behavior
|
|
166
|
+
|
|
167
|
+
**Process**:
|
|
168
|
+
|
|
169
|
+
1. **Make a list of differences** between working and broken
|
|
170
|
+
2. **Test each difference** in isolation
|
|
171
|
+
3. **Find the difference that causes the failure**
|
|
172
|
+
4. **That difference reveals the root cause**
|
|
173
|
+
|
|
174
|
+
<example>
|
|
175
|
+
Works locally, fails in CI:
|
|
176
|
+
|
|
177
|
+
Differences:
|
|
178
|
+
- Node version: Same ✓
|
|
179
|
+
- Environment variables: Same ✓
|
|
180
|
+
- Timezone: Different! ✗
|
|
181
|
+
|
|
182
|
+
Test: Set local timezone to UTC (like CI)
|
|
183
|
+
Result: Now fails locally too
|
|
184
|
+
|
|
185
|
+
**Found it**: Date comparison logic assumes local timezone
|
|
186
|
+
</example>
|
|
187
|
+
</technique>
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
<technique name="observability_first">
|
|
191
|
+
**When to use**: Always. Before making any fix.
|
|
192
|
+
|
|
193
|
+
**Why it matters**: You can't fix what you can't see. Add visibility before changing behavior.
|
|
194
|
+
|
|
195
|
+
**Approaches**:
|
|
196
|
+
|
|
197
|
+
**1. Strategic logging**
|
|
198
|
+
```javascript
|
|
199
|
+
// Not this (useless):
|
|
200
|
+
console.log('in function');
|
|
201
|
+
|
|
202
|
+
// This (useful):
|
|
203
|
+
console.log('[handleSubmit] Input:', { email, password: '***' });
|
|
204
|
+
console.log('[handleSubmit] Validation result:', validationResult);
|
|
205
|
+
console.log('[handleSubmit] API response:', response);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**2. Assertion checks**
|
|
209
|
+
```javascript
|
|
210
|
+
function processUser(user) {
|
|
211
|
+
console.assert(user !== null, 'User is null!');
|
|
212
|
+
console.assert(user.id !== undefined, 'User ID is undefined!');
|
|
213
|
+
// ... rest of function
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**3. Timing measurements**
|
|
218
|
+
```javascript
|
|
219
|
+
console.time('Database query');
|
|
220
|
+
const result = await db.query(sql);
|
|
221
|
+
console.timeEnd('Database query');
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**4. Stack traces at key points**
|
|
225
|
+
```javascript
|
|
226
|
+
console.log('[updateUser] Called from:', new Error().stack);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**The workflow**:
|
|
230
|
+
1. **Add logging/instrumentation** at suspected points
|
|
231
|
+
2. **Run the code**
|
|
232
|
+
3. **Observe the output**
|
|
233
|
+
4. **Form hypothesis** based on what you see
|
|
234
|
+
5. **Only then** make changes
|
|
235
|
+
|
|
236
|
+
Don't code in the dark. Light up the execution path first.
|
|
237
|
+
</technique>
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
<technique name="comment_out_everything">
|
|
241
|
+
**When to use**: Many possible interactions, unclear which code is causing the issue.
|
|
242
|
+
|
|
243
|
+
**How it works**:
|
|
244
|
+
|
|
245
|
+
1. **Comment out everything** in a function/file
|
|
246
|
+
2. **Verify the bug is gone**
|
|
247
|
+
3. **Uncomment one piece at a time**
|
|
248
|
+
4. **After each uncomment, test**
|
|
249
|
+
5. **When the bug returns**, you found the culprit
|
|
250
|
+
|
|
251
|
+
**Variant**: For config files, reset to defaults and add back one setting at a time.
|
|
252
|
+
|
|
253
|
+
<example>
|
|
254
|
+
Problem: Some middleware breaks requests, but you have 8 middleware functions.
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
app.use(helmet()); // Uncomment, test → works
|
|
258
|
+
app.use(cors()); // Uncomment, test → works
|
|
259
|
+
app.use(compression()); // Uncomment, test → works
|
|
260
|
+
app.use(bodyParser.json({ limit: '50mb' })); // Uncomment, test → BREAKS
|
|
261
|
+
|
|
262
|
+
// Found it: Body size limit too high causes memory issues
|
|
263
|
+
```
|
|
264
|
+
</example>
|
|
265
|
+
</technique>
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
<technique name="git_bisect">
|
|
269
|
+
**When to use**: Feature worked in the past, broke at some unknown commit.
|
|
270
|
+
|
|
271
|
+
**How it works**: Binary search through git history to find the breaking commit.
|
|
272
|
+
|
|
273
|
+
**Process**:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
git bisect start
|
|
277
|
+
|
|
278
|
+
git bisect bad
|
|
279
|
+
|
|
280
|
+
git bisect good abc123
|
|
281
|
+
|
|
282
|
+
git bisect bad
|
|
283
|
+
|
|
284
|
+
git bisect good
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Why it's powerful**: Turns "it broke sometime in the last 100 commits" into "it broke in commit abc123" in ~7 tests (log₂ 100 ≈ 7).
|
|
289
|
+
|
|
290
|
+
<example>
|
|
291
|
+
100 commits between working and broken
|
|
292
|
+
Manual testing: 100 commits to check
|
|
293
|
+
Git bisect: 7 commits to check
|
|
294
|
+
|
|
295
|
+
Time saved: Massive
|
|
296
|
+
</example>
|
|
297
|
+
</technique>
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
<decision_tree>
|
|
301
|
+
**Large codebase, many files**:
|
|
302
|
+
→ Binary search / Divide and conquer
|
|
303
|
+
|
|
304
|
+
**Confused about what's happening**:
|
|
305
|
+
→ Rubber duck debugging
|
|
306
|
+
→ Observability first (add logging)
|
|
307
|
+
|
|
308
|
+
**Complex system with many interactions**:
|
|
309
|
+
→ Minimal reproduction
|
|
310
|
+
|
|
311
|
+
**Know the desired output**:
|
|
312
|
+
→ Working backwards
|
|
313
|
+
|
|
314
|
+
**Used to work, now doesn't**:
|
|
315
|
+
→ Differential debugging
|
|
316
|
+
→ Git bisect
|
|
317
|
+
|
|
318
|
+
**Many possible causes**:
|
|
319
|
+
→ Comment out everything
|
|
320
|
+
→ Binary search
|
|
321
|
+
|
|
322
|
+
**Always**:
|
|
323
|
+
→ Observability first before making changes
|
|
324
|
+
</decision_tree>
|
|
325
|
+
|
|
326
|
+
<combining_techniques>
|
|
327
|
+
Often you'll use multiple techniques together:
|
|
328
|
+
|
|
329
|
+
1. **Differential debugging** to identify what changed
|
|
330
|
+
2. **Binary search** to narrow down where in the code
|
|
331
|
+
3. **Observability first** to add logging at that point
|
|
332
|
+
4. **Rubber duck** to articulate what you're seeing
|
|
333
|
+
5. **Minimal reproduction** to isolate just that behavior
|
|
334
|
+
6. **Working backwards** to find the root cause
|
|
335
|
+
|
|
336
|
+
Techniques compose. Use as many as needed.
|
|
337
|
+
</combining_techniques>
|