omgkit 2.1.1 → 2.2.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/package.json +1 -1
- package/plugin/skills/SKILL_STANDARDS.md +743 -0
- package/plugin/skills/databases/mongodb/SKILL.md +797 -28
- package/plugin/skills/databases/prisma/SKILL.md +776 -30
- package/plugin/skills/databases/redis/SKILL.md +885 -25
- package/plugin/skills/devops/aws/SKILL.md +686 -28
- package/plugin/skills/devops/github-actions/SKILL.md +684 -29
- package/plugin/skills/devops/kubernetes/SKILL.md +621 -24
- package/plugin/skills/frameworks/django/SKILL.md +920 -20
- package/plugin/skills/frameworks/express/SKILL.md +1361 -35
- package/plugin/skills/frameworks/fastapi/SKILL.md +1260 -33
- package/plugin/skills/frameworks/laravel/SKILL.md +1244 -31
- package/plugin/skills/frameworks/nestjs/SKILL.md +1005 -26
- package/plugin/skills/frameworks/rails/SKILL.md +594 -28
- package/plugin/skills/frameworks/spring/SKILL.md +528 -35
- package/plugin/skills/frameworks/vue/SKILL.md +1296 -27
- package/plugin/skills/frontend/accessibility/SKILL.md +1108 -34
- package/plugin/skills/frontend/frontend-design/SKILL.md +1304 -26
- package/plugin/skills/frontend/responsive/SKILL.md +847 -21
- package/plugin/skills/frontend/shadcn-ui/SKILL.md +976 -38
- package/plugin/skills/frontend/tailwindcss/SKILL.md +831 -35
- package/plugin/skills/frontend/threejs/SKILL.md +1298 -29
- package/plugin/skills/languages/javascript/SKILL.md +935 -31
- package/plugin/skills/methodology/brainstorming/SKILL.md +597 -23
- package/plugin/skills/methodology/defense-in-depth/SKILL.md +832 -34
- package/plugin/skills/methodology/dispatching-parallel-agents/SKILL.md +665 -31
- package/plugin/skills/methodology/executing-plans/SKILL.md +556 -24
- package/plugin/skills/methodology/finishing-development-branch/SKILL.md +595 -25
- package/plugin/skills/methodology/problem-solving/SKILL.md +429 -61
- package/plugin/skills/methodology/receiving-code-review/SKILL.md +536 -24
- package/plugin/skills/methodology/requesting-code-review/SKILL.md +632 -21
- package/plugin/skills/methodology/root-cause-tracing/SKILL.md +641 -30
- package/plugin/skills/methodology/sequential-thinking/SKILL.md +262 -3
- package/plugin/skills/methodology/systematic-debugging/SKILL.md +571 -32
- package/plugin/skills/methodology/test-driven-development/SKILL.md +779 -24
- package/plugin/skills/methodology/testing-anti-patterns/SKILL.md +691 -29
- package/plugin/skills/methodology/token-optimization/SKILL.md +598 -29
- package/plugin/skills/methodology/verification-before-completion/SKILL.md +543 -22
- package/plugin/skills/methodology/writing-plans/SKILL.md +590 -18
- package/plugin/skills/omega/omega-architecture/SKILL.md +838 -39
- package/plugin/skills/omega/omega-coding/SKILL.md +636 -39
- package/plugin/skills/omega/omega-sprint/SKILL.md +855 -48
- package/plugin/skills/omega/omega-testing/SKILL.md +940 -41
- package/plugin/skills/omega/omega-thinking/SKILL.md +703 -50
- package/plugin/skills/security/better-auth/SKILL.md +1065 -28
- package/plugin/skills/security/oauth/SKILL.md +968 -31
- package/plugin/skills/security/owasp/SKILL.md +894 -33
- package/plugin/skills/testing/playwright/SKILL.md +764 -38
- package/plugin/skills/testing/pytest/SKILL.md +873 -36
- package/plugin/skills/testing/vitest/SKILL.md +980 -35
|
@@ -1,38 +1,649 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: requesting-code-review
|
|
3
|
-
description:
|
|
3
|
+
description: Best practices for requesting effective code reviews that get timely, thorough feedback
|
|
4
|
+
category: methodology
|
|
5
|
+
triggers:
|
|
6
|
+
- request review
|
|
7
|
+
- PR review
|
|
8
|
+
- code review request
|
|
9
|
+
- asking for review
|
|
10
|
+
- review request
|
|
11
|
+
- get feedback
|
|
12
|
+
- submit for review
|
|
4
13
|
---
|
|
5
14
|
|
|
6
|
-
# Requesting Code Review
|
|
15
|
+
# Requesting Code Review
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
17
|
+
Master the art of **requesting effective code reviews** that get timely, thorough feedback and enable smooth collaboration. This skill provides frameworks for preparing code, writing great PR descriptions, and facilitating efficient reviews.
|
|
18
|
+
|
|
19
|
+
## Purpose
|
|
20
|
+
|
|
21
|
+
Get high-quality reviews efficiently:
|
|
22
|
+
|
|
23
|
+
- Prepare code that's easy to review
|
|
24
|
+
- Write PR descriptions that guide reviewers
|
|
25
|
+
- Choose appropriate reviewers for the changes
|
|
26
|
+
- Make review requests at optimal times
|
|
27
|
+
- Reduce review turnaround time
|
|
28
|
+
- Enable focused, valuable feedback
|
|
29
|
+
- Build positive reviewer relationships
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
### 1. The Review Request Framework
|
|
13
34
|
|
|
14
|
-
## PR Description
|
|
15
35
|
```markdown
|
|
36
|
+
## Effective Review Request Model
|
|
37
|
+
|
|
38
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
39
|
+
│ CODE REVIEW REQUEST FRAMEWORK │
|
|
40
|
+
├─────────────────────────────────────────────────────────────────────────┤
|
|
41
|
+
│ │
|
|
42
|
+
│ BEFORE REQUESTING │
|
|
43
|
+
│ ═══════════════════ │
|
|
44
|
+
│ □ Self-review completed │
|
|
45
|
+
│ □ Tests pass and coverage adequate │
|
|
46
|
+
│ □ No debug code or TODOs │
|
|
47
|
+
│ □ Documentation updated │
|
|
48
|
+
│ □ Commits are clean and logical │
|
|
49
|
+
│ │
|
|
50
|
+
│ PR DESCRIPTION │
|
|
51
|
+
│ ═══════════════ │
|
|
52
|
+
│ □ Clear summary of what changed │
|
|
53
|
+
│ □ Why the change was made │
|
|
54
|
+
│ □ How to test the changes │
|
|
55
|
+
│ □ Screenshots for UI changes │
|
|
56
|
+
│ □ Areas needing special attention │
|
|
57
|
+
│ │
|
|
58
|
+
│ REVIEWER SELECTION │
|
|
59
|
+
│ ════════════════════ │
|
|
60
|
+
│ □ Domain expert for complex logic │
|
|
61
|
+
│ □ Code owner for affected areas │
|
|
62
|
+
│ □ Not overloading any single reviewer │
|
|
63
|
+
│ □ At least one senior for critical changes │
|
|
64
|
+
│ │
|
|
65
|
+
│ TIMING │
|
|
66
|
+
│ ══════ │
|
|
67
|
+
│ □ Not end of day/week │
|
|
68
|
+
│ □ Reviewers have availability │
|
|
69
|
+
│ □ Size appropriate for single session │
|
|
70
|
+
│ │
|
|
71
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. Self-Review Checklist
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
/**
|
|
78
|
+
* Self-review before requesting external review
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
interface SelfReviewChecklist {
|
|
82
|
+
category: string;
|
|
83
|
+
items: ChecklistItem[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const selfReviewChecklist: SelfReviewChecklist[] = [
|
|
87
|
+
{
|
|
88
|
+
category: 'Code Quality',
|
|
89
|
+
items: [
|
|
90
|
+
{ check: 'No commented-out code', importance: 'high' },
|
|
91
|
+
{ check: 'No console.log/debug statements', importance: 'high' },
|
|
92
|
+
{ check: 'No hardcoded values that should be config', importance: 'medium' },
|
|
93
|
+
{ check: 'Error handling is appropriate', importance: 'high' },
|
|
94
|
+
{ check: 'No obvious performance issues', importance: 'medium' }
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
category: 'Testing',
|
|
99
|
+
items: [
|
|
100
|
+
{ check: 'All tests pass', importance: 'high' },
|
|
101
|
+
{ check: 'New code has tests', importance: 'high' },
|
|
102
|
+
{ check: 'Edge cases covered', importance: 'medium' },
|
|
103
|
+
{ check: 'Manually tested happy path', importance: 'high' }
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
category: 'Documentation',
|
|
108
|
+
items: [
|
|
109
|
+
{ check: 'Complex logic has comments', importance: 'medium' },
|
|
110
|
+
{ check: 'Public APIs documented', importance: 'high' },
|
|
111
|
+
{ check: 'README updated if needed', importance: 'low' }
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
category: 'Git Hygiene',
|
|
116
|
+
items: [
|
|
117
|
+
{ check: 'Commits are logical units', importance: 'medium' },
|
|
118
|
+
{ check: 'Commit messages are clear', importance: 'medium' },
|
|
119
|
+
{ check: 'No merge conflicts', importance: 'high' },
|
|
120
|
+
{ check: 'Rebased on latest main', importance: 'medium' }
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
// Self-review diff
|
|
126
|
+
async function selfReviewDiff(): Promise<SelfReviewReport> {
|
|
127
|
+
const diff = await getDiffFromMain();
|
|
128
|
+
const issues: SelfReviewIssue[] = [];
|
|
129
|
+
|
|
130
|
+
// Check for debug code
|
|
131
|
+
if (/console\.(log|debug)/g.test(diff)) {
|
|
132
|
+
issues.push({
|
|
133
|
+
type: 'debug-code',
|
|
134
|
+
message: 'Found console.log statements',
|
|
135
|
+
severity: 'warning'
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check for TODOs
|
|
140
|
+
if (/TODO|FIXME|HACK/g.test(diff)) {
|
|
141
|
+
issues.push({
|
|
142
|
+
type: 'todo',
|
|
143
|
+
message: 'Found TODO/FIXME comments',
|
|
144
|
+
severity: 'info'
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check for large files
|
|
149
|
+
const changedFiles = parseChangedFiles(diff);
|
|
150
|
+
const largeChanges = changedFiles.filter(f => f.additions > 300);
|
|
151
|
+
if (largeChanges.length > 0) {
|
|
152
|
+
issues.push({
|
|
153
|
+
type: 'large-change',
|
|
154
|
+
message: `${largeChanges.length} file(s) have 300+ lines changed`,
|
|
155
|
+
severity: 'warning',
|
|
156
|
+
suggestion: 'Consider splitting into smaller PRs'
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { issues, changedFiles };
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 3. PR Description Template
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
/**
|
|
168
|
+
* Generate comprehensive PR description
|
|
169
|
+
*/
|
|
170
|
+
|
|
171
|
+
interface PRDescriptionContext {
|
|
172
|
+
title: string;
|
|
173
|
+
type: 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test';
|
|
174
|
+
summary: string;
|
|
175
|
+
ticket?: string;
|
|
176
|
+
changes: string[];
|
|
177
|
+
testing: TestingInfo;
|
|
178
|
+
screenshots?: string[];
|
|
179
|
+
breakingChanges?: string[];
|
|
180
|
+
attentionAreas?: string[];
|
|
181
|
+
relatedPRs?: string[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function generatePRDescription(context: PRDescriptionContext): string {
|
|
185
|
+
let description = '';
|
|
186
|
+
|
|
187
|
+
// Summary section
|
|
188
|
+
description += `## Summary\n\n`;
|
|
189
|
+
description += `${context.summary}\n\n`;
|
|
190
|
+
|
|
191
|
+
// Link ticket
|
|
192
|
+
if (context.ticket) {
|
|
193
|
+
description += `Resolves ${context.ticket}\n\n`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Type badge
|
|
197
|
+
const typeBadges = {
|
|
198
|
+
feature: '✨ Feature',
|
|
199
|
+
bugfix: '🐛 Bug Fix',
|
|
200
|
+
refactor: '♻️ Refactor',
|
|
201
|
+
docs: '📚 Documentation',
|
|
202
|
+
test: '🧪 Testing'
|
|
203
|
+
};
|
|
204
|
+
description += `**Type:** ${typeBadges[context.type]}\n\n`;
|
|
205
|
+
|
|
206
|
+
// What changed
|
|
207
|
+
description += `## Changes\n\n`;
|
|
208
|
+
context.changes.forEach(change => {
|
|
209
|
+
description += `- ${change}\n`;
|
|
210
|
+
});
|
|
211
|
+
description += '\n';
|
|
212
|
+
|
|
213
|
+
// Testing section
|
|
214
|
+
description += `## Testing\n\n`;
|
|
215
|
+
description += `### Automated Tests\n`;
|
|
216
|
+
description += `- [${context.testing.unitTests ? 'x' : ' '}] Unit tests added/updated\n`;
|
|
217
|
+
description += `- [${context.testing.integrationTests ? 'x' : ' '}] Integration tests pass\n`;
|
|
218
|
+
description += `- [${context.testing.e2eTests ? 'x' : ' '}] E2E tests pass\n\n`;
|
|
219
|
+
|
|
220
|
+
description += `### Manual Testing\n`;
|
|
221
|
+
description += `${context.testing.manualTestSteps || 'N/A'}\n\n`;
|
|
222
|
+
|
|
223
|
+
// Screenshots
|
|
224
|
+
if (context.screenshots && context.screenshots.length > 0) {
|
|
225
|
+
description += `## Screenshots\n\n`;
|
|
226
|
+
context.screenshots.forEach((screenshot, i) => {
|
|
227
|
+
description += `\n`;
|
|
228
|
+
});
|
|
229
|
+
description += '\n';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Breaking changes
|
|
233
|
+
if (context.breakingChanges && context.breakingChanges.length > 0) {
|
|
234
|
+
description += `## ⚠️ Breaking Changes\n\n`;
|
|
235
|
+
context.breakingChanges.forEach(change => {
|
|
236
|
+
description += `- ${change}\n`;
|
|
237
|
+
});
|
|
238
|
+
description += '\n';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Areas needing attention
|
|
242
|
+
if (context.attentionAreas && context.attentionAreas.length > 0) {
|
|
243
|
+
description += `## 👀 Areas Needing Review\n\n`;
|
|
244
|
+
context.attentionAreas.forEach(area => {
|
|
245
|
+
description += `- ${area}\n`;
|
|
246
|
+
});
|
|
247
|
+
description += '\n';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Related PRs
|
|
251
|
+
if (context.relatedPRs && context.relatedPRs.length > 0) {
|
|
252
|
+
description += `## Related PRs\n\n`;
|
|
253
|
+
context.relatedPRs.forEach(pr => {
|
|
254
|
+
description += `- ${pr}\n`;
|
|
255
|
+
});
|
|
256
|
+
description += '\n';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Checklist
|
|
260
|
+
description += `## Checklist\n\n`;
|
|
261
|
+
description += `- [x] Self-review completed\n`;
|
|
262
|
+
description += `- [x] Tests pass locally\n`;
|
|
263
|
+
description += `- [x] Documentation updated\n`;
|
|
264
|
+
description += `- [x] No unresolved TODOs\n`;
|
|
265
|
+
|
|
266
|
+
return description;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Real example
|
|
270
|
+
const examplePRDescription = `
|
|
16
271
|
## Summary
|
|
17
|
-
|
|
272
|
+
|
|
273
|
+
Adds user authentication using JWT tokens with refresh token rotation.
|
|
274
|
+
|
|
275
|
+
Resolves #123
|
|
276
|
+
|
|
277
|
+
**Type:** ✨ Feature
|
|
18
278
|
|
|
19
279
|
## Changes
|
|
20
|
-
|
|
21
|
-
-
|
|
280
|
+
|
|
281
|
+
- Add JWT token generation and validation
|
|
282
|
+
- Implement refresh token rotation for security
|
|
283
|
+
- Add login/logout API endpoints
|
|
284
|
+
- Create authentication middleware
|
|
285
|
+
- Add user session management
|
|
22
286
|
|
|
23
287
|
## Testing
|
|
24
|
-
- [ ] Unit tests added
|
|
25
|
-
- [ ] Manual testing done
|
|
26
288
|
|
|
27
|
-
|
|
28
|
-
[
|
|
289
|
+
### Automated Tests
|
|
290
|
+
- [x] Unit tests added/updated
|
|
291
|
+
- [x] Integration tests pass
|
|
292
|
+
- [ ] E2E tests pass
|
|
293
|
+
|
|
294
|
+
### Manual Testing
|
|
295
|
+
1. Login with valid credentials → Receive access & refresh tokens
|
|
296
|
+
2. Access protected route with token → Success
|
|
297
|
+
3. Wait for token expiry → Auto-refresh works
|
|
298
|
+
4. Logout → Tokens invalidated
|
|
299
|
+
|
|
300
|
+
## 👀 Areas Needing Review
|
|
301
|
+
|
|
302
|
+
- Security: Token generation in \`src/auth/tokens.ts\`
|
|
303
|
+
- Performance: Session lookup efficiency
|
|
304
|
+
- Error handling: Token validation edge cases
|
|
305
|
+
|
|
306
|
+
## Checklist
|
|
307
|
+
|
|
308
|
+
- [x] Self-review completed
|
|
309
|
+
- [x] Tests pass locally
|
|
310
|
+
- [x] Documentation updated
|
|
311
|
+
- [x] No unresolved TODOs
|
|
312
|
+
`;
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### 4. Reviewer Selection Strategy
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
/**
|
|
319
|
+
* Choose the right reviewers for your PR
|
|
320
|
+
*/
|
|
321
|
+
|
|
322
|
+
interface ReviewerProfile {
|
|
323
|
+
username: string;
|
|
324
|
+
expertise: string[];
|
|
325
|
+
codeOwnership: string[];
|
|
326
|
+
currentLoad: number; // Number of pending reviews
|
|
327
|
+
availability: 'high' | 'medium' | 'low';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
interface PRReviewNeeds {
|
|
331
|
+
changedAreas: string[];
|
|
332
|
+
complexity: 'low' | 'medium' | 'high';
|
|
333
|
+
securityRelevant: boolean;
|
|
334
|
+
architectureChange: boolean;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function selectReviewers(
|
|
338
|
+
needs: PRReviewNeeds,
|
|
339
|
+
availableReviewers: ReviewerProfile[]
|
|
340
|
+
): SelectedReviewers {
|
|
341
|
+
const selected: ReviewerProfile[] = [];
|
|
342
|
+
const reasons: string[] = [];
|
|
343
|
+
|
|
344
|
+
// 1. Must have: Code owner for changed areas
|
|
345
|
+
const codeOwner = availableReviewers.find(r =>
|
|
346
|
+
r.codeOwnership.some(area =>
|
|
347
|
+
needs.changedAreas.some(changed => changed.includes(area))
|
|
348
|
+
)
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
if (codeOwner) {
|
|
352
|
+
selected.push(codeOwner);
|
|
353
|
+
reasons.push(`${codeOwner.username}: Code owner for affected areas`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 2. For high complexity: Add domain expert
|
|
357
|
+
if (needs.complexity === 'high') {
|
|
358
|
+
const expert = availableReviewers.find(r =>
|
|
359
|
+
r.expertise.some(e => needs.changedAreas.some(a => a.includes(e))) &&
|
|
360
|
+
!selected.includes(r) &&
|
|
361
|
+
r.currentLoad < 3
|
|
362
|
+
);
|
|
29
363
|
|
|
30
|
-
|
|
31
|
-
|
|
364
|
+
if (expert) {
|
|
365
|
+
selected.push(expert);
|
|
366
|
+
reasons.push(`${expert.username}: Domain expert`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 3. For security changes: Add security reviewer
|
|
371
|
+
if (needs.securityRelevant) {
|
|
372
|
+
const securityReviewer = availableReviewers.find(r =>
|
|
373
|
+
r.expertise.includes('security') &&
|
|
374
|
+
!selected.includes(r)
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
if (securityReviewer) {
|
|
378
|
+
selected.push(securityReviewer);
|
|
379
|
+
reasons.push(`${securityReviewer.username}: Security expertise`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// 4. For architecture changes: Add senior/architect
|
|
384
|
+
if (needs.architectureChange) {
|
|
385
|
+
const architect = availableReviewers.find(r =>
|
|
386
|
+
r.expertise.includes('architecture') &&
|
|
387
|
+
!selected.includes(r)
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
if (architect) {
|
|
391
|
+
selected.push(architect);
|
|
392
|
+
reasons.push(`${architect.username}: Architecture review`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Balance load - don't overload anyone
|
|
397
|
+
const balanced = selected.filter(r => r.currentLoad < 5);
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
reviewers: balanced.map(r => r.username),
|
|
401
|
+
reasons,
|
|
402
|
+
warnings: balanced.length < selected.length
|
|
403
|
+
? ['Some reviewers have high load - consider alternative reviewers']
|
|
404
|
+
: []
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Reviewer selection best practices
|
|
409
|
+
const reviewerGuidelines = {
|
|
410
|
+
minimumReviewers: 1,
|
|
411
|
+
recommendedReviewers: 2,
|
|
412
|
+
maxReviewers: 4, // Too many cooks
|
|
413
|
+
|
|
414
|
+
considerations: [
|
|
415
|
+
'Code ownership - who maintains this area?',
|
|
416
|
+
'Domain expertise - who knows this technology best?',
|
|
417
|
+
'Availability - who has bandwidth this week?',
|
|
418
|
+
'Learning opportunity - can a junior learn from reviewing?',
|
|
419
|
+
'Previous context - who reviewed related changes?'
|
|
420
|
+
],
|
|
421
|
+
|
|
422
|
+
antipatterns: [
|
|
423
|
+
'Always requesting the same person',
|
|
424
|
+
'Requesting too many reviewers',
|
|
425
|
+
'Not considering reviewer workload',
|
|
426
|
+
'Skipping security review for auth changes'
|
|
427
|
+
]
|
|
428
|
+
};
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### 5. PR Size and Timing
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
/**
|
|
435
|
+
* Optimize PR size and request timing
|
|
436
|
+
*/
|
|
437
|
+
|
|
438
|
+
interface PRMetrics {
|
|
439
|
+
filesChanged: number;
|
|
440
|
+
linesAdded: number;
|
|
441
|
+
linesRemoved: number;
|
|
442
|
+
totalChanges: number;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function assessPRSize(metrics: PRMetrics): PRSizeAssessment {
|
|
446
|
+
const { totalChanges, filesChanged } = metrics;
|
|
447
|
+
|
|
448
|
+
// Size categories
|
|
449
|
+
if (totalChanges <= 100 && filesChanged <= 5) {
|
|
450
|
+
return {
|
|
451
|
+
size: 'small',
|
|
452
|
+
reviewTime: '15-30 minutes',
|
|
453
|
+
recommendation: 'Good size for thorough review'
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (totalChanges <= 400 && filesChanged <= 15) {
|
|
458
|
+
return {
|
|
459
|
+
size: 'medium',
|
|
460
|
+
reviewTime: '30-60 minutes',
|
|
461
|
+
recommendation: 'Acceptable, but consider if splittable'
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (totalChanges <= 800) {
|
|
466
|
+
return {
|
|
467
|
+
size: 'large',
|
|
468
|
+
reviewTime: '1-2 hours',
|
|
469
|
+
recommendation: 'Consider splitting into smaller PRs',
|
|
470
|
+
splitSuggestions: generateSplitSuggestions(metrics)
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return {
|
|
475
|
+
size: 'too-large',
|
|
476
|
+
reviewTime: '2+ hours',
|
|
477
|
+
recommendation: 'Strongly recommend splitting',
|
|
478
|
+
splitSuggestions: generateSplitSuggestions(metrics),
|
|
479
|
+
warning: 'Large PRs have lower review quality'
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Optimal request timing
|
|
484
|
+
const requestTimingGuidelines = {
|
|
485
|
+
best: [
|
|
486
|
+
'Morning (9-11 AM) - Reviewers are fresh',
|
|
487
|
+
'Early week (Mon-Wed) - Time for iterations',
|
|
488
|
+
'After standup - Team is engaged'
|
|
489
|
+
],
|
|
490
|
+
|
|
491
|
+
avoid: [
|
|
492
|
+
'Friday afternoon - May not get reviewed until Monday',
|
|
493
|
+
'End of day - Tired reviewers miss issues',
|
|
494
|
+
'Right before meetings - Rushed reviews',
|
|
495
|
+
'During crunch time - Team is focused elsewhere'
|
|
496
|
+
],
|
|
497
|
+
|
|
498
|
+
tips: [
|
|
499
|
+
'Check reviewer calendars before requesting',
|
|
500
|
+
'For urgent PRs, message the reviewer directly',
|
|
501
|
+
'Batch small PRs to reduce context switching',
|
|
502
|
+
'Allow 24-48 hours for non-urgent reviews'
|
|
503
|
+
]
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// Generate split suggestions for large PRs
|
|
507
|
+
function generateSplitSuggestions(metrics: PRMetrics): string[] {
|
|
508
|
+
const suggestions: string[] = [];
|
|
509
|
+
|
|
510
|
+
// Suggest splitting by concern
|
|
511
|
+
suggestions.push('Split by feature area (e.g., UI changes vs backend)');
|
|
512
|
+
suggestions.push('Split refactoring from new features');
|
|
513
|
+
suggestions.push('Split tests into separate PR');
|
|
514
|
+
|
|
515
|
+
// For very large PRs
|
|
516
|
+
if (metrics.totalChanges > 500) {
|
|
517
|
+
suggestions.push('Create a base PR with core changes');
|
|
518
|
+
suggestions.push('Follow up with incremental PRs');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return suggestions;
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### 6. Facilitating Effective Reviews
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
/**
|
|
529
|
+
* Help reviewers give better feedback
|
|
530
|
+
*/
|
|
531
|
+
|
|
532
|
+
// Inline comments for reviewers
|
|
533
|
+
function addReviewerGuidance(prDescription: string): string {
|
|
534
|
+
return prDescription + `
|
|
535
|
+
|
|
536
|
+
## For Reviewers
|
|
537
|
+
|
|
538
|
+
### Key Areas to Review
|
|
539
|
+
1. **Security**: Auth token handling in \`src/auth/\`
|
|
540
|
+
2. **Performance**: Database query efficiency
|
|
541
|
+
3. **Edge Cases**: Error handling for network failures
|
|
542
|
+
|
|
543
|
+
### What You Can Skip
|
|
544
|
+
- Test file formatting (will be auto-fixed)
|
|
545
|
+
- Import ordering (handled by linter)
|
|
546
|
+
|
|
547
|
+
### Questions for Reviewers
|
|
548
|
+
- Is the error message user-friendly?
|
|
549
|
+
- Should we add rate limiting to this endpoint?
|
|
550
|
+
|
|
551
|
+
### How to Test Locally
|
|
552
|
+
\`\`\`bash
|
|
553
|
+
git checkout feature-branch
|
|
554
|
+
npm install
|
|
555
|
+
npm run dev
|
|
556
|
+
# Visit http://localhost:3000/test-feature
|
|
557
|
+
\`\`\`
|
|
558
|
+
`;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// In-code comments for complex logic
|
|
562
|
+
const inCodeGuidanceExamples = {
|
|
563
|
+
// Good: Explains why
|
|
564
|
+
good: `
|
|
565
|
+
// Using exponential backoff to handle rate limiting
|
|
566
|
+
// Max retries: 3, delays: 1s, 2s, 4s
|
|
567
|
+
async function fetchWithRetry(url: string): Promise<Response> {
|
|
568
|
+
// ...
|
|
569
|
+
}
|
|
570
|
+
`,
|
|
571
|
+
|
|
572
|
+
// Bad: Explains what (obvious from code)
|
|
573
|
+
bad: `
|
|
574
|
+
// Fetches URL with retry
|
|
575
|
+
async function fetchWithRetry(url: string): Promise<Response> {
|
|
576
|
+
// ...
|
|
577
|
+
}
|
|
578
|
+
`
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// Conversation starters for reviews
|
|
582
|
+
const conversationStarters = [
|
|
583
|
+
'I went with X approach because Y. Open to alternatives if you see issues.',
|
|
584
|
+
'This is a trade-off between A and B. I chose A because C.',
|
|
585
|
+
'Not sure about this pattern - would appreciate feedback.',
|
|
586
|
+
'This is complex due to X constraint. Happy to explain if unclear.'
|
|
587
|
+
];
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
## Use Cases
|
|
591
|
+
|
|
592
|
+
### Standard Feature PR Request
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
# 1. Self-review
|
|
596
|
+
git diff main...HEAD # Review your changes
|
|
597
|
+
|
|
598
|
+
# 2. Run checks
|
|
599
|
+
npm test && npm run lint && npm run build
|
|
600
|
+
|
|
601
|
+
# 3. Update branch
|
|
602
|
+
git fetch origin main
|
|
603
|
+
git rebase origin/main
|
|
604
|
+
|
|
605
|
+
# 4. Push and create PR
|
|
606
|
+
git push origin feature-branch
|
|
607
|
+
|
|
608
|
+
gh pr create \
|
|
609
|
+
--title "feat(auth): add JWT authentication" \
|
|
610
|
+
--body-file .github/pr-template.md \
|
|
611
|
+
--reviewer alice,bob \
|
|
612
|
+
--label "feature,needs-review"
|
|
613
|
+
|
|
614
|
+
# 5. Add context comment
|
|
615
|
+
gh pr comment --body "Ready for review! Main areas to look at:
|
|
616
|
+
- Token generation in src/auth/tokens.ts
|
|
617
|
+
- Middleware in src/middleware/auth.ts"
|
|
32
618
|
```
|
|
33
619
|
|
|
34
620
|
## Best Practices
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
621
|
+
|
|
622
|
+
### Do's
|
|
623
|
+
|
|
624
|
+
- **Self-review first** - catch obvious issues yourself
|
|
625
|
+
- **Keep PRs small** - under 400 lines when possible
|
|
626
|
+
- **Write clear descriptions** - help reviewers understand context
|
|
627
|
+
- **Highlight key areas** - guide reviewers to important code
|
|
628
|
+
- **Choose reviewers wisely** - match expertise to needs
|
|
629
|
+
- **Be responsive** - address feedback promptly
|
|
630
|
+
- **Test thoroughly** - don't waste reviewer time on broken code
|
|
631
|
+
- **Include screenshots** - for UI changes
|
|
632
|
+
|
|
633
|
+
### Don'ts
|
|
634
|
+
|
|
635
|
+
- Don't submit PRs without testing
|
|
636
|
+
- Don't request review on WIP code
|
|
637
|
+
- Don't overload single reviewers
|
|
638
|
+
- Don't create massive PRs
|
|
639
|
+
- Don't leave cryptic commit messages
|
|
640
|
+
- Don't skip the description
|
|
641
|
+
- Don't ignore reviewer availability
|
|
642
|
+
- Don't rush reviewers
|
|
643
|
+
|
|
644
|
+
## References
|
|
645
|
+
|
|
646
|
+
- [Google Engineering Practices: Sending PRs for Review](https://google.github.io/eng-practices/review/developer/)
|
|
647
|
+
- [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/)
|
|
648
|
+
- [The Art of Code Review](https://www.alexandra-hill.com/2018/06/25/the-art-of-giving-and-receiving-code-reviews/)
|
|
649
|
+
- [GitHub PR Best Practices](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests)
|