code-review-playbook

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Code Review Playbook

《代码评审手册》

Overview

概述

This skill provides a comprehensive framework for effective code reviews that improve code quality, share knowledge, and foster collaboration. Whether you're a reviewer giving feedback or an author preparing code for review, this playbook ensures reviews are thorough, consistent, and constructive.
When to use this skill:
  • Reviewing pull requests or merge requests
  • Preparing code for review (self-review)
  • Establishing code review standards for teams
  • Training new developers on review best practices
  • Resolving disagreements about code quality
  • Improving review processes and efficiency
本技能为高效代码评审提供全面框架,可提升代码质量、促进知识共享并加强团队协作。无论你是给出反馈的评审者,还是准备提交代码待评审的开发者,本手册都能确保评审工作全面、一致且富有建设性。
适用场景:
  • 评审拉取请求(PR)或合并请求(MR)
  • 准备待评审代码(自我评审)
  • 为团队制定代码评审标准
  • 培训新开发者掌握评审最佳实践
  • 解决关于代码质量的分歧
  • 优化评审流程与效率

Code Review Philosophy

代码评审理念

Purpose of Code Reviews

代码评审的目标

Code reviews serve multiple purposes:
  1. Quality Assurance: Catch bugs, logic errors, and edge cases
  2. Knowledge Sharing: Spread domain knowledge across the team
  3. Consistency: Ensure codebase follows conventions and patterns
  4. Mentorship: Help developers improve their skills
  5. Collective Ownership: Build shared responsibility for code
  6. Documentation: Create discussion history for future reference
代码评审具备多重价值:
  1. 质量保障:捕获bug、逻辑错误和边缘情况
  2. 知识共享:在团队内传播领域知识
  3. 一致性:确保代码库遵循约定与模式
  4. 指导培养:帮助开发者提升技能
  5. 集体所有权:建立代码的共同责任意识
  6. 文档记录:创建供未来参考的讨论历史

Principles

核心原则

Be Kind and Respectful:
  • Review the code, not the person
  • Assume positive intent
  • Praise good solutions
  • Frame feedback constructively
Be Specific and Actionable:
  • Point to specific lines of code
  • Explain why something should change
  • Suggest concrete improvements
  • Provide examples when helpful
Balance Speed with Thoroughness:
  • Aim for timely feedback (< 24 hours)
  • Don't rush critical reviews
  • Use automation for routine checks
  • Focus human review on logic and design
Distinguish Must-Fix from Nice-to-Have:
  • Use conventional comments to indicate severity
  • Block merges only for critical issues
  • Allow authors to defer minor improvements
  • Capture deferred work in follow-up tickets

友善尊重:
  • 评审代码,而非针对个人
  • 假设对方出发点是好的
  • 赞扬优秀的解决方案
  • 以建设性的方式提出反馈
具体且可执行:
  • 指向具体的代码行
  • 解释为什么需要修改
  • 提出明确的改进建议
  • 必要时提供示例
平衡速度与全面性:
  • 争取在24小时内给出反馈
  • 关键评审不要仓促
  • 用自动化工具处理常规检查
  • 人力评审聚焦逻辑与设计
区分必须修复与建议优化:
  • 使用标准化评论标注问题严重程度
  • 仅因关键问题阻止合并
  • 允许开发者推迟次要改进
  • 将推迟的工作记录在后续任务中

Conventional Comments

标准化评论

A standardized format for review comments that makes intent clear.
一种标准化的评审评论格式,可清晰传达意图。

Format

格式

<label> [decorations]: <subject>

[discussion]
<label> [修饰符]: <主题>

[讨论内容]

Labels

标签

LabelMeaningBlocks Merge?
praiseHighlight something positiveNo
nitpickMinor, optional suggestionNo
suggestionPropose an improvementNo
issueProblem that should be addressedUsually
questionRequest clarificationNo
thoughtIdea to considerNo
choreRoutine task (formatting, deps)No
noteInformational commentNo
todoFollow-up work neededMaybe
securitySecurity concernYes
bugPotential bugYes
breakingBreaking changeYes
标签含义是否阻止合并?
praise突出优秀的实现
nitpick微小的可选建议
suggestion提出改进方案
issue需要解决的问题通常是
question请求澄清
thought供参考的想法
chore常规任务(格式、依赖)
note信息性说明
todo需要后续跟进的工作可能
security安全问题
bug潜在bug
breaking破坏性变更

Decorations

修饰符

Optional modifiers in square brackets:
DecorationMeaning
[blocking]Must be addressed before merge
[non-blocking]Optional, can be deferred
[if-minor]Only if it's a quick fix
方括号中的可选修饰符:
修饰符含义
[blocking]合并前必须解决
[non-blocking]可选,可推迟处理
[if-minor]仅当修改成本极低时才需要处理

Examples

示例

typescript
// ✅ Good: Clear, specific, actionable

praise: Excellent use of TypeScript generics here!

This makes the function much more reusable while maintaining type safety.

---

nitpick [non-blocking]: Consider using const instead of let

This variable is never reassigned, so `const` would be more appropriate:
```typescript
const MAX_RETRIES = 3;

issue: Missing error handling for API call
If the API returns a 500 error, this will crash the application. Add a try/catch block:
typescript
try {
  const data = await fetchUser(userId);
  // ...
} catch (error) {
  logger.error('Failed to fetch user', { userId, error });
  throw new UserNotFoundError(userId);
}

question: Why use a Map instead of an object here?
Is there a specific reason for this data structure choice? If it's for performance, could you add a comment explaining?

security [blocking]: API endpoint is not authenticated
The
/api/admin/users
endpoint is missing authentication middleware. This allows unauthenticated access to sensitive user data.
Add the auth middleware:
typescript
router.get('/api/admin/users', requireAdmin, getUsers);

suggestion [if-minor]: Extract magic number to named constant
Consider extracting this value:
typescript
const CACHE_TTL_SECONDS = 3600;
cache.set(key, value, CACHE_TTL_SECONDS);

---
typescript
// ✅ 优秀示例:清晰、具体、可执行

praise: 这里TypeScript泛型的使用非常出色!

这让函数在保持类型安全的同时大幅提升了复用性。

---

nitpick [non-blocking]: 考虑使用const替代let

该变量从未被重新赋值,因此使用`const`更合适:
```typescript
const MAX_RETRIES = 3;

