质询
为每个配置的模型生成一个审查者,以对抗性方式审查代码变更。每个模型接收相同的提示和评估标准。对抗信号来自模型多样性,而非分配的角色。
只有经过运行证明的发现才算数。
最终输出是一个综合判定。不要自动应用变更。
步骤 1:确定范围
根据上下文确定需要审查的内容:
- 如果用户指定了特定文件或差异,使用它们
- 如果在功能分支上,运行
git diff main...HEAD(或相应的基分支)以获取完整变更集 - 如果用户的消息引用了最近的工作,收集相关文件
打包差异(或文件内容)以及审查者理解代码所需的任何上下文文件。
步骤 2:声明意图
在启动审查者之前,明确声明意图。从以下信息中推导:
- 用户的消息
- 提交消息
- PR 描述(如果有)
- 代码本身
写一段清晰的文字。如果不确定意图,请先询问用户。
步骤 3:启动审查者
在同一消息中启动所有审查者,每个槽位一个,使用 harness 的子代理工具或 delegate_task。
目标是 模型多样性:不同的模型系列能捕捉不同类型的错误。在 T3 Code 中,从用户收藏中选择 3-4 个强大的模型,来自不同系列,并使用 delegate_task 启动每个模型(t3-tools 技能中有详细步骤)。在其他环境中,选择 3-4 个 harness 暴露的不同高能力模型。如果无法为每个子代理选择模型,则在不覆盖模型的情况下启动审查者,依靠独立上下文获得多样性。
| 子代理 | 角色 |
|---|---|
| 审查者 A | 推理密集型审查者 |
| 审查者 B | 第二个独立模型系列 |
| 审查者 C | 第三个快速/不同系列 |
| 审查者 D | 对抗性/严格代码质量审查者 |
对于每个审查者,启动一个通用子代理:
- OpenCode / Codex:
subagent_type: general(通过task工具) - Claude Code:
subagent_type: general-purpose - 其他 harness:最接近的通用子代理,能够读取仓库
保持审查者精神上的只读性:他们不得编辑文件。需要复现的审查者应在自己的副本或工作树中运行,绝不在原处运行。
为每个审查者提供以下简介以及填充后的模板:
破坏这个变更。通过针对真实代码的运行证明每个发现,例如失败的测试、复现脚本或显示错误行为的命令输出。对于设计或计划,运行原型或探测当前树。将复现保持在自己的工作树中。报告每个发现时包含标题、确切的命令、其打印的输出以及意图要求的输出。省略任何未实际运行的内容。涵盖风格、命名、结构以及需要未来变更才能解决的风险。没有发现也是有效结果。
如果某个模型 slug 被拒绝为无法解析,检查 Task 工具错误消息中的有效 slug,选择最接近的等效项(优先选择同一系列中最高推理层级的版本),并使用有效 slug 启动。不要让 slug 问题阻碍审查。
阅读 references/reviewer-prompt.md 并用以下内容填充模板:
- 声明的意图
- 差异或文件内容
- 来自
references/rubric.md的审查标准 - 来自
references/code-quality-review.md的代码质量视角
相同的填充模板将发送给所有审查者,因此每个模型都应用代码质量视角。
步骤 4:综合
随着结果返回,构建统一视图:
- 验证每个发现:重新运行其命令。当输出显示失败且失败破坏了意图时,保留该发现。丢弃其余部分。合并根因相同的发现。
- 解析所有审查者的发现
- 识别共识:由 2 个或更多模型独立提出的发现信号最强。
- 识别单一模型发现:仍然值得阅读,但相应加权。
- 去重:不同模型可能描述相同问题。合并它们,并注明哪些模型提出了该问题。
- 记录分歧:如果一个模型标记了某点而另一个模型明确表示相反,这对判定是有用的上下文。
步骤 5:主导判断
你是主导审查者,一个务实的高级工程师,而不是中立的聚合器。
阅读 references/lead-judgment.md 以获取完整框架。
将每个发现分类为以下几个类别:
- 立即行动:影响正确性、安全性或可维护性的真实问题(根据实际目标)。这些会阻止一个真正的 PR。
- 考虑:合理观点,但你不确定在当前是否值得花时间解决。值得用户注意。
- 已记录:技术上有效但不可操作。依赖上下文、过早优化或当前阶段影响低。
- 驳回:错误、吹毛求疵或缺乏上下文。简要解释原因。
对于每个发现,包含:
- 提出它的模型
- 分类(立即行动 / 考虑 / 已记录 / 驳回)
- 分类的单行理由
输出格式
按以下结构呈现判定:
意图
[步骤 2 中声明的意图段落]
审查者
- 审查者 [标签]:[模型名称],[发现数量](每个审查者一个要点)
立即行动
[应处理的发现。包含:描述、提出它的模型、为何重要。]
考虑
[值得思考的发现。包含:描述、提出它的模型、涉及的权衡。]
已记录
[有效但优先级低。简要列表。]
驳回
[被拒绝的发现及简要理由,包括未经过运行证明的发现。]
共识地图
[模型在哪里达成一致,在哪里出现分歧,以及这种一致/分歧模式告诉我们什么?]
波及范围
当变更很小但不受信任时使用此模式,问题在于变更会破坏差异之外的内容。列出调用者不是目标。grep 能瞬间找出它们。目标是 grep 不会显示的破坏。
不要相信自己的撰写
关于变更破坏内容的看起来合理的描述毫无价值。无论是否真实,它读起来都令人信服。所以不要只交还描述。找出整个事情依赖的一两个事实,并通过运行代码证明它们。
你有多确定
对于变更安全性依赖的每个事实,尽量在便宜的前提下将其推至列表靠后的层级,并说明它停在了哪里。
- 你说了算。单独来看毫无价值。
- 你指向了行号。真实的
file:line,或库自身的源码。 - 你展示了坏情况不会发生。你逐步跟踪了失败路径,发现它无法到达。
- 你运行了它。一个脚本或测试,调用真实代码,如果出错则大声失败。
- 你在运行的应用中复现了它。
任何不能达到步骤 4 的安全事实,说明这一点。不要将其写成定论。步骤 4 通常是一个小脚本,导入与应用打包相同的库,并调用你担心的确切函数。
步骤
- 阅读变更。差异,它添加、更改和删除的符号,以及现在不同的行为,包括差异没有明确说明的部分。提取 PR 和提交消息以了解背后的原因。
- 找出安全依赖的那个事实。大多数看起来有风险的变更之所以安全,是因为一个单一事实,比如“此调用仅丢弃已失效的缓存条目,并且不做其他事情”。找到那个事实。如果它成立,那么大多数风险情况就立即清除。把时间花在这里,而不是花在漫无边际的“可能”列表上。
- 查看 grep 停止的地方。阅读你调用的库的源码,并检查其固定版本和任何本地补丁。弄清运行时执行顺序:微任务、卸载和清理、Solid 与 React 对比。追踪符号搜索遗漏的内容:API 返回的 JSON、数据库列、线格式、另一种语言读取相同字节、功能标志、下游三步之后的代码。
- 诚实地对待每个风险。给它一个真实的发生概率和真实的成本(如果发生)。保留你确认的风险。列出你检查并排除的风险,并分开说明。引用真实的
file:line,搜索无结果也是一个答案,永远不要编造调用者或 API。 - 证明那个单一事实。编写一个调用真实代码的脚本或测试,运行它,并粘贴结果。如果不能便宜地证明,标记为未证明。不要过度声明。
- 对于大型或广泛的变更,通过上述审查过程使用多个模型运行。不同的模型捕捉不同的真实错误。
返回什么
- 变更内容:什么发生了变化,包括不明显部分。
- 安全依赖的那个事实:陈述它,说明它达到了哪个步骤,并展示证明。如果无法证明,写“未证明”。
- 风险:仅限真实的风险。每个风险命名它如何破坏、
file:line、可能性和严重程度,以及如何检查。粘贴对关键风险的证明。 - 已排除:你检查过且没有问题的事项。
- 合并之前:捕获真实错误的最便宜的测试或复现,包括你编写的脚本。
通过 unslop 编写,引用真实代码,并在任何公开场合之前去掉私有信息。
回复: 上述撰写,其中安全事实要么是已证明,要么标记为未证明。