关于 review-pr
用于审查远程 GitHub PR 的技能,输入 PR URL 后分析代码并提交审查结果。它聚焦语义和跨代码库问题,通过检查修复风险及相似位置来减少后续审查中的重复缺陷。
主要功能
- 01分析远程 GitHub PR
- 02过滤风格类和重复问题
- 03检查修复引入的反向风险
- 04搜索相似代码位置以评估覆盖度
- 05将审查结果发布到 GitHub
- 06支持多 PR 批量审查
适用场景
- 01提交代码变更前检查 PR 的语义问题
- 02确认修复未在相似代码位置遗漏
- 03批量审查多个 PR 并汇总结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bhagyamudgal/ skills --skill review-pr安装后在 Claude Code 中输入/review-pr确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/batch-mode.mdclass-sweep-and-inverse-risk.mdcritic-round2.mdcritic-verify.mdcross-cutting-prompt.mddispatch-prompts.mdfalse-positive-rules.mdfinding-output-format.mdfinding-state-phase4.mdfinding-state-schema.mdgithub-posting-recovery.mdgithub-posting-rerun.mdgithub-posting.mdphase1-timeline-state.mdq5-type-coercion.mdq6-cross-repo.mdq6-reusability-search.mdrepo-map.mdreviewer-prompt.mdschema-design-checks.mdverification-subagents.md详细介绍
/review-pr:深入审查 GitHub PR
使用反噪声过滤审查远程 GitHub PR。只需提供 PR URL。
目标:生成准确、严格且可执行的 PR 审查意见,过滤噪声(风格吹毛求疵、虚构引用、重复内容、泛泛建议),并将结果提交到 GitHub。审查他人创建的 PR 时使用 REQUEST_CHANGES 或 APPROVE;自我审查时使用 COMMENT,因为 GitHub 禁止作者批准自己的 PR。
级联是本审查要防止的问题:针对第 N 轮问题提交的修复,成了第 N+1 轮的新问题。有两个因素会导致级联:建议的修复本身带有缺陷,以及修复只应用于引用的位置,却遗漏了相同的同类位置。因此,每条建议修改代码的问题都要附带一个 Inverse risk: 和一个 Class-sites: 计数,每个诱因各对应一个字段。第 3 阶段会在步骤 7.5 通过 cascade_share 衡量结果,第 8 步的结论会读取该值,判断 PR 是否正在收敛,第 4 阶段会输出该值。
此技能要求仓库中配置了 .coderabbit.yaml,以启用 CodeRabbit。CodeRabbit 会先处理风格和规范问题。/review-pr 只处理它能胜任的深层语义审查和全代码库审查。
对于仍需判断的面向用户的决策,请使用 AskUserQuestion:暂停并询问,以及失败后的恢复。提交不是决策点。调用 /review-pr 即表示授权提交完整审查。大型 PR 一律继续分块审查,无需询问。任何提供 2 个或更多带标签选项的句子都要调用 AskUserQuestion。选项应可通过光标选择、具体且经过斟酌。将最优选项放在首位,并标注“(推荐)”。
参考文件
主流程或子 Agent 仅在进入相应分支时加载每个文件。加载器和触发条件:
references/batch-mode.md:编排规则、“不要停止”语义、汇总报告模板和自动发布顺序。当用户提供 2 个或更多 PR URL,或要求审查所有未关闭的 PR 时,由 main 在 Phase 1 加载。references/reviewer-prompt.md:Subagent 1 的完整提示词、它遵循的反灌水规则,以及关于为何不在其中重述问题格式的说明。每个SIZE_MODE分支的 Phase 2 分派时,由 main 加载。references/cross-cutting-prompt.md:Subagent 3 的完整提示词。SIZE_MODE为parallel-chunked时,由 main 在 Phase 2 分派时加载;未分块模式不会分派 Subagent 3。references/q5-type-coercion.md:Q5 类型强制转换扫描:强制转换方法、如何判断字段是否为数值类型,以及严重性。当 diff 包含 DB 插入/更新或 API 负载构造时,由 Subagent 1 在回答 Q5 时加载。references/class-sweep-and-inverse-risk.md:reviewer-prompt 的步骤 5 和 6:影响范围搜索顺序、class_completeness:和Inverse risk:字段规则,以及逆向风险示例。当任何问题提出代码更改时,由 Subagent 1 加载。references/repo-map.md:repo_map_files/repo_map_exportsshell、本地和跨仓库模式。仓库中仅有这一份;/fix-pr-review也会从这里加载。存在packages/或apps/时,由 main 在 Phase 1 加载。references/q6-reusability-search.md:STEP A 枚举 + STEP B 搜索算法 + Q6 控制流缺口。当 diff 包含 1 个或更多 STEP A 类型的新定义时(不限于顶层定义),由 Subagent 1 加载。跨仓库搜索部分位于references/q6-cross-repo.md,仅当repo_map_exports为跨仓库N/A标记时加载。references/finding-output-format.md:单个问题的字段块、class_completeness:审核格式,以及运行级收尾块。问题格式的唯一副本。在撰写任何问题之前,由 Subagent 1、Subagent 3 和 V3 加载。references/schema-design-checks.md:Q7(重叠)、Q8(一对一整合)、Q9(跨表 FK)检查。INCLUDE_SCHEMA_CHECKS = true时,由 Subagent 1 加载;缺口检查涵盖 Q7-Q9 时,由 V3 加载。references/verification-subagents.md:V1/V2/V3 分派条件 + 分别提供给它们的确切提示词。在 Phase 3 中,步骤 4.55 / 4.9 / 6 中第一个触发的步骤执行时,由 main 加载。references/false-positive-rules.md:四条规则组成的 YAML 表(wrapped-coercion、intent-alignment、library-behavior-citation、default-fallback),每个保留的问题都会经过这些规则检查。当步骤 4.5 后仍有任何问题时,由 main 在 Phase 3 步骤 4.6 加载。references/finding-state-schema.md:两个持久化文件:.claude/review-state/<pr>.yml(架构、问题 ID 策略、状态机、Phase 1 读取路径)和跨运行缓存(架构 + 三个重放分支)。在读取 review-state 和检查缓存之前,由 main 在 Phase 1 加载,并在 Phase 3 中保留。Phase 4 写回和清理位于${CLAUDE_SKILL_DIR}/references/finding-state-phase4.md;发布后在 Phase 4 加载,且在 Phase 1 启动时若状态目录非空,也会加载。references/github-posting.md:全新审查的 REST/GraphQL 发布流程:摘要正文、逐个问题的评论、hunk 验证、Phase A 至 C,以及写回。每次审查完成后,由 main 在 Phase 4 加载。有先前审查或缓存条目的重新运行,也会加载${CLAUDE_SKILL_DIR}/references/github-posting-rerun.md(步骤 0、0b、0c、4-rolling、8d);发布失败时还会加载${CLAUDE_SKILL_DIR}/references/github-posting-recovery.md(步骤 7)。references/phase1-timeline-state.md:先前审查的讨论串查询及整理、review-state 读取及轮次初始化,以及跨运行缓存分支。在 Phase 1 的时间线、状态和缓存步骤中,由 main 加载。references/dispatch-prompts.md:<SKILL_DIR>的推导、<PROMPT_PREAMBLE>和<GROUND_TRUTH>块,以及静默失败排查器的上下文数据包。在 Phase 2 分派时,由 main 加载。references/critic-verify.md:critic 步骤 1 至 4.56,涵盖去重至逆向风险验证。在 Phase 3 步骤 1 由 main 加载,保留至步骤 4.56;步骤 6 会为分流后的问题重新加载。references/critic-round2.md:critic 步骤 4.9、4.95 和 4.96,涵盖回归扫描、抑制和溯源。在 Phase 3 步骤 4.9 由 main 加载,仅从第 2 轮开始加载。 四个闭包,因此计数是确定的。Main 从不加载finding-output-format.md:只有 Subagent 1、Subagent 3 和 V3 会在写入发现项之前加载它。V1 和 V2 不加载任何参考资料:它们根据发现项文本给出简洁的判定。Main 从不加载schema-design-checks.md或q5-type-coercion.md:Subagent 1 会在各自条件满足时加载它们;只有当差距检查涵盖 Q7-Q9 时,V3 才会加载架构检查。反废话规则只存在于reviewer-prompt.md中:任何调度都不会将第二份副本粘贴到其他提示词中。
规划文档依据(可选的审查前上下文)
如果 docs/superpowers/specs/ 或 ~/.claude/plans/*.md 中有文档提及此 PR,请根据其中记录的设计决策检查差异,并将未记录的偏离标记在 Q1 Intent 下。如果不存在此类文件,则跳过此检查。
用法
/review-pr https://github.com/owner/repo/pull/123
如果未提供 URL,请向用户索要。如果只提供 gh 命令,则根据当前分支推断 PR。此技能会审查提供给它的 URL。
批处理模式(多个 PR)
当用户提供 2 个或更多 PR URL,或要求审查 所有未关闭的 PR 时触发。单个 PR 的运行会完全跳过此模式,直接进入阶段 1。在此分支中,必须先加载 ${CLAUDE_SKILL_DIR}/references/batch-mode.md,然后才能执行任何操作:其中包含 PR 枚举、编排规则(每个 PR 使用一个子 Agent,Main 从不内联审查,子 Agent 从不发帖或提问)、仅审查检查点的“不要停止”语义、汇总报告模板以及自动发帖顺序。
阶段 1:收集上下文(main)
在同一条助手消息中,将这些命令作为 两个独立的 Bash 工具调用运行。真正的并行需要使用独立的 tool_use 块,而不是用 && 串联。
gh pr view <url> --json number,title,body,author,baseRefName,headRefName,headRefOid,baseRefOid,additions,deletions,changedFiles,files,closingIssuesReferences,reviews,comments,state,isDraft
gh pr diff <url>
记录 CURRENT_HEAD(来自 headRefOid)、PINNED_BASE_OID(来自 baseRefOid)和 BASE_REF_NAME(来自 baseRefName)。如果推送恰好在两次调用之间落地,就会混合不同修订版本,因此差异结果到达后,要重新读取两个 OID,并要求它们与记录的那组值一致。如果任一项不匹配,则丢弃两个结果,并重新开始阶段 1。若第二次仍不匹配,则继续审查,并注明 PR 在审查过程中发生了变动。
在同一条助手消息中,将下面的独立读取作为并行 Bash 工具调用发出:查看者登录名、关联问题正文、审查线程、当前工作目录中的仓库、CodeRabbit 配置和抑制规则。它们只依赖 PR URL 和 owner/repo,因此按顺序执行只会浪费时间。
阶段 1 会获取 完整差异。将其暂存到 main 上下文中。错误处理内容扫描和阶段 3 的审查者参考检查都需要它。
空差异快速结束
如果 changedFiles == 0 或 additions + deletions == 0:
无需审查。 此 PR 不包含可供审查的文件变更。
立即停止。
私有仓库/访问错误处理
如果 gh pr view 返回 GraphQL 解析错误或 HTTP 404:
无法访问 PR。 请检查仓库访问权限。尝试运行
gh auth refresh -s repo,然后重试。
立即失败退出。
检测是否为作者本人发起审查
元数据请求成功后,将已认证的查看者与该响应中记录的 PR 作者进行比较:
VIEWER=$(gh api user -q .login)
AUTHOR=<.author.login from the Phase 1 metadata>
GitHub 文档说明,拉取请求作者不能批准自己的拉取请求。如果账户匹配,则设置 IS_SELF_REVIEW=true 并继续完成完整审查。阶段 3 仍会将语义判定设为 approve 或 request-changes;阶段 4 则使用 COMMENT 提交审查,保留其摘要和逐条发现的讨论串,同时不声称获得了 GitHub 无法记录的批准。否则,设置 IS_SELF_REVIEW=false。
提取关联的问题
- 优先使用
closingIssuesReferences(每项都带有自己的repository.nameWithOwner;使用该值,而不是 PR 所属仓库)。 - 回退到正文正则:
(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)(仅限同一仓库)。 - 对每个关联的问题执行:
gh issue view <num> --repo <owner>/<repo> --json title,body,state。 - 如果关联的问题 ≥ 2 个,注明
multiple linked issues, so intent may be ambiguous。如果它们的目标明显矛盾,则转入停止并询问的回退流程。
构建意图模型
Goal: <one sentence from issue + PR description>
Expected touches: <what files/areas should be changed>
Out of scope: <anything the issue explicitly excludes, or "none">
Size: <additions>/<deletions> lines across <N> files
Draft: <yes|no>
构建先前审查时间线
拉取所有审查线程,并根据 ${CLAUDE_SKILL_DIR}/references/phase1-timeline-state.md 读取已保存的状态。现在加载该文件。它包含线程查询、先前发现的问题结构、状态文件读取与轮次初始化,以及缓存分支。其构建结果将用于 Phase 3 去重和第 2 轮回归检查。
加载 review-state(多轮去重)
上述已加载的参考文件已涵盖此内容。
停止并询问的回退流程
满足以下条件时触发:没有关联的问题,且 PR 描述缺少以下所有内容:
- 文件路径或目录引用
- 函数 / 类 / 符号名称
- 错误消息或堆栈跟踪
- 复现命令
- 正文中的关联问题 URL(即使不在
closingIssuesReferences中)
像“update X”“fix bug”或“wip”这样信息不足的描述不合格。像“修复 auth/cache.ts 驱逐逻辑中的竞争条件;使用 make stress-test-auth 可复现”这样简短但有依据的描述则合格。
触发时,执行 AskUserQuestion:
header: "Intent"
text: "Intent is unclear. No linked issue and the description lacks grounding signals. How should I proceed?"
options:
- "Proceed anyway": Review with just the diff; findings will be generic without grounding
- "Skip this PR": Abort the review
- "I'll provide intent": Wait for user to type intent text
对于“I'll provide intent”,等待后续文本,然后根据该文本构建意图模型。
大小警告
如果 additions + deletions > 2000:
此 PR 涉及 X 行代码,分布在 Y 个文件中。审查可能会有较多干扰且耗时较长。继续执行。
墙钟时间记录(开始)
在 Phase 1 开始处捕获 PHASE_START_TIME=$(date +%s),并在每个后续阶段以类似方式记录。在 Phase 4 输出总耗时。
检测 cwd 与 PR 仓库不匹配(跨仓库模式)
CWD_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "")
PR_REPO="<owner>/<repo>"
[ -z "$CWD_REPO" ] || [ "$CWD_REPO" != "$PR_REPO" ] && CROSS_REPO_MODE=true || CROSS_REPO_MODE=false
跨仓库模式的变更:
- 仓库映射计算回退为通过远程
gh api获取树。 - Phase 3 的已修复检查使用
gh api,而非本地git log。
在 Phase 4 输出标题中注明此模式。
CodeRabbit 配置检查(一次性提示)
每个会话中,对每个 (owner, repo) 检查一次 PR 仓库中是否存在 .coderabbit.yaml:
gh api "repos/<owner>/<repo>/contents/.coderabbit.yaml" >/dev/null 2>&1 \
&& CR_CONFIG_PRESENT=true \
|| CR_CONFIG_PRESENT=false
如果 CR_CONFIG_PRESENT=false,且这是当前会话中针对该仓库首次运行 /review-pr,则在 Phase 4 输出后提示一次:
<owner>/<repo>中没有.coderabbit.yaml。添加该文件可将风格与约定检查交由 CodeRabbit 处理。将模板从https://raw.githubusercontent.com/bhagyamudgal/skills/main/coderabbit-config/coderabbit.yaml.template复制到<repo>/.coderabbit.yaml(该仓库的coderabbit-config/README.md中包含初始化步骤)。今后在此仓库运行/review-pr时,审查会更严格。
此提示仅供参考,不会阻止发布。
基于大小的路由(确定 SIZE_MODE)
SIZE = additions + deletions
if SIZE <= 500: SIZE_MODE = "parallel-standard" # Subagent 1 reviewer + conditional silent-failure hunter
else: SIZE_MODE = "parallel-chunked" # Per-chunk reviewers + hunter + cross-cutting reviewer, always proceed without asking
Subagent 1 始终会被调度;微型 PR 也需要经过一轮 subagent 往返。
跨运行缓存检查
根据上文已加载的 ${CLAUDE_SKILL_DIR}/references/phase1-timeline-state.md 检查跨运行缓存。
如果 PRIOR_STATE.convergence 存在,则在 Phase 2 之前,使用当前请求、base/head、diff 哈希、路径以及计划中的 roster/lenses 调用 converge-reviews。复用匹配的结果,不再调度。如果返回 closure_check: available,则仅针对指定的 blocker ID 和变更位置,调度一次定向检查。保持记录的轮次不变,并拒绝该检查提出的任何新发现或扩大的覆盖范围。将该检查的证据和更新后的 blocker 处置结果传回 converge-reviews,保存新结果以及 closure_check: passed | failed,然后应用该结果:检查通过时可返回 converged;检查失败时仍保持当前轮次的 blocked-at-cap。如果初始结果为 continue,则仅审查其中指出的已失效覆盖范围;其他结果直接应用,不再开启新一轮。
计算共享包仓库映射(针对 Q6)
如果 CROSS_REPO_MODE=true,加载 ${CLAUDE_SKILL_DIR}/references/repo-map.md,并无条件运行跨仓库代码块:以目标仓库的布局为准,而不是本地 cwd。否则,如果存在 packages/ 或 apps/,加载 ${CLAUDE_SKILL_DIR}/references/repo-map.md,并运行当前模式对应的代码块:其中包含两个 shell 代码块(跨仓库的 gh api 树结构获取,以及本地的 bash -c find/grep 对,每个最多截取 500 行),并将 repo_map_files + repo_map_exports 写入暂存的 repo-map.md,供子 Agent 提示词使用。这是那份 shell 脚本的唯一副本,与 /fix-pr-review 共用。
如果本地模式下两个目录都不存在,则跳过 shell。将两者都设为 N/A (not a monorepo),并标记 IS_MONOREPO=false。子 Agent 1 将 grep 范围改为已更改文件所在目录;若这些目录无法提供线索,则改为仓库根目录。切勿假设存在 src/。
检查是否涉及错误处理(为 Phase 2 设置标记)
在 diff 内容的新增或修改行中 grep 错误处理模式:
try \{ | catch \( | catch \{ | throw new | throw \s | \.catch\( | Result< | rescue | err := | raise
如果出现任何模式,或用户提到错误处理,则设置 INCLUDE_SILENT_FAILURE_HUNTER = true。
检查是否新增数据库表(为 Phase 2 设置标记)
在 diff 内容的新增行中 grep:
pgTable\( | createTable\( | CREATE TABLE | knex\.schema\.createTable | Schema\.create\(
如果出现任何模式,则设置 INCLUDE_SCHEMA_CHECKS = true。同时提取 SCHEMA_DIR。常见值有 db/schema/、drizzle/schema/、src/schema/ 或 migrations/。如果无法识别,则设置 SCHEMA_DIR = ".",并将 Q7-Q9 的 grep 限定在与表定义模式匹配的文件中,例如 Grep("pgTable", ".", glob: "**/*.ts")。
在跨仓库模式下,使用 gh api git/trees/<head-sha>?recursive=1 列出文件。读取 Q7-Q9 时,使用 gh api repos/<owner>/<repo>/contents/<path>?ref=<head-sha>。
加载项目级评审抑制规则
在基础修订版本读取,切勿从工作树读取:已检出的 PR 不得抑制对自身的评审。
SUPPRESSIONS_FILE=".claude/review-suppressions.yml"
SUPPRESSIONS=$(git show "$PINNED_BASE_OID:$SUPPRESSIONS_FILE" 2>/dev/null || { git fetch --no-tags origin "$BASE_REF_NAME" 2>/dev/null; git show "$PINNED_BASE_OID:$SUPPRESSIONS_FILE" 2>/dev/null; } || true)
如果基础版本中没有此类文件,则设置 SUPPRESSIONS = "",并记录已忽略 PR 新增的抑制规则文件。PR 可以提议在合并后用于未来评审的抑制规则,但绝不能用于自身评审。
格式:
suppressions:
- pattern: "factory pattern"
category: Architecture
reason: "YAGNI - single provider by design"
added: 2026-04-13
- pattern: "missing timeout"
file: "claude-code.ts"
reason: "Timeout handled at caller level"
pattern 为必填项。它会针对发现项的 Issue 文本进行不区分大小写的匹配。category 和 file 为可选项,用于限定抑制规则的范围。reason 为必填项,并会显示在 Filtered Out 中以便审计。
如果文件存在,则将其传入子 Agent 1 的提示词,内容为“评审抑制规则:本项目已接受的模式;跳过这些模式”。Phase 3 的第 5.5 步也会作为安全措施应用这些规则。
在跨仓库模式下,通过 gh api repos/<owner>/<repo>/contents/.claude/review-suppressions.yml?ref=$PINNED_BASE_OID 获取。遇到 404 时跳过。固定的基础 OID 可信;PR head 不可信,因此 PR 永远不能抑制对自身的评审。
暂存交接文件
子 Agent 绝不获取 diff,也不会收到粘贴的上下文。在 Phase 1 结束时,将以下文件写入 $STATE_FILE 旁边的每个 PR 专属子目录中,目录名取状态文件名去掉 .yml 的部分(批处理模式下,并发流程共用此目录):diff.full.patch(完整 diff,供 hunter、跨领域评审器和 V3 使用)、diff.chunk-N.patch(按文件拆分的分块 diff,仅用于分块模式)、repo-map.md(上述步骤生成的仓库映射)、timeline.md(意图模型、先前时间线及已关闭的发现项)。任何提示词都不会指示子 Agent 运行 gh pr diff。提示词只包含文件路径及少量内嵌意图信息。
Phase 2:评审子 Agent
根据 SIZE_MODE,通过一条包含多个 Agent 工具调用的消息启动。评审子 Agent 在此处一次性启动,Phase 3 验证器也会在对应阶段一次性启动。这就是整个评审流程。如果 PR 需要再次审查,请重新启动一次 /review-pr。切勿在本次运行中重新派发。
分派策略
SIZE_MODE == "parallel-standard"(500 行或更少,默认):
- 并行分派子 Agent 1(Claude 审查员)和有条件分派的子 Agent 2(静默失败猎手)。子 Agent 1 读取
diff.full.patch;两者都读取repo-map.md和timeline.md。
SIZE_MODE == "parallel-chunked"(超过 500 行):
- 每个分块分派一个子 Agent 1,并提供简短的内联意图说明,以及其分块文件、
repo-map.md和timeline.md。提示词:“你的审查范围是上面列出的文件。只读取 。不要报告其他文件中的问题。” - 在完整 PR 范围内分派一名静默失败猎手和一名跨领域审查员,两者都读取
diff.full.patch。分块审查员只报告各自分块内的问题,因此子 Agent 3 是唯一能发现跨两个分块的问题的审查员。没有它,这类问题会直接引发连锁反应。 - 始终继续进行分块并行审查。无论规模大小,都不要请求确认。
降级模式规则
如果任何子 Agent 出错或返回空结果,请使用其余子 Agent 继续,并在第 4 阶段的输出标题中注明 <reviewer> unavailable。只有全部失败时才中止。
关于 CodeRabbit 的说明。 如果仓库中有 .coderabbit.yaml,CodeRabbit 的审查结果会在第 1 阶段通过 PR 现有评论从先前审查时间线中获取。请参阅上方的一次性提示。不会分派 CodeRabbit 子 Agent。如果 PR 的最新提交尚无 CodeRabbit 评论,则由子 Agent 1 负责审查,下一轮再纳入 CodeRabbit 的输入。
子 Agent 1:Claude 审查员(general-purpose)
根据 ${CLAUDE_SKILL_DIR}/references/dispatch-prompts.md,替换 <SKILL_DIR>、共享前言和真实依据块,然后在分派时加载 ${CLAUDE_SKILL_DIR}/references/reviewer-prompt.md。每次分派都要列出第 1 阶段末尾的暂存文件路径。
子 Agent 2(有条件):静默失败猎手
仅在 INCLUDE_SILENT_FAILURE_HUNTER = true 时分派。
subagent_type:pr-review-toolkit:silent-failure-hunter
上下文包是提示词的一部分,而不是提示词之外的说明。请逐字分派 ${CLAUDE_SKILL_DIR}/references/dispatch-prompts.md 中的 ### Subagent 2 (conditional) 数据包,并替换 <GROUND_TRUTH>。如果只提供 URL,该子 Agent 就不知道 PR 的目标是什么,也不知道之前哪些轮次已经解决了哪些问题,因此会重复发现已解决的问题,也会漏掉其余问题。
子 Agent 3(有条件):跨领域审查员
当 SIZE_MODE 为 parallel-chunked 时分派,否则跳过。
在非分块模式下,子 Agent 1 已能看到所有文件。
subagent_type:general-purpose- 范围:整个 PR。它是唯一获准报告跨文件问题的审查员。
提示词位于 ${CLAUDE_SKILL_DIR}/references/cross-cutting-prompt.md。请在
分派时加载。
阶段 3:批评者审查(主上下文)
批评者审查始终会运行。它能捕获审查者提示词遗漏的问题。任何分支都不得输出、发布或持久化跳过此审查的发现。
所有子 Agent 返回后,主 Claude 会运行批评者审查,并将工作划分为两类:
- 判断留在主上下文中。 去重、三项测试、误报规则、抑制、排序、结论。这些工作需要意图模型和先前的审查时间线,而主上下文已经掌握这些信息。交给子 Agent 就意味着必须重新发送全部内容。
- 证据收集交给子 Agent。 任何需要在代码库中搜索、枚举调用方或在 HEAD 上重新读取文件的工作。这些工作会消耗与代码库规模成正比的上下文,却只返回几行结论。主上下文应掌握结论,而不是搜索过程。
步骤 4.55、4.9 和 6 会按照 ${CLAUDE_SKILL_DIR}/references/verification-subagents.md 调度子 Agent。到达其中第一个满足条件的步骤时加载该文件,并在其余步骤中继续使用。三个步骤在一条消息中调度。如果没有任何步骤满足条件,就不需要该文件。
其他所有工作都在主上下文中执行。验证子 Agent 会以精简的结构化结论报告证据;主上下文负责判定严重程度、是否删除以及状态文件的内容。
按顺序执行:
步骤 1 至 4.56 按照 ${CLAUDE_SKILL_DIR}/references/critic-verify.md 执行。在步骤 1 加载该文件,并持续使用至步骤 4.56;然后在步骤 6 重新加载,以处理经由 4.55 和 4.56 返回的发现。步骤 4.9、4.95 和 4.96 按照 ${CLAUDE_SKILL_DIR}/references/critic-round2.md 执行,仅从第 2 轮开始加载。
1. 去重
按照参考文档合并描述同一问题的发现,包括不同审查者之间以及同一份输出中的发现。文件、行号和符号相同,就视为重复,无论类别如何。
1.5. 快速行数合理性检查
按照参考文档,先删除引用了不可能存在的行的发现,再投入精力判定结论。
2. 验证 file:line
按照参考文档,根据暂存的差异检查每个引用。只检查变更后的内容。
3. 删除已知问题
按照参考文档,删除阶段 1 已经报告的所有问题,除非其包含 Category: Prior-finding-correction。如果作者已经在讨论串中回复了某项发现,即使新提交没有修改对应代码,该发现也应继续删除。
4. 使用三项测试质疑发现
仅当一项发现同时满足以下三点时才删除:仅属表面问题、不影响行为、无需重构。任意一点不满足,就保留该发现。将删除项记录为 noise / 3-prong test。
4.5. 可复用性审计验证
按照参考文档,统计新定义,解析 reusability_searches: 审计(缺失、哨兵值或条目),并记录所有删除项。
4.55. 类完整性验证
按照参考文档,通过 V1 检查每项代码变更相关发现的同类位置。所有进入此步骤的发现都必须在离开时扩大范围,并带有非空的 Class-sites。
4.56. 反向风险验证
为每个 Suggested fix: 推导或审核 Inverse risk:。/fix-pr-review 会逐字执行这些内容,因此未经审核的补救方案会变成生产代码。
4.6. 应用误报规则表
使用统一迭代器遍历规则表。每条规则包含:id、trigger(与 Issue 或 Why 匹配的正则表达式)、evidence_check(返回 evidence_present | evidence_absent | inapplicable 的可调用项)、action(drop / downgrade-1 / downgrade-1-and-note)。
按顺序应用每条规则。每条触发的规则都要记录到「已过滤」中,并注明规则 id 和原因。
规则本身以及包含所有 trigger 正则表达式和 evidence_check 正文的四规则 YAML 表,位于 references/false-positive-rules.md。只要至少有一项发现通过步骤 4.5,就在此处加载该文件;如果发现列表为空,则跳过。该表是误报过滤的唯一事实来源:添加新的误报类别时,只需在那里新增一行 YAML,无需在此处添加新的说明章节。
4.9. 主动回归扫描(在抑制先前状态之前运行,4.95)
当 CURRENT_ROUND == 1 时,完全跳过。从第 2 轮开始,按照 ${CLAUDE_SKILL_DIR}/references/critic-round2.md 扫描每条先前状态记录。在此处加载该文件。缺少判定时,应在此处重新检查,绝不能视为仍已关闭。
4.95. 应用先前状态抑制(多轮去重)
从第 2 轮开始,按照第 4.9 步加载的参考文件,抑制已处理的发现。每条发现最终必须且只能处于 active、resolved、dismissed、wontfix、regression 之一。
4.96. 为本轮发现标注来源关系
当 CURRENT_ROUND == 1 时,完全跳过。没有可归因的早期修复,且每条发现的 caused_by: null。从第 2 轮开始,按照第 4.9 步加载的参考文件为新发现标注来源关系,仅追溯一跳,边界与第 4.9 步相同。第 7.5 步只统计可解析的链接;按照 references/finding-state-schema.md(caused_by 基数)的规定,排除悬空 id。
5. 基于置信度进行剔除
剔除所有严重程度为 Moderate 或 Minor 且 Confidence: low 的发现。记录为 low-confidence filler。保留置信度较低的 Critical/Serious 发现。人们希望看到有风险但不确定的标记。
5.5. 应用项目级抑制规则
如果在阶段 1 加载了 SUPPRESSIONS,则对每条剩余发现进行匹配:
- 检查
Issue文本是否包含pattern(不区分大小写的子字符串)。 - 如果设置了
category,还需检查发现的Category是否完全匹配。 - 如果设置了
file,还需检查发现的File路径是否包含该字符串。
如果所有指定条件都匹配:剔除,并记录 suppressed by .claude/review-suppressions.yml: "<reason>" (pattern: "<pattern>")。
Critical/Serious 覆盖规则:无论严重程度如何,抑制规则都可以剔除发现。团队明确判定某种模式可接受时,其决定优先于审查,而 reason 可确保剔除操作可审计。
6. 缺口检查(Q1-Q6;如果是架构 PR,则检查 Q7-Q9)
对于子代理 1 未提及的任何问题类别,简要考虑差异中是否存在该类别的问题。如发现遗漏,则添加相应发现。仅当 INCLUDE_SCHEMA_CHECKS = true 时,才包含 Q7-Q9。
大型 PR 路由。 如果 additions + deletions >= 500 且 main 没有完整差异,
则将此检查路由到 V3: Deep gap check,并将其发现汇总到此处。V3 有足够的
上下文预算,能够直接根据差异作答,而 main 只能根据文件列表猜测。向 V3 传递
INCLUDE_SCHEMA_CHECKS 和 SCHEMA_DIR。正是在架构变更所在的大型 PR 中调度
V3,因此省略该标志会导致 Q7-Q9 恰好在最可能触发的场景中被跳过。
对此步骤新增的所有内容重新运行级联门控。 针对此路由,重新加载 ${CLAUDE_SKILL_DIR}/references/critic-verify.md。此处创建的发现——无论来自 main 还是 V3——都是在第 4.55、4.56 和 4.96 步已运行之后才产生的,因此其 Class-sites 为空,Inverse risk 为空,并且没有 caused_by,除非将其重新路由。将此步骤新增的每条发现重新通过以下步骤:
- 3:剔除已知问题,包括已有回复的讨论串。
- 4.55:执行类完整性扫描,使
Class-sites: <A>/<N>不为空。若 V1 已返回,则由 main 在此处直接执行扫描,而不是再次调度 V1;仍须遵守最多 4 个子代理的限制。 - 4.56:推导逆向风险,使每条
Suggested fix:都包含Inverse risk:。 - 4.96:标注来源关系,使
caused_by有值或明确设为 null。
无论在哪一步提出,只要发现建议修改代码,Inverse risk 和 Class-sites 就是必填项;缺口检查发现若跳过这些字段,就会将 null 直接写入状态文件,并使下一轮的回归扫描失效。
7. 按严重程度排序
Critical > Serious > Moderate > Minor。
7.5. 计算 cascade_share
这是计算该比率的唯一位置。此时排名已完成,发现项集合已确定,且每项发现都带有来自步骤 4.9 或 4.96 的 caused_by,因此这是该数值首次既可计算又稳定的时刻。
当 CURRENT_ROUND == 1 时,没有可归因的上一轮:将 cascade_share = 0,跳过趋势句,然后继续。
从第 2 轮开始:
cascade_share: <count of active findings with a resolvable caused_by> / <count of active findings>
只有当目标发现项仍然存在时,caused_by 才会计入。根据 references/finding-state-schema.md(caused_by 基数规则),悬空 ID 不计入;该文档规定了此规则。
没有有效发现项时,cascade_share = 0,不得除以零。
第 8 步会读取此值作为判定前缀,Phase 4 的 Cascade 检查会打印该值。两者都不会重新计算:一个数值,一个定义,每轮一次。
8. 确定判定结果
- 存在一个或多个未被消除的发现项 →
request-changes - 不存在未被消除的发现项,且没有未解决的阻塞项 →
approve - 不存在未被消除的发现项,但存在一个或多个未解决的阻塞项(Phase 1 中的
OPEN_BLOCKERS)→ 在被未解决讨论串阻塞的情况下执行request-changes。去重操作正确地丢弃了重复报告的发现项,因此不会新增讨论串。评审会随事件一起发布仅含正文的内容,正文会列出每个阻塞项的path:line(对于没有行号的文件级讨论串,仅列出path)、作者和一句话问题描述。自我评审会以COMMENT发布相同正文,同时在正文和终端输出中保留语义上的request-changes判定结果。讨论串覆盖率会显示0/0,并指出原因是阻塞讨论串列表。
在任何轮次中,如果 cascade_share > 0.5,则在判定理由前加上:
本轮超过一半的发现项由上一轮的修复引入。 逐处打补丁无法实现收敛。此模块需要进行设计审查。
9. 确定高级工程师审批结果
二元评估:
- 否:一项或多项发现项在评审者检查后仍然存在,或存在一个或多个未解决的阻塞项,或 Q1 发现了意图缺口
- 是:其他情况
写一句审批理由,并以最重要的发现项或没有发现项为依据。组合文本中不得使用 em dash 或 en dash。引用自问题或差异的文本保持原样。
Phase 4:输出
Phase 4 的所有路径都会在主流程提交 GitHub 评审并写回本地状态后,到达收敛交接。
始终将此区块打印到终端
# PR Review: <title> (#<number>)
**Senior engineer approval**: <emoji> <Yes | No>, <one-sentence reason>
**Verdict**: <emoji> <approve | request-changes>
**GitHub event**: <APPROVE | REQUEST_CHANGES | COMMENT; use COMMENT when IS_SELF_REVIEW=true>
**Goal**: <intent goal>
**Size**: <additions>/<deletions> across <N> files
**Reviewers**: <list, with "(unavailable)" marker for any failed subagent>
**Round**: <CURRENT_ROUND> (<active>/<resolved>/<dismissed> findings carried across rounds)
**Convergence**: <N> new · <C> caused by earlier fixes · <R> regressions reopened · <F> carried
**Thread coverage**: <threaded>/<surviving> findings as review threads<; reason when below full>
<trend line, omit at round 1>
**Review URL**: <https://github.com/<owner>/<repo>/pull/<number>#pullrequestreview-<REVIEW_DB_ID> | <same URL> (pending draft) | not posted (<reason>)>
## Summary
<2-3 sentence summary>
## Findings (<count>)
### Critical
<entries>
### Serious
<entries>
### Moderate
<entries>
### Minor
<entries>
## Filtered out (<count>)
<dropped findings with reasons, for auditability>
## Multi-round status
<for each finding in PRIOR_STATE: id, file, status, round_resolved/dismissed, dismissal_reason. Useful for "did I really ship M3 in round 5?" scanning.>
判定结果和审批结果的表情映射
高级工程师审批:是 → ✅ · 否 → ❌ 判定结果:approve → ✅ · request-changes → ❌ 严重性标题:Critical → 🔴 · Serious → 🟠 · Moderate → 🟡 · Minor → 🔵
终端输出必须包含 Filtered out。它用于显示评审者过滤过度的情况。当 PRIOR_STATE.findings 非空时,包含多轮状态。
评审 URL
始终将 Review URL 行打印在标题区块的最后,并在发布或恢复流程结束后再打印,以便用户一键打开已提交的评审。使用协调后的评审数据库 ID 构建该 URL:
REVIEW_URL="https://github.com/<owner>/<repo>/pull/<number>#pullrequestreview-<REVIEW_DB_ID>"
使用 Phase C 中新评审的 REVIEW_DB_ID、滚动路径上复用评审的 PRIOR_REVIEW_DB_ID,或整体恢复写回后协调得到的 ID。当用户保留待处理草稿(“Show payload & keep draft”)时,打印待处理评审的 URL,并附加 (pending draft) 后缀。当没有发布任何内容(中止、阻塞、保留本地状态)时,用 not posted (<reason>) 替代 URL。运行若在发布前阻塞或中止,仍须打印区块并注明原因。
线程覆盖率
在存续问题的线程发布/恢复结果确定后,统计这些问题的线程覆盖率:该行报告的是发布结果,而非计划发布的内容。行级和文件级线程均计入;正文回退的问题计为存续问题,而非线程问题。线程数 < 存续问题数时,必须注明原因:正文回退、恢复回退、阶段被阻止或中止,或完全没有发布线程(批处理子 Agent;由编排器发布)。如果运行在发布前被阻止或中止,仍须打印该阻止状态及原因。存续问题数为零时,打印 0/0。
级联检查
从第 2 轮开始必须执行。打印第 7.5 步的值。不要在此重新计算:第 8 步已读取同一个数值作为判定前缀;用不同的问题集再次计算,正是两者产生分歧的原因。
根据数值所示,恰好输出一个趋势句:
cascade_share > 0.5→未收敛,因为修复正在产生新的问题。- 新问题数逐轮下降且
cascade_share == 0→正在收敛,待处理问题逐步减少。 - 连续 3 轮或更多轮的新问题数持平 →
每轮问题数量都相同,陷入停滞;范围可能正在扩大。
Convergence: 4 new · 3 caused by earlier fixes · 1 regression reopened · 2 carried
Trend: cascade_share 0.75. Not converging, because the fixes are generating the findings.
如果判定推翻了先前的 approve 评估,须在摘要中明确说明,并给出两个 SHA 及原因。对于其他作者的 PR,写 "我在 dd142e0 批准了此 PR。现在我撤销该决定,因为 e4f7432 让一件事变得更糟。"。对于自我审查,写 "我在 dd142e0 将其评估为 approve。现在我撤销该决定,因为 e4f7432 让一件事变得更糟。 "
墙钟时间统计(末尾)
根据 PHASE_START_* 时间戳计算总耗时和各阶段耗时。在 Filtered Out 之前追加:
## Timing
Phase 1: <s> (metadata + diff + intent + repo map + state load)
Phase 2: <s> wall / <sum> CPU (parallel: <N> subagents)
Phase 3: <s> (dedupe + verify + 3-prong + reusability audit + FP rules + prior-state + suppressions + gap + verdict)
Phase 4: <s>
Total: <s>
发布到 GitHub
显式调用 /review-pr <PR URL> 即表示获得新的授权,可向该确切 PR 提交完整审查。只有当目标 PR、head SHA、语义判定、GitHub 事件和冻结的载荷均与后续变更卡匹配时,该授权才有效。照常应用 preflight-mutations,遇到任何非 ready 判定都必须阻止;不得绕过检查,也不得要求用户选择问题、确认发布、将审查保留在本地、编辑正文或选择下一步操作。
- 当
IS_SELF_REVIEW=false时,将每个存续问题分别作为审查评论提交,并使用REQUEST_CHANGES;没有未解决阻碍项的干净审查使用APPROVE,且不附审查评论;有未解决阻碍项的干净审查走“被未解决线程阻止”路径(第 3 阶段第 8 步)。 - 当
IS_SELF_REVIEW=true时,使用COMMENT提交同一组完整问题,或提交干净审查摘要。正文和终端输出中均须保留语义判定。 - 将
Filtered out中的每一项都保留为仅供终端查看的审计输出。已过滤项不得进入 GitHub 载荷。 - 每个存续问题都必须以审查线程形式发布;否则,“线程覆盖率”行必须明确说明该问题未发布及其原因。不得将终端报告粘贴为问题评论。
现在加载 ${CLAUDE_SKILL_DIR}/references/github-posting.md:摘要正文、逐条问题评论、代码块验证、阶段 A 至 C,以及回写。如果此 PR 存在先前的 /review-pr 审查或缓存条目,也加载 ${CLAUDE_SKILL_DIR}/references/github-posting-rerun.md;如果任一发布阶段失败,则加载 ${CLAUDE_SKILL_DIR}/references/github-posting-recovery.md。
向参考文件传入:<owner>、<repo>、<pr-num>、<head_sha>、CURRENT_ROUND、IS_SELF_REVIEW、摘要正文内容、完整的存续问题列表(行级 + 文件级)、PRIOR_STATE(重跑文件中的第 0c 步会与其比较)、$CACHE_FILE 路径、$STATE_FILE 路径,以及作为发布授权来源的 /review-pr 调用。
收敛交接
权威发布并写回后,使用 PR 请求、基础/当前 head 和差异哈希、已审查路径、审查者名单及审查视角、当前发现及处置结果,以及 $STATE_FILE 调用 converge-reviews。将生成的 convergence 块存入该现有状态文件,不得替换 review-pr 的发现状态。在建议再进行一轮审查或宣布审查已收敛之前,先应用其结果约定。
错误处理
- 未安装
gh/ 未完成身份验证 → 立即失败:Run 'gh auth login' and retry. - PR URL 无效 →
Couldn't parse PR URL. Expected: https://github.com/owner/repo/pull/NUMBER. - 无法访问 PR(404 / GraphQL 错误) →
Couldn't access PR. Check repo access; try 'gh auth refresh -s repo'. - PR 已关闭/已合并 → 发出警告,但继续(事后审查)。
- PR 是草稿 → 在输出标头中注明,并继续。
- PR 没有更改 → 提前结束(阶段 1)。
- 阶段 2 子 Agent 失败 → 继续处理其余任务;仅在全部失败时中止。
gh出现网络错误 → 明确报告,不要静默回退。- 审查事件权限被拒绝 → 报告 GitHub 错误并停止。仅当阶段 1 确认
IS_SELF_REVIEW=true时才使用COMMENT;权限失败后绝不要将其他作者的审查降级。 - 状态文件写入失败 → 记录警告,不要阻止发布。状态文件持久化尽力而为。