issue: API调用缺少错误处理
如果API返回500错误,应用会崩溃。 请添加try/catch块:
typescript
try {
  const data = await fetchUser(userId);
  // ...
} catch (error) {
  logger.error('获取用户失败', { userId, error });
  throw new UserNotFoundError(userId);
}

question: 为什么这里使用Map而不是普通对象?
选择这个数据结构有特定原因吗? 如果是出于性能考虑,能否添加注释说明?

security [blocking]: API端点未做身份验证
/api/admin/users
端点缺少身份验证中间件, 这会导致未授权用户访问敏感数据。
请添加身份验证中间件:
typescript
router.get('/api/admin/users', requireAdmin, getUsers);

suggestion [if-minor]: 将魔法数字提取为命名常量
考虑提取该值:
typescript
const CACHE_TTL_SECONDS = 3600;
cache.set(key, value, CACHE_TTL_SECONDS);

---

Review Process

评审流程

1. Before Reviewing

1. 评审前准备

Check Context:
  • Read the PR/MR description
  • Understand the purpose and scope
  • Review linked tickets or issues
  • Check CI/CD pipeline status
Verify Automated Checks:
  • Tests are passing
  • Linting has no errors
  • Type checking passes
  • Code coverage meets targets
  • No merge conflicts
Set Aside Time:
  • Small PR (< 200 lines): 15-30 minutes
  • Medium PR (200-500 lines): 30-60 minutes
  • Large PR (> 500 lines): 1-2 hours (or ask to split)
检查上下文:
  • 阅读PR/MR描述
  • 理解变更的目的与范围
  • 查看关联的工单或问题
  • 检查CI/CD流水线状态
验证自动化检查结果:
  • 测试通过
  • 代码无语法检查错误
  • 类型检查通过
  • 代码覆盖率达标
  • 无合并冲突
预留时间:
  • 小型PR(<200行):15-30分钟
  • 中型PR(200-500行):30-60分钟
  • 大型PR(>500行):1-2小时(或要求拆分)

2. During Review

2. 评审进行中

Follow a Pattern:
  1. High-Level Review (5-10 minutes)
    • Read PR description and understand intent
    • Skim all changed files to get overview
    • Verify approach makes sense architecturally
    • Check that changes align with stated purpose
  2. Detailed Review (20-45 minutes)
    • Line-by-line code review
    • Check logic, edge cases, error handling
    • Verify tests cover new code
    • Look for security vulnerabilities
    • Ensure code follows team conventions
  3. Testing Considerations (5-10 minutes)
    • Are tests comprehensive?
    • Do tests test the right things?
    • Are edge cases covered?
    • Is test data realistic?
  4. Documentation Check (5 minutes)
    • Are complex sections commented?
    • Is public API documented?
    • Are breaking changes noted?
    • Is README updated if needed?
遵循以下步骤:
  1. 整体评审(5-10分钟)
    • 阅读PR描述,理解变更意图
    • 快速浏览所有变更文件,掌握整体情况
    • 验证实现方案在架构上是否合理
    • 检查变更是否符合预期目标
  2. 细节评审(20-45分钟)
    • 逐行检查代码
    • 验证逻辑、边缘情况和错误处理
    • 确认新代码有对应的测试覆盖
    • 排查安全漏洞
    • 确保代码符合团队规范
  3. 测试考量(5-10分钟)
    • 测试是否全面?
    • 测试是否覆盖了正确的场景?
    • 边缘情况是否被覆盖?
    • 测试数据是否真实?
  4. 文档检查(5分钟)
    • 复杂代码段是否有注释?
    • 公共API是否有文档?
    • 破坏性变更是否有标注?
    • 必要时是否更新了README?

3. After Reviewing

3. 评审完成后

Provide Clear Decision:
  • Approve: Code is ready to merge
  • 💬 Comment: Feedback provided, no action required
  • 🔄 Request Changes: Issues must be addressed before merge
Respond to Author:
  • Answer questions promptly
  • Re-review after changes made
  • Approve when issues resolved
  • Thank author for addressing feedback

给出明确结论:
  • 批准:代码可合并
  • 💬 评论:提供了反馈,但无需修改
  • 🔄 要求修改:必须解决问题后才能合并
回复开发者:
  • 及时回答问题
  • 修改完成后重新评审
  • 问题解决后批准合并
  • 感谢开发者处理反馈

Review Checklists

评审检查清单

General Code Quality

通用代码质量

  • Readability: Code is easy to understand
  • Naming: Variables and functions have clear, descriptive names
  • Comments: Complex logic is explained
  • Formatting: Code follows team style guide
  • DRY: No unnecessary duplication
  • SOLID Principles: Code follows SOLID where applicable
  • Function Size: Functions are focused and < 50 lines
  • Cyclomatic Complexity: Functions have complexity < 10
  • 可读性:代码易于理解
  • 命名:变量和函数的名称清晰、有描述性
  • 注释:复杂逻辑有说明
  • 格式:代码遵循团队风格指南
  • DRY原则:无不必要的重复代码
  • SOLID原则:适用的代码遵循SOLID原则
  • 函数规模:函数职责单一且少于50行
  • 圈复杂度:函数圈复杂度低于10

Functionality

