@pilllesss/yorn 1.0.182 → 1.0.183

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.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/providers/data/.manifest.json +1 -1
  3. package/dist/skills/code-review/LICENSE +21 -0
  4. package/dist/skills/code-review/SKILL.md +233 -0
  5. package/dist/skills/code-review/assets/pr-review-template.md +137 -0
  6. package/dist/skills/code-review/assets/review-checklist.md +123 -0
  7. package/dist/skills/code-review/reference/angular.md +768 -0
  8. package/dist/skills/code-review/reference/architecture-review-guide.md +472 -0
  9. package/dist/skills/code-review/reference/c.md +890 -0
  10. package/dist/skills/code-review/reference/code-quality-universal.md +488 -0
  11. package/dist/skills/code-review/reference/code-review-best-practices.md +136 -0
  12. package/dist/skills/code-review/reference/common-bugs-checklist.md +302 -0
  13. package/dist/skills/code-review/reference/cpp.md +893 -0
  14. package/dist/skills/code-review/reference/cross-cutting/async-concurrency-patterns.md +515 -0
  15. package/dist/skills/code-review/reference/cross-cutting/error-handling-principles.md +492 -0
  16. package/dist/skills/code-review/reference/cross-cutting/n-plus-one-queries.md +309 -0
  17. package/dist/skills/code-review/reference/cross-cutting/sql-injection-prevention.md +308 -0
  18. package/dist/skills/code-review/reference/cross-cutting/xss-prevention.md +264 -0
  19. package/dist/skills/code-review/reference/csharp.md +525 -0
  20. package/dist/skills/code-review/reference/css-less-sass.md +661 -0
  21. package/dist/skills/code-review/reference/dart.md +670 -0
  22. package/dist/skills/code-review/reference/django.md +985 -0
  23. package/dist/skills/code-review/reference/fastapi.md +580 -0
  24. package/dist/skills/code-review/reference/go.md +993 -0
  25. package/dist/skills/code-review/reference/java.md +409 -0
  26. package/dist/skills/code-review/reference/java8.md +586 -0
  27. package/dist/skills/code-review/reference/kotlin.md +1018 -0
  28. package/dist/skills/code-review/reference/nestjs.md +593 -0
  29. package/dist/skills/code-review/reference/performance-review-guide.md +816 -0
  30. package/dist/skills/code-review/reference/php.md +684 -0
  31. package/dist/skills/code-review/reference/python.md +1073 -0
  32. package/dist/skills/code-review/reference/qt.md +757 -0
  33. package/dist/skills/code-review/reference/react.md +871 -0
  34. package/dist/skills/code-review/reference/ruby.md +964 -0
  35. package/dist/skills/code-review/reference/rust.md +846 -0
  36. package/dist/skills/code-review/reference/security-review-guide.md +494 -0
  37. package/dist/skills/code-review/reference/svelte.md +1064 -0
  38. package/dist/skills/code-review/reference/swift.md +936 -0
  39. package/dist/skills/code-review/reference/typescript.md +1016 -0
  40. package/dist/skills/code-review/reference/vue.md +924 -0
  41. package/dist/skills/code-review/reference/zig.md +440 -0
  42. package/dist/skills/code-review/scripts/pr-analyzer.py +435 -0
  43. package/dist/skills/code-review/scripts/test_pr_analyzer.py +380 -0
  44. package/dist/yorn.cjs +628 -628
  45. package/package.json +2 -2
