关于 code-review
一种以参与方之间的约定为审查单位的代码审查技能,核心关注正确性,也可检查性能与安全。它要求构造可行的违规执行并尝试反证,只报告有证据支持的发现。
主要功能
- 01按跨边界约定审查代码
- 02覆盖正确性、性能与安全维度
- 03构造可行的违规执行
- 04主动检验反驳机制
- 05区分发现与未决问题
适用场景
- 01检查调用方与被调用方的契约
- 02追查并发操作的身份关联问题
- 03分析状态写入与后续读取不一致
- 04评估变更引入的性能或安全缺陷
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ phuryn/ pm-skills --skill code-review安装后在 Claude Code 中输入/code-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/correctness-taxonomy.mdperformance-review.mdsecurity-review.md详细介绍
代码审查
目的
大多数审查结果都是噪声:一串看起来有问题、没有优先级、没有反驳依据且无法采取行动的事项。这项技能则会给出相反的结果——少量发现,每项都包含明确的行为要求、可行的触发条件、具体矛盾、可观察到的后果,以及已核查的最有力反驳理由。
它的核心判断是:审查者漏掉的缺陷,很少只在一个文件中显现。它们是两个参与方之间的不一致:单独看来都合理——调用方与被调用方、生产者与消费者、写入者与后续读取者,或两个理应建立相同状态的分支。逐文件套用检查清单无法发现这些问题,因为两个方面不会同时呈现在视野中。因此,这里的审查单位是约定,而不是文件。
结构:一个引擎,三个锚点
代码审查就是这项技能。正确性是其核心——通用工具覆盖最薄弱的维度,也是下文完整描述的维度。性能和安全性是它的子类别:使用相同的引擎、相同的反驳规范和相同的报告约定,但锚点不同,且各自多一两条规则。
| 子类别 | 锚点 | 规则所在位置 |
|---|---|---|
| 正确性(核心,默认) | 跨越边界的参与方之间的约定 | 本文件 + references/correctness-taxonomy.md |
| 性能 | 工作负载 → 资源需求 → 增长或争用 → 后果 | references/performance-review.md |
| 安全性 | 来源 → 信任边界 → 接收点,且攻击者可以控制来源 | references/security-review.md |
仅在选中某个子类别时,才阅读对应的文件。每个文件都刻意保持简短:只说明有哪些不同之处,本文件的其余内容仍然适用。
各子类别可以独立启用,并非互斥。一个根因可能同时影响正确性和安全性——报告一次,并注明两方面的影响。
调用方式
/pm-ai-shipping:code-review
/pm-ai-shipping:code-review dimensions=correctness scope=changes
/pm-ai-shipping:code-review dimensions=performance,security
/pm-ai-shipping:code-review dimensions=all
Claude Code 自带 /code-review。如果要使用这里介绍的技能,请使用上面的插件限定形式。
这些是指令参数,不是 shell 标志。
- **默认:
correctness。**只说“审查这个”或“找 bug”时,表示仅审查正确性。 - 明确列出的子类别会且只会选中这些类别;
all则会选中三类。不要擅自重新解释未知或空的选择——应先询问。 - **范围:**按用户要求确定范围。否则,如果存在未提交的工作变更,就审查这些变更;若没有,则审查整个仓库。
- 调查前说明选定的维度、范围和比较基准。
- 审查变更时,要追踪变更行之外的依赖关系,并区分缺陷是由这次变更引入的,还是仅被这次变更揭示的。
- 进行审查并报告结果。只有用户要求时才应用修复。
共享引擎
每个子类别都使用同一个框架。不同之处仅在锚点和反驳规则。
梳理流程 → 确定义务 → 检查每个参与方 → 构造违反义务的执行过程 → 追踪后果 → 尝试反驳 → 报告。
先构建一份精简的流程图:输入、主要执行流程、各状态的所有者、外部依赖和可观察到的影响。每个选定的子类别都在此基础上补充内容——不要构建三份流程图,也不要让仅审查安全性的任务等待正确性映射完成。
正确性:一致性引擎
边界是语义上的,而不是文件划分。它分隔调用方和被调用方、两个回调、同一函数的两次执行、生产者和消费者,或现在写入、稍后读取的值。
对每项重要的一致性约定,在工作笔记中记录以下内容,而非写入报告:
Participants:
Value, entity or effect exchanged:
Authority (who decides the real answer):
Identity and lifetime/version:
Required relationship:
Evidence for that relationship:
Relevant transitions or orderings:
Observable consumer or consequence:
在不臆造意图的前提下确立义务。 证据可以来自规范、文档化的契约、语言或协议语义、体现预期的测试,或必要的生产者/消费者关系。仅凭消费者的实现,并不能证明消费者是对的。如果参与方意见不一致,请说明这种分歧为何会导致错误结果——有时矛盾确凿无疑,但究竟哪一方应该修改则确实无法确定。缺少文档是一种局限,不会自动构成问题。
从最容易破坏一致性约定的地方入手: 被转换或协商的值、被重新分配的身份、转为异步的工作、持久化后重新加载的状态,以及必须保持一致的多项效果。然后检查普通决策、算术、边界和错误分支;不能让检查重点变成过滤器,把明显的错误排除在外。
构造违反约定的执行过程
在构造出破坏约定的执行过程之前,怀疑还不能算作发现问题。在实现允许的情况下:
- 让请求的值与接受或生效的值不同;
- 同时让两个操作保持进行中,并改变它们的完成顺序;
- 在观察与使用之间更改相关身份或代次;
- 比较不同的转换路径,确认它们是否应以等价状态结束;
- 在各项效果之间注入故障,并测试完成前中断;
- 测试空输入、精确边界值和相邻边界值。
确认每种情况确实可达,不要想当然。
两个需要强制探测、不能只提及的视角
在对真实代码库中植入的运行时缺陷进行大规模评估时,即使是表现出色的 Agent,也几乎从未报告过以下两类问题——不是发现后没能修复,而是根本没有注意到。把它们列入检查清单并无帮助;每一类都需要明确探测:
- 权威值协调。 跟踪一个提议值经过验证、规范化、协商或提交的过程,并找出下游状态仍由提议值派生的地方,而权威方可能会返回不同值。请求的值不等于实际应用的值。 探测:强制让两者不同,并检查还有哪些地方读取了请求值。
- 身份与关联。 跟踪操作结果如何找到其来源实体,并确认相关键在并发、乱序、移除和复用情况下,是否足够长时间地保持唯一、稳定且有效。只有当这些属性可能失效时,标签、位置或到达顺序才值得怀疑。探测:并发运行两个操作,并以乱序方式完成。
完整的十三种诊断视角及其各自的检测信号,见 references/correctness-taxonomy.md。这些视角彼此重叠,不是必须逐项填满的配额。
反证:让这项工作值得开展的严谨准则
只有同时满足以下五项,候选问题才能成为发现:
- 有依据的义务——必须满足什么要求,以及依据什么证据。
- 可行的执行过程——真实系统允许的输入、状态和顺序。
- 具体的矛盾——义务在哪一点上未能满足。
- 可观察的后果——错误的输出、状态、效果、完成结果或进度。
- 经过审视的反驳理由——能够阻止或修复问题的最有力机制。
积极寻找反证:是否存在某项外层保证,使该执行过程不可能发生;是否有同步机制排除了这种交错;是否会在任何有影响的读取之前完成协调;是否属于有意设计的契约;是否有前置条件排除了该输入;是否由其他责任方负责。
| 结果 | 规则 |
|---|---|
| 保留 | 证据证实缺陷存在;经核查的反驳理由无法阻止该缺陷。 |
| 排除 | 引用的证据推翻了该执行过程、义务或后果。 |
| 未解决 | 某项必要的契约或运行时事实未知。请将其与发现分开列出。 |
不要把安全子案例中的攻击者/受害者测试套用于正确性。**正确性缺陷即使只会伤害触发它的人,也仍可能很严重。**同样,“除非证明有误,否则保留”在这里过于宽松——没有构造出可行执行过程的无依据猜测,不算发现。如果两个子案例都适用,应分别只对各自的维度应用相应测试。
被吸收不等于被阻止。最容易导致错误反证的情况,是发现下游某个机制恰好掩盖了缺陷——比如缓存通常能保存该值、重试通常会成功、默认值通常正确——于是就排除了这项发现。这不是保证,而只是碰巧成功的概率较高;当吸收该问题的机制处于冷态、被逐出或重新配置后,这种情况就会失效。只有当某项机制使该执行过程不可能发生时,才排除该发现,并指出具体是哪项机制。出于同样的原因,“几乎总能正常工作”描述的是竞态,而不是反证——如果某个时序窗口通常会正确化解,这仍是一项发现;而你不得不推敲哪一方通常会胜出这一事实,本身就是证据。
测试通过、代码不熟悉、名称可疑、缺少测试以及同类实现之间存在差异,都是值得调查的线索——但没有一项能证明问题存在,也没有一项能构成反证。应按被违反的约定和根本原因去重,而不是按文件去重。发现数量没有配额;没有任何有依据的发现,也是有效结果。
并行处理
按完整流程或相互关联的约定组进行分派,绝不要按文件分派,也不要每个分类配一个 Agent。按文件划分正是会掩盖跨边界缺陷的拆分方式,而这些缺陷才值得发现。
- 协调者构建初始映射并识别共享状态。
- 每位工作 Agent 都会获得一个范围明确的流程、相关参与方、选定的子案例和待解问题。
- 工作 Agent 检查约定的双方,也可以跟进其任务列表之外的依赖项。
- 工作 Agent 返回候选问题、引用的证据、已完成的反驳验证以及未解决的关系。
- 协调者协调各项假设以及跨任务分配的关系。
- 对有力的候选问题进行单独验证,然后再报告。
允许读取范围重叠。 两位工作 Agent 读取同一权威来源,远比任何一方只掌握部分约定要划算。预留集成处理能力:跨越两项任务分配的未解决关系,在有人理清之前仍未得到检查。目标是只进行一层分派;如果无法委派或范围较小,则按相同流程依次执行。
让工作 Agent 使用当前可用的最强模型,并与当前会话的推理强度保持一致。 这项工作优先保证召回率:漏掉跨边界流程是代价高昂的失败,而工作 Agent 悄悄切换到更便宜的模型或较低的推理强度,是丢失发现结果最容易的方式。如果有任何工作 Agent 被重新路由或降级,请在报告中说明具体情况——如果读者以为所有内容都由同一个模型检查过,就会错误评估覆盖情况。
只用一个模型。为每位工作 Agent 指定该模型。 在此处进行分派是为了扩大覆盖面,而不是寻求第二种意见。每次生成工作 Agent 时,都要明确传入协调者使用的模型——“继承”不是路由决策,而工作 Agent 悄悄使用更便宜的模型,是漏掉发现结果最容易的方式。除非有人明确要求,否则不要引入不同的模型来复核或交叉检查:混用模型会导致结果无法归因;而且,在衡量或比较这项技能在不同模型上的表现时,哪怕只引入一个不同模型的工作 Agent,也会使结果失效。独立的第二模型复核是一个单独、需明确调用的步骤(/ship-check 第 6 步),绝不是这项技能会自行启动的环节。
告诉工作 Agent 只需读取,不得编辑。 审查工作 Agent 需要读取、搜索和浏览;不得修改代码树。在工作 Agent 的指令中明确这一点——如果工作 Agent 开始编辑,就会从审查偏离到“热心”修复,并停止报告它悄悄修复的内容,这样就无法再根据其描述的代码核查发现结果。要在提示词中明确说明,而不要假定宿主会强制执行;运行结束时,还要确认代码树没有变化。
报告
先列出有证据支持的发现,并按影响排序。严重程度与证据强度应分开说明。
Review scope:
Comparison baseline:
Selected dimensions:
[Severity] [Dimension] Concrete consequence
Expectation: required behaviour, and the evidence for it
Trigger: feasible preconditions and execution
Defect: the violated relationship
Evidence: source locations for EVERY participant
Impact: observable consequence and affected scope
Refutation: strongest counterargument checked, and why it fails
Remedy: minimal correction to the violated relationship
Verification: what was executed, versus established from source
Coverage:
Unexamined areas and essential unknowns:
对于跨边界缺陷,引用双方参与者;不要只按文件归类发现——这样会掩盖这项审查旨在发现的关系。
覆盖情况指实际完成的工作,而不是勾选的方框。 对每个选定的子案例,报告以下情况之一:已检查且有证据支持的发现 · 已检查,无发现得到支持 · 不适用,并说明原因 · 未检查,并说明原因。某个类别中没有发现,不意味着“未覆盖”;勾选表也不能证明检查完整。请写“在已检查范围内没有有证据支持的发现”,绝不要声称代码没有缺陷。
备注
- 明确指出哪些地方做得很好。只会指责的审查很容易被人忽视。
- 这两个子场景都有成熟的命令支持:
/security-audit-static(信任边界、数据接收点、OWASP 检查项)和/performance-audit-static(过度获取、索引、缓存)。如果子场景就是全部工作内容,请运行相应命令;如果它只是更广泛审查的一个维度,请使用参考文件。本技能不会重复说明这两者。 - 对于文档与代码的对照,请使用
intended-vs-implemented技能。 - 静态审查得出的是代码审查发现,而非已确认的漏洞或经测量的性能回退。