mcpField
R
review-pr

review-pr

github.com/bhagyamudgal测试与质量2136 次安装4 天前更新
代码仓库

关于 review-pr

用于审查远程 GitHub PR 的技能,输入 PR URL 后分析代码并提交审查结果。它聚焦语义和跨代码库问题,通过检查修复风险及相似位置来减少后续审查中的重复缺陷。

主要功能

  1. 01分析远程 GitHub PR
  2. 02过滤风格类和重复问题
  3. 03检查修复引入的反向风险
  4. 04搜索相似代码位置以评估覆盖度
  5. 05将审查结果发布到 GitHub
  6. 06支持多 PR 批量审查

适用场景

  1. 01提交代码变更前检查 PR 的语义问题
  2. 02确认修复未在相似代码位置遗漏
  3. 03批量审查多个 PR 并汇总结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bhagyamudgal/skills --skill review-pr

安装后在 Claude Code 中输入/review-pr确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
batch-mode.md
class-sweep-and-inverse-risk.md
critic-round2.md
critic-verify.md
cross-cutting-prompt.md
dispatch-prompts.md
false-positive-rules.md
finding-output-format.md
finding-state-phase4.md
finding-state-schema.md
github-posting-recovery.md
github-posting-rerun.md
github-posting.md
phase1-timeline-state.md
q5-type-coercion.md
q6-cross-repo.md
q6-reusability-search.md
repo-map.md
reviewer-prompt.md
schema-design-checks.md
verification-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_exports shell、本地和跨仓库模式。仓库中仅有这一份;/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。

提取关联的问题
  1. 优先使用 closingIssuesReferences(每项都带有自己的 repository.nameWithOwner;使用该值,而不是 PR 所属仓库)。
  2. 回退到正文正则:(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)(仅限同一仓库)。
  3. 对每个关联的问题执行:gh issue view <num> --repo <owner>/<repo> --json title,body,state。
  4. 如果关联的问题 ≥ 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

跨仓库模式的变更:

  1. 仓库映射计算回退为通过远程 gh api 获取树。
  2. 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,则对每条剩余发现进行匹配:

  1. 检查 Issue 文本是否包含 pattern(不区分大小写的子字符串)。
  2. 如果设置了 category,还需检查发现的 Category 是否完全匹配。
  3. 如果设置了 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,除非将其重新路由。将此步骤新增的每条发现重新通过以下步骤:

  1. 3:剔除已知问题,包括已有回复的讨论串。
  2. 4.55:执行类完整性扫描,使 Class-sites: <A>/<N> 不为空。若 V1 已返回,则由 main 在此处直接执行扫描,而不是再次调度 V1;仍须遵守最多 4 个子代理的限制。
  3. 4.56:推导逆向风险,使每条 Suggested fix: 都包含 Inverse risk:。
  4. 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;权限失败后绝不要将其他作者的审查降级。
  • 状态文件写入失败 → 记录警告,不要阻止发布。状态文件持久化尽力而为。

评论

支持 Markdown