@@ -0,0 +1,488 @@
1
+ # Universal Code Quality Anti-Patterns
2
+
3
+ > 语言无关的代码质量反模式指南,覆盖代码复用、抽象泄漏、参数膨胀、嵌套条件、字符串类型化、TOCTOU、空操作更新等核心主题。适用于所有语言的 PR 审查。
4
+
5
+ ## 目录
6
+
7
+ - [代码复用审查](#代码复用审查)
8
+ - [参数膨胀](#参数膨胀)
9
+ - [抽象泄漏](#抽象泄漏)
10
+ - [字符串类型化](#字符串类型化)
11
+ - [嵌套条件表达式](#嵌套条件表达式)
12
+ - [复制粘贴变种](#复制粘贴变种)
13
+ - [空操作更新](#空操作更新)
14
+ - [TOCTOU 竞争条件](#toctou-竞争条件)
15
+ - [过度宽泛操作](#过度宽泛操作)
16
+ - [冗余状态](#冗余状态)
17
+ - [通用质量审查清单](#通用质量审查清单)
18
+
19
+ ---
20
+
21
+ ## 代码复用审查
22
+
23
+ Before accepting new code, search the existing codebase for reusable utilities.
24
+
25
+ ### 搜索现有工具函数
26
+
27
+ ```python
28
+ # ❌ 新写的路径拼接逻辑——项目中已有 PathBuilder
29
+ def get_config_path(name):
30
+ base = os.environ.get("APP_ROOT", ".")
31
+ return os.path.join(base, "config", name + ".json")
32
+
33
+ # ✅ 使用已有的 PathBuilder
34
+ def get_config_path(name):
35
+ return PathBuilder.config(f"{name}.json")
36
+ ```
37
+
38
+ ```javascript
39
+ // ❌ 手写 debounce——项目已有 lodash 或 utils/debounce.ts
40
+ function debounce(fn, ms) {
41
+ let timer;
42
+ return (...args) => {
43
+ clearTimeout(timer);
44
+ timer = setTimeout(() => fn(...args), ms);
45
+ };
46
+ }
47
+
48
+ // ✅ 使用已有的工具函数
49
+ import { debounce } from "@/utils/debounce";
50
+ ```
51
+
52
+ **审查要点:**
53
+ - 新增函数是否与已有 utility 重名或功能重叠?
54
+ - inline 逻辑是否可以提取为已有模块的调用?
55
+ - 检查相邻文件和 shared/utils 目录
56
+
57
+ ---
58
+
59
+ ## 参数膨胀
60
+
61
+ ### 函数参数不断增长
62
+
63
+ ```python
64
+ # ❌ 每次新需求加一个参数
65
+ def create_user(name, email, role, team, active, avatar_url, timezone):
66
+ ...
67
+
68
+ # ✅ 使用配置对象 / dataclass
69
+ @dataclass
70
+ class CreateUserParams:
71
+ name: str
72
+ email: str
73
+ role: Role = Role.MEMBER
74
+ team: str | None = None
75
+ active: bool = True
76
+ avatar_url: str | None = None
77
+ timezone: str = "UTC"
78
+
79
+ def create_user(params: CreateUserParams) -> User:
80
+ ...
81
+ ```
82
+
83
+ ```typescript
84
+ // ❌ 6+ 个 positional 参数
85
+ function renderWidget(
86
+ title: string, width: number, height: number,
87
+ theme: string, collapsible: boolean, icon: string
88
+ ) { ... }
89
+
90
+ // ✅ Options object pattern
91
+ interface WidgetOptions {
92
+ title: string;
93
+ width?: number;
94
+ height?: number;
95
+ theme?: "light" | "dark";
96
+ collapsible?: boolean;
97
+ icon?: string;
98
+ }
99
+ function renderWidget(options: WidgetOptions) { ... }
100
+ ```
101
+
102
+ **审查要点:**
103
+ - 函数参数是否 ≥ 4 个?考虑 options object / dataclass
104
+ - 新参数是否只是布尔标志?考虑 enum 或 strategy pattern
105
+ - 是否有 `enable_x`, `disable_y` 这类互斥参数?
106
+
107
+ ---
108
+
109
+ ## 抽象泄漏
110
+
111
+ ### 暴露内部实现细节
112
+
113
+ ```python
114
+ # ❌ 返回内部 ORM 对象——调用者被迫了解 SQLAlchemy
115
+ def get_users():
116
+ return session.query(User).filter(User.active == True).all()
117
+
118
+ # ✅ 返回 domain 对象,隐藏持久化层
119
+ def get_active_users() -> list[UserDTO]:
120
+ rows = user_repo.find_active()
121
+ return [UserDTO.from_row(r) for r in rows]
122
+ ```
123
+
124
+ ```typescript
125
+ // ❌ 组件接收 API response 原始结构
126
+ <UserCard user={apiResponse.data.results[0]} />
127
+
128
+ // ✅ 组件接收 domain 类型,adapter 处理映射
129
+ interface UserSummary {
130
+ displayName: string;
131
+ avatarUrl: string;
132
+ }
133
+ <UserCard user={adaptUser(apiResponse)} />
134
+ ```
135
+
136
+ **审查要点:**
137
+ - 函数返回类型是否泄露底层实现(ORM, HTTP client, file format)?
138
+ - 组件/函数是否依赖外部系统的数据结构?
139
+ - 是否破坏了已有的抽象边界?
140
+
141
+ ---
142
+
143
+ ## 字符串类型化
144
+
145
+ ### 用原始字符串代替常量/枚举
146
+
147
+ ```python
148
+ # ❌ Magic strings 散落各处
149
+ if status == "active":
150
+ ...
151
+ if role == "admin":
152
+ ...
153
+
154
+ # ✅ 使用 enum
155
+ class Status(StrEnum):
156
+ ACTIVE = "active"
157
+ SUSPENDED = "suspended"
158
+ ARCHIVED = "archived"
159
+
160
+ if user.status == Status.ACTIVE:
161
+ ...
162
+ ```
163
+
164
+ ```typescript
165
+ // ❌ Raw string event names——拼写错误不会报错
166
+ emitter.emit("userCreated", data);
167
+ emitter.on("usercreated", handler); // bug: typo
168
+
169
+ // ✅ 常量或 branded type
170
+ const Events = {
171
+ USER_CREATED: "userCreated",
172
+ USER_SUSPENDED: "userSuspended",
173
+ } as const;
174
+ emitter.emit(Events.USER_CREATED, data);
175
+ ```
176
+
177
+ **审查要点:**
178
+ - 是否用字符串代替了已有的 enum/union type?
179
+ - 事件名、action type、status 值是否散落在多个文件?
180
+ - 字符串比较是否 case-sensitive 但未验证?
181
+
182
+ ---
183
+
184
+ ## 嵌套条件表达式
185
+
186
+ ### 三元链和嵌套 if/else
187
+
188
+ ```python
189
+ # ❌ 三元链难以阅读
190
+ label = (
191
+ "Admin" if role == "admin" else
192
+ "Manager" if role == "manager" else
193
+ "Viewer" if role == "viewer" else
194
+ "Unknown"
195
+ )
196
+
197
+ # ✅ 查找表或 match
198
+ ROLE_LABELS = {
199
+ "admin": "Admin",
200
+ "manager": "Manager",
201
+ "viewer": "Viewer",
202
+ }
203
+ label = ROLE_LABELS.get(role, "Unknown")
204
+ ```
205
+
206
+ ```typescript
207
+ // ❌ 嵌套三元
208
+ const bg = isHovered
209
+ ? isSelected ? "blue" : "gray"
210
+ : isSelected ? "navy" : "white";
211
+
212
+ // ✅ 查找表(lookup map)
213
+ const bgMap: Record<string, string> = {
214
+ "true-true": "blue",
215
+ "true-false": "gray",
216
+ "false-true": "navy",
217
+ "false-false": "white",
218
+ };
219
+ const bg = bgMap[`${isHovered}-${isSelected}`];
220
+ ```
221
+
222
+ ```python
223
+ # ❌ 嵌套 if 3+ 层
224
+ def process(order):
225
+ if order is not None:
226
+ if order.items:
227
+ for item in order.items:
228
+ if item.price > 0:
229
+ ...
230
+
231
+ # ✅ Early return + guard clauses
232
+ def process(order):
233
+ if not order or not order.items:
234
+ return
235
+ for item in order.items:
236
+ if item.price <= 0:
237
+ continue
238
+ ...
239
+ ```
240
+
241
+ **审查要点:**
242
+ - 三元表达式是否嵌套 ≥ 2 层?
243
+ - if/else 嵌套是否 ≥ 3 层?
244
+ - 能否用 lookup table、early return 或 match 替换?
245
+
246
+ ---
247
+
248
+ ## 复制粘贴变种
249
+
250
+ ### 近乎重复的代码块
251
+
252
+ ```python
253
+ # ❌ 两个函数几乎一样,只有字段名不同
254
+ def format_user(user):
255
+ return f"{user.first_name} {user.last_name} ({user.email})"
256
+
257
+ def format_employee(emp):
258
+ return f"{emp.first_name} {emp.last_name} ({emp.work_email})"
259
+
260
+ # ✅ 统一抽象
261
+ def format_person(first: str, last: str, email: str) -> str:
262
+ return f"{first} {last} ({email})"
263
+ ```
264
+
265
+ ```typescript
266
+ // ❌ Copy-paste handler 只改了 URL
267
+ async function deletePost(id: string) {
268
+ await fetch(`/api/posts/${id}`, { method: "DELETE" });
269
+ router.push("/posts");
270
+ }
271
+ async function deleteComment(id: string) {
272
+ await fetch(`/api/comments/${id}`, { method: "DELETE" });
273
+ router.push("/comments");
274
+ }
275
+
276
+ // ✅ 参数化
277
+ async function deleteResource(resource: string, id: string) {
278
+ await fetch(`/api/${resource}/${id}`, { method: "DELETE" });
279
+ router.push(`/${resource}`);
280
+ }
281
+ ```
282
+
283
+ **审查要点:**
284
+ - 是否有 ≥ 2 段代码仅变量名/URL/字符串不同?
285
+ - 能否提取参数化的共享函数?
286
+ - 是否可以用 template method 或 strategy 消除变种?
287
+
288
+ ---
289
+
290
+ ## 空操作更新
291
+
292
+ ### 无条件触发状态更新
293
+
294
+ ```typescript
295
+ // ❌ 每次 poll 都触发 update——即使数据未变
296
+ useEffect(() => {
297
+ const interval = setInterval(() => {
298
+ fetch("/api/status").then(r => r.json()).then(setStatus);
299
+ }, 5000);
300
+ return () => clearInterval(interval);
301
+ }, []);
302
+
303
+ // ✅ 仅在值变化时更新
304
+ useEffect(() => {
305
+ const interval = setInterval(() => {
306
+ fetch("/api/status")
307
+ .then(r => r.json())
308
+ .then(data => {
309
+ setStatus(prev => isEqual(prev, data) ? prev : data);
310
+ });
311
+ }, 5000);
312
+ return () => clearInterval(interval);
313
+ }, []);
314
+ ```
315
+
316
+ ```python
317
+ # ❌ 每次 loop 都写 DB——即使值未变
318
+ for item in items:
319
+ item.status = compute_status(item)
320
+ session.commit()
321
+
322
+ # ✅ 仅在变化时写入
323
+ for item in items:
324
+ new_status = compute_status(item)
325
+ if item.status != new_status:
326
+ item.status = new_status
327
+ session.commit()
328
+ ```
329
+
330
+ **审查要点:**
331
+ - polling / interval / event handler 是否无条件更新?
332
+ - wrapper function 是否尊重 same-reference return?
333
+ - DB 写入是否检查了实际变化?
334
+
335
+ ---
336
+
337
+ ## TOCTOU 竞争条件
338
+
339
+ ### Time-of-Check-to-Time-of-Use
340
+
341
+ ```python
342
+ # ❌ 先检查后操作——中间文件可能被删除/创建
343
+ if os.path.exists(path):
344
+ with open(path) as f:
345
+ data = f.read()
346
+
347
+ # ✅ 直接操作 + 处理异常
348
+ try:
349
+ with open(path) as f:
350
+ data = f.read()
351
+ except FileNotFoundError:
352
+ data = None
353
+ ```
354
+
355
+ ```python
356
+ # ❌ 检查余额 → 扣款 两步操作不是原子的
357
+ if account.balance >= amount:
358
+ account.balance -= amount
359
+
360
+ # ✅ 原子操作或锁
361
+ with account.lock:
362
+ if account.balance < amount:
363
+ raise InsufficientFundsError()
364
+ account.balance -= amount
365
+ ```
366
+
367
+ ```typescript
368
+ // ❌ Check-then-act 在 async 环境中不安全
369
+ if (!fileExists(path)) {
370
+ await writeFile(path, content);
371
+ }
372
+
373
+ // ✅ 直接操作 + catch
374
+ try {
375
+ await writeFile(path, content, { flag: "wx" });
376
+ } catch (e) {
377
+ if (e.code === "EEXIST") { /* handle */ }
378
+ else throw e;
379
+ }
380
+ ```
381
+
382
+ **审查要点:**
383
+ - `if exists → operate` 模式是否可替换为 `try operate → catch`?
384
+ - 多步状态变更是否在事务/锁内?
385
+ - async 操作中 check 和 act 之间是否有 await?
386
+
387
+ ---
388
+
389
+ ## 过度宽泛操作
390
+
391
+ ### 读取过多数据
392
+
393
+ ```python
394
+ # ❌ 读取整个文件再取第一行
395
+ content = Path("log.txt").read_text()
396
+ first_line = content.split("\n")[0]
397
+
398
+ # ✅ 只读第一行,不加载整个文件
399
+ with open("log.txt") as f:
400
+ first_line = f.readline()
401
+ ```
402
+
403
+ ```typescript
404
+ // ❌ 加载所有 items 再过滤
405
+ const allItems = await db.query("SELECT * FROM orders");
406
+ const pending = allItems.filter(o => o.status === "pending");
407
+
408
+ // ✅ 数据库层过滤
409
+ const pending = await db.query(
410
+ "SELECT * FROM orders WHERE status = ?", ["pending"]
411
+ );
412
+ ```
413
+
414
+ ```python
415
+ # ❌ 读取整个列表找一条记录
416
+ users = list(User.objects.all())
417
+ user = next(u for u in users if u.id == user_id)
418
+
419
+ # ✅ 精确查询
420
+ user = User.objects.get(id=user_id)
421
+ ```
422
+
423
+ **审查要点:**
424
+ - 是否读取了整个集合/文件再只用一小部分?
425
+ - 能否将过滤推到数据库/存储层?
426
+ - API 调用是否支持 pagination/limit 参数?
427
+
428
+ ---
429
+
430
+ ## 冗余状态
431
+
432
+ ### 状态可以被推导
433
+
434
+ ```typescript
435
+ // ❌ 同时存储 fullName 和 firstName + lastName
436
+ interface User {
437
+ firstName: string;
438
+ lastName: string;
439
+ fullName: string; // redundant
440
+ }
441
+
442
+ // ✅ fullName 是推导值
443
+ interface User {
444
+ firstName: string;
445
+ lastName: string;
446
+ }
447
+ const fullName = `${user.firstName} ${user.lastName}`;
448
+ ```
449
+
450
+ ```python
451
+ # ❌ 缓存值在源数据变化时可能过时
452
+ class Order:
453
+ total: float
454
+ item_count: int # redundant if len(items) gives the same
455
+ items: list[Item]
456
+
457
+ # ✅ 推导或 property
458
+ class Order:
459
+ items: list[Item]
460
+
461
+ @property
462
+ def total(self) -> float:
463
+ return sum(item.price for item in self.items)
464
+
465
+ @property
466
+ def item_count(self) -> int:
467
+ return len(self.items)
468
+ ```
469
+
470
+ **审查要点:**
471
+ - 是否有字段可以从其他字段推导?
472
+ - 缓存值是否有 invalidation 机制?
473
+ - observer/effect 是否可以替换为直接调用?
474
+
475
+ ---
476
+
477
+ ## 通用质量审查清单
478
+
479
+ - [ ] **复用审查**: 搜索了现有 utility/helper,没有重复造轮子?
480
+ - [ ] **参数数量**: 函数参数 ≤ 3 个?超过则用 options object / dataclass?
481
+ - [ ] **抽象边界**: 返回类型没有暴露内部实现细节(ORM、HTTP client、file format)?
482
+ - [ ] **类型安全**: 没有 magic strings 代替已有的 enum/constant/union type?
483
+ - [ ] **条件深度**: 三元嵌套 ≤ 1 层?if/else 嵌套 ≤ 2 层?
484
+ - [ ] **DRY**: 没有 copy-paste-with-variation(≥ 2 段近似代码)?
485
+ - [ ] **空操作防护**: polling / interval / event handler 有 change-detection guard?
486
+ - [ ] **TOCTOU**: `if exists → operate` 替换为 `try operate → catch`?
487
+ - [ ] **数据精度**: 没有读取整个集合/文件只为了取子集?
488
+ - [ ] **冗余状态**: 没有可以从其他字段推导的存储字段?
@@ -0,0 +1,136 @@
1
+ # Code Review Best Practices
2
+
3
+ Comprehensive guidelines for conducting effective code reviews.
4
+
5
+ ## Review Philosophy
6
+
7
+ ### Goals of Code Review
8
+
9
+ **Primary Goals:**
10
+ - Catch bugs and edge cases before production
11
+ - Ensure code maintainability and readability
12
+ - Share knowledge across the team
13
+ - Enforce coding standards consistently
14
+ - Improve design and architecture decisions
15
+
16
+ **Secondary Goals:**
17
+ - Mentor junior developers
18
+ - Build team culture and trust
19
+ - Document design decisions through discussions
20
+
21
+ ### What Code Review is NOT
22
+
23
+ - A gatekeeping mechanism to block progress
24
+ - An opportunity to show off knowledge
25
+ - A place to nitpick formatting (use linters)
26
+ - A way to rewrite code to personal preference
27
+
28
+ ## Review Timing
29
+
30
+ ### When to Review
31
+
32
+ | Trigger | Action |
33
+ |---------|--------|
34
+ | PR opened | Review within 24 hours, ideally same day |
35
+ | Changes requested | Re-review within 4 hours |
36
+ | Blocking issue found | Communicate immediately |
37
+
38
+ ### Time Allocation
39
+
40
+ - **Small PR (<100 lines)**: 10-15 minutes
41
+ - **Medium PR (100-400 lines)**: 20-40 minutes
42
+ - **Large PR (>400 lines)**: Request to split, or 60+ minutes
43
+
44
+ ## Review Depth Levels
45
+
46
+ ### Level 1: Skim Review (5 minutes)
47
+ - Check PR description and linked issues
48
+ - Verify CI/CD status
49
+ - Look at file changes overview
50
+ - Identify if deeper review needed
51
+
52
+ ### Level 2: Standard Review (20-30 minutes)
53
+ - Full code walkthrough
54
+ - Logic verification
55
+ - Test coverage check
56
+ - Security scan
57
+
58
+ ### Level 3: Deep Review (60+ minutes)
59
+ - Architecture evaluation
60
+ - Performance analysis
61
+ - Security audit
62
+ - Edge case exploration
63
+
64
+ ## Communication Guidelines
65
+
66
+ ### Tone and Language
67
+
68
+ **Use collaborative language:**
69
+ - "What do you think about..." instead of "You should..."
70
+ - "Could we consider..." instead of "This is wrong"
71
+ - "I'm curious about..." instead of "Why didn't you..."
72
+
73
+ **Be specific and actionable:**
74
+ - Include code examples when suggesting changes
75
+ - Link to documentation or past discussions
76
+ - Explain the "why" behind suggestions
77
+
78
+ ### Handling Disagreements
79
+
80
+ 1. **Seek to understand**: Ask clarifying questions
81
+ 2. **Acknowledge valid points**: Show you've considered their perspective
82
+ 3. **Provide data**: Use benchmarks, docs, or examples
83
+ 4. **Escalate if needed**: Involve senior dev or architect
84
+ 5. **Know when to let go**: Not every hill is worth dying on
85
+
86
+ ## Review Prioritization
87
+
88
+ ### Must Fix (Blocking)
89
+ - Security vulnerabilities
90
+ - Data corruption risks
91
+ - Breaking changes without migration
92
+ - Critical performance issues
93
+ - Missing error handling for user-facing features
94
+
95
+ ### Should Fix (Important)
96
+ - Test coverage gaps
97
+ - Moderate performance concerns
98
+ - Code duplication
99
+ - Unclear naming or structure
100
+ - Missing documentation for complex logic
101
+
102
+ ### Nice to Have (Non-blocking)
103
+ - Style preferences beyond linting
104
+ - Minor optimizations
105
+ - Additional test cases
106
+ - Documentation improvements
107
+
108
+ ## Anti-Patterns to Avoid
109
+
110
+ ### Reviewer Anti-Patterns
111
+ - **Rubber stamping**: Approving without actually reviewing
112
+ - **Bike shedding**: Debating trivial details extensively
113
+ - **Scope creep**: "While you're at it, can you also..."
114
+ - **Ghosting**: Requesting changes then disappearing
115
+ - **Perfectionism**: Blocking for minor style preferences
116
+
117
+ ### Author Anti-Patterns
118
+ - **Mega PRs**: Submitting 1000+ line changes
119
+ - **No context**: Missing PR description or linked issues
120
+ - **Defensive responses**: Arguing every suggestion
121
+ - **Silent updates**: Making changes without responding to comments
122
+
123
+ ## Metrics and Improvement
124
+
125
+ ### Track These Metrics
126
+ - Time to first review
127
+ - Review cycle time
128
+ - Number of review rounds
129
+ - Defect escape rate
130
+ - Review coverage percentage
131
+
132
+ ### Continuous Improvement
133
+ - Hold retrospectives on review process
134
+ - Share learnings from escaped bugs
135
+ - Update checklists based on common issues
136
+ - Celebrate good reviews and catches