Create SKILL.md
This commit is contained in:
379
skills/bug-hunter/SKILL.md
Normal file
379
skills/bug-hunter/SKILL.md
Normal file
@@ -0,0 +1,379 @@
|
||||
---
|
||||
name: bug-hunter
|
||||
description: "Systematically finds and fixes bugs using proven debugging techniques. Traces from symptoms to root cause, implements fixes, and prevents regression."
|
||||
category: development
|
||||
risk: safe
|
||||
source: community
|
||||
date_added: "2026-03-05"
|
||||
---
|
||||
|
||||
# Bug Hunter
|
||||
|
||||
Systematically hunt down and fix bugs using proven debugging techniques. No guessing—follow the evidence.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- User reports a bug or error
|
||||
- Something isn't working as expected
|
||||
- User says "fix the bug" or "debug this"
|
||||
- Intermittent failures or weird behavior
|
||||
- Production issues need investigation
|
||||
|
||||
## The Debugging Process
|
||||
|
||||
### 1. Reproduce the Bug
|
||||
|
||||
First, make it happen consistently:
|
||||
|
||||
```
|
||||
1. Get exact steps to reproduce
|
||||
2. Try to reproduce locally
|
||||
3. Note what triggers it
|
||||
4. Document the error message/behavior
|
||||
5. Check if it happens every time or randomly
|
||||
```
|
||||
|
||||
If you can't reproduce it, gather more info:
|
||||
- What environment? (dev, staging, prod)
|
||||
- What browser/device?
|
||||
- What user actions preceded it?
|
||||
- Any error logs?
|
||||
|
||||
### 2. Gather Evidence
|
||||
|
||||
Collect all available information:
|
||||
|
||||
**Check logs:**
|
||||
```bash
|
||||
# Application logs
|
||||
tail -f logs/app.log
|
||||
|
||||
# System logs
|
||||
journalctl -u myapp -f
|
||||
|
||||
# Browser console
|
||||
# Open DevTools → Console tab
|
||||
```
|
||||
|
||||
**Check error messages:**
|
||||
- Full stack trace
|
||||
- Error type and message
|
||||
- Line numbers
|
||||
- Timestamp
|
||||
|
||||
**Check state:**
|
||||
- What data was being processed?
|
||||
- What was the user trying to do?
|
||||
- What's in the database?
|
||||
- What's in local storage/cookies?
|
||||
|
||||
### 3. Form a Hypothesis
|
||||
|
||||
Based on evidence, guess what's wrong:
|
||||
|
||||
```
|
||||
"The login times out because the session cookie
|
||||
expires before the auth check completes"
|
||||
|
||||
"The form fails because email validation regex
|
||||
doesn't handle plus signs"
|
||||
|
||||
"The API returns 500 because the database query
|
||||
has a syntax error with special characters"
|
||||
```
|
||||
|
||||
### 4. Test the Hypothesis
|
||||
|
||||
Prove or disprove your guess:
|
||||
|
||||
**Add logging:**
|
||||
```javascript
|
||||
console.log('Before API call:', userData);
|
||||
const response = await api.login(userData);
|
||||
console.log('After API call:', response);
|
||||
```
|
||||
|
||||
**Use debugger:**
|
||||
```javascript
|
||||
debugger; // Execution pauses here
|
||||
const result = processData(input);
|
||||
```
|
||||
|
||||
**Isolate the problem:**
|
||||
```javascript
|
||||
// Comment out code to narrow down
|
||||
// const result = complexFunction();
|
||||
const result = { mock: 'data' }; // Use mock data
|
||||
```
|
||||
|
||||
### 5. Find Root Cause
|
||||
|
||||
Trace back to the actual problem:
|
||||
|
||||
**Common root causes:**
|
||||
- Null/undefined values
|
||||
- Wrong data types
|
||||
- Race conditions
|
||||
- Missing error handling
|
||||
- Incorrect logic
|
||||
- Off-by-one errors
|
||||
- Async/await issues
|
||||
- Missing validation
|
||||
|
||||
**Example trace:**
|
||||
```
|
||||
Symptom: "Cannot read property 'name' of undefined"
|
||||
↓
|
||||
Where: user.profile.name
|
||||
↓
|
||||
Why: user.profile is undefined
|
||||
↓
|
||||
Why: API didn't return profile
|
||||
↓
|
||||
Why: User ID was null
|
||||
↓
|
||||
Root cause: Login didn't set user ID in session
|
||||
```
|
||||
|
||||
### 6. Implement Fix
|
||||
|
||||
Fix the root cause, not the symptom:
|
||||
|
||||
**Bad fix (symptom):**
|
||||
```javascript
|
||||
// Just hide the error
|
||||
const name = user?.profile?.name || 'Unknown';
|
||||
```
|
||||
|
||||
**Good fix (root cause):**
|
||||
```javascript
|
||||
// Ensure user ID is set on login
|
||||
const login = async (credentials) => {
|
||||
const user = await authenticate(credentials);
|
||||
if (user) {
|
||||
session.userId = user.id; // Fix: Set user ID
|
||||
return user;
|
||||
}
|
||||
throw new Error('Invalid credentials');
|
||||
};
|
||||
```
|
||||
|
||||
### 7. Test the Fix
|
||||
|
||||
Verify it actually works:
|
||||
|
||||
```
|
||||
1. Reproduce the original bug
|
||||
2. Apply the fix
|
||||
3. Try to reproduce again (should fail)
|
||||
4. Test edge cases
|
||||
5. Test related functionality
|
||||
6. Run existing tests
|
||||
```
|
||||
|
||||
### 8. Prevent Regression
|
||||
|
||||
Add a test so it doesn't come back:
|
||||
|
||||
```javascript
|
||||
test('login sets user ID in session', async () => {
|
||||
const user = await login({ email: 'test@example.com', password: 'pass' });
|
||||
|
||||
expect(session.userId).toBe(user.id);
|
||||
expect(session.userId).not.toBeNull();
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Techniques
|
||||
|
||||
### Binary Search
|
||||
|
||||
Cut the problem space in half repeatedly:
|
||||
|
||||
```javascript
|
||||
// Does the bug happen before or after this line?
|
||||
console.log('CHECKPOINT 1');
|
||||
// ... code ...
|
||||
console.log('CHECKPOINT 2');
|
||||
// ... code ...
|
||||
console.log('CHECKPOINT 3');
|
||||
```
|
||||
|
||||
### Rubber Duck Debugging
|
||||
|
||||
Explain the code line by line out loud. Often you'll spot the issue while explaining.
|
||||
|
||||
### Print Debugging
|
||||
|
||||
Strategic console.logs:
|
||||
|
||||
```javascript
|
||||
console.log('Input:', input);
|
||||
console.log('After transform:', transformed);
|
||||
console.log('Before save:', data);
|
||||
console.log('Result:', result);
|
||||
```
|
||||
|
||||
### Diff Debugging
|
||||
|
||||
Compare working vs broken:
|
||||
- What changed recently?
|
||||
- What's different between environments?
|
||||
- What's different in the data?
|
||||
|
||||
### Time Travel Debugging
|
||||
|
||||
Use git to find when it broke:
|
||||
|
||||
```bash
|
||||
git bisect start
|
||||
git bisect bad # Current commit is broken
|
||||
git bisect good abc123 # This old commit worked
|
||||
# Git will check out commits for you to test
|
||||
```
|
||||
|
||||
## Common Bug Patterns
|
||||
|
||||
### Null/Undefined
|
||||
|
||||
```javascript
|
||||
// Bug
|
||||
const name = user.profile.name;
|
||||
|
||||
// Fix
|
||||
const name = user?.profile?.name || 'Unknown';
|
||||
|
||||
// Better fix
|
||||
if (!user || !user.profile) {
|
||||
throw new Error('User profile required');
|
||||
}
|
||||
const name = user.profile.name;
|
||||
```
|
||||
|
||||
### Race Condition
|
||||
|
||||
```javascript
|
||||
// Bug
|
||||
let data = null;
|
||||
fetchData().then(result => data = result);
|
||||
console.log(data); // null - not loaded yet
|
||||
|
||||
// Fix
|
||||
const data = await fetchData();
|
||||
console.log(data); // correct value
|
||||
```
|
||||
|
||||
### Off-by-One
|
||||
|
||||
```javascript
|
||||
// Bug
|
||||
for (let i = 0; i <= array.length; i++) {
|
||||
console.log(array[i]); // undefined on last iteration
|
||||
}
|
||||
|
||||
// Fix
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
console.log(array[i]);
|
||||
}
|
||||
```
|
||||
|
||||
### Type Coercion
|
||||
|
||||
```javascript
|
||||
// Bug
|
||||
if (count == 0) { // true for "", [], null
|
||||
|
||||
// Fix
|
||||
if (count === 0) { // only true for 0
|
||||
```
|
||||
|
||||
### Async Without Await
|
||||
|
||||
```javascript
|
||||
// Bug
|
||||
const result = asyncFunction(); // Returns Promise
|
||||
console.log(result.data); // undefined
|
||||
|
||||
// Fix
|
||||
const result = await asyncFunction();
|
||||
console.log(result.data); // correct value
|
||||
```
|
||||
|
||||
## Debugging Tools
|
||||
|
||||
### Browser DevTools
|
||||
|
||||
```
|
||||
Console: View logs and errors
|
||||
Sources: Set breakpoints, step through code
|
||||
Network: Check API calls and responses
|
||||
Application: View cookies, storage, cache
|
||||
Performance: Find slow operations
|
||||
```
|
||||
|
||||
### Node.js Debugging
|
||||
|
||||
```javascript
|
||||
// Built-in debugger
|
||||
node --inspect app.js
|
||||
|
||||
// Then open chrome://inspect in Chrome
|
||||
```
|
||||
|
||||
### VS Code Debugging
|
||||
|
||||
```json
|
||||
// .vscode/launch.json
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug App",
|
||||
"program": "${workspaceFolder}/app.js"
|
||||
}
|
||||
```
|
||||
|
||||
## When You're Stuck
|
||||
|
||||
1. Take a break (seriously, walk away for 10 minutes)
|
||||
2. Explain it to someone else (or a rubber duck)
|
||||
3. Search for the exact error message
|
||||
4. Check if it's a known issue (GitHub issues, Stack Overflow)
|
||||
5. Simplify: Create minimal reproduction
|
||||
6. Start over: Delete and rewrite the problematic code
|
||||
7. Ask for help (provide context, what you've tried)
|
||||
|
||||
## Documentation Template
|
||||
|
||||
After fixing, document it:
|
||||
|
||||
```markdown
|
||||
## Bug: Login timeout after 30 seconds
|
||||
|
||||
**Symptom:** Users get logged out immediately after login
|
||||
|
||||
**Root Cause:** Session cookie expires before auth check completes
|
||||
|
||||
**Fix:** Increased session timeout from 30s to 3600s in config
|
||||
|
||||
**Files Changed:**
|
||||
- config/session.js (line 12)
|
||||
|
||||
**Testing:** Verified login persists for 1 hour
|
||||
|
||||
**Prevention:** Added test for session persistence
|
||||
```
|
||||
|
||||
## Key Principles
|
||||
|
||||
- Reproduce first, fix second
|
||||
- Follow the evidence, don't guess
|
||||
- Fix root cause, not symptoms
|
||||
- Test the fix thoroughly
|
||||
- Add tests to prevent regression
|
||||
- Document what you learned
|
||||
|
||||
## Related Skills
|
||||
|
||||
- `@systematic-debugging` - Advanced debugging
|
||||
- `@test-driven-development` - Testing
|
||||
- `@codebase-audit-pre-push` - Code review
|
||||
Reference in New Issue
Block a user