zerocopy 仓库的 AI Agent 代码评审协议:Analyze-First、四重评审人格与 Rust 安全审查标准
zerocopy 仓库的 AI Agent 代码评审协议:Analyze-First、四重评审人格与 Rust 安全审查标准
本文以 libs/vulkan/zerocopy/agent_docs/reviewing.md 为核心骨架,系统讲解 zerocopy(一个以安全 API 包装底层内存操作、在安全关键场景广泛使用的 Rust 库)为 AI Agent 制定的代码评审协议。你将掌握:为什么评审前必须"先读文件"(Analyze-First)、如何以安全审计员/逻辑侦探/风格警察/简洁主义者四种人格分层审查代码、如何输出带推理链与可执行修复建议的评审结论,以及如何正确对待
TODO与// SAFETY:注释,最终形成一套可直接复用的"防幻觉、可落地"的 Agent 评审工作流。
一、背景:为什么一个 Rust 库需要面向 AI Agent 的评审协议
zerocopy 定位为"零成本内存操作的库"——它的宣传语是 Fast, safe, compile error. Pick two.,即让不安全的内存操作在编译期或显式 API 边界上被约束住。仓库根目录的 AGENTS.md 明确指出,zerocopy 是一个"在零成本内存操作之上提供安全 API、否则就要面对危险操作"的库,被用于安全固件、密码学实现、hypervisor 等安全关键场景;其 POLICIES.md 进一步声明:zerocopy 致力于在"任何不低于 MSRV 的 Rust 版本以及未来任意版本"上都保持 sound(健全、无未定义行为)。
正因如此,zerocopy 的代码变更(包括由 AI Agent 编写或由 Agent 评审的变更)必须达到极高正确性标准。reviewing.md 正是为此而生的"Agent 评审宪章":它规定了评审的强制前置动作、评审视角、输出格式与禁区,目标是用可验证的程序化步骤压制 Agent 幻觉(hallucination),让机器评审与人工评审遵循同一套可追溯的纪律。
二、Analyze-First 强制要求:评论任何代码前必须先读文件
reviewing.md 的第一条规则是所有评审纪律的基石:
Rule: Before commenting on any line of code, you MUST read the file using
view_file(或你所用协议中的等价工具)来确认上下文。
它给出的理由直指 Agent 评审最常见的失败模式:diff 往往缺少周边上下文,例如 cfg 门控、trait 约束、import 集合,而这些恰恰决定了一段代码是否成立。一段看起来"显然有问题"的代码,可能因为有 #[cfg] 条件编译或某个 trait 约束而完全合法;反之亦然。
协议流程被明确固化为四步:
- 评审请求到来(用户手动触发,或 CI/PR 自动触发);
- Agent 必须对相关文件调用
view_file(或等价工具); - Agent 按固定顺序分析代码:Safety(安全)→ Logic(逻辑)→ Style(风格);
- 生成评审结论。
这套顺序本身就是方法论:先排查未定义行为与安全不变量,再谈正确性与边界,最后才谈可读性与风格。从源码看,src/lib.rs 顶部就堆叠了大量 #![deny] / #![warn] 属性(如 clippy::undocumented_unsafe_blocks、clippy::unwrap_used),正是这种"安全优先"价值观在编译期层面的体现——评审者必须与编译器站在同一条线上。
三、四重评审人格:从多学科视角交叉审查
reviewing.md 要求 Agent 不做"通用助手",而是切换四种专家人格,每一重人格都有独立的检查清单。
A. 安全审计员(Security Auditor)——最关键的一层
聚焦:未定义行为(UB)、unsafe 块、安全不变量。其检查清单只有三项,但每一项都直接对应仓库的强制政策:
- [ ] 每个
unsafe块是否都有// SAFETY:注释? - [ ] 每个
unsafe函数、unsafetrait、以及带有安全前置条件的宏,是否都有/// # Safety文档? - ] 安全注释是否逐条符合 [agent_docs/unsafe_code.md 的每条规则?
这一层不是纸面要求,而是被编译期强制执行的。在 src/lib.rs 的 crate 级属性中明确启用了 clippy::undocumented_unsafe_blocks lint——这意味着任何没有安全注释的 unsafe 块都无法通过 clippy,评审者只是人类/Agent 版的"最后一道 lint"。该文件中仅 // SAFETY: 注释就有 29 处、/// # Safety 文档 20 余处,评审时这些注释的质量正是审查对象:注释是否真的证明了 soundness,还是只是形式化占位。
安全注释的硬性标准(来自 agent_docs/unsafe_code.md 与 POLICIES.md 双重规定):
- 注释必须构成一个(可以是非正式的)证明,说明所有 Rust soundness 规则都被满足;
- 论证依据只能来自稳定版 Rust Reference 或标准库(
core/alloc/std)文档,引用 beta/nightly 文档的论证视为不完整; - 被依赖的文档原文**必须被引用(quote)**在注释中,避免歧义,也避免未来文档改版时论证失效。
B. 逻辑侦探(Logic Detective)
聚焦:正确性、边界情况、off-by-one 错误、内部可变性(interior mutability)。检查清单:
- [ ] 代码在合法输入上是否会 panic?
- [ ]
unwrap/expect调用是否有充分理由? - [ ] 逻辑是否正确处理 ZST(零大小类型)?
- [ ] 泛型是否被正确约束?
其中"ZST 处理"和"泛型边界"在 zerocopy 这类以类型系统为安全边界的库中尤其关键——例如 KnownLayout、IntoBytes 等 trait 的泛型实现往往依赖"调用方必须满足的 trait 约束"来保证内存布局安全,评审时必须核对约束是否完整传递。
C. 风格警察(Style Cop)
聚焦:可读性、惯用 Rust、项目标准。参照文档为 agent_docs/style.md,其核心规范包括:
- 每个文件必须携带基于创建年份的版权头(见
src/lib.rs示例); - 注释(
//、///、//!)从左边距起 80 列 换行,Markdown 表格、ASCII 图、长 URL、代码块等除外; - Markdown 文件段落与列表同样按 80 列换行,列表续行缩进 2 空格,不得断开链接;
- 提交信息使用 GitHub issue 语法:
Closes #123(解决问题)、Makes progress on #123(推进问题)。
D. 简洁主义者(Simplicity Advocate)
聚焦:可维护性与代码复用。检查清单:
- [ ] 是否可以用既有工具完成?(先搜索代码库中的相似模式)
- [ ] 实现是否与其功能不成比例地复杂?
- [ ] 是否存在为了"炫技"而写的单行表达式,应当拆开以提高可读性?
- [ ] 是否在手动重造标准库或 crates.io 上流行 crate 已提供的功能?
这一人格与 zerocopy 的库定位直接相关:作为底层库,它理应为上层提供抽象而非制造重复轮子,评审者需要警惕"重新发明轮子"和"过度工程"两个方向。
四、操作协议:评审输出的硬性格式
1. Chain-of-Thought(推理链)强制要求
reviewing.md 规定:必须先输出推理过程,再给出最终结论。禁止"Looks good."式的空泛结论,必须展示证据链。文档给出的正例是:
"I checked the
unsafeblock on line 42. It casts*mut Tto*mut u8. The safety comment argues thatTisIntoBytes, butTis a generic without bounds. This is unsound. Finding: Unsoundunsafeblock."
这条规则的作用是双重的:对内,它迫使 Agent 显式暴露推理路径,便于人工复核;对外,它把"结论"与"证据"解耦,让评审意见可被追溯、可被反驳。这与仓库 agent_docs/unsafe_code.md 中"每个论证都要引用文档原文"的精神一脉相承——无论是写 unsafe 还是评 unsafe,都不能依赖"理所当然"。
2. 可操作反馈(Actionable Feedback)
每一条批评都必须可执行:
- 严重性分级:明确标注是
BLOCKING(合并前必须修复)还是NIT(可选/风格层面); - 修复方案:必须给出精确的修复代码片段,而不是"建议改进"。
3. TODO 注释的处理规则(含安全占位符豁免)
reviewing.md 为 TODO 制定了三条专门规则,这也是整个协议中最容易被 Agent 误报的部分:
- 以"TODO 将被解决"为前提评估周边代码——只评审"即便 TODO 解决后依然有问题"的地方;
- 仅当 TODO 本身不足以覆盖问题时才提出批评;
- 安全占位符豁免:
// SAFETY: TODO是安全注释的合法占位符,/// # Safety段中的/// TODO也是安全文档的合法占位符。不得将前者标记为"缺少安全论证",不得将后者标记为"缺少安全文档"。必须假设作者会在合并前写出健全的论证。
这一规则与 AGENTS.md 中的 TODO 政策互为表里:该仓库中 TODO 注释会阻塞 PR 合并(CI 遇到 TODO 即失败),非阻塞问题应使用 FIXME。也就是说,TODO 是"必须兑现的承诺",安全占位符则是"合并前必须补全的承诺"——评审者只需确保承诺会被兑现,而不是在评审阶段就假设违约。
五、反模式清单:评审中的绝对禁区
reviewing.md 以 NEVER 定义了四条红线,违反任何一条都属于评审事故:
- NEVER 批准缺少
// SAFETY:注释的 PR——这是被 clippy lint 与 POLICIES.md 双重背书的最低底线; - NEVER 仅凭函数命名假定其行为——必须查看定义(命名可能具有误导性);
- NEVER 在未检查
Cargo.toml是否已包含某依赖的情况下建议新增依赖——避免重复引入、版本冲突与供应链膨胀。
其中第二条"不要相信名字"在 zerocopy 这样的库中尤其危险:底层函数往往有极强的先验条件(如指针来源、对齐、provenance 范围),名字无法承载这些语义。
六、把评审协议放进仓库工作流:评审者应该知道的周边机制
reviewing.md 是 AGENTS.md 明确指定的评审必读文档("When reviewing changes, you MUST also read agent_docs/reviewing.md")。要把评审落地,还需要了解与其咬合的工作流机制:
- 提交前检查:运行 githooks/pre-push 会执行格式化、工具链校验、脚本校验等一整套检查——评审者可以将这些检查结果视为"代码已通过的基础门槛",把注意力集中在检查覆盖不到的语义问题上;
- 工具链纪律:该仓库要求一律通过 cargo.sh 包装脚本执行 cargo 命令(
./cargo.sh +msrv/+stable/+nightly),见 agent_docs/development.md。理由是 UI 测试依赖编译器错误文本、部分特性依赖特定工具链,这解释了为什么评审中看到的cfg门控如此常见——Analyze-First 中的"读全文件"正是为了识别这些门控; - 验证入口:代码变更需对照 agent_docs/validation.md 与 agent_docs/style.md 检查,评审者可据此把反馈指向具体的验证命令;
- 编译期防线示例:src/lib.rs 中
unsafe impl<T> KnownLayout for [T]的实现展示了"教科书级"的 SAFETY 注释——它逐条列出前置条件、逐条标注依据编号([1]、[2]、[3]),每条依据都引用特定版本的官方文档(如 1.81.0 / 1.82.0 的 std 与 reference 文档),完全符合 POLICIES.md 的"引用稳定版 + 引用原文"要求;同时以FIXME(#67)标注非阻塞的已知问题,与 AGENTS.md 的 TODO/FIXME 约定一致。安全审计员人格评审这类实现时,应逐条验证注释中的每个前提是否与代码事实吻合(例如.cast是否真的保留地址与 provenance、切片布局是否真的背靠背连续等)。
七、沉淀为可复用的 Agent 评审检查清单
将 reviewing.md 的纪律浓缩为一次评审的落地流程,供直接采用:
- 前置动作:对涉及变更的每个文件执行
view_file(含完整周边上下文,重点看cfg门控、trait 边界、import 与宏展开面),然后才允许开始评论; - 分层审查:严格按 Safety → Logic → Style 顺序逐层过检,每层调用对应人格的检查清单;
- 安全层:核对每个
unsafe块(含宏展开后生成的)都有// SAFETY:;核对每个unsafe fn/unsafe trait/ 安全前置宏都有/// # Safety;核对注释依据均来自稳定版文档且逐条引用原文;对// SAFETY: TODO与/// # Safety中的/// TODO行使占位符豁免; - 逻辑层:验证合法输入的 panic 面、
unwrap/expect的论证、ZST 处理、泛型边界传递; - 风格层:对照 style.md 的 80 列换行、版权头、提交信息 issue 语法;
- 简洁层:搜索既有工具/标准库/crates.io 替代实现,警惕过度复杂与炫技单行;
- 输出:先给推理链,再给结论;每条批评标注
BLOCKING/NIT并附修复代码片段;对TODO以"将被解决"为前提评估; - 红线自检:是否违反五节中的任何一条
NEVER。
这套协议的核心思想可以概括为一句话:在 zerocopy 这样的安全关键型 Rust 库中,AI Agent 评审的价值不在于"发现问题"的直觉,而在于"可验证、可追溯、可执行"的证明式纪律——先读文件、再分层推理、最后给修复,让每次评审都经得起编译器、lint 与人工复核的三重检验。