功能正确性

  • Correctness: Code does what it's supposed to do
  • Edge Cases: Boundary conditions handled (null, empty, min/max)
  • Error Handling: Errors caught and handled appropriately
  • Logging: Appropriate log levels and messages
  • Input Validation: User input is validated and sanitized
  • Output Validation: Responses match expected schema
  • 正确性:代码实现了预期功能
  • 边缘情况:处理了边界条件(null、空值、最大/最小值)
  • 错误处理:错误被正确捕获和处理
  • 日志:日志级别和信息合适
  • 输入验证:用户输入已验证和清理
  • 输出验证:响应符合预期格式

Testing

测试

  • Test Coverage: New code has tests
  • Test Quality: Tests actually test the right things
  • Edge Cases Tested: Tests cover boundary conditions
  • Error Paths Tested: Error handling is tested
  • Test Isolation: Tests don't depend on each other
  • Test Naming: Test names describe what's being tested
  • 测试覆盖率:新代码有对应的测试
  • 测试质量:测试确实覆盖了正确的场景
  • 边缘情况测试:测试覆盖了边界条件
  • 错误路径测试:错误处理逻辑已测试
  • 测试隔离:测试之间无依赖
  • 测试命名:测试名称清晰描述了测试内容

Performance

性能

  • Database Queries: N+1 queries avoided
  • Caching: Appropriate caching used
  • Algorithm Efficiency: No unnecessarily slow algorithms (O(n²) when O(n) possible)
  • Resource Cleanup: Files, connections, memory released
  • Lazy Loading: Heavy operations deferred when possible
  • 数据库查询:避免了N+1查询
  • 缓存:合理使用了缓存
  • 算法效率:无不必要的低效算法(如能用O(n)却用了O(n²))
  • 资源清理:文件、连接、内存已释放
  • 懒加载:重型操作已按需延迟执行

Security

安全

  • Authentication: Protected endpoints require auth
  • Authorization: Users can only access their own data
  • Input Sanitization: SQL injection, XSS prevented
  • Secrets Management: No hardcoded credentials or API keys
  • Encryption: Sensitive data encrypted at rest and in transit
  • HTTPS Only: Production traffic uses HTTPS
  • Rate Limiting: Endpoints protected from abuse
  • 身份验证:受保护的端点需要身份验证
  • 授权:用户只能访问自己的数据
  • 输入清理:防止SQL注入、XSS攻击
  • 密钥管理:无硬编码的凭证或API密钥
  • 加密:敏感数据在静态和传输时已加密
  • 仅HTTPS:生产环境流量使用HTTPS
  • 限流:端点已做防滥用限流

Language-Specific (JavaScript/TypeScript)

