关于 code-review
code-review 是用于审查分支、Pull Request 和未提交改动的 Skill,按风险优先级引导审查。它要求发现项提供代码证据,并规定分阶段检查、适度验证,以及在用户要求时执行修复和复审流程。
主要功能
- 01审查前确认基线与范围
- 02按顺序执行六类审计
- 03发现项附文件、行号和代码证据
- 04按风险制定验证方案
- 05按需修复并重新审查
- 06发布前自检
适用场景
- 01审查 Pull Request 或分支
- 02检查已暂存与未暂存改动
- 03优先识别安全与可靠性风险
- 04基于完整差异验证修复
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ whhe/ ai-workshop --skill code-review安装后在 Claude Code 中输入/code-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdreferences/code-quality-checklist.mdoutput-template.mdremoval-plan.mdsecurity-checklist.mdsolid-checklist.md详细介绍
铁律:每项发现都必须附上文件、行范围和代码证据。没有证据 = 不报告发现。
代码审查 — 按风险优先级进行比例适当的验证
工作流
- 步骤 1:预检 ⚠️ 必须执行
- 步骤 2:按风险优先级审计(检查 A–F)⚠️ 必须执行
- 步骤 3:呈现发现 ⚠️ 必须执行
- 步骤 4:修复循环(有条件——范围由步骤 3 确定)
- 步骤 5:发布前自检 ⚠️ 必须执行
1. 预检 — 确立基线 ⚠️ 必须执行
对于 PR URL,获取平台差异和元数据(base/head 引用、描述、评论、CI 状态)。在计算本地基线之前,确认本地审查所针对的 head 与该 PR 对应。
确立请求的审查范围,并在审查前固定 baseline_commit:
- 对分支或 PR 审查,解析 base 分支,并将
baseline_commit设为它与初始审查 head 的合并基点(git merge-base <base> HEAD)。除非用户或 PR 元数据指定其他分支,否则base默认为main。 - 对未提交更改的审查,将初始
HEAD设为baseline_commit。 - 记录用户指定的路径限制。在整个修复循环中保持基线不变,包括提交修复后。
在该范围内并行收集:
- 分支状态:
git status --short --branch - 基线之后的提交:
git log --oneline --decorate --no-merges <baseline_commit>..HEAD - 已跟踪的更改,包括提交、暂存更改和未暂存更改:
git diff --stat <baseline_commit>、git diff --name-only <baseline_commit>和git diff <baseline_commit> - 暂存层:当暂存和未暂存编辑并存时,也检查
git diff --cached <baseline_commit>和git diff,避免在最终工作树中相互抵消的编辑掩盖暂存状态。 - 新文件:
git ls-files --others --exclude-standard;单独读取范围内的每个文件,因为已跟踪文件的差异不包含其内容。
探索相关模块、用法、契约、入口点、所有权边界和关键路径。
2. 按风险优先级审计 ⚠️ 必须执行
审查既定范围内的每项更改,包括适用时所有分支/PR 提交,以及范围内未提交的更改和新文件。按顺序执行各项检查。
检查 A — 行为回归与兼容性
- 分支逻辑、默认值、功能标志或输入/输出契约是否有变化?
- API 参数、默认值和旧数据处理是否向后兼容?
- 命名/返回值语义是否符合现有代码库?标记“接口声明为 X,实际实现为 Y”的偏差。
对于每项影响现有逻辑的更改,说明:原有行为 → 新行为、影响范围、风险。
检查 B — SOLID 与架构
- SRP:此模块是否只有一个变更原因?
- OCP:能否在不修改现有代码的情况下添加新变体?
- LSP:任何子类能否在调用方不知情的情况下替代父类?
- ISP:所有实现者是否都使用了接口的全部方法?
- DIP:业务逻辑是否依赖具体的 I/O、存储或硬编码值?
- 过于宽泛的类型(
Any/any/dict/未标注类型)是否掩盖了领域约束?
优先采用渐进式重构方案,而非大规模重写。加载 solid-checklist.md,查看更多异味检查提示。
检查 C — 安全与可靠性
- 未认证或未授权的用户能否访问此代码路径?租户 A 的数据是否可能泄露给租户 B?
- 两个请求同时到达时会发生什么?状态是否可能在检查和执行之间发生变化?
- 如果操作中途失败,数据是否会处于不一致状态?
- 依赖项是否未固定版本、存在依赖混淆风险或已知 CVE?
- HTTP 客户端是否禁用了 TLS 验证(
verify=False、InsecureSkipVerify、rejectUnauthorized: false)?
同时指出可利用性和影响。加载 security-checklist.md,进行更深入的威胁模型分析。
Pass D — 性能与稳定性
- 如果数据量扩大到 10×/100×,会怎样?资源是否有上限并会被释放?
- 是否存在 N+1 查询?热路径中是否有可缓存或批量处理的 CPU 密集型工作?
- 发生故障时:是否有足够的上下文用于调试?日志或错误输出中是否泄露了机密?
- 如果此值为 null、0 或空值,会怎样?
加载 code-quality-checklist.md 以查看详细的子项检查。
Pass E — 待移除项
- 找出未使用、冗余或已关闭功能标志的代码。
- 区分现在可安全删除和推迟删除并制定计划。
如果发现待移除项,加载 removal-plan.md。
Pass F — 测试覆盖与语言特定检查
- 判断变更后的可观察契约是否有足够且有区分力的验证,以匹配其风险。添加新检查前,先复用现有测试和检查。
- 只有当变更逻辑未得到实质性验证,且无法通过更小范围的现有检查、静态检查或手动检查覆盖风险时,缺少测试才算作回归风险。
- 对于 Bug 修复,只有当当前测试套件无法捕获原始故障,且该用例稳定且值得保留时,才添加针对性的回归测试。如果现有的有区分力测试已在修复前因同一原始故障而失败,或者变更仅涉及文档、配置、接线或保持行为不变的重构,则不要添加重复测试。
- 只有当聚焦检查无法有效验证跨模块契约或边界时,才要求集成级覆盖。不要重复添加能够证明相同可观察结果的单元测试和集成测试。
- 断言的区分力:确认测试固件和断言能够区分真实行为与绕过逻辑/无操作情况——包括在所用数据下,筛选结果与未筛选结果看起来相同,或单条成功路径无法证明某个分支已执行的情况。根据功能特点,通过数量、标识或反例,或其他可观察效果来增强测试。
语言特定的易错点(通用检查可能遗漏的非显而易见问题):
| 语言 | 检查项 | 在以下情况标记 | 检查阶段 |
|---|---|---|---|
| Python | 混用朴素与带时区的 datetime | 对朴素和带时区的 datetime 对象进行比较、相减,或将其赋给同一字段,且未显式转换 | A |
| Python | ORM 分离实例上的延迟加载 | 关闭加载对象的会话后,访问 ORM 关系或延迟加载列 | D |
| Python | ORM 方言可移植性 | 查询依赖特定引擎的 SQL、仅适用于特定供应商的函数、原始 SQL 片段或仅适用于特定方言的类型,而非 ORM 可转换为项目所支持所有后端通用形式的 API。请确认可在该支持范围内的每种方言/版本中编译或执行 | A, D |
| TS/React | useEffect/useMemo/useCallback 依赖项问题 | 缺少响应式依赖、存在多余依赖,或依赖是不稳定引用(每次渲染都会新建对象/数组/函数) | D |
| JS/Node | 未添加保护条件的全局补丁/polyfill | monkey patch 或 polyfill 无条件执行——没有环境检查、特性检测或作用域隔离 | A |
3. 呈现发现 ⚠️ 必需
先报告 — 在进行任何更改之前呈现发现。 加载 output-template.md,了解文档结构、严重性级别和证据规则。
呈现后:
- 如果用户的原始请求明确包含修复(例如“审查并修复”“修复所有问题”“审查后修复所有问题”):自动进入修复循环,处理所有发现,无需确认。只有用户明确限定了修复范围时(例如“只修复 High 级问题”),才按其限定范围处理。反例——以下不算修复请求:“审查此修复”“审查我的 bug 修复分支”“检查此修复是否正确”——这里的“修复”指的是现有工作,而不是要求应用修复。
- 否则:询问用户如何继续(修复全部/仅修复 High 级/修复指定项目/不做更改)。在用户确认之前,不要实施更改。
4. 修复循环(有条件执行)
⛔ 仅在第 3 步确定修复范围后进入。只修复范围内的问题。
每次迭代:
-
运行最小范围的相关验证,建立修复前基线。
-
应用最小修复(避免引入新行为);只有当上述风险评估表明有必要保护已更改的契约时,才添加或更新针对性测试。
-
重新运行相同验证,确认修复有效。
-
针对第 1 步冻结的
baseline_commit,对所有累积更改进行对抗性复审:重新阅读git diff <baseline_commit>和所有范围内的新文件,以及第 1 步中适用的单独暂存层差异。这包括原始更改和每次修复,无论它们已提交、已暂存、未暂存还是未跟踪。仅包含提交的差异(例如<base>..HEAD)会遗漏未提交的修复;仅包含工作树的差异则会遗漏分支上的提交。保留原始范围和基线,不要只审查最新补丁。复审必须具有对抗性:默认立场是修复引入了新问题。审查者必须主动尝试证伪修复的正确性,之后才能接受。只标记会导致生产环境中可观察到的故障或违反已记录契约的问题——需要多个不太可能的前提条件的理论担忧不算发现。
独立判断:每次复审都要重新阅读当前完整差异、项目约定和受影响的调用方。将先前的发现和修复理由视为需要根据当前代码核实的主张。保留迭代历史,以便追溯。
应用 Pass A、C、D、F(Pass B 和 E 属于初始审计的一部分)。对于每个已修改区域,在接受之前,尝试构造一个现实的故障场景。如果有可用的独立审查者且已获准委派,请提供项目背景和完整差异,不要用预期结论或修复理由引导对方。否则,在当前对话中执行相同的证据驱动审查;不要声称对话上下文已被清除。
-
只有在复审(第 4 步)发现约定修复范围内的新问题时,才扩大范围。如果发现范围外的问题,请将其记录在修复循环迭代表中,并在修复循环结束时报告给用户。
持续迭代,不设固定迭代次数上限,直到相关验证通过,且对最新完整差异的复审未发现剩余的范围内问题。如果缺少前置条件、需要授权范围之外的决策,或在没有新证据或进展的情况下反复尝试,导致无法继续,则停止并报告未解决的发现、验证状态和具体阻碍。不得仅因迭代次数而停止或要求重新授权。 迭代跟踪:记录每次迭代的发现和修复。最终报告必须包含逐次迭代摘要(迭代编号、处理的问题、应用的修复、验证结果、复审结果),以便用户追溯修复历史(参见 output-template.md § 修复循环迭代)。
测试策略(根据项目调整):
- 先运行能够验证所改动契约的最小现有检查;只有当改动跨越边界,或针对性检查发现相关依赖时,才扩大检查范围。
- Python:先运行目标测试或现有的针对性检查;仅当改动有此需要时,再运行相关目录的检查。
- 前端:先运行受影响组件或页面的检查;仅当改动跨越其契约时,再运行相关测试套件。
- API 变更:使用现有覆盖验证变更后的请求、响应或错误契约;仅当该契约尚未得到验证时,才添加一个有区分度的用例。
- 不要仅为提高覆盖率、照搬实现分支或让报告显得完整而创建测试。无法在合理的回归情形下失败的测试没有价值。如果现有检查或低风险范围已足够,无需新增测试,请说明原因。
- 缺少前置条件(找不到命令、缺少依赖):注明“未验证”及其影响范围;提供可复现的命令;绝不可伪造结果。
5. 发布前自检 ⚠️ 必须执行
定稿前,按照 output-template.md § 发布前自检执行自检。
约束与反模式
绝不:
- 忽视默认值变更带来的隐式行为变化。
- 将未经验证的项目标记为“已通过”。
- 为了让测试通过而绕过关键检查(移除身份验证、吞掉异常、降低安全性)。
- 未经用户明确要求就提交或推送。
- 在呈现发现之前进行修复。
避免:
- 在安全性和正确性问题之前列出风格或命名问题。
- 不列出已检查内容就声称“未发现问题”。
- 复制粘贴代码却不解释问题所在。
- 将所有发现视为同等严重。
- 不阅读实际代码和差异就猜测行为。
资源
按需加载——仅在某项发现需要深入分析时加载。
| 文件 | 加载时机 |
|---|---|
| solid-checklist.md | 第 B 轮发现需要代码异味提示或重构启发时 |
| security-checklist.md | 第 C 轮发现需要威胁建模细节时 |
| code-quality-checklist.md | 第 D 轮发现需要稳定性或性能子检查时 |
| removal-plan.md | 第 E 轮发现可移除项时 |
| output-template.md | 第 3 和第 5 步——文档结构、证据规则、自检 |