@malamute/ai-rules 1.0.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.
- package/README.md +174 -0
- package/bin/cli.js +5 -0
- package/configs/_shared/.claude/commands/fix-issue.md +38 -0
- package/configs/_shared/.claude/commands/generate-tests.md +49 -0
- package/configs/_shared/.claude/commands/review-pr.md +77 -0
- package/configs/_shared/.claude/rules/accessibility.md +270 -0
- package/configs/_shared/.claude/rules/performance.md +226 -0
- package/configs/_shared/.claude/rules/security.md +188 -0
- package/configs/_shared/.claude/skills/debug/SKILL.md +118 -0
- package/configs/_shared/.claude/skills/learning/SKILL.md +224 -0
- package/configs/_shared/.claude/skills/review/SKILL.md +86 -0
- package/configs/_shared/.claude/skills/spec/SKILL.md +112 -0
- package/configs/_shared/CLAUDE.md +174 -0
- package/configs/angular/.claude/rules/components.md +257 -0
- package/configs/angular/.claude/rules/state.md +250 -0
- package/configs/angular/.claude/rules/testing.md +422 -0
- package/configs/angular/.claude/settings.json +31 -0
- package/configs/angular/CLAUDE.md +251 -0
- package/configs/dotnet/.claude/rules/api.md +370 -0
- package/configs/dotnet/.claude/rules/architecture.md +199 -0
- package/configs/dotnet/.claude/rules/database/efcore.md +408 -0
- package/configs/dotnet/.claude/rules/testing.md +389 -0
- package/configs/dotnet/.claude/settings.json +9 -0
- package/configs/dotnet/CLAUDE.md +319 -0
- package/configs/nestjs/.claude/rules/auth.md +321 -0
- package/configs/nestjs/.claude/rules/database/prisma.md +305 -0
- package/configs/nestjs/.claude/rules/database/typeorm.md +379 -0
- package/configs/nestjs/.claude/rules/modules.md +215 -0
- package/configs/nestjs/.claude/rules/testing.md +315 -0
- package/configs/nestjs/.claude/rules/validation.md +279 -0
- package/configs/nestjs/.claude/settings.json +15 -0
- package/configs/nestjs/CLAUDE.md +263 -0
- package/configs/nextjs/.claude/rules/components.md +211 -0
- package/configs/nextjs/.claude/rules/state/redux-toolkit.md +429 -0
- package/configs/nextjs/.claude/rules/state/zustand.md +299 -0
- package/configs/nextjs/.claude/rules/testing.md +315 -0
- package/configs/nextjs/.claude/settings.json +29 -0
- package/configs/nextjs/CLAUDE.md +376 -0
- package/configs/python/.claude/rules/database/sqlalchemy.md +355 -0
- package/configs/python/.claude/rules/fastapi.md +272 -0
- package/configs/python/.claude/rules/flask.md +332 -0
- package/configs/python/.claude/rules/testing.md +374 -0
- package/configs/python/.claude/settings.json +18 -0
- package/configs/python/CLAUDE.md +273 -0
- package/package.json +41 -0
- package/src/install.js +315 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/*.ts"
|
|
4
|
+
- "**/*.js"
|
|
5
|
+
- "**/*.py"
|
|
6
|
+
- "**/*.cs"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Performance Rules
|
|
10
|
+
|
|
11
|
+
## Database
|
|
12
|
+
|
|
13
|
+
### N+1 Query Problem
|
|
14
|
+
```typescript
|
|
15
|
+
// Bad - N+1 queries
|
|
16
|
+
const users = await db.users.findAll();
|
|
17
|
+
for (const user of users) {
|
|
18
|
+
user.posts = await db.posts.findByUserId(user.id); // N queries!
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Good - eager loading
|
|
22
|
+
const users = await db.users.findAll({
|
|
23
|
+
include: [{ model: Post }],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Good - batch loading
|
|
27
|
+
const users = await db.users.findAll();
|
|
28
|
+
const userIds = users.map(u => u.id);
|
|
29
|
+
const posts = await db.posts.findByUserIds(userIds);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Missing Indexes
|
|
33
|
+
```sql
|
|
34
|
+
-- Add indexes for:
|
|
35
|
+
-- 1. Foreign keys
|
|
36
|
+
-- 2. Columns used in WHERE clauses
|
|
37
|
+
-- 3. Columns used in ORDER BY
|
|
38
|
+
-- 4. Columns used in JOIN conditions
|
|
39
|
+
|
|
40
|
+
CREATE INDEX idx_posts_user_id ON posts(user_id);
|
|
41
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Select Only Needed Fields
|
|
45
|
+
```typescript
|
|
46
|
+
// Bad - select *
|
|
47
|
+
const users = await db.query('SELECT * FROM users');
|
|
48
|
+
|
|
49
|
+
// Good - select specific fields
|
|
50
|
+
const users = await db.query('SELECT id, name, email FROM users');
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Pagination
|
|
54
|
+
```typescript
|
|
55
|
+
// Always paginate large datasets
|
|
56
|
+
const users = await db.users.findAll({
|
|
57
|
+
limit: 20,
|
|
58
|
+
offset: (page - 1) * 20,
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Caching
|
|
63
|
+
|
|
64
|
+
### Cache Expensive Operations
|
|
65
|
+
```typescript
|
|
66
|
+
// Cache database queries
|
|
67
|
+
const cacheKey = `user:${userId}`;
|
|
68
|
+
let user = await cache.get(cacheKey);
|
|
69
|
+
if (!user) {
|
|
70
|
+
user = await db.users.findById(userId);
|
|
71
|
+
await cache.set(cacheKey, user, { ttl: 3600 });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Invalidate on update
|
|
75
|
+
await db.users.update(userId, data);
|
|
76
|
+
await cache.delete(`user:${userId}`);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Memoization
|
|
80
|
+
```typescript
|
|
81
|
+
// Memoize pure functions
|
|
82
|
+
const memoize = <T>(fn: (...args: any[]) => T): ((...args: any[]) => T) => {
|
|
83
|
+
const cache = new Map();
|
|
84
|
+
return (...args) => {
|
|
85
|
+
const key = JSON.stringify(args);
|
|
86
|
+
if (!cache.has(key)) {
|
|
87
|
+
cache.set(key, fn(...args));
|
|
88
|
+
}
|
|
89
|
+
return cache.get(key);
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Frontend
|
|
95
|
+
|
|
96
|
+
### Avoid Unnecessary Re-renders
|
|
97
|
+
```typescript
|
|
98
|
+
// React - use memo for expensive components
|
|
99
|
+
const ExpensiveList = React.memo(({ items }) => {
|
|
100
|
+
return items.map(item => <Item key={item.id} {...item} />);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Use useMemo for expensive calculations
|
|
104
|
+
const sortedItems = useMemo(
|
|
105
|
+
() => items.sort((a, b) => a.name.localeCompare(b.name)),
|
|
106
|
+
[items]
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Use useCallback for stable function references
|
|
110
|
+
const handleClick = useCallback(() => {
|
|
111
|
+
doSomething(id);
|
|
112
|
+
}, [id]);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Angular - OnPush Change Detection
|
|
116
|
+
```typescript
|
|
117
|
+
@Component({
|
|
118
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
119
|
+
})
|
|
120
|
+
export class MyComponent {
|
|
121
|
+
// Only re-renders when inputs change
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Lazy Loading
|
|
126
|
+
```typescript
|
|
127
|
+
// React - lazy load routes
|
|
128
|
+
const Dashboard = React.lazy(() => import('./Dashboard'));
|
|
129
|
+
|
|
130
|
+
// Angular - lazy load modules
|
|
131
|
+
{ path: 'admin', loadChildren: () => import('./admin/admin.module') }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Virtual Scrolling for Large Lists
|
|
135
|
+
```typescript
|
|
136
|
+
// Use virtualization for 100+ items
|
|
137
|
+
// React: react-window, react-virtualized
|
|
138
|
+
// Angular: @angular/cdk/scrolling
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Async Operations
|
|
142
|
+
|
|
143
|
+
### Don't Block the Event Loop
|
|
144
|
+
```typescript
|
|
145
|
+
// Bad - blocking in async context
|
|
146
|
+
async function processData() {
|
|
147
|
+
const result = heavySyncComputation(); // Blocks!
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Good - offload to worker or break up
|
|
152
|
+
async function processData() {
|
|
153
|
+
return new Promise(resolve => {
|
|
154
|
+
setImmediate(() => {
|
|
155
|
+
const result = heavySyncComputation();
|
|
156
|
+
resolve(result);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Parallel Execution
|
|
163
|
+
```typescript
|
|
164
|
+
// Bad - sequential
|
|
165
|
+
const user = await getUser(id);
|
|
166
|
+
const posts = await getPosts(id);
|
|
167
|
+
const comments = await getComments(id);
|
|
168
|
+
|
|
169
|
+
// Good - parallel when independent
|
|
170
|
+
const [user, posts, comments] = await Promise.all([
|
|
171
|
+
getUser(id),
|
|
172
|
+
getPosts(id),
|
|
173
|
+
getComments(id),
|
|
174
|
+
]);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Streaming for Large Data
|
|
178
|
+
```typescript
|
|
179
|
+
// Bad - load all in memory
|
|
180
|
+
const allData = await db.query('SELECT * FROM huge_table');
|
|
181
|
+
res.json(allData);
|
|
182
|
+
|
|
183
|
+
// Good - stream
|
|
184
|
+
const stream = db.queryStream('SELECT * FROM huge_table');
|
|
185
|
+
stream.pipe(res);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Memory
|
|
189
|
+
|
|
190
|
+
### Avoid Memory Leaks
|
|
191
|
+
```typescript
|
|
192
|
+
// Clean up subscriptions
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
const subscription = observable.subscribe();
|
|
195
|
+
return () => subscription.unsubscribe(); // Cleanup!
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
// Remove event listeners
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
window.addEventListener('resize', handler);
|
|
201
|
+
return () => window.removeEventListener('resize', handler);
|
|
202
|
+
}, []);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Limit Collection Sizes
|
|
206
|
+
```typescript
|
|
207
|
+
// Use LRU cache with max size
|
|
208
|
+
const cache = new LRUCache({ max: 500 });
|
|
209
|
+
|
|
210
|
+
// Limit array growth
|
|
211
|
+
if (items.length > MAX_ITEMS) {
|
|
212
|
+
items.shift(); // Remove oldest
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Quick Checklist
|
|
217
|
+
|
|
218
|
+
- [ ] Database queries use indexes
|
|
219
|
+
- [ ] No N+1 queries
|
|
220
|
+
- [ ] Large lists are paginated
|
|
221
|
+
- [ ] Expensive operations cached
|
|
222
|
+
- [ ] Frontend components use memoization
|
|
223
|
+
- [ ] Change detection optimized (Angular OnPush)
|
|
224
|
+
- [ ] Large lists use virtual scrolling
|
|
225
|
+
- [ ] Async operations run in parallel when possible
|
|
226
|
+
- [ ] No memory leaks (subscriptions cleaned up)
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/*.ts"
|
|
4
|
+
- "**/*.js"
|
|
5
|
+
- "**/*.py"
|
|
6
|
+
- "**/*.cs"
|
|
7
|
+
- "**/*.java"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Security Rules (OWASP Top 10)
|
|
11
|
+
|
|
12
|
+
## 1. Injection Prevention
|
|
13
|
+
|
|
14
|
+
### SQL Injection
|
|
15
|
+
```typescript
|
|
16
|
+
// Bad - string concatenation
|
|
17
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
18
|
+
|
|
19
|
+
// Good - parameterized queries
|
|
20
|
+
const query = 'SELECT * FROM users WHERE id = $1';
|
|
21
|
+
await db.query(query, [userId]);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### NoSQL Injection
|
|
25
|
+
```typescript
|
|
26
|
+
// Bad - user input directly in query
|
|
27
|
+
db.users.find({ email: req.body.email });
|
|
28
|
+
|
|
29
|
+
// Good - validate and sanitize
|
|
30
|
+
const email = validateEmail(req.body.email);
|
|
31
|
+
db.users.find({ email });
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Command Injection
|
|
35
|
+
```typescript
|
|
36
|
+
// Bad - user input in command
|
|
37
|
+
exec(`ls ${userInput}`);
|
|
38
|
+
|
|
39
|
+
// Good - use safe APIs or sanitize
|
|
40
|
+
exec('ls', [sanitize(userInput)]);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 2. Authentication
|
|
44
|
+
|
|
45
|
+
- Never store plain passwords - use bcrypt/argon2
|
|
46
|
+
- Use secure session tokens (cryptographically random)
|
|
47
|
+
- Implement account lockout after failed attempts
|
|
48
|
+
- Use constant-time comparison for secrets
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// Bad
|
|
52
|
+
if (password === storedPassword) { }
|
|
53
|
+
|
|
54
|
+
// Good
|
|
55
|
+
import { timingSafeEqual } from 'crypto';
|
|
56
|
+
if (timingSafeEqual(Buffer.from(a), Buffer.from(b))) { }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 3. Sensitive Data Exposure
|
|
60
|
+
|
|
61
|
+
### Never log sensitive data
|
|
62
|
+
```typescript
|
|
63
|
+
// Bad
|
|
64
|
+
logger.info('User login', { email, password });
|
|
65
|
+
|
|
66
|
+
// Good
|
|
67
|
+
logger.info('User login', { email, password: '[REDACTED]' });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Never commit secrets
|
|
71
|
+
- Use environment variables
|
|
72
|
+
- Add to `.gitignore`: `.env`, `*.pem`, `credentials.json`
|
|
73
|
+
- Use secret managers in production
|
|
74
|
+
|
|
75
|
+
### Mask in responses
|
|
76
|
+
```typescript
|
|
77
|
+
// Bad - return full credit card
|
|
78
|
+
{ cardNumber: '4111111111111111' }
|
|
79
|
+
|
|
80
|
+
// Good - mask sensitive parts
|
|
81
|
+
{ cardNumber: '************1111' }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 4. XSS Prevention
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Bad - innerHTML with user content
|
|
88
|
+
element.innerHTML = userInput;
|
|
89
|
+
|
|
90
|
+
// Good - use safe methods
|
|
91
|
+
element.textContent = userInput;
|
|
92
|
+
|
|
93
|
+
// React/Angular - avoid dangerouslySetInnerHTML / [innerHTML]
|
|
94
|
+
// If needed, sanitize first with DOMPurify
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 5. CSRF Protection
|
|
98
|
+
|
|
99
|
+
- Use anti-CSRF tokens for state-changing operations
|
|
100
|
+
- Validate `Origin` and `Referer` headers
|
|
101
|
+
- Use `SameSite` cookie attribute
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Set secure cookies
|
|
105
|
+
res.cookie('session', token, {
|
|
106
|
+
httpOnly: true,
|
|
107
|
+
secure: true,
|
|
108
|
+
sameSite: 'strict',
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 6. Access Control
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// Always check ownership
|
|
116
|
+
async function getDocument(userId: string, docId: string) {
|
|
117
|
+
const doc = await db.documents.findById(docId);
|
|
118
|
+
|
|
119
|
+
// Bad - missing authorization check
|
|
120
|
+
return doc;
|
|
121
|
+
|
|
122
|
+
// Good - verify ownership
|
|
123
|
+
if (doc.ownerId !== userId) {
|
|
124
|
+
throw new ForbiddenError();
|
|
125
|
+
}
|
|
126
|
+
return doc;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 7. Security Headers
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// Essential headers
|
|
134
|
+
{
|
|
135
|
+
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
|
136
|
+
'X-Content-Type-Options': 'nosniff',
|
|
137
|
+
'X-Frame-Options': 'DENY',
|
|
138
|
+
'Content-Security-Policy': "default-src 'self'",
|
|
139
|
+
'X-XSS-Protection': '1; mode=block',
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 8. Input Validation
|
|
144
|
+
|
|
145
|
+
- Validate all inputs on server side (never trust client)
|
|
146
|
+
- Use allowlists over denylists
|
|
147
|
+
- Validate type, length, format, range
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Use schema validation
|
|
151
|
+
const schema = z.object({
|
|
152
|
+
email: z.string().email().max(256),
|
|
153
|
+
age: z.number().int().min(0).max(150),
|
|
154
|
+
role: z.enum(['user', 'admin']),
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 9. Error Handling
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// Bad - expose internal errors
|
|
162
|
+
catch (error) {
|
|
163
|
+
res.status(500).json({ error: error.stack });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Good - generic message, log internally
|
|
167
|
+
catch (error) {
|
|
168
|
+
logger.error('Database error', { error });
|
|
169
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 10. Dependencies
|
|
174
|
+
|
|
175
|
+
- Keep dependencies updated
|
|
176
|
+
- Audit regularly: `npm audit`, `pip-audit`, `dotnet list package --vulnerable`
|
|
177
|
+
- Remove unused dependencies
|
|
178
|
+
- Pin versions in production
|
|
179
|
+
|
|
180
|
+
## Quick Checklist
|
|
181
|
+
|
|
182
|
+
Before committing, verify:
|
|
183
|
+
- [ ] No secrets in code
|
|
184
|
+
- [ ] User inputs validated and sanitized
|
|
185
|
+
- [ ] SQL/NoSQL queries parameterized
|
|
186
|
+
- [ ] Sensitive data not logged
|
|
187
|
+
- [ ] Authorization checks in place
|
|
188
|
+
- [ ] Error messages don't expose internals
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug
|
|
3
|
+
description: Structured debugging workflow for investigating issues
|
|
4
|
+
argument-hint: [error-or-issue-description]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Debug Skill
|
|
8
|
+
|
|
9
|
+
You are now in **debug mode**. Investigate the issue systematically.
|
|
10
|
+
|
|
11
|
+
## Issue
|
|
12
|
+
|
|
13
|
+
Problem to debug: `$ARGUMENTS`
|
|
14
|
+
|
|
15
|
+
If no argument, ask: "What issue are you experiencing?"
|
|
16
|
+
|
|
17
|
+
## Debugging Workflow
|
|
18
|
+
|
|
19
|
+
### Phase 1: Gather Information
|
|
20
|
+
|
|
21
|
+
1. **Reproduce the issue**
|
|
22
|
+
- Ask for exact steps to reproduce
|
|
23
|
+
- Ask for error messages (full stack trace)
|
|
24
|
+
- Ask for environment (dev/prod, browser, OS)
|
|
25
|
+
|
|
26
|
+
2. **Understand expected vs actual behavior**
|
|
27
|
+
- What should happen?
|
|
28
|
+
- What actually happens?
|
|
29
|
+
|
|
30
|
+
### Phase 2: Investigate
|
|
31
|
+
|
|
32
|
+
1. **Locate the error**
|
|
33
|
+
- Parse stack trace to find origin
|
|
34
|
+
- Search codebase for relevant files
|
|
35
|
+
- Read the failing code
|
|
36
|
+
|
|
37
|
+
2. **Trace the flow**
|
|
38
|
+
- Follow data from input to error
|
|
39
|
+
- Check function calls in sequence
|
|
40
|
+
- Look for state mutations
|
|
41
|
+
|
|
42
|
+
3. **Form hypotheses**
|
|
43
|
+
- List possible causes (ranked by likelihood)
|
|
44
|
+
- For each hypothesis, identify how to verify
|
|
45
|
+
|
|
46
|
+
### Phase 3: Verify
|
|
47
|
+
|
|
48
|
+
For each hypothesis:
|
|
49
|
+
1. Describe what to check
|
|
50
|
+
2. Check it (read code, run command, add log)
|
|
51
|
+
3. Confirm or eliminate
|
|
52
|
+
|
|
53
|
+
Format:
|
|
54
|
+
```
|
|
55
|
+
Hypothesis: [Description]
|
|
56
|
+
Check: [What to verify]
|
|
57
|
+
Result: [Confirmed/Eliminated] - [Evidence]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Phase 4: Fix
|
|
61
|
+
|
|
62
|
+
Once root cause is found:
|
|
63
|
+
1. Explain the root cause clearly
|
|
64
|
+
2. Propose fix(es)
|
|
65
|
+
3. Consider side effects
|
|
66
|
+
4. Implement with user approval
|
|
67
|
+
|
|
68
|
+
### Phase 5: Prevent
|
|
69
|
+
|
|
70
|
+
After fixing:
|
|
71
|
+
1. Add test to prevent regression
|
|
72
|
+
2. Consider if similar bugs exist elsewhere
|
|
73
|
+
3. Document if it was a tricky issue
|
|
74
|
+
|
|
75
|
+
## Output Format
|
|
76
|
+
|
|
77
|
+
Use this structure as you debug:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
## Issue Summary
|
|
81
|
+
[One line description]
|
|
82
|
+
|
|
83
|
+
## Reproduction
|
|
84
|
+
[Steps or command to reproduce]
|
|
85
|
+
|
|
86
|
+
## Investigation Log
|
|
87
|
+
[Timestamped notes of what you checked]
|
|
88
|
+
|
|
89
|
+
## Root Cause
|
|
90
|
+
[Clear explanation of why this happens]
|
|
91
|
+
|
|
92
|
+
## Fix
|
|
93
|
+
[Code changes with explanation]
|
|
94
|
+
|
|
95
|
+
## Prevention
|
|
96
|
+
[Test added or recommendation]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Debugging Tools
|
|
100
|
+
|
|
101
|
+
Use these as needed:
|
|
102
|
+
- Read files to understand code
|
|
103
|
+
- Grep/search for patterns
|
|
104
|
+
- Run tests to isolate behavior
|
|
105
|
+
- Check git history for recent changes (`git log`, `git blame`)
|
|
106
|
+
- Run the app to reproduce
|
|
107
|
+
|
|
108
|
+
## Behavior
|
|
109
|
+
|
|
110
|
+
1. Don't guess - investigate
|
|
111
|
+
2. One hypothesis at a time
|
|
112
|
+
3. Show your reasoning
|
|
113
|
+
4. Ask for more info if needed
|
|
114
|
+
5. Explain findings in simple terms
|
|
115
|
+
|
|
116
|
+
## Exit
|
|
117
|
+
|
|
118
|
+
When fixed, ask: "Issue resolved. Want me to add a test to prevent regression?"
|