关于 review-verification-protocol
用于代码审查的技能,规定证据门槛、严重性等级和报告格式,以减少缺乏依据的问题。它面向代码审查者,要求在给出结论前核对当前来源。
主要功能
- 01要求核对当前来源
- 02逐项执行验证门槛
- 03校准问题严重性
- 04规范审查报告格式
- 05检查常见误报情形
适用场景
- 01验证疑似代码缺陷
- 02校准审查问题的严重性
- 03检查 React 或 TypeScript 审查疑虑
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ existential-birds/ beagle --skill review-verification-protocol安装后在 Claude Code 中输入/review-verification-protocol确认已加载。
详细介绍
审查验证协议
报告任何代码审查发现之前,必须遵循本协议。跳过这些步骤会导致误报,浪费开发者的时间,并损害大家对审查的信任。
防止臆造(第 0 道关卡——适用于所有审查/验证技能)
在给出任何判定之前——无论是确认、驳回、撤销、修复还是裁决——你都必须复述你正在评判的确切内容,并从你在本轮中读取的来源引用:
- 对于代码问题:文件:行号以及引用的代码;现在重新读取,不要依赖本轮对话之前的记忆。
- 对于差异审查:正在审查的实际差异块。
- 对于结构化报告(例如
verify-llm-artifacts裁决findings[]):从已解析的源文件中打印问题的 ID、文件、行号和描述,不得凭记忆复述。
评判依据只有实际内容。切勿根据分支名称、工作目录、周边文件或记忆推断你正在审查什么。如果你的认知与刚刚读取的来源不一致,以来源为准。如果未在本轮中复述评判对象,判定即无效——先复述内容,否则不要给出判定。
这道关卡的存在,是因为受到上下文提示影响的大模型会自信地裁决文件中并不存在的内容。它先于下方针对每个问题的硬性关卡。使用本协议的技能会具体实现此流程:verify-llm-artifacts(加载 + 复述 + ID 锁定关卡)、review-llm-artifacts(写入 JSON 前复述问题)、llm-artifacts-detection(从已打开的缓冲区定位 FILE:LINE)。
硬性关卡(按顺序执行)
每个问题在纳入审查前,都必须完成一次以下流程。如果某道关卡未通过,则省略该问题、将其降级为信息提示(参见严重性校准),或将其改写为疑问——不要提交缺乏依据的指控。
| 步骤 | 执行事项 | 通过条件(客观) |
|---|---|---|
| 1. 定位 | 阅读完整的封闭符号或模块,而不只是差异块。 | 能明确指出正在评判的文件路径和行范围(或符号名称 + 文件)。 |
| 2. 证据 | 针对该问题的类型,执行按问题类型进行验证中的检查。 | 每项必需检查都有实际依据:粘贴的工具输出、文件:行号引用,或仓库搜索后明确写出**“无”或“N 个匹配项”**——不能只声称“检查过”。 |
| 3. 严重性 | 根据严重性校准确定严重性。 | 标签与表格相符;要求编写范围内原本不存在的新代码,仅可标为信息提示。 |
| 4. 格式 | 为报告起草问题描述。 | 符合 [FILE:LINE] ISSUE_TITLE 格式;信息提示不计入可执行问题数量。 |
纯风格或偏好类问题必须未通过第 2 道关卡,或归入不要标记——不得为其标注严重性。
报告前验证清单
标记任何问题之前,请先验证以下事项(这些事项是第 2 道关卡必须提供证据的内容):
- 我已阅读实际代码——不只是差异上下文,还包括完整的函数/类
- 我已搜索代码用法——声称“未使用”之前,已搜索所有引用
- 我已检查周边代码——问题可能已在其他位置处理(保护条件、更早执行的检查)
- 我已根据当前文档验证语法——框架语法会不断演进(Tailwind v4、TS 5.x、React 19)
- 我已区分“错误”和“风格不同”——两种做法都可能有效
- 我已考虑这是有意的设计——已检查注释、项目约定(例如 AGENTS.md 或 CLAUDE.md)和架构背景
按问题类型进行验证
“未使用的变量/函数”
标记之前,你必须:
- 在整个代码库中搜索所有引用(grep/find)
- 检查它是否已导出,以及外部使用方是否会使用它
- 检查它是否通过反射、装饰器或动态分派使用
- 确认它不是传递给框架的回调
常见误报:
- React 中的状态设置函数(即使值看起来未被使用,也可能触发重新渲染)
- 在模板/JSX 中使用的变量
- 被使用方包使用的导出项
“缺少验证/错误处理”
标记之前,你必须:
- 检查更高层级(调用方、中间件、路由处理程序)是否已执行验证
- 检查框架是否提供验证功能(Pydantic、Zod、TypeScript)
- 确认所谓“缺失”的检查是否以其他形式存在
常见误报:
- 框架已执行验证(FastAPI + Pydantic、React Hook Form)
- 父组件在传递 props 前已执行验证
- 更高层级的错误边界会捕获错误
“类型断言/不安全的类型转换”
标记之前,你必须:
- 确认这确实是断言,而不是注解
- 检查该位置之前是否通过运行时检查缩小了类型范围
- 确认框架是否保证了该类型(加载器数据、表单数据)
常见的有效模式可能会被误标:
// Type annotation, NOT assertion
const data: UserData = await loader()
// Type narrowing makes this safe
if (isUser(data)) {
data.name // TypeScript knows this is User
}
“潜在内存泄漏/竞态条件”
标记之前,你必须:
- 确认清理函数确实缺失(而不只是位于其他位置)
- 检查是否在 await 之后检查了 AbortController 信号
- 确认异步操作期间组件确实可能卸载
常见误报:
- 清理逻辑存在于 useEffect 的返回函数中
- 已检查信号(代码审查者漏看了)
- 操作会在组件可能卸载之前完成
“性能问题”
标记之前,你必须:
- 确认代码运行频率足以产生影响(渲染时运行,还是点击处理程序中运行)
- 确认优化能带来可衡量的影响
- 检查框架是否已对此进行优化(React 编译器、记忆化)
不要标记:
- 在点击处理程序中创建的函数(每次点击只运行一次)
- 针对小型数组(< 100 项)使用的数组方法
- 在事件处理程序中创建对象
严重性评估
严重(阻止合并)
仅用于:
- 安全漏洞(注入、绕过身份验证、数据泄露)
- 数据损坏错误
- 在正常流程中导致崩溃的错误
- 对公共 API 的破坏性更改
主要(应该修复)
用于:
- 影响功能的逻辑错误
- 导致用户体验不佳的错误处理缺失
- 产生可衡量影响的性能问题
- 无障碍问题
次要(可考虑修复)
用于:
- 提高代码清晰度
- 文档缺漏
- 风格不一致(合理范围内)
- 非关键测试覆盖缺口
信息性(无需采取行动)
用于:
- 需要添加新依赖项或模块才能实现的改进
- 针对代码库中原本不存在的新代码提出的建议(新模块、测试套件、抽象)
- 供未来考虑的架构构想
- 测试基础设施建议(新的模拟库、行为提取)
- 在当前情境下没有可衡量影响的优化
这些内容不会阻止审查通过。 应提示作者注意,但不得计入可操作问题的数量。评审结论应完全忽略信息性事项。
完全不要标记
- 两种做法都合理时的风格偏好
- 没有可衡量收益的优化
- 未达到生产标准的测试代码(有意保持简单)
- 库/框架内部代码(shadcn 组件、生成的代码)
- 需要不太可能出现的条件才会发生的假设性问题
有效模式(不要标记)
TypeScript
| 模式 | 为什么有效 |
|---|---|
map.get(key) || [] | Map.get() 返回 T | undefined,使用后备值是正确的 |
| 导出类而不单独导出类型 | 类既可作为值,也可作为类型 |
在字面量数组上使用 as const | 创建只读元组类型 |
| 在变量声明中添加类型注解 | 这不是类型断言 |
使用 satisfies 而非 as | 无需断言即可进行类型检查 |
React
| 模式 | 为什么有效 |
|---|---|
| 使用数组索引作为键(静态列表) | 以下条件下有效:项不会重新排序、列表是静态的、不需要项标识 |
| 在 onClick 中使用内联箭头函数 | 对性能要求不高的处理程序有效(每次点击运行一次) |
| 看似未使用的状态 | 可能通过 ref、外部回调设置,或用于触发重新渲染 |
| ref 配合空依赖数组 | ref 是稳定的,无需作为依赖项 |
| 检查后使用非空断言 | TypeScript 的类型收窄可能无法跟踪所有模式 |
测试
| 模式 | 为什么有效 |
|---|---|
toHaveTextContent 不使用正则表达式 | 能正确处理嵌套文本 |
| 在模块级别创建 Mock | 只定义一次,不会重复 |
| 使用基于索引的测试数据 | 测试不需要稳定标识 |
| 简化错误消息 | 测试清晰度优先于生产环境中的精致程度 |
通用
| 模式 | 为什么有效 |
|---|---|
正则表达式中的 +? 懒惰量词 | 可防止过度匹配,适用于许多模式 |
| 直接拼接字符串 | 对于简单情况,比模板字面量更简洁 |
| 函数中使用多个 return | 可以提升可读性 |
| 解释“原因”的注释 | 比没有注释更好 |
上下文相关规则
React 键
仅当以下所有条件都满足时,才将数组索引作为键标记:
- 项可以重新排序(可排序列表、拖放)
- 项可以从中间插入或删除
- 项有可用的稳定标识符(id、uuid)
- 列表不是以原子方式完全替换的
useEffect 依赖项
仅当以下条件都满足时,才标记缺少依赖项:
- 该值在组件生命周期内确实会改变
- 过时闭包会导致行为错误
- 该值不是 ref(ref 是稳定的)
- 该值不是稳定的回调(依赖项为空的 useCallback)
错误处理
仅当以下条件都满足时,才标记缺少 try/catch:
- 更高层没有错误边界捕获此错误
- 框架不会处理错误(loader errorElement)
- 错误会导致崩溃,而不只是操作失败
- 用户需要针对这种错误类型获得特定反馈
提交审查前
最终验证: 0. 每条发现都通过了 反臆测(门槛 0) —— 目标内容是从本轮读取的源代码中复述的,而不是回忆或推断出来的。
- 每条发现都通过了 硬性门槛(顺序)(锚点、带有依据的证据、严重程度、格式)。
- 重新阅读每条发现并自问:“我是否确认这确实是个问题?”
- 对于每条发现,你能否指出证明问题存在的具体代码行?
- 领域专家会认为这是个问题,还是仅仅是风格偏好?
- 修复它能带来实际价值,还是只是无意义的忙碌?
- 将每条发现格式化为:
[FILE:LINE] ISSUE_TITLE - 对于每条发现,请自问:“这是在修复现有代码,还是要求编写此前完全不存在的新代码?”如果是后者,将其降级为信息提示。
- 如果这是重新审查:仅验证先前的修复。不要引入新的发现。
如果对任何发现不确定,请:
- 将其从审查中移除
- 将其标记为问题,而非缺陷
- 通过阅读更多代码上下文进行验证