📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# Evidence Gathering Patterns
|
||||
|
||||
Techniques for gathering diagnostic information without changing behavior.
|
||||
|
||||
## Instrumentation
|
||||
|
||||
Add diagnostic logging at key points:
|
||||
|
||||
```typescript
|
||||
function processData(data: Data): Result {
|
||||
console.log('[DEBUG] processData input:', JSON.stringify(data));
|
||||
|
||||
const transformed = transform(data);
|
||||
console.log('[DEBUG] after transform:', JSON.stringify(transformed));
|
||||
|
||||
const validated = validate(transformed);
|
||||
console.log('[DEBUG] after validate:', JSON.stringify(validated));
|
||||
|
||||
const result = finalize(validated);
|
||||
console.log('[DEBUG] processData result:', JSON.stringify(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
Key points to instrument:
|
||||
- Function entry/exit with parameters and return values
|
||||
- Before/after each transformation
|
||||
- Error catch blocks
|
||||
- State mutations
|
||||
|
||||
## Binary Search Debugging
|
||||
|
||||
Find commit that introduced bug:
|
||||
|
||||
```bash
|
||||
git bisect start
|
||||
git bisect bad # Current commit is bad
|
||||
git bisect good <last-good-commit> # Known good commit
|
||||
|
||||
# Git checks out middle commit
|
||||
# Test if bug exists, then:
|
||||
git bisect bad # if bug exists
|
||||
git bisect good # if bug doesn't exist
|
||||
|
||||
# Repeat until git identifies exact commit
|
||||
```
|
||||
|
||||
## Differential Analysis
|
||||
|
||||
Compare versions side by side:
|
||||
|
||||
```bash
|
||||
# Working version
|
||||
git show <good-commit>:path/to/file.ts > file-working.ts
|
||||
|
||||
# Broken version
|
||||
git show <bad-commit>:path/to/file.ts > file-broken.ts
|
||||
|
||||
# Detailed diff
|
||||
diff -u file-working.ts file-broken.ts
|
||||
```
|
||||
|
||||
## Timeline Analysis
|
||||
|
||||
Correlate events for timing issues:
|
||||
|
||||
```
|
||||
12:00:01.123 - Request received
|
||||
12:00:01.145 - Database query started
|
||||
12:00:01.167 - Cache check started
|
||||
12:00:01.169 - Cache hit returned <-- Returned before DB!
|
||||
12:00:01.234 - Database query completed
|
||||
12:00:01.235 - Error: stale data <-- Bug symptom
|
||||
```
|
||||
|
||||
Pattern: Log timestamps at every step, look for unexpected ordering or delays.
|
||||
|
||||
## Print Debugging Checklist
|
||||
|
||||
When adding debug output:
|
||||
|
||||
- [ ] Log function entry with all parameters
|
||||
- [ ] Log variable values before conditionals
|
||||
- [ ] Log loop iteration values
|
||||
- [ ] Log before/after external calls
|
||||
- [ ] Log error details in catch blocks
|
||||
- [ ] Include timestamps for timing issues
|
||||
- [ ] Use consistent prefix (e.g., `[DEBUG]`) for easy removal
|
||||
|
||||
## State Snapshots
|
||||
|
||||
Capture intermediate state for inspection:
|
||||
|
||||
```typescript
|
||||
// Save state at checkpoint
|
||||
const checkpoint = {
|
||||
timestamp: Date.now(),
|
||||
state: structuredClone(currentState),
|
||||
lastOperation: 'after validation',
|
||||
};
|
||||
debugSnapshots.push(checkpoint);
|
||||
|
||||
// Later: inspect what state looked like at each point
|
||||
```
|
||||
@@ -0,0 +1,97 @@
|
||||
# Debugging Integration
|
||||
|
||||
Connect debugging to broader development workflow.
|
||||
|
||||
## Test-Driven Debugging
|
||||
|
||||
Debugging follows TDD pattern:
|
||||
|
||||
1. Write test that reproduces bug (RED - fails)
|
||||
2. Fix the bug (GREEN - passes)
|
||||
3. Confirm fix works and prevents regression
|
||||
|
||||
The failing test becomes regression protection.
|
||||
|
||||
## Defensive Programming After Fix
|
||||
|
||||
Add validation at multiple layers:
|
||||
|
||||
```typescript
|
||||
function processUser(userId: string): User {
|
||||
// Input validation
|
||||
if (!userId || typeof userId !== 'string') {
|
||||
throw new Error('Invalid userId: must be non-empty string');
|
||||
}
|
||||
|
||||
// Fetch with error handling
|
||||
const user = await fetchUser(userId);
|
||||
if (!user) {
|
||||
throw new Error(`User not found: ${userId}`);
|
||||
}
|
||||
|
||||
// Output validation
|
||||
if (!user.email || !user.name) {
|
||||
throw new Error('Invalid user data: missing required fields');
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
```
|
||||
|
||||
Key layers:
|
||||
- Input validation (reject bad data early)
|
||||
- Operation error handling (catch failures)
|
||||
- Output validation (ensure correct results)
|
||||
- Invariant assertions (verify assumptions)
|
||||
|
||||
## Post-Fix Documentation
|
||||
|
||||
After fixing, document:
|
||||
|
||||
1. **What broke**: Symptom description
|
||||
2. **Root cause**: Why it happened
|
||||
3. **The fix**: What changed
|
||||
4. **Prevention**: How to avoid in future
|
||||
|
||||
Example:
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Processes user data from API.
|
||||
*
|
||||
* Bug fix (2024-01-15): Added validation for missing email field.
|
||||
* Root cause: API sometimes returns partial user objects when
|
||||
* user hasn't completed onboarding.
|
||||
* Prevention: Always validate required fields before processing.
|
||||
*/
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
Common debugging mistakes to avoid:
|
||||
|
||||
**Random Walk** - trying different things hoping one works
|
||||
- Why it fails: Wastes time, may mask real issue
|
||||
- Instead: Follow stages 1-2 to understand system
|
||||
|
||||
**Quick Fix** - stopping symptom without finding root cause
|
||||
- Why it fails: Bug will resurface or manifest differently
|
||||
- Instead: Use stage 1 to find root cause before fixing
|
||||
|
||||
**Cargo Cult** - copying code without understanding why
|
||||
- Why it fails: May not apply to your context
|
||||
- Instead: Use stage 2 to understand working examples
|
||||
|
||||
**Shotgun Approach** - changing multiple things simultaneously
|
||||
- Why it fails: Can't tell which change fixed it
|
||||
- Instead: Test one hypothesis at a time
|
||||
|
||||
## Escalation Triggers
|
||||
|
||||
When to ask for help:
|
||||
|
||||
1. After 3 failed fix attempts - architecture may be wrong
|
||||
2. No clear reproduction - need more context/access
|
||||
3. External system issues - need vendor/team involvement
|
||||
4. Security implications - need security expertise
|
||||
5. Data corruption risks - need backup/recovery planning
|
||||
@@ -0,0 +1,126 @@
|
||||
# Bug-Type Playbooks
|
||||
|
||||
Investigation focus and techniques by bug category.
|
||||
|
||||
## Runtime Errors
|
||||
|
||||
Crashes, exceptions, uncaught errors.
|
||||
|
||||
**Investigation focus:**
|
||||
- Stack trace analysis (line, function, call chain)
|
||||
- Variable state at crash point
|
||||
- Input values that trigger crash
|
||||
- Environment differences (dev vs prod)
|
||||
|
||||
**Common causes:**
|
||||
- Null/undefined access
|
||||
- Type mismatches
|
||||
- Array out of bounds
|
||||
- Missing error handling
|
||||
- Resource exhaustion
|
||||
|
||||
**Techniques:**
|
||||
- Add try-catch with detailed logging
|
||||
- Validate assumptions with assertions
|
||||
- Check null/undefined before access
|
||||
- Log input values before processing
|
||||
|
||||
## Logic Bugs
|
||||
|
||||
Wrong result, unexpected behavior.
|
||||
|
||||
**Investigation focus:**
|
||||
- Expected vs actual output comparison
|
||||
- Data transformations step by step
|
||||
- Conditional logic evaluation
|
||||
- State changes over time
|
||||
|
||||
**Common causes:**
|
||||
- Off-by-one errors
|
||||
- Incorrect comparison operators
|
||||
- Wrong order of operations
|
||||
- Missing edge case handling
|
||||
- State not reset between operations
|
||||
|
||||
**Techniques:**
|
||||
- Print intermediate values
|
||||
- Step through with debugger
|
||||
- Write test cases for edge cases
|
||||
- Check loop boundaries
|
||||
|
||||
## Integration Failures
|
||||
|
||||
API, database, external service issues.
|
||||
|
||||
**Investigation focus:**
|
||||
- Request/response logging
|
||||
- Network traffic inspection
|
||||
- Authentication/authorization
|
||||
- Data format mismatches
|
||||
- Timing and timeouts
|
||||
|
||||
**Common causes:**
|
||||
- API version mismatch
|
||||
- Authentication token expired
|
||||
- Wrong content-type headers
|
||||
- Data serialization differences
|
||||
- Network timeout too short
|
||||
- Rate limiting
|
||||
|
||||
**Techniques:**
|
||||
- Log full request/response
|
||||
- Test with curl/httpie directly
|
||||
- Check API documentation version
|
||||
- Verify credentials and permissions
|
||||
- Monitor network timing
|
||||
|
||||
## Intermittent Issues
|
||||
|
||||
Works sometimes, fails others.
|
||||
|
||||
**Investigation focus:**
|
||||
- What's different when it fails?
|
||||
- Timing dependencies
|
||||
- Shared state/resources
|
||||
- External conditions
|
||||
- Concurrency issues
|
||||
|
||||
**Common causes:**
|
||||
- Race conditions
|
||||
- Cache inconsistency
|
||||
- Clock/timezone issues
|
||||
- Resource contention
|
||||
- External service flakiness
|
||||
|
||||
**Techniques:**
|
||||
- Add timestamps to all logs
|
||||
- Run many times to find pattern
|
||||
- Check for async operations
|
||||
- Look for shared mutable state
|
||||
- Test under different loads
|
||||
|
||||
## Performance Issues
|
||||
|
||||
Slow, memory leaks, high CPU.
|
||||
|
||||
**Investigation focus:**
|
||||
- Profiling and metrics
|
||||
- Resource usage over time
|
||||
- Algorithm complexity
|
||||
- Data volume scaling
|
||||
- Memory allocation patterns
|
||||
|
||||
**Common causes:**
|
||||
- N+1 queries
|
||||
- Inefficient algorithms
|
||||
- Memory leaks (unreleased resources)
|
||||
- Excessive allocations
|
||||
- Missing indexes
|
||||
- Unbounded caching
|
||||
|
||||
**Techniques:**
|
||||
- Profile with appropriate tools
|
||||
- Measure time/memory at checkpoints
|
||||
- Test with various data sizes
|
||||
- Check for cleanup in destructors
|
||||
- Monitor resource usage trends
|
||||
@@ -0,0 +1,402 @@
|
||||
# Reproduction Techniques
|
||||
|
||||
Reliable reproduction is the foundation of effective debugging. If you can't reproduce the bug consistently, you can't verify your fix works.
|
||||
|
||||
## Minimal Reproduction
|
||||
|
||||
Goal: Smallest possible code that demonstrates the bug.
|
||||
|
||||
### Process
|
||||
|
||||
1. Start with full failing case
|
||||
2. Remove one thing at a time
|
||||
3. After each removal, verify bug still occurs
|
||||
4. Continue until nothing else can be removed
|
||||
5. Result: minimal reproduction case
|
||||
|
||||
### Example
|
||||
|
||||
**Initial failing case** (500 lines):
|
||||
|
||||
```typescript
|
||||
// Complex app with many features
|
||||
// Bug: Login fails
|
||||
```
|
||||
|
||||
**Minimal reproduction** (15 lines):
|
||||
|
||||
```typescript
|
||||
import { authenticate } from './auth';
|
||||
|
||||
// Bug occurs when password contains special chars
|
||||
const result = await authenticate({
|
||||
username: 'test@example.com',
|
||||
password: 'p@ssw0rd!',
|
||||
});
|
||||
// Expected: success
|
||||
// Actual: fails with "Invalid credentials"
|
||||
```
|
||||
|
||||
### Benefits
|
||||
|
||||
- Isolates exact cause
|
||||
- Eliminates red herrings
|
||||
- Makes debugging tractable
|
||||
- Helps others reproduce
|
||||
- Creates focused test case
|
||||
|
||||
## Reproduction Checklist
|
||||
|
||||
Create checklist for consistent reproduction:
|
||||
|
||||
```markdown
|
||||
## Environment
|
||||
- [ ] OS/platform: macOS 14.1
|
||||
- [ ] Node version: 20.10.0
|
||||
- [ ] Package versions: see package.json
|
||||
- [ ] Environment variables: NODE_ENV=production
|
||||
|
||||
## Setup
|
||||
- [ ] Database state: Empty database with schema v2.3
|
||||
- [ ] File system state: No cache files
|
||||
- [ ] Configuration: Default config.json
|
||||
- [ ] Prerequisites: Redis running on localhost:6379
|
||||
|
||||
## Steps to Reproduce
|
||||
1. [ ] Start server: `npm run start`
|
||||
2. [ ] Navigate to `/login`
|
||||
3. [ ] Enter credentials with special chars in password
|
||||
4. [ ] Click "Login"
|
||||
|
||||
## Expected vs Actual
|
||||
**Expected**: User logged in successfully
|
||||
**Actual**: Error message "Invalid credentials" (password is correct)
|
||||
|
||||
## Additional Context
|
||||
- Bug does NOT occur with alphanumeric passwords
|
||||
- Bug started after upgrading bcrypt from 5.0.0 to 5.1.0
|
||||
- Affects 3% of login attempts based on logs
|
||||
```
|
||||
|
||||
### Template
|
||||
|
||||
```markdown
|
||||
## Environment
|
||||
- [ ] OS/platform: _____
|
||||
- [ ] Language/runtime version: _____
|
||||
- [ ] Dependency versions: _____
|
||||
- [ ] Environment variables: _____
|
||||
|
||||
## Setup
|
||||
- [ ] Database state: _____
|
||||
- [ ] File system state: _____
|
||||
- [ ] Configuration: _____
|
||||
- [ ] Prerequisites: _____
|
||||
|
||||
## Steps to Reproduce
|
||||
1. [ ] _____
|
||||
2. [ ] _____
|
||||
3. [ ] _____
|
||||
|
||||
## Expected vs Actual
|
||||
**Expected**: _____
|
||||
**Actual**: _____
|
||||
|
||||
## Additional Context
|
||||
- _____
|
||||
```
|
||||
|
||||
## Automated Reproduction
|
||||
|
||||
Convert manual steps to automated test.
|
||||
|
||||
### Benefits
|
||||
|
||||
- Runs in CI/CD
|
||||
- Documents exact conditions
|
||||
- Verifies fix automatically
|
||||
- Prevents regression
|
||||
|
||||
### Example: Manual to Automated
|
||||
|
||||
**Manual steps**:
|
||||
1. Create user with ID "test-123"
|
||||
2. Set user email to null
|
||||
3. Call getUserDisplay(user)
|
||||
4. Observe crash
|
||||
|
||||
**Automated test**:
|
||||
|
||||
```typescript
|
||||
describe('getUserDisplay', () => {
|
||||
it('reproduces crash with null email', () => {
|
||||
// Setup
|
||||
const userWithNullEmail = {
|
||||
id: 'test-123',
|
||||
name: 'Test User',
|
||||
email: null, // This triggers the bug
|
||||
};
|
||||
|
||||
// Execute - currently crashes
|
||||
expect(() => getUserDisplay(userWithNullEmail)).toThrow(
|
||||
TypeError // Will be fixed to throw proper validation error
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
After fix:
|
||||
|
||||
```typescript
|
||||
expect(() => getUserDisplay(userWithNullEmail)).toThrow(
|
||||
'User email is required'
|
||||
);
|
||||
```
|
||||
|
||||
## Reproduction Patterns by Bug Type
|
||||
|
||||
### Runtime Errors
|
||||
|
||||
Focus on input values:
|
||||
|
||||
```typescript
|
||||
// Reproduce with specific input that triggers error
|
||||
const problematicInput = {
|
||||
value: undefined, // Causes crash
|
||||
nested: { field: null },
|
||||
};
|
||||
|
||||
expect(() => process(problematicInput)).toThrow(TypeError);
|
||||
```
|
||||
|
||||
### Logic Bugs
|
||||
|
||||
Focus on edge cases:
|
||||
|
||||
```typescript
|
||||
// Reproduce with boundary conditions
|
||||
expect(calculateTotal([])).toBe(0); // Empty array
|
||||
expect(calculateTotal([5])).toBe(5); // Single item
|
||||
expect(calculateTotal([5, -3])).toBe(2); // Negative values
|
||||
expect(calculateTotal([0.1, 0.2])).toBe(0.3); // Floating point
|
||||
```
|
||||
|
||||
### Integration Failures
|
||||
|
||||
Mock external dependencies:
|
||||
|
||||
```typescript
|
||||
// Reproduce API failure
|
||||
const mockApi = {
|
||||
fetchUser: vi.fn().mockRejectedValue(
|
||||
new Error('API timeout')
|
||||
),
|
||||
};
|
||||
|
||||
await expect(
|
||||
getUserProfile('123', mockApi)
|
||||
).rejects.toThrow('Failed to fetch user');
|
||||
```
|
||||
|
||||
### Intermittent Issues
|
||||
|
||||
Add timing/concurrency:
|
||||
|
||||
```typescript
|
||||
// Reproduce race condition
|
||||
const results = await Promise.all([
|
||||
updateUser('123', { name: 'Alice' }),
|
||||
updateUser('123', { name: 'Bob' }),
|
||||
]);
|
||||
|
||||
// One update should fail or last write should win consistently
|
||||
expect(results.filter(r => r.success)).toHaveLength(1);
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
Reproduce with scale:
|
||||
|
||||
```typescript
|
||||
// Reproduce performance degradation
|
||||
const largeDataset = Array.from(
|
||||
{ length: 10000 },
|
||||
(_, i) => ({ id: i, data: 'x'.repeat(1000) })
|
||||
);
|
||||
|
||||
const startTime = Date.now();
|
||||
const result = processData(largeDataset);
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Should complete in reasonable time
|
||||
expect(duration).toBeLessThan(1000); // 1 second
|
||||
```
|
||||
|
||||
## Flaky Test Handling
|
||||
|
||||
When test sometimes passes, sometimes fails:
|
||||
|
||||
### Techniques
|
||||
|
||||
**Run multiple times**:
|
||||
|
||||
```bash
|
||||
# Run test 100 times to find pattern
|
||||
for i in {1..100}; do
|
||||
npm test -- --grep "flaky test" || echo "Failed on run $i"
|
||||
done
|
||||
```
|
||||
|
||||
**Add delays to expose timing**:
|
||||
|
||||
```typescript
|
||||
// If suspected race condition
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
// See if consistent delay changes behavior
|
||||
```
|
||||
|
||||
**Check for shared state**:
|
||||
|
||||
```typescript
|
||||
// Isolate test with fresh setup
|
||||
beforeEach(() => {
|
||||
// Reset all state
|
||||
clearCache();
|
||||
resetDatabase();
|
||||
clearEventListeners();
|
||||
});
|
||||
```
|
||||
|
||||
**Log timing information**:
|
||||
|
||||
```typescript
|
||||
console.log(`[${new Date().toISOString()}] Step 1 completed`);
|
||||
console.log(`[${new Date().toISOString()}] Step 2 completed`);
|
||||
// Look for timing patterns in failures
|
||||
```
|
||||
|
||||
## Reproduction in Different Environments
|
||||
|
||||
Bugs may only occur in specific environments.
|
||||
|
||||
### Environment Matrix
|
||||
|
||||
Test across:
|
||||
- Operating systems (macOS, Linux, Windows)
|
||||
- Runtime versions (Node 18, 20, 22)
|
||||
- Dependency versions (latest, locked)
|
||||
- Environment modes (dev, staging, production)
|
||||
|
||||
### Docker Reproduction
|
||||
|
||||
Ensure consistent environment:
|
||||
|
||||
```dockerfile
|
||||
FROM node:20.10.0
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY . .
|
||||
|
||||
# Reproduce bug
|
||||
RUN npm test -- --grep "bug reproduction"
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Consistent across machines
|
||||
- Documents exact environment
|
||||
- Easy for others to reproduce
|
||||
|
||||
## Documentation
|
||||
|
||||
When sharing reproduction:
|
||||
|
||||
### Include
|
||||
|
||||
1. **Exact steps** — numbered, detailed
|
||||
2. **Expected behavior** — what should happen
|
||||
3. **Actual behavior** — what actually happens
|
||||
4. **Environment details** — versions, config
|
||||
5. **Minimal code** — smallest failing example
|
||||
6. **Screenshots/logs** — visual confirmation
|
||||
|
||||
### Template
|
||||
|
||||
```markdown
|
||||
# Bug: {Brief Description}
|
||||
|
||||
## Reproduction
|
||||
|
||||
**Environment:**
|
||||
- OS: macOS 14.1
|
||||
- Runtime: Node.js 20.10.0
|
||||
- Dependencies: see lockfile commit abc123
|
||||
|
||||
**Steps:**
|
||||
1. Clone repo at commit abc123
|
||||
2. Run `npm install`
|
||||
3. Run `npm test -- --grep "specific test"`
|
||||
4. Observe failure
|
||||
|
||||
**Expected:** Test passes
|
||||
**Actual:** Test fails with "TypeError: ..."
|
||||
|
||||
**Minimal code:**
|
||||
\`\`\`typescript
|
||||
// 10 lines that trigger bug
|
||||
\`\`\`
|
||||
|
||||
**Logs:**
|
||||
\`\`\`
|
||||
[full error output]
|
||||
\`\`\`
|
||||
|
||||
## Additional Context
|
||||
- Fails 100% of time with these steps
|
||||
- Does not fail if X is changed to Y
|
||||
- Started after commit abc123
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Non-deterministic Reproduction
|
||||
|
||||
**Problem**: Can't reproduce consistently
|
||||
|
||||
**Solutions**:
|
||||
- Control randomness (seed random number generators)
|
||||
- Control timing (use fixed delays, not timeouts)
|
||||
- Control environment (Docker, locked dependencies)
|
||||
- Control input (save exact input that triggers bug)
|
||||
|
||||
### Over-complex Reproduction
|
||||
|
||||
**Problem**: Reproduction requires too much setup
|
||||
|
||||
**Solutions**:
|
||||
- Simplify to minimal case
|
||||
- Mock external dependencies
|
||||
- Use in-memory databases for tests
|
||||
- Extract core logic that fails
|
||||
|
||||
### Environment-specific Bugs
|
||||
|
||||
**Problem**: "Works on my machine"
|
||||
|
||||
**Solutions**:
|
||||
- Document exact environment (Docker)
|
||||
- Check for environment variables
|
||||
- Verify dependency versions match
|
||||
- Test on clean install
|
||||
|
||||
## Summary
|
||||
|
||||
Reliable reproduction is critical for:
|
||||
- Understanding the bug
|
||||
- Verifying the fix
|
||||
- Preventing regression
|
||||
- Communicating the issue
|
||||
|
||||
Time invested in solid reproduction saves time in debugging and verification.
|
||||
Reference in New Issue
Block a user