特定语言(JavaScript/TypeScript)

  • Async/Await: Promises handled correctly
  • Type Safety: TypeScript types are specific (not
    any
    )
  • Nullability: Null checks where needed (
    ?.
    operator)
  • Array Methods: Using map/filter/reduce appropriately
  • Const vs Let: Using const for immutable values
  • Arrow Functions: Appropriate use of arrow vs regular functions
  • Async/Await:Promise处理正确
  • 类型安全:TypeScript类型明确(不使用
    any
  • 空值处理:必要时做了null检查(使用
    ?.
    操作符)
  • 数组方法:合理使用map/filter/reduce
  • Const vs Let:不可变值使用const
  • 箭头函数:合理区分箭头函数与普通函数的使用场景

Language-Specific (Python)

特定语言(Python)

  • PEP 8: Follows Python style guide
  • Type Hints: Functions have type annotations
  • List Comprehensions: Used where appropriate (not overused)
  • Context Managers: Using
    with
    for file/connection handling
  • Exception Handling: Specific exceptions caught (not bare
    except:
    )
  • F-Strings: Modern string formatting used
  • PEP 8:遵循Python风格指南
  • 类型提示:函数有类型注解
  • 列表推导式:合理使用(不过度使用)
  • 上下文管理器:使用
    with
    处理文件/连接
  • 异常处理:捕获特定异常(不使用裸
    except:
  • F-字符串:使用现代字符串格式化方式

API Design

API设计

  • RESTful: Follows REST conventions (if REST API)
  • Consistent Naming: Endpoints follow naming patterns
  • HTTP Methods: Correct methods used (GET, POST, PUT, DELETE)
  • Status Codes: Appropriate HTTP status codes returned
  • Error Responses: Consistent error format
  • Pagination: Large lists are paginated
  • Versioning: API version strategy followed
  • REST规范:遵循REST约定(如果是REST API)
  • 命名一致性:端点遵循命名模式
  • HTTP方法:使用正确的HTTP方法(GET、POST、PUT、DELETE)
  • 状态码:返回合适的HTTP状态码
  • 错误响应:错误格式一致
  • 分页:大型列表已做分页
  • 版本控制:遵循API版本策略

Database

数据库

  • Migrations: Database changes have migrations
  • Indexes: Appropriate indexes created
  • Transactions: ACID properties maintained
  • Cascades: Delete cascades handled correctly
  • Constraints: Foreign keys, unique constraints defined
  • N+1 Queries: Eager loading used where needed
  • 迁移:数据库变更有对应的迁移脚本
  • 索引:创建了合适的索引
  • 事务:维护了ACID属性
  • 级联操作:删除级联处理正确
  • 约束:定义了外键、唯一约束
  • N+1查询:必要时使用了预加载

Documentation

文档

  • PR Description: Clear explanation of changes
  • Code Comments: Complex logic explained
  • API Docs: Public API documented (JSDoc, docstrings)
  • README: Updated if functionality changed
  • CHANGELOG: Breaking changes documented

  • PR描述:清晰说明变更内容
  • 代码注释:复杂逻辑有注释
  • API文档:公共API已文档化(JSDoc、docstrings)
  • README:功能变更时已更新
  • 变更日志:破坏性变更已记录

Review Feedback Patterns

评审反馈模式

How to Give Constructive Feedback

如何给出建设性反馈

✅ Good Feedback

✅ 优秀反馈示例

issue: This function doesn't handle the case where the user is null

If `getUserById()` returns null (user not found), this will throw:
`Cannot read property 'email' of null`

Add a null check:
```typescript
const user = await getUserById(userId);
if (!user) {
  throw new UserNotFoundError(userId);
}
return user.email;

**Why it's good:**
- Specific (points to exact problem)
- Explains the impact (what will happen)
- Suggests a concrete solution
- Provides example code
issue: 这个函数未处理用户为null的情况

如果`getUserById()`返回null(用户不存在),会抛出错误:
`Cannot read property 'email' of null`

请添加null检查:
```typescript
const user = await getUserById(userId);
if (!user) {
  throw new UserNotFoundError(userId);
}
return user.email;

**为什么优秀:**
- 具体(指出了确切问题)
- 说明了影响(会发生什么)
- 给出了明确的解决方案
- 提供了代码示例

❌ Bad Feedback

❌ 糟糕反馈示例

This is wrong. Fix it.
Why it's bad:
  • Not specific (what's wrong?)
  • Not helpful (how to fix?)
  • Sounds harsh (not constructive)

这不对,修复它。
为什么糟糕:
  • 不具体(哪里错了?)
  • 无帮助(怎么修复?)
  • 语气生硬(没有建设性)

How to Receive Feedback

如何接收反馈

As an Author:
  1. Assume Good Intent: Reviewers are trying to help
  2. Ask Questions: If feedback is unclear, ask for clarification
  3. Acknowledge Valid Points: Accept feedback graciously
  4. Explain Your Reasoning: If you disagree, explain why
  5. Make Changes Promptly: Address feedback quickly
  6. Say Thank You: Appreciate the reviewer's time
Responding to Feedback:
markdown
✅ Good Response:
> Good catch! I didn't consider the null case.
> I've added the null check in commit abc123.

✅ Good Response (Disagreement):
> I chose a Map here because we need O(1) lookups on a large dataset.
> An object would work but performs worse at scale (n > 10,000).
> I added a comment explaining this tradeoff.

❌ Bad Response:
> This works fine. Not changing it.

作为代码提交者:
  1. 假设善意:评审者是在提供帮助
  2. 提问澄清:如果反馈不明确,请询问细节
  3. 认可合理建议:欣然接受正确的反馈
  4. 解释你的思路:如果不同意,请说明原因
  5. 及时修改:尽快处理反馈
  6. 表达感谢:感谢评审者付出的时间
回复反馈的示例:
markdown
✅ 优秀回复:
> 好发现!我之前没考虑到null的情况。
> 我已经在提交abc123中添加了null检查。

✅ 优秀回复(有分歧):
> 我选择Map是因为我们需要对大数据集进行O(1)查找。
> 对象也能工作,但在数据量较大时(n > 10,000)性能更差。
> 我已经添加了注释说明这个权衡。

❌ 糟糕回复:
> 这个没问题,我不改。

Code Review Anti-Patterns

代码评审反模式

For Reviewers

评审者的反模式

Nitpicking Without Clear Value
nitpick: Add a space here
nitpick: Rename this variable to `userInfo` instead of `userData`
nitpick: Move this import to the top
Better: Use automated tools (Prettier, linters) for formatting.
Reviewing Line-by-Line Without Understanding Context Better: Read PR description first, understand the big picture.
Blocking on Personal Preferences
This should be a class instead of functions.
Better: Only block on objective issues (bugs, security). Discuss preferences separately.
Rewriting Code in Comments Better: Suggest improvements, don't provide full implementations (unless very helpful).
Review Fatigue (Approving Without Reading) Better: If you don't have time, say so. Don't rubber-stamp.
无意义的吹毛求疵
nitpick: 这里加个空格
nitpick: 把变量名从`userData`改成`userInfo`
nitpick: 把这个导入移到顶部
更好的做法: 用自动化工具(Prettier、代码检查器)处理格式问题。
不理解上下文就逐行评审 更好的做法: 先读PR描述,理解整体情况。
因个人偏好阻止合并
这应该用类而不是函数。
更好的做法: 仅因客观问题(bug、安全)阻止合并,偏好问题单独讨论。
在评论中重写代码 更好的做法: 提出改进建议,不要提供完整实现(除非特别有帮助)。
评审疲劳(未阅读就批准) 更好的做法: 如果没时间,直接说明,不要草率批准。

For Authors

提交者的反模式

Giant Pull Requests (> 1000 lines) Better: Break into smaller, focused PRs.
No Description Better: Write clear PR description with context and testing notes.
Submitting Failing Tests Better: Ensure all automated checks pass before requesting review.
Getting Defensive About Feedback Better: Accept feedback gracefully, discuss respectfully.
Force-Pushing After Review Better: Add new commits so reviewers can see what changed.

超大PR(>1000行) 更好的做法: 拆分成更小、聚焦的PR。
无PR描述 更好的做法: 写清晰的PR描述,包含上下文和测试说明。
提交测试未通过的代码 更好的做法: 确保所有自动化检查通过后再请求评审。
对反馈有抵触情绪 更好的做法: 欣然接受反馈,礼貌讨论。
评审后强制推送 更好的做法: 添加新提交,让评审者能看到变更内容。

Review Templates

评审模板

Standard PR Template

标准PR模板

markdown
undefined
markdown
undefined

Description

描述

Brief summary of what changed and why.
Fixes #[issue number]
变更内容及原因的简要说明。
修复了 #[工单号]

Type of Change

变更类型

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactoring (no functional changes)
  • Documentation update
  • Bug修复(非破坏性变更)
  • 新功能(非破坏性变更)
  • 破坏性变更(会导致现有功能无法正常工作)
  • 重构(无功能变更)
  • 文档更新

How Has This Been Tested?

测试情况

  • Unit tests added/updated
  • Integration tests added/updated
  • Tested manually in local environment
  • Tested in staging environment
  • 添加/更新了单元测试
  • 添加/更新了集成测试
  • 在本地环境手动测试
  • 在预发布环境测试

Checklist

检查清单

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published
  • 代码符合项目风格指南
  • 我已对自己的代码做了自我评审
  • 复杂代码段已添加注释
  • 已同步更新相关文档
  • 我的变更未产生新警告
  • 我添加了测试以证明修复有效或功能可用
  • 新的和现有的单元测试在本地都能通过
  • 所有相关依赖变更已合并并发布

Screenshots (if applicable)

截图(如适用)

[Add screenshots for UI changes]
[添加UI变更的截图]

Additional Notes

补充说明

[Any additional context or notes for reviewers]
undefined
[给评审者的额外上下文或说明]
undefined

Security Review Template

安全评审模板

markdown
undefined
markdown
undefined

Security Review Checklist

安全评审检查清单

Authentication & Authorization

身份验证与授权

  • Endpoints require appropriate authentication
  • User permissions are checked before actions
  • JWT tokens are validated and not expired
  • Session management is secure
  • 受保护的端点需要身份验证
  • 用户权限已在操作前检查
  • JWT令牌已验证且未过期
  • 会话管理安全

Input Validation

输入验证

  • All user inputs are validated
  • SQL injection prevented (parameterized queries)
  • XSS prevented (input sanitization, CSP headers)
  • CSRF protection in place for state-changing operations
  • 所有用户输入已验证
  • 已防止SQL注入(使用参数化查询)
  • 已防止XSS攻击(输入清理、CSP头)
  • 状态变更操作已做CSRF保护

Data Protection

数据保护

  • Sensitive data is encrypted at rest
  • TLS/HTTPS used for data in transit
  • API keys and secrets not hardcoded
  • PII is properly handled (GDPR/CCPA compliance)
  • 敏感数据在静态时已加密
  • 数据传输使用TLS/HTTPS
  • API密钥和密钥未硬编码
  • PII数据已按GDPR/CCPA合规处理

Dependencies

依赖

  • No known vulnerabilities in dependencies (npm audit / pip-audit)
  • Dependencies from trusted sources
  • Dependency versions pinned
  • 依赖无已知漏洞(npm audit / pip-audit)
  • 依赖来自可信源
  • 依赖版本已固定

Logging & Monitoring

日志与监控

  • Sensitive data not logged (passwords, tokens)
  • Security events logged (failed auth attempts)
  • Rate limiting in place for public endpoints
Security Concerns Identified: [List any security issues found]
Reviewer Signature: [Name, Date]

---
  • 日志中未包含敏感数据(密码、令牌)
  • 安全事件已记录(如失败的登录尝试)
  • 公共端点已做限流
发现的安全问题: [列出发现的所有安全问题]
评审者签名: [姓名,日期]

---

Review Metrics and Goals

评审指标与目标

Healthy Review Metrics

健康的评审指标

MetricTargetPurpose
Review Time< 24 hoursFast feedback loop
PR Size< 400 linesManageable reviews
Approval Rate (first review)20-30%Balance speed vs quality
Comments per PR3-10Engaged but not overwhelming
Back-and-Forth Rounds1-2Efficient communication
Time to Merge (after approval)< 2 hoursAvoid stale branches
指标目标目的
评审耗时<24小时快速反馈循环
PR规模<400行便于评审
首次评审批准率20-30%平衡速度与质量
每个PR的评论数3-10充分参与但不过度
往返次数1-2高效沟通
批准后合并耗时<2小时避免分支过时

Warning Signs

预警信号

  • ⚠️ PRs sitting unreviewed for > 3 days (review capacity issue)
  • ⚠️ 90%+ approval rate on first review (rubber-stamping)
  • ⚠️ Average PR size > 800 lines (PRs too large)
  • ⚠️ 15+ comments per PR (overly nitpicky or unclear requirements)
  • ⚠️ 5+ review rounds (poor communication or unclear standards)

  • ⚠️ PR超过3天未评审(评审能力不足)
  • ⚠️ 首次评审批准率90%+(草率批准)
  • ⚠️ 平均PR规模>800行(PR过大)
  • ⚠️ 每个PR的评论数>15(过度吹毛求疵或需求不明确)
  • ⚠️ 评审往返次数>5(沟通不畅或标准不清晰)

Integration with Agents

与Agent集成

Code Quality Reviewer Agent

代码质量评审Agent

  • Uses this playbook when reviewing code
  • Applies conventional comments format
  • Follows language-specific checklists
  • Provides structured, actionable feedback
  • 使用本手册进行代码评审
  • 应用标准化评论格式
  • 遵循特定语言检查清单
  • 提供结构化、可执行的反馈

Backend System Architect

后端系统架构师Agent

  • Reviews for architectural soundness
  • Checks design patterns and scalability
  • Validates API design against best practices
  • 评审架构合理性
  • 检查设计模式与可扩展性
  • 验证API设计是否符合最佳实践

Frontend UI Developer

前端UI开发者Agent

  • Reviews component structure and patterns
  • Checks accessibility and responsive design
  • Validates UI/UX implementation
  • 评审组件结构与模式
  • 检查可访问性与响应式设计
  • 验证UI/UX实现

Security Reviewer (Future Agent)

安全评审Agent(未来规划)

  • Focuses on security checklist
  • Identifies vulnerabilities
  • Validates compliance requirements

  • 聚焦安全检查清单
  • 识别漏洞
  • 验证合规要求

Advanced Pattern Detection (Opus 4.5)

高级模式检测(Opus 4.5)

Extended Thinking for Complex Reviews

复杂评审的深度思考

For large PRs or systemic analysis, leverage Opus 4.5's extended thinking to perform deep pattern detection:
When to Use Extended Thinking:
  • PR touches > 10 files across multiple modules
  • Reviewing security-critical code paths
  • Analyzing architectural consistency
  • Detecting cross-file code smells
  • Evaluating breaking change impact
Extended Thinking Review Pattern:
typescript
import Anthropic from '@anthropic-ai/sdk';

interface ReviewResult {
  issues: ReviewIssue[];
  patterns: DetectedPattern[];
  recommendations: string[];
  riskScore: number;
}

async function performDeepCodeReview(
  prDiff: string,
  codebaseContext: string
): Promise<ReviewResult> {
  const anthropic = new Anthropic();

  // Extended thinking requires budget_tokens < max_tokens
  // Minimum budget: 1,024 tokens
  const response = await anthropic.messages.create({
    model: 'claude-opus-4-5-20251101',
    max_tokens: 16000,
    thinking: {
      type: 'enabled',
      budget_tokens: 8000 // Deep analysis for complex reviews
    },
    messages: [{
      role: 'user',
      content: `
        Perform a comprehensive code review analyzing:

        ## PR Changes
        ${prDiff}

        ## Codebase Context
        ${codebaseContext}

        ## Analysis Requirements
        1. **Systemic Pattern Detection**: Identify recurring patterns (good and bad)
        2. **Cross-File Impact**: Trace how changes affect other modules
        3. **Security Analysis**: Deep scan for vulnerabilities (OWASP Top 10)
        4. **Architectural Consistency**: Verify alignment with existing patterns
        5. **Technical Debt Assessment**: Identify debt being added or resolved

        Provide structured output with:
        - Critical issues (must fix)
        - Warnings (should fix)
        - Suggestions (nice to have)
        - Detected patterns (positive and negative)
        - Risk score (1-10)
      `
    }]
  });

  // Response contains thinking blocks followed by text blocks
  // content: [{ type: 'thinking', thinking: '...' }, { type: 'text', text: '...' }]
  return parseReviewResponse(response);
}
对于大型PR或系统性分析,可利用Opus 4.5的深度思考能力进行模式检测:
何时使用深度思考:
  • PR修改了10个以上文件,涉及多个模块
  • 评审安全关键代码路径
  • 分析架构一致性
  • 检测跨文件代码异味
  • 评估破坏性变更的影响
深度思考评审模式:
typescript
import Anthropic from '@anthropic-ai/sdk';

interface ReviewResult {
  issues: ReviewIssue[];
  patterns: DetectedPattern[];
  recommendations: string[];
  riskScore: number;
}

async function performDeepCodeReview(
  prDiff: string,
  codebaseContext: string
): Promise<ReviewResult> {
  const anthropic = new Anthropic();

  // 深度思考要求budget_tokens < max_tokens
  // 最小预算:1,024 tokens
  const response = await anthropic.messages.create({
    model: 'claude-opus-4-5-20251101',
    max_tokens: 16000,
    thinking: {
      type: 'enabled',
      budget_tokens: 8000 // 复杂评审的深度分析
    },
    messages: [{
      role: 'user',
      content: `
        执行全面的代码评审,分析以下内容:

        ## PR变更
        ${prDiff}

        ## 代码库上下文
        ${codebaseContext}

        ## 分析要求
        1. **系统性模式检测**:识别重复出现的模式(好的和坏的)
        2. **跨文件影响**:追踪变更对其他模块的影响
        3. **安全分析**:深度扫描漏洞(OWASP Top 10)
        4. **架构一致性**:验证与现有模式的对齐度
        5. **技术债务评估**:识别新增或解决的技术债务

        提供结构化输出,包含:
        - 关键问题(必须修复)
        - 警告(应该修复)
        - 建议(优化项)
        - 检测到的模式(正面和负面)
        - 风险评分(1-10)
      `
    }]
  });

  // 响应包含思考块和文本块
  // content: [{ type: 'thinking', thinking: '...' }, { type: 'text', text: '...' }]
  return parseReviewResponse(response);
}

Systemic Code Smell Detection

系统性代码异味检测

Detect patterns that span multiple files:
typescript
interface CodeSmellPattern {
  type: 'duplication' | 'coupling' | 'complexity' | 'naming' | 'architecture';
  severity: 'critical' | 'warning' | 'info';
  locations: FileLocation[];
  description: string;
  suggestion: string;
}

const SMELL_PATTERNS = {
  // Cross-file duplication
  duplication: {
    triggers: ['similar logic in 3+ files', 'copy-paste patterns', 'repeated error handling'],
    action: 'Extract to shared utility or base class'
  },

  // Tight coupling
  coupling: {
    triggers: ['circular imports', 'god objects', 'feature envy'],
    action: 'Apply dependency injection or interface segregation'
  },

  // Complexity creep
  complexity: {
    triggers: ['nested callbacks > 3 levels', 'functions > 50 lines', 'cyclomatic complexity > 10'],
    action: 'Decompose into smaller, focused functions'
  },

  // Inconsistent naming
  naming: {
    triggers: ['mixed conventions', 'unclear abbreviations', 'inconsistent pluralization'],
    action: 'Align with codebase naming conventions'
  },

  // Architectural drift
  architecture: {
    triggers: ['layer violations', 'missing abstractions', 'inappropriate intimacy'],
    action: 'Refactor to follow established architectural patterns'
  }
};
检测跨多个文件的模式:
typescript
interface CodeSmellPattern {
  type: 'duplication' | 'coupling' | 'complexity' | 'naming' | 'architecture';
  severity: 'critical' | 'warning' | 'info';
  locations: FileLocation[];
  description: string;
  suggestion: string;
}

const SMELL_PATTERNS = {
  // 跨文件重复
  duplication: {
    触发条件: ['3个以上文件有相似逻辑', '复制粘贴模式', '重复的错误处理'],
    行动: '提取到共享工具类或基类'
  },

  // 紧耦合
  coupling: {
    触发条件: ['循环导入', '上帝对象', '特性羡慕'],
    行动: '应用依赖注入或接口隔离'
  },

  // 复杂度攀升
  complexity: {
    触发条件: ['嵌套回调>3层', '函数>50行', '圈复杂度>10'],
    行动: '分解为更小、聚焦的函数'
  },

  // 命名不一致
  naming: {
    触发条件: ['混合命名规范', '模糊的缩写', '复数形式不一致'],
    行动: '与代码库命名规范对齐'
  },

  // 架构漂移
  architecture: {
    触发条件: ['层级违反', '缺少抽象', '不当亲密'],
    行动: '重构以遵循既定架构模式'
  }
};

Security Deep Analysis

安全深度分析

Extended thinking enables comprehensive security review:
typescript
interface SecurityFinding {
  category: 'injection' | 'auth' | 'crypto' | 'exposure' | 'config';
  severity: 'critical' | 'high' | 'medium' | 'low';
  cwe: string; // CWE ID
  location: FileLocation;
  description: string;
  remediation: string;
}

async function performSecurityReview(
  code: string,
  context: SecurityContext
): Promise<SecurityFinding[]> {
  const anthropic = new Anthropic();

  const response = await anthropic.messages.create({
    model: 'claude-opus-4-5-20251101',
    max_tokens: 12000,
    thinking: {
      type: 'enabled',
      budget_tokens: 6000 // Security analysis needs deep reasoning
    },
    messages: [{
      role: 'user',
      content: `
        Perform security analysis on this code:

        ${code}

        Context:
        - Language: ${context.language}
        - Framework: ${context.framework}
        - Exposure: ${context.isPublicFacing ? 'Public' : 'Internal'}

        Check for:
        1. Injection vulnerabilities (SQL, XSS, command)
        2. Authentication/Authorization flaws
        3. Cryptographic weaknesses
        4. Sensitive data exposure
        5. Security misconfiguration

        For each finding, provide CWE ID and specific remediation.
      `
    }]
  });

  return parseSecurityFindings(response);
}
深度思考能力支持全面的安全评审:
typescript
interface SecurityFinding {
  category: 'injection' | 'auth' | 'crypto' | 'exposure' | 'config';
  severity: 'critical' | 'high' | 'medium' | 'low';
  cwe: string; // CWE编号
  location: FileLocation;
  description: string;
  remediation: string;
}

async function performSecurityReview(
  code: string,
  context: SecurityContext
): Promise<SecurityFinding[]> {
  const anthropic = new Anthropic();

  const response = await anthropic.messages.create({
    model: 'claude-opus-4-5-20251101',
    max_tokens: 12000,
    thinking: {
      type: 'enabled',
      budget_tokens: 6000 // 安全分析需要深度推理
    },
    messages: [{
      role: 'user',
      content: `
        对以下代码进行安全分析:

        ${code}

        上下文:
        - 语言: ${context.language}
        - 框架: ${context.framework}
        - 暴露程度: ${context.isPublicFacing ? '公开' : '内部'}

        检查内容:
        1. 注入漏洞(SQL、XSS、命令注入)
        2. 身份验证/授权缺陷
        3. 加密弱点
        4. 敏感数据暴露
        5. 安全配置错误

        每个发现请提供CWE编号和具体修复建议。
      `
    }]
  });

  return parseSecurityFindings(response);
}

Cross-File Impact Analysis

跨文件影响分析

Trace how changes ripple through the codebase:
typescript
interface ImpactAnalysis {
  directImpact: FileImpact[];
  indirectImpact: FileImpact[];
  breakingChanges: BreakingChange[];
  testCoverage: TestCoverageGap[];
}

async function analyzeChangeImpact(
  changedFiles: string[],
  dependencyGraph: DependencyGraph
): Promise<ImpactAnalysis> {
  // Build impact graph
  const directlyAffected = new Set<string>();
  const indirectlyAffected = new Set<string>();

  for (const file of changedFiles) {
    // Files that import this file
    const dependents = dependencyGraph.getDependents(file);
    dependents.forEach(d => directlyAffected.add(d));

    // Second-level dependents
    for (const dependent of dependents) {
      const secondLevel = dependencyGraph.getDependents(dependent);
      secondLevel.forEach(d => {
        if (!directlyAffected.has(d)) {
          indirectlyAffected.add(d);
        }
      });
    }
  }

  // Use extended thinking for breaking change analysis
  const breakingAnalysis = await analyzeBreakingChanges(
    changedFiles,
    Array.from(directlyAffected)
  );

  return {
    directImpact: Array.from(directlyAffected).map(f => ({ file: f, type: 'direct' })),
    indirectImpact: Array.from(indirectlyAffected).map(f => ({ file: f, type: 'indirect' })),
    breakingChanges: breakingAnalysis.breaking,
    testCoverage: breakingAnalysis.gaps
  };
}
追踪变更在代码库中的连锁反应:
typescript
interface ImpactAnalysis {
  directImpact: FileImpact[];
  indirectImpact: FileImpact[];
  breakingChanges: BreakingChange[];
  testCoverage: TestCoverageGap[];
}

async function analyzeChangeImpact(
  changedFiles: string[],
  dependencyGraph: DependencyGraph
): Promise<ImpactAnalysis> {
  // 构建影响图
  const directlyAffected = new Set<string>();
  const indirectlyAffected = new Set<string>();

  for (const file of changedFiles) {
    // 导入了该文件的文件
    const dependents = dependencyGraph.getDependents(file);
    dependents.forEach(d => directlyAffected.add(d));

    // 二级依赖文件
    for (const dependent of dependents) {
      const secondLevel = dependencyGraph.getDependents(dependent);
      secondLevel.forEach(d => {
        if (!directlyAffected.has(d)) {
          indirectlyAffected.add(d);
        }
      });
    }
  }

  // 使用深度思考分析破坏性变更
  const breakingAnalysis = await analyzeBreakingChanges(
    changedFiles,
    Array.from(directlyAffected)
  );

  return {
    directImpact: Array.from(directlyAffected).map(f => ({ file: f, type: 'direct' })),
    indirectImpact: Array.from(indirectlyAffected).map(f => ({ file: f, type: 'indirect' })),
    breakingChanges: breakingAnalysis.breaking,
    testCoverage: breakingAnalysis.gaps
  };
}

Review Automation with Model Tiering

模型分层的评审自动化

Optimize review costs with intelligent model selection:
typescript
type ModelTier = 'opus' | 'sonnet' | 'haiku';

interface ReviewConfig {
  model: ModelTier;
  thinkingBudget?: number;
  focus: string[];
}

function selectReviewModel(pr: PullRequest): ReviewConfig {
  // Critical path - use Opus with extended thinking
  if (pr.touchesCriticalPath || pr.isSecurityRelated) {
    return {
      model: 'opus',
      thinkingBudget: 8000,
      focus: ['security', 'architecture', 'breaking-changes']
    };
  }

  // Large PRs - use Opus for systemic analysis
  if (pr.filesChanged > 10 || pr.linesChanged > 500) {
    return {
      model: 'opus',
      thinkingBudget: 5000,
      focus: ['patterns', 'impact', 'consistency']
    };
  }

  // Standard PRs - Sonnet for thorough review
  if (pr.linesChanged > 100) {
    return {
      model: 'sonnet',
      focus: ['correctness', 'style', 'tests']
    };
  }

  // Small changes - Haiku for quick review
  return {
    model: 'haiku',
    focus: ['correctness', 'style']
  };
}
通过智能模型选择优化评审成本:
typescript
type ModelTier = 'opus' | 'sonnet' | 'haiku';

interface ReviewConfig {
  model: ModelTier;
  thinkingBudget?: number;
  focus: string[];
}

function selectReviewModel(pr: PullRequest): ReviewConfig {
  // 关键路径 - 使用Opus并开启深度思考
  if (pr.touchesCriticalPath || pr.isSecurityRelated) {
    return {
      model: 'opus',
      thinkingBudget: 8000,
      focus: ['security', 'architecture', 'breaking-changes']
    };
  }

  // 大型PR - 使用Opus进行系统性分析
  if (pr.filesChanged > 10 || pr.linesChanged > 500) {
    return {
      model: 'opus',
      thinkingBudget: 5000,
      focus: ['patterns', 'impact', 'consistency']
    };
  }

  // 标准PR - 使用Sonnet进行全面评审
  if (pr.linesChanged > 100) {
    return {
      model: 'sonnet',
      focus: ['correctness', 'style', 'tests']
    };
  }

  // 小型变更 - 使用Haiku快速评审
  return {
    model: 'haiku',
    focus: ['correctness', 'style']
  };
}

Review Comment Generation

评审评论自动生成

Generate conventional comments automatically:
typescript
interface GeneratedComment {
  label: 'praise' | 'nitpick' | 'suggestion' | 'issue' | 'question' | 'security' | 'bug';
  decoration?: 'blocking' | 'non-blocking' | 'if-minor';
  subject: string;
  discussion: string;
  location: { file: string; line: number };
}

function formatConventionalComment(comment: GeneratedComment): string {
  const decoration = comment.decoration ? ` [${comment.decoration}]` : '';
  return `${comment.label}${decoration}: ${comment.subject}\n\n${comment.discussion}`;
}

// Example output:
// security [blocking]: SQL injection vulnerability in user search
//
// The search query is constructed using string concatenation:
// ```typescript
// const query = `SELECT * FROM users WHERE name = '${searchTerm}'`;
// ```
//
// Use parameterized queries instead:
// ```typescript
// const query = 'SELECT * FROM users WHERE name = $1';
// const result = await db.query(query, [searchTerm]);
// ```

自动生成标准化评论:
typescript
interface GeneratedComment {
  label: 'praise' | 'nitpick' | 'suggestion' | 'issue' | 'question' | 'security' | 'bug';
  decoration?: 'blocking' | 'non-blocking' | 'if-minor';
  subject: string;
  discussion: string;
  location: { file: string; line: number };
}

function formatConventionalComment(comment: GeneratedComment): string {
  const decoration = comment.decoration ? ` [${comment.decoration}]` : '';
  return `${comment.label}${decoration}: ${comment.subject}\n\n${comment.discussion}`;
}

// 示例输出:
// security [blocking]: 用户搜索存在SQL注入漏洞
//
// 查询语句使用字符串拼接构建:
// ```typescript
// const query = `SELECT * FROM users WHERE name = '${searchTerm}'`;
// ```
//
// 请改用参数化查询:
// ```typescript
// const query = 'SELECT * FROM users WHERE name = $1';
// const result = await db.query(query, [searchTerm]);
// ```

Quick Start Guide

快速入门指南

For Reviewers:
  1. Read PR description and understand intent
  2. Check that automated checks pass
  3. Do high-level review (architecture, approach)
  4. Do detailed review (logic, edge cases, tests)
  5. Use conventional comments for clear communication
  6. Provide decision: Approve, Comment, or Request Changes
For Authors:
  1. Write clear PR description
  2. Perform self-review before requesting review
  3. Ensure all automated checks pass
  4. Keep PR focused and reasonably sized (< 400 lines)
  5. Respond to feedback promptly and respectfully
  6. Make requested changes or explain reasoning

Skill Version: 2.0.0 Last Updated: 2025-11-27 Maintained by: AI Agent Hub Team
评审者:
  1. 阅读PR描述,理解变更意图
  2. 确认自动化检查已通过
  3. 进行整体评审(架构、方案)
  4. 进行细节评审(逻辑、边缘情况、测试)
  5. 使用标准化评论进行清晰沟通
  6. 给出明确结论:批准、评论或要求修改
提交者:
  1. 写清晰的PR描述
  2. 提交前先做自我评审
  3. 确保所有自动化检查通过
  4. 保持PR聚焦且规模合理(<400行)
  5. 及时、礼貌地回复反馈
  6. 根据反馈修改代码或解释思路

技能版本: 2.0.0 最后更新: 2025-11-27 维护团队: AI Agent Hub Team