review-anvil

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

review-anvil — Iterative Multi-Agent Fix/Review Loop

review-anvil — 多Agent迭代修复/审查循环

Wrap a code change in requested rounds of parallel reviewer subagents + orchestrator-applied fixes. Each round = (parallel review by M agents, each with a distinct lens) → (you synthesize and verify findings) → (you apply fixes, run the build/test gate, commit) → next round. In productive
per_fix
runs, the orchestrator may continue adaptively after the requested rounds until convergence or
max_rounds
.
将代码变更包裹在请求轮次的并行审查子代理 + 编排器应用修复流程中。每一轮流程 =(M个代理从不同视角并行审查)→(你综合并验证审查结果)→(你应用修复、运行构建/测试关卡、提交代码)→ 进入下一轮。在生产环境的
per_fix
运行模式下,编排器可能在请求轮次结束后自适应继续运行,直到代码收敛或达到
max_rounds
上限。

Preset skills

预设技能

This is the engine. Three preset skills in the same plugin pin common configurations; each is a separate
skills/<name>/SKILL.md
whose
description
triggers activation cross-agent.
PresetPinsIntent
review-anvil
(engine)
nothingDefault fix/commit loop, or any custom param combination.
review-anvil-readonly
commit_mode=none
; default
rounds=1
Read-only review — no edits, no commits.
review-anvil-pr [<locator>]
commit_mode=none
,
target=<locator>
,
report_path=<file>
, trusted
run_ordinal=<observed>
Review a GitHub PR and post the report back as a PR comment (orchestrates
scripts/pr-helper.sh
). Locator auto-detected from the current branch when omitted.
review-anvil-improve-pr [<locator>]
commit_mode=per_fix
,
target=<base>...HEAD
,
report_path=<file>
, trusted
run_ordinal=<observed>
Improve a checked-out PR: fix commits across requested rounds plus any adaptive continuation, then push. Targets the branch (not a PR locator), deliberately routing around the PR-target/per_fix rule below.
本工具是核心引擎。同一插件中的三个预设技能对应常见配置;每个预设技能对应独立的
skills/<name>/SKILL.md
文件,其
description
字段可触发跨代理激活。
预设技能固定参数用途
review-anvil
(引擎)
默认修复/提交循环,或任意自定义参数组合。
review-anvil-readonly
commit_mode=none
;默认
rounds=1
只读审查 — 不编辑、不提交代码。
review-anvil-pr [<locator>]
commit_mode=none
,
target=<locator>
,
report_path=<file>
, 可信
run_ordinal=<observed>
审查GitHub PR并将报告作为PR评论发布(编排
scripts/pr-helper.sh
脚本)。省略定位符时会自动从当前分支检测。
review-anvil-improve-pr [<locator>]
commit_mode=per_fix
,
target=<base>...HEAD
,
report_path=<file>
, 可信
run_ordinal=<observed>
优化已检出的PR:在请求轮次中修复并提交代码,同时支持自适应延续,然后推送。目标为分支(而非PR定位符),特意绕过下文的PR目标/per_fix规则。

Parameters

参数

Parse the user's free-form args string into:
ParamDefaultPlain-English forms
rounds
3
"5 rounds", "three rounds", "do 4 passes"
max_rounds
per_fix
:
min(max(6, rounds), rounds + adaptive budget)
— budget 1/2/3 for small/medium/large diffs (see Parsing);
rounds
for
commit_mode=none
"max 4 rounds", "allow one extra round", "3 rounds, continue if needed"; "exactly 3 rounds", "only 3 rounds", or "no extra rounds" keeps
max_rounds=rounds
agents
3
"3 agents", "2 reviewers", or a mix like
"2 codex + 1 claude"
focus
the four pillars (correctness, maintainability, simplicity, production blast-radius)"focus on async correctness"; an
only:
prefix replaces the defaults instead of appending
target
auto-detect"PR #42", "branch", "uncommitted", "src/auth/", "last 3 commits"
allow_new_deps
false
"allow new deps" — auto-apply fixes that introduce new imports/subsystems instead of deferring them
min_fix_severity
medium
"auto-fix high and above", "fix only critical" — minimum severity for auto-fix; lower findings are listed, not applied
commit_mode
per_fix
per_fix
(one commit per fix-group) or
none
("review only", "don't commit", "no fixes")
approve
allowed
"never approve", "comment only",
approve: never
— always write
{"event": "COMMENT"}
to
.approval.json
. Presets additionally export
REVIEW_ANVIL_NO_APPROVE=1
so the helper enforces it mechanically. Only meaningful for review-only PR runs
reproduction
auto
auto
,
on
, or
off
— default-on batched reproduction of uncertain
medium
+ findings before auto-fix/reporting; "skip reproduction" disables it and marks single-reviewer material findings as unconfirmed
adversarial
off
off
,
auto
,
challenge
,
targeted
,
full
, or
strict
— read-only post-synthesis review that attacks candidate findings and would-apply plans before they become final guidance
adversarial_rounds
1
one adversarial pass by default; max 2, and a second pass runs only when the first pass materially changes
medium
+ guidance
disagreement_policy
defer
defer
moves unresolved material disputes to Deferred;
comment
keeps the finding actionable but forces review-only PR approvals to COMMENT
verify_cmd
auto-detect"verify with
npm test
",
verify_cmd: none
to skip — build/test command run after each round's fixes (see "Build/test gate"; per_fix only)
reviewer_timeout
600
(
420
for small diffs)
"timeout 10 minutes" — hard per-reviewer wall-clock cap in seconds for Bash-dispatched reviewers (see
run-reviewer.sh
). Default is ~3× the slowest legitimate reviewer observed in real runs (98–213s); when unset and the diff is under ~500 changed lines (added+removed — the same measure as the adaptive budget tiers), requested rounds use
420
(~2× that observed max) so a hung reviewer pins the wave 3 minutes less. Adaptive rounds always use the full base value —
600
, or
1200
after the >5000-line doubling (doubling transforms the base; the small-diff reduction never applies to adaptive rounds). Explicit user values are never scaled or doubled
report_path
unsetFile path; when set, the engine writes the final report there (creating parent dirs) and prints exactly that path as its last output line so downstream consumers can pick it up
run_ordinal
is trusted invocation context, not a free-form user parameter. Use
run_ordinal
only when it is a positive trusted value. Treat an absent value or
unavailable
as local/degraded context and omit
RUN
from item IDs. Keep UUID markers as the collision-resistant run identity. The ordinal adds human-readable provenance; it does not replace the marker.
将用户的自由格式参数解析为以下内容:
参数默认值自然语言表述
rounds
3
"5轮"、"三轮"、"进行4次审查"
max_rounds
per_fix
模式:
min(max(6, rounds), rounds + 自适应预算)
— 预算根据差异大小分为小/中/大三种(见解析规则);
commit_mode=none
模式:
rounds
"最多4轮"、"允许额外1轮"、"3轮,必要时继续";"正好3轮"、"仅3轮"或"无额外轮次"会将
max_rounds
设为
rounds
agents
3
"3个代理"、"2个审查者",或类似
"2 codex + 1 claude"
的混合配置
focus
四大核心维度(正确性、可维护性、简洁性、生产环境影响范围)"聚焦异步正确性";前缀
only:
会替换默认维度而非追加
target
自动检测"PR #42"、"分支"、"未提交变更"、"src/auth/"、"最近3次提交"
allow_new_deps
false
"允许新增依赖" — 自动应用引入新导入/子系统的修复,而非推迟处理
min_fix_severity
medium
"自动修复严重及以上问题"、"仅修复关键问题" — 自动修复的最低严重级别;较低级别的问题仅列出,不应用修复
commit_mode
per_fix
per_fix
(每组修复对应一次提交)或
none
("仅审查"、"不提交"、"不修复")
approve
allowed
"绝不批准"、"仅评论"、
approve: never
— 始终向
.approval.json
写入
{"event": "COMMENT"}
。预设技能还会导出
REVIEW_ANVIL_NO_APPROVE=1
,以便辅助脚本强制实施该规则。仅对只读PR审查有意义
reproduction
auto
auto
on
off
— 默认批量复现不确定的
medium
及以上级别问题,然后再进行自动修复/报告;"跳过复现"会禁用该功能,并将单审查者发现的重要问题标记为未确认
adversarial
off
off
auto
challenge
targeted
full
strict
— 只读的合成后审查,在候选结果和拟应用方案成为最终指导之前对其进行质疑
adversarial_rounds
1
默认1次对抗性审查;最多2次,仅当第一次审查实质性改变
medium
及以上级别的指导意见时才会进行第二次
disagreement_policy
defer
defer
会将未解决的重大争议移至推迟处理;
comment
会保留问题的可操作性,但强制只读PR审查的批准结果为COMMENT
verify_cmd
自动检测"用
npm test
验证",
verify_cmd: none
表示跳过 — 每轮修复后运行的构建/测试命令(见"构建/测试关卡";仅适用于per_fix模式)
reviewer_timeout
600
(小差异为
420
"超时10分钟" — Bash调度的审查者的硬时钟上限(单位:秒,见
run-reviewer.sh
)。默认值约为实际运行中最慢合法审查者耗时的3倍(98–213秒);当未设置且差异小于约500行变更(添加+删除 — 与自适应预算层级的衡量标准相同)时,请求轮次使用
420
(约为观察到的最大耗时的2倍),这样挂起的审查者会减少3分钟的阻塞。自适应轮次始终使用完整的基准值 —
600
,或在超过5000行时翻倍(翻倍会转换基准值;小差异的缩减规则从不应用于自适应轮次)。用户明确设置的值不会被缩放或翻倍
report_path
未设置文件路径;设置后,引擎会将最终报告写入该路径(会创建父目录),并将该路径作为最后一行输出,以便下游消费者获取
run_ordinal
是可信调用上下文,不是自由格式的用户参数。仅当它是正可信值时才使用
run_ordinal
。将缺失值或
unavailable
视为本地/降级上下文,并从项目ID中省略
RUN
。保留UUID标记作为防冲突的运行标识。序数添加了人类可读的来源信息;它不会替代标记。

Parsing

解析规则

  • Split the args on top-level commas; canonicalize each segment to a
    (param, value)
    pair — explicit
    key: value
    maps directly, plain-English forms per the table. Unrecognized segments are noted and ignored.
  • First occurrence wins per param; later duplicates are dropped with
    warning: user-supplied <param>=<value> ignored — earlier value wins
    . Unset params take defaults.
  • Presets assemble
    <pins>, <user-args>, <overridable defaults>
    : pins come first so first-occurrence-wins makes them authoritative; defaults come last so user args beat them.
  • Pin-rejection (presets; defense in depth against the prose parser being talked into overrides): before assembling, segment-split
    $ARGUMENTS
    as above, lowercase each segment's key (the text before its first
    :
    ), and abort with
    error: <param> is pinned by <preset-name> and cannot be overridden in args
    if any key equals a pinned param. Match segment keys, never raw substrings —
    focus: "target: PR safety"
    has key
    focus
    and must pass. A host that cannot segment-split must abort (
    error: pin-rejection unavailable in this environment; refusing to invoke engine without pin enforcement
    ), not degrade to substring scanning.
  • agents
    : a count (use the mix table below) or an explicit mix naming
    codex
    /
    codex-exec
    /
    claude
    /
    claude-exec
    — honor a mix exactly.
  • target
    auto-detect order: currently checked-out PR (e.g.
    gh pr view --json number,headRefName
    , a GitHub MCP query, or REST) → branch-vs-main diff (
    git diff main...HEAD
    ) → uncommitted changes (
    git diff
    +
    git diff --cached
    ). Empty args = all defaults.
  • rounds
    is the requested count. Resolve
    max_rounds
    after
    rounds
    , the final
    commit_mode
    (including the PR-locator rule below), and the target: the
    per_fix
    default is
    min(max(6, rounds), rounds + budget)
    , where the adaptive budget scales with the target's changed-line count (added+removed in the materialized diff; materialize it once at resolution —
    per_fix
    targets are always local git diffs): under ~200 lines →
    1
    , up to ~1000 →
    2
    , above →
    3
    . The
    min()
    against the legacy
    max(6, rounds)
    cap makes the scaling a pure reduction: runs with
    rounds >= 6
    gain nothing. Default to
    rounds
    for
    commit_mode=none
    ; reject
    max_rounds < rounds
    . Phrases like "allow one extra round" set
    max_rounds=rounds+1
    , and explicit caps like
    max_rounds: 4
    or "up to 4 rounds" set the cap directly. Phrases like "continue if needed" restore the legacy
    max(6, rounds)
    cap unless paired with an explicit cap. Phrases that constrain the round count itself — "exactly 3 rounds", "only 3 rounds", "3 rounds only", or "no extra rounds" — force
    max_rounds=rounds
    . Do not treat
    only:
    focus syntax or severity gates like "fix only critical" as exact-round requests.
  • Adaptive continuation is on by default for
    per_fix
    . A plain "3 rounds" means
    rounds=3
    with
    max_rounds
    between
    4
    and
    6
    by diff size, so the organizing agent may continue after round 3 if §6 says another pass is justified. Use "exactly 3 rounds", "only 3 rounds", "no extra rounds", or
    max_rounds: 3
    when the run must stop at the requested count.
  • If
    commit_mode=none
    and the user explicitly set
    max_rounds > rounds
    , warn and collapse
    max_rounds
    to
    rounds
    . Extra normal rounds review the same baseline, so use
    rounds
    for reviewer redundancy and
    adversarial
    for skeptical challenge.
  • reproduction=auto
    and
    reproduction=on
    both run the selective batched reproduction gate in §3.
    auto
    may skip dispatch only when there are no candidates.
    off
    is allowed for speed, but the round summary and final report must say it was disabled; unconfirmed single-reviewer
    medium
    + findings stay in Deferred unless the orchestrator independently reproduced them from code/tests/runtime evidence.
  • adversarial
    applies only when
    commit_mode=none
    . If set with
    per_fix
    , warn and ignore it — productive mode already applies real fixes and gates them with the build/test command. Reject
    adversarial_rounds > 2
    ; adversarial loops must be bounded.
    auto
    means choose the cheapest sufficient adversarial mode after normal synthesis using the default policy below.
  • 按顶级逗号分割参数;将每个段规范化为
    (参数, 值)
    对 — 明确的
    key: value
    直接映射,自然语言表述参考表格。未识别的段会被记录并忽略。
  • 首次出现优先;后续重复项会被丢弃,并提示
    warning: user-supplied <param>=<value> ignored — earlier value wins
    。未设置的参数使用默认值。
  • 预设技能按
    <固定参数>, <用户参数>, <可覆盖默认值>
    组合:固定参数优先,因此首次出现优先规则使其具有权威性;默认值最后,因此用户参数会覆盖默认值。
  • 固定参数拒绝(预设技能;防止 prose 解析器被说服覆盖参数的深度防御):组合前,按上述规则分割
    $ARGUMENTS
    ,将每个段的键(第一个
    :
    之前的文本)转换为小写,如果任何键等于固定参数,则中止并提示
    error: <param> is pinned by <preset-name> and cannot be overridden in args
    。匹配段的,而非原始子字符串 —
    focus: "target: PR safety"
    的键是
    focus
    ,必须通过。无法分割段的宿主必须中止(
    error: pin-rejection unavailable in this environment; refusing to invoke engine without pin enforcement
    ),而不能降级为子字符串扫描。
  • agents
    :数量(使用下表的混合规则)或明确的混合配置,命名
    codex
    /
    codex-exec
    /
    claude
    /
    claude-exec
    — 严格遵循混合配置。
  • target
    自动检测顺序:当前检出的PR(例如
    gh pr view --json number,headRefName
    、GitHub MCP查询或REST)→ 分支与主分支的差异(
    git diff main...HEAD
    )→ 未提交变更(
    git diff
    +
    git diff --cached
    )。空参数 = 全部使用默认值。
  • rounds
    是请求的轮次计数。在确定
    rounds
    、最终
    commit_mode
    (包括下文的PR定位符规则)和目标后解析
    max_rounds
    per_fix
    模式的默认值为
    min(max(6, rounds), rounds + budget)
    ,其中自适应预算根据目标的变更行数(已具体化差异中的添加+删除行数;在解析时具体化一次 —
    per_fix
    模式的目标始终是本地git差异)缩放:小于约200行 →
    1
    ,最多约1000行 →
    2
    ,超过 →
    3
    。与旧版
    max(6, rounds)
    上限的
    min()
    使缩放成为纯缩减:
    rounds >= 6
    的运行不会获得额外预算。
    commit_mode=none
    模式默认使用
    rounds
    ;拒绝
    max_rounds < rounds
    。类似“允许额外1轮”的表述会将
    max_rounds
    设为
    rounds+1
    ,明确的上限如
    max_rounds: 4
    或“最多4轮”会直接设置上限。类似“必要时继续”的表述会恢复旧版
    max(6, rounds)
    上限,除非与明确上限配对。限制轮次计数的表述 — “正好3轮”、“仅3轮”、“3轮仅”或“无额外轮次” — 会强制
    max_rounds=rounds
    不要
    only:
    聚焦语法或“仅修复关键问题”等严重级别关卡视为精确轮次请求。
  • per_fix
    模式默认启用自适应延续。单纯的“3轮”意味着
    rounds=3
    max_rounds
    根据差异大小在4到6之间,因此编排代理可能在第3轮后继续运行,如果§6规则认为有必要进行另一轮。当运行必须在请求的轮次结束时停止,使用“正好3轮”、“仅3轮”、“无额外轮次”或
    max_rounds: 3
  • 如果
    commit_mode=none
    且用户明确设置
    max_rounds > rounds
    ,则发出警告并将
    max_rounds
    缩减为
    rounds
    。额外的普通轮次会审查相同的基线,因此使用
    rounds
    实现审查者冗余,使用
    adversarial
    实现质疑性审查。
  • reproduction=auto
    reproduction=on
    都会运行§3中的选择性批量复现关卡。
    auto
    仅在没有候选问题时可能跳过调度。
    off
    允许以速度为代价,但轮次摘要和最终报告必须说明它已被禁用;未确认的单审查者
    medium
    及以上级别问题会留在推迟处理中,除非编排器从代码/测试/运行时证据中独立复现了它们。
  • adversarial
    仅在
    commit_mode=none
    时适用。如果在
    per_fix
    模式下设置,则发出警告并忽略 — 生产模式已通过构建/测试命令验证真实修复。拒绝
    adversarial_rounds > 2
    ;对抗性循环必须有界。
    auto
    意味着在正常合成后使用默认规则选择最便宜且足够的对抗模式。

PR-target / per_fix incompatibility

PR目标 / per_fix不兼容

If
target
is a GitHub PR locator (URL
https://<host>/<owner>/<repo>/pull/<N>
, slug
<owner>/<repo>#<N>
, or "PR #N"), the only valid
commit_mode
is
none
. Force it, and warn if the user asked for
per_fix
:
warning: PR locators are read-only — forcing commit_mode=none (use 'target: branch' to fix-and-commit on your checked-out PR branch).
Reviewers of a PR locator see the GitHub-fetched diff, which may not match the local worktree; committing against a baseline the user can't see locally is unpredictable. Branch targets make the local tree the source of truth.
如果
target
是GitHub PR定位符(URL
https://<host>/<owner>/<repo>/pull/<N>
、slug
<owner>/<repo>#<N>
或“PR #N”),唯一有效的
commit_mode
none
。强制设置该值,如果用户要求
per_fix
则发出警告:
warning: PR locators are read-only — forcing commit_mode=none (use 'target: branch' to fix-and-commit on your checked-out PR branch).
PR定位符的审查者看到的是GitHub获取的差异,可能与本地工作树不匹配;针对用户本地无法看到的基线提交代码是不可预测的。分支目标将本地树作为事实来源。

Commit modes

提交模式

  • per_fix
    (default)
    — full loop: review → synthesize/reproduce/verify → apply fixes → build/test gate → commit, each round.
  • none
    (review-only)
    — review → synthesize/reproduce/verify only. No edits, no commits, no staging. Read-only mode may write temporary prompt/reviewer/report artifacts under
    .review-anvil/
    and the explicit
    report_path
    ; it must not modify source files, the index, commits, branches, or remotes. Every normal round reviews the same baseline, so
    rounds > 1
    buys reviewer redundancy, not code refinement; the natural default is
    rounds=1
    , and adaptive continuation is disabled by collapsing
    max_rounds
    to
    rounds
    . Skip Loop Mechanics §4 entirely; the round summary reads
    Fixes applied: 0 (review-only)
    ; the auto-fix policy is still evaluated in the abstract so findings classify as would-apply / suggestions / deferred. Optional adversarial review is a separate post-synthesis gate that attacks finding validity and fix proportionality without pretending code changed.
  • per_fix
    (默认)
    — 完整循环:审查 → 综合/复现/验证 → 应用修复 → 构建/测试关卡 → 提交,每轮执行。
  • none
    (仅审查)
    — 仅执行审查 → 综合/复现/验证。不编辑、不提交、暂存。只读模式可能在
    .review-anvil/
    和明确的
    report_path
    下写入临时提示/审查者/报告工件;不得修改源文件、索引、提交、分支或远程仓库。每一轮普通审查都会审查相同的基线,因此
    rounds > 1
    仅能获得审查者冗余,而非代码优化;自然默认值为
    rounds=1
    ,自适应延续通过将
    max_rounds
    缩减为
    rounds
    来禁用。完全跳过循环机制§4;轮次摘要显示
    Fixes applied: 0 (review-only)
    ;自动修复规则仍会抽象评估,因此问题会被分类为拟应用/建议/推迟处理。可选的对抗性审查是独立的合成后关卡,用于质疑问题的有效性和修复的合理性,而不假装代码已变更。

Posting reports externally

外部发布报告

The engine never posts anywhere. Downstream consumers set
report_path
, let the engine write a GitHub-ready PR report, and post after it returns —
review-anvil-pr
+ its
pr-helper.sh
is the reference implementation.
When
report_path
is set, optimize the report for a PR timeline reader, not for archival completeness. The per-round console output and reviewer artifacts are the transcript; the posted report is the decision summary plus the few findings that need action. Adaptive continuation details belong in Run Details unless they change the review decision; do not paste per-round continuation reasoning into PR reports.
引擎从不向任何外部发布报告。下游消费者设置
report_path
,让引擎写入GitHub兼容的PR报告,然后在引擎返回后发布 —
review-anvil-pr
及其
pr-helper.sh
是参考实现。
当设置
report_path
时,优化报告以适应PR时间线读者,而非归档完整性。每轮控制台输出和审查者工件是完整记录;发布的报告是决策摘要加上需要行动的少数问题。自适应延续细节属于运行详情,除非它们改变审查决策;不要将每轮延续推理粘贴到PR报告中。

Examples

示例

  • Skill review-anvil
    → 3 requested rounds, adaptive up to 4–6 total rounds by diff size, 2 codex + 1 claude, four-pillar focus, auto-detected target.
  • Skill review-anvil "5 rounds, 2 codex + 1 claude, focus: async correctness, target: PR #42"
  • Skill review-anvil "3 rounds, max_rounds: 4"
    → 3 requested rounds, then at most 1 adaptive round if the continuation policy allows it.
  • Skill review-anvil "1 round, only: security, target: src/auth/"
  • Skill review-anvil "fix only critical"
    → severity gate raised to
    critical
    ; everything else surfaces as suggestions.
  • Skill review-anvil "target: PR #42, adversarial: auto"
    → normal review first, then adversarial review only if the synthesized findings/fix plans need a validity or proportionality challenge.
  • Skill review-anvil
    → 3轮请求轮次,根据差异大小自适应最多4–6轮,2个codex + 1个claude,四大核心维度聚焦,自动检测目标。
  • Skill review-anvil "5 rounds, 2 codex + 1 claude, focus: async correctness, target: PR #42"
  • Skill review-anvil "3 rounds, max_rounds: 4"
    → 3轮请求轮次,然后如果延续规则允许,最多1轮自适应轮次。
  • Skill review-anvil "1 round, only: security, target: src/auth/"
  • Skill review-anvil "fix only critical"
    → 严重级别关卡提升至
    critical
    ;其他所有问题作为建议呈现。
  • Skill review-anvil "target: PR #42, adversarial: auto"
    → 先进行正常审查,然后仅当合成的问题/修复方案需要有效性或合理性质疑时才进行对抗性审查。

Default Mix Policy

默认混合规则

When the user gives a count but no mix:
agents
Mix
11 codex-exec
21 codex-exec + 1 claude-exec
32 codex-exec + 1 claude-exec
42 codex-exec + 2 claude-exec
53 codex-exec + 2 claude-exec
N~60/40 codex/claude split, codex gets the odd one
Rationale: codex-exec surfaces more issues per call in our usage, so it gets the larger share (and the
agents=1
slot).
当用户给出数量但未指定混合配置时:
agents
数量
混合配置
11个codex-exec
21个codex-exec + 1个claude-exec
32个codex-exec + 1个claude-exec
42个codex-exec + 2个claude-exec
53个codex-exec + 2个claude-exec
N约60/40的codex/claude比例,codex占奇数位
原理:在我们的使用中,codex-exec每次调用能发现更多问题,因此占更大比例(包括
agents=1
的情况)。

Loop Mechanics

循环机制

Run the loop for the requested
rounds
, then continue adaptively up to
max_rounds
only when §6 allows adaptive continuation. Within a round:
运行请求的
rounds
轮次,然后仅当§6允许自适应延续时,继续运行至
max_rounds
上限。每一轮内:

1. Snapshot the target

1. 快照目标

Capture the target's state at round start so all reviewers see the same input:
  • Non-PR targets (branch, uncommitted, path): materialize the diff with the appropriate
    git diff …
    .
  • PR targets (always
    commit_mode=none
    ): fetch the PR's diff via
    gh pr diff <N> -R <owner>/<repo>
    (or equivalent MCP/REST). The local worktree is irrelevant — reviewers see the PR as it exists on GitHub.
  • Whenever PR context is available — a PR-locator target, or a preset that supplies it (
    review-anvil-improve-pr
    does, after
    verify-checkout
    ) — fetch the PR title/body/base branch/file list too, then infer the PR's intended scope in one sentence (e.g. "performance optimization in annotation seeding", "left-sidebar UX reorganization"). Put that scope in every reviewer prompt. A finding is actionable only if the PR introduces/regresses it or if it directly undermines the PR's stated purpose. Obvious, high-confidence pre-existing defects may be mentioned, but only under a separate "Out-of-scope follow-ups" section — never as blockers or inline actionable review comments for the current PR.
  • Likewise gather the complete PR review history before dispatch: when a preset supplied the ledger (improve-pr captures it at verify-checkout time), use that; for PR-locator targets fetch it via
    pr-helper.sh history <host> <owner> <repo> <n>
    (ships with
    review-anvil-pr
    ; threads, review bodies, and fallback comments are paginated and retried once). Include the status-tagged ledger in every reviewer prompt (PR REVIEW HISTORY block):
    open
    threads,
    resolved
    threads,
    outdated
    anchors, summary-only
    reported
    findings, prior
    deferred
    /
    review-dismissed
    items, and explicit local
    suppressed
    findings. Pending reviews are not shown to the author and are excluded. Before dispatch, semantically coalesce entries with the same root cause (summary wording often differs from its inline comment), retaining every source URL and state; explicit suppression wins, otherwise preserve all observed states. If lookup fails after retry, abort rather than review without prior feedback — unless the user opted into degraded mode (
    REVIEW_ANVIL_SKIP_DISMISSED=1
    ), which also forces the review decision to COMMENT.
  • Note
    git rev-parse HEAD
    so the round summary can reference the exact baseline (informational-only for PR targets).
在轮次开始时捕获目标状态,以便所有审查者看到相同的输入:
  • 非PR目标(分支、未提交变更、路径):使用适当的
    git diff …
    命令具体化差异。
  • PR目标(始终为
    commit_mode=none
    ):通过
    gh pr diff <N> -R <owner>/<repo>
    (或等效的MCP/REST)获取PR的差异。本地工作树无关紧要 — 审查者看到的是GitHub上的PR状态。
  • 只要PR上下文可用 — PR定位符目标,或提供PR上下文的预设技能(
    review-anvil-improve-pr
    verify-checkout
    后提供) — 同时获取PR标题/正文/基准分支/文件列表,然后用一句话推断PR的预期范围(例如“注释种子的性能优化”、“左侧边栏UX重组”)。将该范围放入每个审查者的提示中。只有当PR引入/回归问题,或直接破坏PR的既定目标时,问题才具有可操作性。明显的、高置信度的预先存在的缺陷可以提及,但必须放在单独的“范围外后续事项”部分 — 绝不能作为当前PR的阻塞点或内联可操作审查评论。
  • 同样,在调度前收集完整的PR审查历史:当预设技能提供记录(improve-pr在verify-checkout时捕获)时,使用该记录;对于PR定位符目标,通过
    pr-helper.sh history <host> <owner> <repo> <n>
    获取(随
    review-anvil-pr
    提供;线程、审查正文和回退评论会分页并重试一次)。将带有状态标记的记录放入每个审查者的提示中(PR REVIEW HISTORY块):
    open
    线程、
    resolved
    线程、
    outdated
    锚点、仅摘要的
    reported
    问题、先前的
    deferred
    /
    review-dismissed
    项目,以及明确的本地
    suppressed
    问题。待处理的审查不会显示给作者,并被排除。调度前,语义合并具有相同根本原因的条目(摘要措辞通常与其内联评论不同),保留每个源URL和状态;明确的抑制优先,否则保留所有观察到的状态。如果重试后查找失败,则中止而非在没有先前反馈的情况下进行审查 — 除非用户选择降级模式(
    REVIEW_ANVIL_SKIP_DISMISSED=1
    ),这也会强制审查决策为COMMENT。
  • 记录
    git rev-parse HEAD
    ,以便轮次摘要可以引用确切的基线(仅对PR目标提供信息)。

2. Dispatch reviewers in parallel

2. 并行调度审查者

In Claude Code (the primary host)

在Claude Code(主宿主)中

Use the Agent tool for
claude-exec
reviewers. Do NOT use
claude -p
via Bash — that path is for non-Claude hosts only.
  • claude-exec
    : Agent tool,
    subagent_type: "general-purpose"
    , the assembled Reviewer Prompt as
    prompt
    ,
    run_in_background: true
    . The Agent tool streams natively, has no
    --max-turns
    ceiling, and inherits the session environment.
  • codex-exec
    : Bash through the wrapper:
    REVIEW_ANVIL_REQUIRE_FINDINGS=1 bash <wrapper> .review-anvil/round<N>-<label>.md <reviewer_timeout> -- codex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/null
    , with
    run_in_background: true
    . The validation flag makes the wrapper reject confirmation-only, plan-only, or otherwise incomplete responses that do not end with the required fenced findings block.
    --ephemeral
    prevents reviewer sessions from leaking into later dispatches. The
    < /dev/null
    is load-bearing: codex takes its prompt as argv and must not inherit an open stdin — the wrapper passes its stdin through (
    <&0
    , which the claude fallback needs), and codex blocking on a never-closing fd 0 is a known hang class from real runs.
  • Send all M reviewers in a single message with multiple tool calls. The harness notifies you on completion; do not poll.
claude-exec
审查者使用Agent工具。不要通过Bash使用
claude -p
— 该路径仅适用于非Claude宿主。
  • claude-exec
    :Agent工具,
    subagent_type: "general-purpose"
    ,将组装好的审查者提示作为
    prompt
    run_in_background: true
    。Agent工具原生支持流式传输,没有
    --max-turns
    上限,并继承会话环境。
  • codex-exec
    :通过包装器执行Bash命令:
    REVIEW_ANVIL_REQUIRE_FINDINGS=1 bash <wrapper> .review-anvil/round<N>-<label>.md <reviewer_timeout> -- codex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/null
    run_in_background: true
    。验证标志使包装器拒绝仅确认、仅计划或不完整的响应,这些响应未以所需的围栏式问题块结尾。
    --ephemeral
    防止审查者会话泄漏到后续调度中。
    < /dev/null
    是必需的:codex将提示作为argv,不得继承打开的stdin — 包装器传递其stdin(
    <&0
    ,claude回退需要),codex阻塞在永不关闭的fd 0上是实际运行中已知的挂起类型。
  • 单个消息中发送所有M个审查者,包含多个工具调用。工具会在完成时通知你;不要轮询。

In Codex CLI or other hosts without the Agent tool

在Codex CLI或其他无Agent工具的宿主中

  • claude-exec
    : write the assembled prompt to a file, then:
    bash
    REVIEW_ANVIL_REQUIRE_FINDINGS=1 bash <wrapper> .review-anvil/round<N>-<label>.md <reviewer_timeout> -- \
      claude -p --max-turns 100 --no-session-persistence \
        --permission-mode dontAsk --output-format text \
        --tools "Bash,Read,Glob,Grep" \
        --allowedTools "Bash(git:*)" "Read" "Glob" "Grep" \
      < .review-anvil/round<N>-<label>.prompt.md
    --tools
    restricts the built-in tool set;
    --allowedTools
    auto-approves the listed safe tool uses and is variadic, so the prompt MUST arrive via stdin (the wrapper passes its stdin through).
    --permission-mode dontAsk
    keeps the fallback non-interactive by denying anything outside the allowed/read-only path. Do not size
    --max-turns
    to the task
    — task-sized caps keep biting (20 was hit in production), and a reviewer that hits the cap loses its entire output. The wrapper's wall-clock timeout is the real bound;
    100
    is a runaway backstop that should never bind.
  • codex-exec
    : same validation-enabled wrapper around
    codex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/null
    — stdin from
    /dev/null
    here too.
  • Launch all M wrapper invocations as background shell processes and
    wait
    .
  • claude-exec
    :将组装好的提示写入文件,然后执行:
    bash
    REVIEW_ANVIL_REQUIRE_FINDINGS=1 bash <wrapper> .review-anvil/round<N>-<label>.md <reviewer_timeout> -- \
      claude -p --max-turns 100 --no-session-persistence \
        --permission-mode dontAsk --output-format text \
        --tools "Bash,Read,Glob,Grep" \
        --allowedTools "Bash(git:*)" "Read" "Glob" "Grep" \
      < .review-anvil/round<N>-<label>.prompt.md
    --tools
    限制内置工具集;
    --allowedTools
    自动批准列出的安全工具使用,且是可变参数,因此提示必须通过stdin传递(包装器传递其stdin)。
    --permission-mode dontAsk
    通过拒绝允许/只读路径之外的任何操作,使回退模式非交互式。不要根据任务大小设置
    --max-turns
    — 任务大小的限制在生产中经常触发(20次已被命中),达到限制的审查者会丢失所有输出。包装器的时钟超时是真正的限制;
    100
    是失控的后备值,不应触发。
  • codex-exec
    :与上述相同的启用验证的包装器,执行
    codex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/null
    — 此处stdin也来自
    /dev/null
  • 启动所有M个包装器调用作为后台shell进程并
    wait

Bash-dispatched reviewers MUST go through
run-reviewer.sh

Bash调度的审查者必须通过
run-reviewer.sh
运行

Every shell-dispatched reviewer (codex-exec everywhere; claude-exec outside Claude Code) runs under
scripts/run-reviewer.sh
(next to this SKILL.md). Never background a bare
claude -p ... > out.md 2>&1
and wait on the file
— in text mode nothing prints until the final answer, so a hung reviewer and a working one are both a 0-byte file (a production run waited on exactly that for many minutes). The wrapper:
run-reviewer.sh <out_file> <timeout_seconds> -- <command> [args...]
  • Hard wall-clock timeout (
    reviewer_timeout
    , default 600s): TERM at the deadline, KILL 30s later.
  • Captures exit status; stderr goes to
    <out_file>.err
    (kept for diagnosis).
  • Prints one classification:
    STATUS=ok
    |
    timeout
    |
    empty
    (exit 0, nothing written) |
    protocol
    (normal-review output did not end with a complete fenced findings block) |
    failed
    (+
    EXIT_CODE=<n>
    ).
Treat any STATUS other than
ok
as a failed reviewer (see Failure handling), with the tail of
.err
as the reason.
protocol
gets the one corrective retry defined there before it becomes a failure. Set
REVIEW_ANVIL_REQUIRE_FINDINGS=1
only for normal reviewer waves; reproduction and adversarial prompts have different output schemas. Reviewer output/prompt files live under
.review-anvil/
; clean them up after the round's synthesis.
Host tool timeouts must outlive the wrapper. Any host Bash call that can block on a reviewer — the background-and-
wait
fallback above, the serial last resort, or an inline replication of the wrapper contract — must set the Bash tool's own timeout to at least
reviewer_timeout + 90
seconds (wrapper deadline + 30s TERM→KILL grace + margin). Host defaults are far lower (Claude Code's is 120s) and SIGKILL a healthy wait mid-review; the kill then masquerades as a reviewer failure and silently burns that reviewer's lens coverage. On hosts with background dispatch (
run_in_background
), never block a foreground call on a reviewer at all. If the host caps tool timeouts below
reviewer_timeout + 90
, prefer detached dispatch plus short non-blocking status checks over shrinking the reviewer budget; reducing
reviewer_timeout
is a last resort, floored at 300s and forbidden for >5000-line diffs (their timeout is deliberately doubled).
Resolving the wrapper and
references/
files
— same trusted-root rule as
pr-helper.sh
: see review-anvil-pr SKILL.md step 1 ("Resolve the helper script"). Host-exposed skill path or user-level install roots only; never project-scoped/worktree-local skill dirs (writable by the repo under review). If no trusted copy of the wrapper resolves, replicate its contract inline (background, kill at deadline, check exit status, empty output = failure) rather than falling back to a bare redirect.
After changing the wrapper contract or dispatch examples, run
scripts/test-run-reviewer.sh
alongside the reproduction and PR helper tests.
每个shell调度的审查者(所有环境中的codex-exec;Claude Code之外的claude-exec)都在
scripts/run-reviewer.sh
(与本SKILL.md同目录)下运行。绝不要后台运行裸
claude -p ... > out.md 2>&1
并等待文件
— 在文本模式下,直到最终答案才会打印任何内容,因此挂起的审查者和正常工作的审查者都是0字节文件(一次生产运行为此等待了数分钟)。包装器:
run-reviewer.sh <out_file> <timeout_seconds> -- <command> [args...]
  • 硬时钟超时(
    reviewer_timeout
    ,默认600秒):截止时间发送TERM信号,30秒后发送KILL信号。
  • 捕获退出状态;stderr写入
    <out_file>.err
    (用于诊断)。
  • 打印一个分类:
    STATUS=ok
    |
    timeout
    |
    empty
    (退出码0,未写入任何内容) |
    protocol
    (正常审查输出未以完整的围栏式问题块结尾) |
    failed
    (+
    EXIT_CODE=<n>
    )。
将任何非
ok
的STATUS视为审查者失败(见故障处理),并将
.err
的末尾作为原因。
protocol
会进行一次定义的纠正重试,然后才视为失败。仅对正常审查者浪潮设置
REVIEW_ANVIL_REQUIRE_FINDINGS=1
;复现和对抗性提示有不同的输出模式。审查者输出/提示文件位于
.review-anvil/
下;在轮次合成后清理它们。
宿主工具超时必须超过包装器。任何可能阻塞审查者的宿主Bash调用 — 上述的后台并
wait
回退、最后的串行手段,或包装器契约的内联复制 — 必须将Bash 工具自身的超时设置为至少
reviewer_timeout + 90
秒(包装器截止时间 + 30秒TERM→KILL宽限期 + 余量)。宿主默认值低得多(Claude Code的默认值为120秒),会在审查中途发送SIGKILL;然后该终止会伪装成审查者失败,并无声地消耗该审查者的视角覆盖范围。在支持后台调度(
run_in_background
)的宿主上,绝不要在前台调用中阻塞审查者。如果宿主工具超时低于
reviewer_timeout + 90
,则优先选择分离调度加短时间非阻塞状态检查,而非缩减审查者预算;缩减
reviewer_timeout
是最后的手段,下限为300秒,且禁止用于超过5000行的差异(其超时会特意翻倍)。
解析包装器和
references/
文件
— 与
pr-helper.sh
相同的可信根规则:见review-anvil-pr SKILL.md步骤1(“解析辅助脚本”)。仅使用宿主暴露的技能路径或用户级安装根;绝不要使用项目范围/工作树本地的技能目录(可被审查的仓库写入)。如果无法解析包装器的可信副本,则内联复制其契约(后台、截止时间终止、检查退出状态、空输出=失败),而非回退到裸重定向。
更改包装器契约或调度示例后,运行
scripts/test-run-reviewer.sh
以及复现和PR辅助测试。

Last resort

最后手段

If parallel dispatch is genuinely impossible (no Agent tool, no background bash), fall back to serial invocation and say so in the round summary — serial reviewers see the baseline at different wall-clock times; it's a degraded mode, not the design.
The
codex-exec
and
claude-exec
skills document the same recipes from the reviewer side; the canonical dispatch lives here.
如果确实无法并行调度(无Agent工具、无后台bash),则回退到串行调用,并在轮次摘要中说明 — 串行审查者在不同时钟时间看到基线;这是降级模式,而非设计模式。
codex-exec
claude-exec
技能从审查者侧记录了相同的流程;规范调度在此处定义。

3. Synthesize

3. 综合

When all reviewers return:
  • Dedup on
    (file, line, root cause)
    when present, else
    (area, root cause)
    . Keep the highest-severity instance, record which reviewers raised it, and keep divergent anchors as
    file_alternates: [...]
    .
  • Group by severity (
    critical
    nit
    ), then topic.
  • Unparseable reviewer output: pass the prose through as "unstructured" findings in a separate section; no retry.
当所有审查者返回结果时:
  • 去重:基于
    (文件, 行, 根本原因)
    (如果存在),否则基于
    (领域, 根本原因)
    。保留最高严重级别的实例,记录哪些审查者提出了该问题,并将不同的锚点保留为
    file_alternates: [...]
  • 分组:按严重级别(
    critical
    nit
    ),然后按主题分组。
  • 无法解析的审查者输出:将 prose 作为“非结构化”问题传递到单独的部分;不重试。

Verify and reproduce findings before acting on them

行动前验证并复现问题

Plausible-but-wrong findings are the dominant failure mode of LLM review, and both downstream actions are expensive: a bogus fix commit pollutes the branch, a bogus finding posted to a PR burns the author's trust. After dedup:
  • Prior-feedback check first (orchestrator judgment). Compare every merged finding against PR REVIEW HISTORY semantically — same root cause counts even when wording differs. Revalidate
    open
    ,
    resolved
    , and summary-only
    reported
    items against the current head. An open item that remains real is a carry-forward finding and must retain its effect on severity/approval, but must not create a duplicate inline thread; a resolved item means only that GitHub discussion was closed, not that the code was proven fixed. Record a still-present resolved item as
    resolved-but-still-present
    in the summary and do not create a new inline thread. Items now fixed/stale become one-line status notes. Explicit local
    suppressed
    items are never auto-fixed or posted as actionable findings, but remain as compact status-only audit rows. Keep
    author-resolved
    items in PR REVIEW HISTORY for reviewer context. After synthesis and dedup, drop semantic matches to
    author-resolved
    items before building reproduction candidates. Exception: retain a finding when the reviewer explicitly set
    prior_feedback: reintroduced
    for a distinct new instance with new evidence. Do not report, post, auto-fix, or let ordinary
    author-resolved
    matches affect approval. A reintroduced finding remains actionable; it affects approval only at
    critical
    or
    high
    severity. The post-time helper catches near-verbatim repeats (exact path + text similarity ≥ 0.9) as a deterministic duplicate-thread backstop.
  • Scope/artifact filter next (orchestrator judgment). Drop or move to out-of-scope follow-ups before reproduction when the claim is about archived design notes, changelogs, old migration examples, generated fixtures, vendored files, or historical docs that are not the review's live product surface. Do not spend verifier budget proving historical provenance is stale. Conversely, live docs that users rely on — README usage, CLI help, API docs, config reference, plugin metadata, or marketplace copy — are product surface and may become reproduction candidates when they drift from code/runtime behavior.
  • Assign provenance IDs. Assign IDs after semantic deduplication, prior-feedback classification, and scope filtering, and before reproduction or adversarial dispatch. Use this output recipe:
    text
    PR finding: `RAV-RUN<run>-R<origin-round>-F<ordinal>`
    PR plan:    `RAV-RUN<run>-R<origin-round>-P<ordinal>`
    Local:      `RAV-R<origin-round>-F<ordinal>` / `RAV-R<origin-round>-P<ordinal>`
    Canonical grammar:
    RAV-(RUN<run>-)?R<origin-round>-(F|P)<ordinal>
    .
    run
    and
    origin-round
    are unpadded positive base-10 integers. Encode
    ordinal
    from an unpadded positive base-10 integer by left-padding only to a minimum width of three digits: encode 1 as
    001
    , 10 as
    010
    , 100 as
    100
    , and 1000 as
    1000
    ; do not add any other leading zero. Valid multi-digit examples are
    RAV-RUN12-R10-F010
    and
    RAV-R12-P1000
    . Invalid forms include
    RAV-RUN03-R2-F001
    ,
    RAV-RUN3-R02-F001
    ,
    RAV-RUN3-R2-F0001
    ,
    RAV-RUN0-R2-F001
    ,
    RAV-RUN3-R0-F001
    , and
    RAV-RUN3-R2-F000
    .
    ID legend:
    RUN
    is the observed PR review run,
    R
    is the immutable origin round,
    F
    is a finding, and
    P
    is a plan. Examples are
    RAV-RUN3-R2-F001
    ,
    RAV-RUN3-R2-P001
    ,
    RAV-R2-F001
    , and
    RAV-R2-P001
    . Cross-round allocation example: in trusted PR run 3, a history finding with
    id=RAV-RUN1-R2-F007
    keeps that ID. A new round-1 finding receives
    RAV-RUN3-R1-F001
    and keeps it when re-raised in round 2. The next new round-2 finding receives
    RAV-RUN3-R2-F002
    . A round-2 plan covering those two current-run findings receives
    RAV-RUN3-R2-P001
    . The matching local/degraded allocation for the same newly allocated items has no history carry-forward:
    RAV-R1-F001
    ,
    RAV-R2-F002
    , and
    RAV-R2-P001
    . The carried
    RAV-RUN1-R2-F007
    has no new inline comment. It remains available in history, the report, reproduction, and adversarial review.
    Finding and plan ordinals are independent, run-wide counters named
    next_finding_ordinal
    and
    next_plan_ordinal
    . Both start at
    001
    . Counters never reset each round and never reuse gaps. Before assignment, order findings by priority, normalized path, line, and topic; order plans by covered-finding priority, area, and subject.
    A finding's origin round is the first normal review round that raises it. A plan's origin round is the normal review round in which its concrete fix group is first assembled. The origin round never changes after confirmation, refutation, priority change, deferral, fix, or re-raise. Reproduction and adversarial passes are not rounds.
    Carried findings consume the exact
    id=
    value supplied in
    PR REVIEW HISTORY
    ; use that complete ID unchanged without advancing a current-run counter. For an actionable history entry that has only
    legacy=
    , use the
    legacy=
    value as a source alias and assign the next canonical ID. Do not assign a new ID to a non-actionable legacy-only entry. Historical
    RAVF###
    ,
    RAVW###
    ,
    F-###
    , and
    W-###
    forms are migration/read-boundary aliases only. New findings and plans always use the recipe above.
    Once assigned, keep the complete ID unchanged in reproduction candidates, adversarial targets, report rows, plan coverage, and later round references. ID reuse flows to an inline body only when the finding is otherwise eligible for a new inline. Ordinary
    open
    ,
    resolved
    , and
    reported
    carry-forwards retain their IDs in history, reports, reproduction, and adversarial targets, but do not create a new inline thread. Already-assigned in-scope low/nit and set-aside findings keep their complete canonical F IDs. Truly unassigned out-of-scope follow-ups stay distinct and do not receive an F ID.
  • Build
    REPRODUCTION CANDIDATES
    after prior-feedback classification and ID assignment:
    • every
      medium
      + finding raised by exactly one reviewer,
    • every
      medium
      + deletion/dead-code/unused/redundant-code/simplification finding, and any deletion/simplification that would remove runtime code, public docs/API, compatibility behavior, or another high-blast-radius surface, regardless of reviewer count,
    • every
      critical
      /
      high
      finding whose evidence is mostly inferred from a hunk rather than confirmed from code/runtime context,
    • every finding the orchestrator is materially uncertain about after reading the cited files.
  • When
    reproduction=auto
    or
    on
    and candidates exist, dispatch one batched reproduction verifier using
    references/reproduction-prompt.md
    . Do not spawn one verifier per finding unless the batch is too large to fit in one prompt. Dispatch it backgrounded under the Concurrency section's deadline rule — never an unbounded foreground wait. The verifier is not another broad review pass; it returns
    confirmed
    ,
    refuted
    ,
    unclear
    ,
    narrowed
    , or
    downgraded
    verdicts for the supplied complete canonical finding IDs only, and returns each ID unchanged.
  • Apply reproduction verdicts before auto-fix/reporting:
    • confirmed
      and
      narrowed
      findings may remain actionable, with narrowed wording when supplied.
    • downgraded
      findings re-enter the normal severity gates after changing severity.
    • refuted
      findings are dropped from final Findings (or, if useful for transparency, one-line Deferred notes).
    • unclear
      findings move to Deferred with
      We set this aside because <plain-language description of the missing proof>.
      Rewrite the verifier's reason; do not copy it.
  • Findings raised independently by 2+ reviewers and not listed as reproduction candidates may skip batched reproduction; consensus is the signal (this is why dedup records who raised what). Still open enough code/context before destructive action to ensure the fix path is coherent.
  • Deletions ("delete this"/dead/unused/redundant) require reproduction plus execution when
    per_fix
    applies the cut
    — the highest-blast-radius, highest-false-positive class. In
    per_fix
    , after reproduction confirms the cut, apply it and run the full test suite: a red gate means keep it. A green gate is necessary but not sufficient (it only proves test-covered behavior), so the reproduction/skeptic pass must also look for a concrete reason the code must stay, visible in the diff (trust boundary, aliasing copy, ordering, back-compat, dedup, edge semantics — or another specific contract). The two cover different blind spots: the gate catches callers the skeptic can't see; the skeptic catches behavior no test exercises. Block only on a red gate or a specific skeptic refutation — not on generic "there might be an unseen caller" (that's what the gate tests). Read-only mode has only the skeptic. Blocked → Deferred (
    We set this aside because the code is still needed — <what>
    ).
  • If
    reproduction=off
    , say so in the round summary and final report. Required reproduction candidates — including single-reviewer
    medium
    + findings, deletion/high-risk findings, and orchestrator-uncertain findings — cannot become actionable unless the orchestrator independently reproduces them from code/tests/runtime evidence; otherwise move them to Deferred with
    We set this aside because the needed check was not run.
  • low
    /
    nit
    findings skip verification: they're below the auto-fix gate and surface as suggestions either way.
Canonical examples for where reproduction helps and where it must stay out of the way live in
references/reproduction-examples.md
. After changing this policy or the reproduction prompt, run
scripts/test-reproduction-policy.sh
alongside the PR helper tests.
看似合理但错误的问题是LLM审查的主要故障模式,且下游操作成本高昂:虚假的修复提交会污染分支,发布到PR的虚假问题会消耗作者的信任。去重后:
  • 先检查先前反馈(编排器判断)。将每个合并的问题与PR REVIEW HISTORY进行语义比较 — 即使措辞不同,相同的根本原因也会被视为匹配。针对当前HEAD重新验证
    open
    resolved
    和仅摘要的
    reported
    项目。仍然存在的开放项目是遗留问题,必须保留其对严重级别/批准的影响,但不得创建重复的内联线程;已解决的项目仅表示GitHub讨论已关闭,而非代码已被证明修复。将仍然存在的已解决项目记录为
    resolved-but-still-present
    在摘要中,且不得创建新的内联线程。现已修复/过时的项目成为单行状态说明。明确的本地
    suppressed
    项目永远不会被自动修复或作为可操作问题发布,但会保留为紧凑的仅状态审计行。在PR REVIEW HISTORY中保留
    author-resolved
    项目供审查者参考。合成和去重后,在构建复现候选之前,删除与
    author-resolved
    项目的语义匹配项。例外:当审查者明确为具有新证据的不同新实例设置
    prior_feedback: reintroduced
    时,保留该问题。不报告、不发布、不自动修复,也不要让普通的
    author-resolved
    匹配项影响批准。重新引入的问题仍然具有可操作性;仅在
    critical
    high
    严重级别时影响批准。发布时的辅助脚本会捕获近似重复项(精确路径 + 文本相似度≥0.9)作为确定性重复线程的后备。
  • 接下来过滤范围/工件(编排器判断)。在复现之前,如果问题是关于存档的设计说明、变更日志、旧迁移示例、生成的 fixture、供应商文件或不属于审查的实时产品表面的历史文档,则删除或移至范围外后续事项。不要花费验证者预算证明历史来源已过时。相反,用户依赖的实时文档 — README用法、CLI帮助、API文档、配置参考、插件元数据或市场文案 — 是产品表面,当它们与代码/运行时行为不一致时,可能成为复现候选。
  • 分配来源ID。在语义去重、先前反馈分类和范围过滤之后,复现或对抗性调度之前分配ID。使用以下输出规则:
    text
    PR问题: `RAV-RUN<run>-R<origin-round>-F<ordinal>`
    PR计划:    `RAV-RUN<run>-R<origin-round>-P<ordinal>`
本地:
RAV-R<origin-round>-F<ordinal>
/
RAV-R<origin-round>-P<ordinal>

规范语法: `RAV-(RUN<run>-)?R<origin-round>-(F|P)<ordinal>`。
`run`和`origin-round`是无填充的正十进制整数。通过仅左填充到最小宽度三位来编码`ordinal`(无填充的正十进制整数):将1编码为`001`,10编码为`010`,100编码为`100`,1000编码为`1000`;不要添加任何其他前导零。有效的多位示例为
`RAV-RUN12-R10-F010`和`RAV-R12-P1000`。无效形式包括
`RAV-RUN03-R2-F001`, `RAV-RUN3-R02-F001`, `RAV-RUN3-R2-F0001`,
`RAV-RUN0-R2-F001`, `RAV-RUN3-R0-F001`,和`RAV-RUN3-R2-F000`。

ID图例: `RUN`是观察到的PR审查运行,`R`是不可变的起源轮次,`F`是问题,`P`是计划。示例为`RAV-RUN3-R2-F001`, `RAV-RUN3-R2-P001`, `RAV-R2-F001`,和`RAV-R2-P001`。
跨轮分配示例: 在可信PR运行3中,ID为`RAV-RUN1-R2-F007`的历史问题保留该ID。新的第1轮问题获得`RAV-RUN3-R1-F001`,并在第2轮重新提出时保留该ID。下一个新的第2轮问题获得`RAV-RUN3-R2-F002`。涵盖这两个当前运行问题的第2轮计划获得`RAV-RUN3-R2-P001`。相同新分配项目的匹配本地/降级分配没有历史遗留:`RAV-R1-F001`, `RAV-R2-F002`,和`RAV-R2-P001`。
遗留的`RAV-RUN1-R2-F007`没有新的内联评论。它仍然在历史、报告、复现和对抗性审查中可用。

问题和计划序数是独立的、运行范围内的计数器,名为
`next_finding_ordinal`和`next_plan_ordinal`。两者都从`001`开始。
计数器不会在每轮重置,也不会重用间隙。分配前,按优先级、规范化路径、行和主题排序问题;按涵盖问题的优先级、领域和主题排序计划。

问题的起源轮次是首次正常审查轮次提出该问题的轮次。计划的起源轮次是首次组装其具体修复组的正常审查轮次。
确认、反驳、优先级变更、推迟处理、修复或重新提出后,起源轮次永远不会改变。
复现和对抗性审查不是轮次。

遗留问题使用`PR REVIEW HISTORY`中提供的确切`id=`值;使用完整的ID不变,不推进当前运行的计数器。对于仅具有`legacy=`的可操作历史条目,使用`legacy=`值作为源别名,并分配下一个规范ID。不要为不可操作的仅遗留条目分配新ID。历史的`RAVF###`, `RAVW###`, `F-###`,和`W-###`形式仅作为迁移/读取边界别名。新问题和计划始终使用上述规则。

分配后,在复现候选、对抗性目标、报告行、计划覆盖范围和后续轮次引用中保持完整ID不变。仅当问题符合新内联条件时,ID重用才会流入内联正文。普通的`open`、`resolved`和`reported`遗留问题在历史、报告、复现和对抗性目标中保留其ID,但不会创建新的内联线程。
已分配的范围内低/nit问题和搁置的问题保留其完整的规范F ID。
真正未分配的范围外后续事项保持独立,不接收F ID。
- 在先前反馈分类和ID分配后构建`REPRODUCTION CANDIDATES`:
- 恰好一个审查者提出的每个`medium`及以上级别问题,
- 每个`medium`及以上级别的删除/死代码/未使用/冗余代码/简化问题,以及任何会删除运行时代码、公共文档/API、兼容性行为或其他高影响范围表面的删除/简化问题,无论审查者数量多少,
- 每个`critical`/`high`级别问题,其证据主要来自代码块推断而非代码/运行时上下文确认,
- 编排器阅读引用文件后对其存在实质性不确定性的每个问题。
- 当`reproduction=auto`或`on`且存在候选问题时,使用`references/reproduction-prompt.md`调度**一个批量复现验证者**。除非批处理太大无法放入一个提示,否则不要为每个问题生成一个验证者。根据并发部分的截止时间规则后台调度 — 绝不要无限制地前台等待。验证者不是另一个广泛的审查轮次;它仅对提供的完整规范问题ID返回`confirmed`、`refuted`、`unclear`、`narrowed`或`downgraded` verdict,并保持每个ID不变。
- 在自动修复/报告前应用复现verdict:
- `confirmed`和`narrowed`问题可能保持可操作性,使用缩小后的措辞(如果提供)。
- `downgraded`问题在更改严重级别后重新进入正常严重级别关卡。
- `refuted`问题从最终问题中删除(或如果对透明度有用,作为单行推迟处理说明)。
- `unclear`问题移至推迟处理,并附带`We set this aside because <plain-language description of the missing proof>.`。重写验证者的原因;不要复制它。
- 由**2个或更多审查者**独立提出且未列为复现候选的问题可以跳过批量复现;共识是信号(这就是去重记录哪些审查者提出了问题的原因)。在采取破坏性行动前,仍需检查足够的代码/上下文以确保修复路径连贯。
- **删除(“删除此代码”/死代码/未使用/冗余)在`per_fix`应用删除时需要复现加执行** — 这是影响范围最大、误报率最高的类别。在`per_fix`模式下,复现确认删除后,应用删除并运行完整测试套件:**红牌意味着保留代码**。绿牌是必要但不充分的(它仅证明*测试覆盖*的行为),因此复现/质疑审查还必须寻找代码必须保留的具体原因,在差异中可见(信任边界、别名副本、顺序、向后兼容性、去重、边缘语义 — 或其他特定契约)。两者覆盖不同的盲点:关卡捕获质疑者无法看到的调用者;质疑者捕获测试未覆盖的行为。仅在**红牌或特定质疑者反驳**时阻止删除 — 不要基于通用的“可能存在未被发现的调用者”(这正是关卡要测试的)。只读模式仅质疑者。阻止 → **推迟处理**(`We set this aside because the code is still needed — <what>`)。
- 如果`reproduction=off`,在轮次摘要和最终报告中说明。必需的复现候选 — 包括单审查者的`medium`及以上级别问题、删除/高风险问题和编排器不确定的问题 — 除非编排器从代码/测试/运行时证据中独立复现,否则无法成为可操作问题;否则移至推迟处理,并附带`We set this aside because the needed check was not run.`。
- `low`/`nit`问题跳过验证:它们低于自动修复关卡,无论如何都会作为建议呈现。

关于复现有帮助的场景和必须避免的场景的规范示例位于`references/reproduction-examples.md`中。更改此规则或复现提示后,运行`scripts/test-reproduction-policy.sh`以及PR辅助测试。

Approving out-of-scope follow-ups

批准范围外后续事项

A pre-existing issue outside the PR's scope can still be worth noting, but it must not become an inline/blocking PR finding. Classify each out-of-scope follow-up:
  • Auto-approved follow-up — create/queue separate work when all are true: severity is
    critical
    /
    high
    (or clearly reproducible
    medium
    ), the bug is confirmed from code/tests/runtime evidence, it is not a product decision/style preference, it is not already tracked in prior PR feedback or explicitly suppressed, and the fix is plausibly separable from the current PR.
  • Needs human triage — mention only as a non-blocking follow-up when the issue is real but severity/ownership/product intent is ambiguous.
  • Do not surface — drop if speculative, low/nit, a product decision, already dismissed/tracked, or only discoverable by reviewing unrelated code paths deeply.
When
report_path
is set, write follow-ups once, after the final round, to
<report_path>.followups.json
— schema in
references/report-artifacts.md
. Automation may file issues only for
auto_approved
entries after duplicate search; presets read the file before posting (the helper deletes it afterwards).
PR范围外的预先存在的问题仍然值得注意,但不得成为内联/阻塞PR问题。对每个范围外后续事项进行分类:
  • 自动批准的后续事项 — 当所有以下条件都满足时,创建/排队单独的工作:严重级别为
    critical
    /
    high
    (或明确可复现的
    medium
    ),错误已从代码/测试/运行时证据中确认,不是产品决策/风格偏好,未在先前PR反馈中跟踪或明确抑制,且修复可与当前PR分离。
  • 需要人工分类 — 当问题真实但严重级别/所有权/产品意图不明确时,仅作为非阻塞后续事项提及。
  • 不呈现 — 如果是推测性的、低/nit级别、产品决策、已被驳回/跟踪,或仅通过深入审查无关代码路径才能发现,则丢弃。
当设置
report_path
时,在最后一轮后将后续事项写入
<report_path>.followups.json
— 模式位于
references/report-artifacts.md
中。自动化工具在重复搜索后仅可为
auto_approved
条目创建问题;预设技能在发布前读取该文件(辅助脚本随后删除它)。

Optional adversarial review (
commit_mode=none
only)

可选对抗性审查(仅
commit_mode=none

When
adversarial
is not
off
, run a bounded post-synthesis gate after dedup/reproduction and before writing the final report artifacts. Read
references/adversarial-prompt.md
before dispatching adversarial reviewers. Dispatch every adversary of the selected mode in parallel — one message, multiple background tool calls, exactly like §2 reviewers, under the Concurrency section's deadline rule — and synthesize verdicts when all return or the deadline fires. Never await one adversary before launching the next.
Adversarial review is not another broad review pass and not a simulated patch application. It attacks the candidate synthesis:
  • Finding validity — false-positive claims, wrong anchors, dismissed findings, out-of-scope issues, over-severity, and missing reachability evidence.
  • Fix proportionality — suggested fixes that would technically address a problem but create more trouble than they solve: harmful blast radius, unnecessary dependencies, bloated abstractions, future tech debt, non-local churn, unsafe deletions, brittle tests, or symptom fixes that miss root cause.
  • Report safety — unsafe one-click GitHub suggestions, unclear fix paths, overconfident approvals, and actionable comments that should be deferred.
Modes:
ModeDispatchIntent
auto
Chosen after synthesisSelects
off
,
challenge
,
targeted
, or
strict
using the default policy below.
challenge
1 adversaryCheap local check over all
medium
+ findings and would-apply plans.
targeted
2 adversariesRecommended PR mode: false-positive/scope auditor + fix-plan breaker. Force a deletion skeptic when any would-apply item removes code.
full
3 adversariesAdds second-order bug hunting across interacting plans, config, migrations, and tests.
strict
Same as
full
Approval-sensitive: any required adversary failure or unresolved
high
+ dispute forces COMMENT.
Role mapping:
  • challenge
    : one combined adversary using the core prompt plus both the
    false-positive-scope-auditor
    and
    fix-plan-breaker
    role additions.
  • targeted
    : two adversaries, one
    false-positive-scope-auditor
    and one
    fix-plan-breaker
    ; add/replace with the deletion skeptic behavior from
    fix-plan-breaker
    when any would-apply plan removes code.
  • full
    /
    strict
    :
    false-positive-scope-auditor
    ,
    fix-plan-breaker
    , and
    second-order-bug-hunter
    ; add
    report-auditor
    only if the report/approval artifact itself is the risky surface.
Default policy:
  • Local
    review-anvil-readonly
    defaults to
    off
    . If the user asks for careful, skeptical, high-confidence, low-noise, or thorough read-only review, the orchestrator should append
    adversarial: auto
    unless the user explicitly asked for a fast/rough pass.
  • review-anvil-pr
    defaults to
    adversarial: auto
    because GitHub output is public reviewer speech and may include inline comments, one-click suggestions, or an approval event.
  • Explicit user input wins:
    adversarial: off
    disables the gate; explicit
    challenge
    /
    targeted
    /
    full
    /
    strict
    uses that mode. In review-only PR runs, explicit
    adversarial: off
    also forces
    .approval.json
    to
    {"event": "COMMENT"}
    ; unchallenged LLM review should not satisfy branch protection by accident.
auto
selection after normal synthesis:
  • First estimate meaningful changed size from the reviewed snapshot. Exclude generated/vendor/build artifacts, lockfiles, and snapshot/fixture churn unless those files are the review's product surface. Treat
    >1000
    meaningful changed lines or
    >20
    meaningful files as large, and
    >5000
    meaningful changed lines,
    >50
    meaningful files, or several interacting subsystems as very large. Size is an escalation floor, not the only signal: a small risky auth or migration diff can still choose
    targeted
    , while a huge mechanical rename may stay below
    full
    after exclusions.
  • Use
    off
    only when approval is disabled/impossible and the result is clean or low/nit-only, has no
    medium
    + inline comments, no GitHub suggestion blocks, no
    critical
    /
    high
    actionable or deferred author-action items, and no would-apply plan with deletion, dependency, non-local behavior, or abstraction/churn risk. For local non-PR runs, ignore the approval condition.
  • Use
    challenge
    for small or self-authored comment-only reviews with material feedback but no suggestion blocks, no high-risk fix plans, and
    approve: never
    /
    REVIEW_ANVIL_NO_APPROVE=1
    .
  • Use
    targeted
    when candidate output includes any
    medium
    + inline comment, any GitHub suggestion block, any
    critical
    /
    high
    actionable/deferred item, any would-apply plan that removes code, adds dependencies, changes behavior non-locally, touches auth/security/data/schema/migrations/concurrency/config, or looks like abstraction/tech-debt risk, or when open/resolved prior PR feedback touches the same files/root causes, or when the diff is large by meaningful changed size.
  • Use
    full
    when the meaningful diff is very large or cross-cutting across several subsystems, unless exclusions show it is mostly mechanical/generated churn.
    full
    adds second-order plan scrutiny without making approval more brittle by itself.
  • Use
    strict
    only when the user explicitly asks for approval-sensitive behavior or branch protection / CODEOWNER requirements are confirmed. If any required adversary fails, times out, or returns unparseable output in
    strict
    , force
    COMMENT
    . Do not escalate to
    strict
    merely because branch protection is unknown; use
    targeted
    and force
    COMMENT
    if approval safety cannot be established.
Build would-apply plans from the same concrete fix groups
per_fix
would have committed. Assign each plan its provenance ID when that fix group is first assembled, before adversarial dispatch; reproduction results may remove or reshape a group, but they never renumber a surviving plan or let another plan reuse its gap. Each plan lists covered finding IDs unchanged, the simulated conventional-commit subject, the intended fix path, risk tags such as
deletion
/
dependency
/
non-local
/
abstraction
, and any exact suggestion blocks that would be emitted. For local non-PR reviews, set
CANDIDATE APPROVAL
to
not-applicable
; for PR/report-path reviews, set it to the tentative
.approval.json
event/reason. Adversarial reviewers return verdicts against those complete unchanged IDs using the schema in
adversarial-prompt.md
.
Apply verdicts conservatively:
  • drop
    only when concrete evidence shows a false positive, dismissed finding, or out-of-scope claim.
  • defer
    when the issue may be real but the proposed fix is harmful, bloated, tech-debt-heavy, too non-local, or disproportionate for this PR.
  • modify
    to harden or simplify the prose fix path while keeping the finding actionable.
  • uphold
    when the finding and fix path survive challenge.
Generic uncertainty does not defer a finding. The adversary must cite code, configuration, tests, runtime behavior, status-aware PR feedback, or PR scope evidence. Adversaries must not create new actionable findings. If they notice a new issue while attacking a plan such as
RAV-RUN3-R2-P001
, record it only as a second-order plan risk or follow-up; it remains Deferred unless the orchestrator runs a separate normal review/verification pass.
Adversarial review may make the output more conservative. It must never make a speculative fix more authoritative. It can strip unsafe
"suggestion"
fields from
.inline.json
, move items to Deferred, harden/simplify fix prose, or downgrade approval. It must not create patches, commits, or final actionable findings from unverified adversarial ideas.
Run at most
adversarial_rounds
passes, capped at 2. A second adversarial pass runs only when the first pass materially changes
medium
+ guidance, changes approval, or rewrites a would-apply plan. Complete
P
target verdicts affect fix plans, suggestions, and fix prose only; linked complete
F
finding IDs change only when an independent verdict against that same finding ID refutes or defers it. With
disagreement_policy=defer
, unresolved
medium
adversarial disputes move the item to Deferred but do not by themselves block
APPROVE
; unresolved
critical
/
high
disputes block
APPROVE
. With
disagreement_policy=comment
, unresolved
medium
+ disputes keep the item actionable but force the review event to
COMMENT
.
adversarial
不是
off
时,在去重/复现后、写入最终报告工件前运行有界的合成后关卡。调度对抗性审查者前阅读
references/adversarial-prompt.md
。并行调度所选模式的每个对抗者 — 一个消息,多个后台工具调用,与§2审查者完全相同,遵循并发部分的截止时间规则 — 并在所有对抗者返回或截止时间触发时综合verdict。绝不要在启动下一个对抗者前等待前一个。
对抗性审查不是另一个广泛的审查轮次,也不是模拟补丁应用。它攻击候选合成结果:
  • 问题有效性 — 误报声明、错误锚点、已驳回的问题、范围外问题、过度严重级别,以及缺失的可达性证据。
  • 修复合理性 — 技术上解决问题但造成更多麻烦的建议修复:有害的影响范围、不必要的依赖、臃肿的抽象、未来的技术债务、非本地变更、不安全的删除、脆弱的测试,或未解决根本原因的症状修复。
  • 报告安全性 — 不安全的一键GitHub建议、不明确的修复路径、过度自信的批准,以及应推迟处理的可操作评论。
模式:
模式调度用途
auto
合成后选择使用以下默认规则选择
off
challenge
targeted
strict
challenge
1个对抗者对所有
medium
及以上级别问题和拟应用计划进行廉价本地检查。
targeted
2个对抗者推荐的PR模式:误报/范围审计员 + 修复计划质疑者。当任何拟应用项目删除代码时,强制添加删除质疑者。
full
3个对抗者添加对交互计划、配置、迁移和测试的二阶错误排查。
strict
full
相同
批准敏感:任何必需的对抗者失败或未解决的
high
及以上争议强制COMMENT。
角色映射:
  • challenge
    :一个组合对抗者,使用核心提示加上
    false-positive-scope-auditor
    fix-plan-breaker
    角色附加内容。
  • targeted
    :两个对抗者,一个
    false-positive-scope-auditor
    和一个
    fix-plan-breaker
    ;当任何拟应用计划删除代码时,添加/替换为
    fix-plan-breaker
    中的删除质疑者行为。
  • full
    /
    strict
    false-positive-scope-auditor
    fix-plan-breaker
    second-order-bug-hunter
    ;仅当报告/批准工件本身是风险表面时,添加
    report-auditor
默认规则:
  • 本地
    review-anvil-readonly
    默认
    off
    。如果用户要求仔细、质疑、高置信度、低噪声或彻底的只读审查,编排器应附加
    adversarial: auto
    ,除非用户明确要求快速/粗略审查。
  • review-anvil-pr
    默认
    adversarial: auto
    ,因为GitHub输出是公开的审查者言论,可能包含内联评论、一键建议或批准事件。
  • 用户明确输入优先:
    adversarial: off
    禁用关卡;明确的
    challenge
    /
    targeted
    /
    full
    /
    strict
    使用该模式。在只读PR运行中,明确的
    adversarial: off
    还会强制
    .approval.json
    {"event": "COMMENT"}
    ;未受质疑的LLM审查不应意外满足分支保护要求。
正常合成后的
auto
选择:
  • 首先从审查的快照估计有意义的变更大小。排除生成/供应商/构建工件、锁文件和快照/fixture变更,除非这些文件是审查的产品表面。将
    >1000
    行有意义变更或
    >20
    个有意义文件视为大变更,将
    >5000
    行有意义变更、
    >50
    个有意义文件或多个交互子系统视为非常大的变更。大小是升级下限,不是唯一信号:小的高风险认证或迁移差异仍可选择
    targeted
    ,而排除后巨大的机械重命名可能仍低于
    full
  • 仅当批准被禁用/不可能且结果干净或仅低/nit级别、没有
    medium
    及以上级别的内联评论、没有GitHub建议块、没有
    critical
    /
    high
    级别的可操作或推迟处理的作者行动项目,且没有拟应用计划涉及删除、依赖、非本地行为或抽象/技术债务风险时,才使用
    off
    。对于本地非PR运行,忽略批准条件。
  • 对于小的或自作者的仅评论审查,有实质性反馈但无建议块、无高风险修复计划,且
    approve: never
    /
    REVIEW_ANVIL_NO_APPROVE=1
    时,使用
    challenge
  • 当候选输出包含任何
    medium
    及以上级别的内联评论、任何GitHub建议块、任何
    critical
    /
    high
    级别的可操作/推迟处理项目、任何拟应用计划涉及删除代码、添加依赖、非本地变更行为、触及认证/安全/数据/架构/迁移/并发/配置,或看起来有抽象/技术债务风险,或开放/已解决的先前PR反馈触及相同文件/根本原因,或差异按有意义变更大小为大变更时,使用
    targeted
  • 当有意义的差异非常大或跨多个子系统时,使用
    full
    ,除非排除后显示主要是机械/生成变更。
    full
    添加二阶计划审查,本身不会使批准更脆弱。
  • 仅当用户明确要求批准敏感行为或确认分支保护/CODEOWNER要求时,使用
    strict
    。如果
    strict
    模式下任何必需的对抗者失败、超时或返回无法解析的输出,则强制
    COMMENT
    。不要仅因为分支保护未知就升级到
    strict
    ;使用
    targeted
    ,如果无法确定批准安全性,则强制
    COMMENT
per_fix
会提交的相同具体修复组构建拟应用计划。在对抗性调度前,首次组装该修复组时为每个计划分配来源ID;复现结果可能删除或重塑组,但绝不会重新编号幸存的计划或让另一个计划重用其间隙。每个计划列出未更改的涵盖问题ID、模拟的常规提交主题、预期修复路径、风险标签如
deletion
/
dependency
/
non-local
/
abstraction
,以及任何会发出的确切建议块。对于本地非PR审查,将
CANDIDATE APPROVAL
设置为
not-applicable
;对于PR/报告路径审查,将其设置为暂定的
.approval.json
事件/原因。对抗性审查者使用
adversarial-prompt.md
中的模式针对这些完整未更改的ID返回verdict。
保守应用verdict:
  • 仅当具体证据显示错误阳性、已驳回的问题或范围外声明时,才
    drop
  • 当问题可能真实但建议修复有害、臃肿、技术债务沉重、过于非本地或与PR不成比例时,
    defer
  • modify
    以强化或简化 prose 修复路径,同时保持问题的可操作性。
  • 当问题和修复路径经受住挑战时,
    uphold
通用不确定性不会推迟问题。对抗者必须引用代码、配置、测试、运行时行为、状态感知的PR反馈或PR范围证据。对抗者不得创建新的可操作问题。如果他们在攻击计划(如
RAV-RUN3-R2-P001
)时注意到新问题,仅将其记录为二阶计划风险或后续事项;除非编排器运行单独的正常审查/验证轮次,否则它仍处于推迟处理状态。
对抗性审查可能使输出更保守。绝不能使推测性修复更具权威性。它可以从
.inline.json
中删除不安全的
"suggestion"
字段、将项目移至推迟处理、强化/简化修复 prose,或降级批准。绝不能从未经验证的对抗性想法创建补丁、提交或最终可操作问题。
最多运行
adversarial_rounds
次审查,上限为2。仅当第一次审查实质性改变
medium
及以上级别的指导意见、更改批准或重写拟应用计划时,才进行第二次对抗性审查。完整的
P
目标verdict仅影响修复计划、建议和修复 prose;链接的完整
F
问题ID仅当针对同一问题ID的独立verdict反驳或推迟处理时才会改变。使用
disagreement_policy=defer
时,未解决的
medium
级别对抗性争议会将项目移至推迟处理,但本身不会阻止
APPROVE
;未解决的
critical
/
high
级别争议会阻止
APPROVE
。使用
disagreement_policy=comment
时,未解决的
medium
及以上级别争议会保持项目的可操作性,但强制审查事件为
COMMENT

4. Apply fixes

4. 应用修复

Skip entirely when
commit_mode=none
(the policy below is still evaluated in the abstract for the report).
Otherwise read
references/fix-application.md
before making any edit
: it defines the conventional-commit fix-group style, the auto-fix proportionality rules (severity gate >=
min_fix_severity
; no new dependencies without
allow_new_deps
; per-round size cap; noise is deferred with a reason, never silently dropped), and the build/test gate (
verify_cmd
resolution, baseline run, fix-forward-or-revert, revert-failure escalation). The invariant: a round never ends with the build/test gate newly red.
commit_mode=none
时完全跳过
(下文规则仍会抽象评估用于报告)。
否则,在进行任何编辑前阅读
references/fix-application.md
:它定义了常规提交修复组风格、自动修复合理性规则(严重级别关卡≥
min_fix_severity
;无
allow_new_deps
时不添加新依赖;每轮大小上限;噪声会附带原因推迟处理,绝不静默丢弃),以及构建/测试关卡(
verify_cmd
解析、基线运行、修复前进或回退、回退失败升级)。不变量:轮次永远不会以构建/测试关卡新变红结束

5. Round summary

5. 轮次摘要

Append to running output:
undefined
追加到运行输出:
undefined

Round N — <convergence flag>

第N轮 — <收敛标志>

  • Parameters: rounds=3, max_rounds=3, target=acme/widgets#42 [pin], commit_mode=none [pin], focus=4-pillar
  • Reviewers: <list dispatched>
  • Earlier review comments: none | <open> open, <resolved> closed, <reported> summary-only, <author-resolved> author-resolved (skipped), <suppressed> skipped; <still-present>/<fixed>/<stale> after checking
  • What I noticed: C critical, H high, M medium, L low, N nit
  • Fixes applied: K commits (<sha1>..<shaN>) # or "0 (review-only)"
  • Verification: <cmd> — passed | failed → round reverted | pre-existing failures (no new) | none detected | skipped # per_fix only
  • Checks: off | skipped (no findings needed checking) | <C> concerns checked, <confirmed> confirmed, <refuted> ruled out, <deferred> set aside, <downgraded> lowered in priority; <elapsed>
  • Things to try: W items # commit_mode=none only
  • Second check: off | <mode>, <A> reviewers, <upheld> kept, <hardened> clarified, <deferred> set aside, <dropped> removed
  • Other notes: S items (low-priority items; not applied)
  • Set aside: D items (reasons: noise / new dependency / size cap / not confirmed / failed verification / product decision)
  • More rounds: off | not continued because <reason> | continued to round <next_round> because <reason>; cap=<max_rounds>

Pinned params carry `[pin]` (authority comes from preset argument order; the PR-target/per_fix rule is the final safety net). Convergence flag: `clean` (no findings), `nits_only` (nothing above `low`), `material_findings` (≥1 medium+).
  • 参数: rounds=3, max_rounds=3, target=acme/widgets#42 [固定], commit_mode=none [固定], focus=四大核心维度
  • 审查者: <调度的列表>
  • 先前审查评论: 无 | <open>个开放, <resolved>个关闭, <reported>个仅摘要, <author-resolved>个作者解决(跳过), <suppressed>个跳过; 检查后<still-present>/<fixed>/<stale>
  • 发现的问题: C个critical, H个high, M个medium, L个low, N个nit
  • 应用的修复: K次提交(<sha1>..<shaN>) # 或 "0 (仅审查)"
  • 验证: <cmd> — 通过 | 失败 → 轮次回退 | 预先存在的失败(无新失败) | 未检测到 | 跳过 # 仅per_fix模式
  • 检查: 关闭 | 跳过(无需要检查的问题) | <C>个问题已检查, <confirmed>个确认, <refuted>个排除, <deferred>个搁置, <downgraded>个优先级降低; <耗时>
  • 建议事项: W个项目 # 仅commit_mode=none模式
  • 二次检查: 关闭 | <模式>, <A>个审查者, <upheld>个保留, <hardened>个澄清, <deferred>个搁置, <dropped>个删除
  • 其他说明: S个项目(低优先级项目;未应用)
  • 搁置: D个项目(原因: 噪声 / 新依赖 / 大小上限 / 未确认 / 验证失败 / 产品决策)
  • 更多轮次: 关闭 | 未继续,原因<原因> | 继续到第<next_round>轮,原因<原因>; 上限=<max_rounds>

固定参数带有`[固定]`(权威性来自预设参数顺序;PR目标/per_fix规则是最终安全网)。收敛标志: `clean`(无问题)、`nits_only`(无高于`low`的问题)、`material_findings`(≥1个medium+问题)。

6. Continue or finish

6. 继续或结束

If completed rounds are still below
rounds
, start the next requested round; round N+1 reviews the new state including round N's commits.
Early exit on convergence (
per_fix
only).
A
clean
or
nits_only
round ends the loop even if requested or adaptive rounds remain — further rounds re-review converged code and mostly produce noise. Note this in Run Details, e.g.
Rounds: N completed (R requested + A adaptive, max M); converged after round N of R requested
. (In
commit_mode=none
, multi-round = reviewer redundancy over the same baseline; no early exit and no adaptive continuation.)
Adaptive continuation (
per_fix
only).
After the requested
rounds
are complete, the orchestrator may start one more round only while
completed_rounds < max_rounds
and all continuation criteria hold:
  • The latest round was
    material_findings
    and produced at least one new material finding. New = not raised in any earlier round, or a reproduction-confirmed re-detection of a finding a previous round fixed and verified (evidence the fix failed — the core case continuation exists for). Unconfirmed or refuted re-detections and items already Deferred do not count.
  • The latest round applied at least one verified fix commit, or changed a risky/shared surface where another pass is likely to catch second-order bugs.
  • Verification for the latest round ended
    passed
    ;
    skipped
    ,
    none detected
    ,
    pre-existing failures (no new)
    , and
    failed → round reverted
    are acceptable for requested rounds but not strong enough to justify extra automatic work.
  • All expected reviewers succeeded with parseable output. Degraded reviewer signal can finish requested rounds, but it must not trigger adaptive rounds. During an adaptive round, this is a hard gate before §4: any reviewer failure, timeout, empty output, or unparseable findings block stops the run before applying fixes from that adaptive round, writes a failure report when
    report_path
    is set, and prevents improve-PR pushes.
  • The remaining risk is likely to converge with another review/fix pass. Do not extend for low/nit-only feedback, suggestions below
    min_fix_severity
    , items already Deferred, product decisions, new-dependency deferrals, size-cap deferrals, or repeated findings that were not fixed.
Record the continuation decision in the final requested round's summary and in the adaptive round summary when one runs. If an adaptive round still has
material_findings
and hits
max_rounds
, finish and use the tuning suggestion rule; do not keep extending without a larger explicit cap.
After the final round, emit the Final Report (Output Format). If
report_path
is set:
  1. Write the rendered PR report there (creating parent dirs).
  2. Write a sibling
    <report_path>.inline.json
    : an array of GitHub PR review comment payloads for findings with both
    file
    and
    line
    json
    [
      {"path": "src/auth.ts", "line": 50, "side": "RIGHT", "severity": "high", "body": "**Refresh creates a session before CSRF validation**\n\nThe handler rotates the session before it checks the state token. A stale tab can create a new session with an invalid token.\n\n**What to change**\n\n- Check the state token before rotating the session.\n- Reject invalid tokens without creating sessions.\n- Add a missing-state-token test.\n\n<!-- review-anvil: id=RAV-RUN3-R2-F001 severity=high area=auth -->"},
      {"path": "src/db.ts", "start_line": 100, "line": 110, "side": "RIGHT", "start_side": "RIGHT", "severity": "medium", "body": "**Retry accounting records success before the write succeeds**\n\nThe retry block increments `attempts_succeeded` before `insert_event` returns. A timeout records success even when no row was written.\n\n**What to change**\n\n- Increment `attempts_succeeded` only after `insert_event` returns.\n- Keep timed-out attempts eligible for retry.\n- Add a timeout test.\n\n<!-- review-anvil: id=RAV-RUN3-R2-F002 severity=medium area=db -->", "suggestion": "result = insert_event(payload)\nattempts_succeeded += 1\nreturn result"}
    ]
    Single line →
    {"line": N, "side": "RIGHT"}
    ; range
    <N>-<M>
    {"start_line": N, "line": M, "side": "RIGHT", "start_side": "RIGHT"}
    . Findings without anchors stay in the markdown body only; no anchored findings →
    []
    . Start each identified inline body with the natural bold title
    **<finding>**
    . End it with exactly one
    <!-- review-anvil: id=<complete-id> severity=<severity> area=<area> -->
    marker on its own final line. The marker area is the same machine-safe area token used by the report row: letters, digits,
    .
    ,
    _
    ,
    /
    , or single
    -
    separators. No visible ID, severity tag, or area label belongs in the title. A reader must be able to create the fix from each visible
    body
    alone.
    Include helper-only
    "severity"
    for every inline item. The posting helper strips it before calling GitHub and uses it to keep low/nit findings summary-only by default. Include helper-only
    "suggestion"
    only when the fix is an exact replacement for the commented line/range; the helper turns it into a GitHub suggestion fenced block, inserts that block before the final finding-metadata marker, and strips the extra key before posting. Preserve an exact source suggestion only when it satisfies every safety exclusion in the next sentence and still matches the verified anchor and replacement. Do not include suggestions for design fixes, cross-file edits, deleted lines, anything that requires judgment, or any suggestion whose anchor/replacement/blast-radius was disputed by adversarial review.
    The helper-only
    "severity"
    must match the terminal marker severity exactly; the helper aborts before filtering or posting when they disagree. A present but unrecognized helper severity also aborts; an absent helper field may use the terminal marker during migration.
    For an explicitly reintroduced
    author-resolved
    finding, place
    <!-- review-anvil: prior_feedback=reintroduced -->
    immediately after its visible final-report finding row or bullet. Its matching inline item must carry helper-only
    "prior_feedback": "reintroduced"
    ; the posting helper uses it before author-resolved suppression, strips the JSON field before the GitHub REST request, and inserts the hidden prior-feedback marker before the final finding-metadata marker so later history retains the disposition.
    Each eligible new
    body
    puts the same complete finding ID as its report row, reproduction target, and adversarial target inside the final finding-metadata marker, then follows the inline-comment voice in
    references/report-artifacts.md
    — read it before composing bodies. Keep it short and plain: say what the code does, what happens because of it, and every source-backed requested obligation. Treat remediation as a request, not as code already present. Group work by cohesive implementation obligation, not by grammar; do not split values governed by one rule. Only work the author must perform belongs under
    **What to change**
    . Keep each permission, exception, carve-out, or already-correct behavior with the action it limits or in short modal prose immediately after that action. Keep exact source scope wording. Treat a required source-backed test as author work. For one
    critical
    /
    high
    /
    medium
    obligation, use one concise
    Please
    sentence. For two or more independently implementable obligations, use
    **What to change**
    and one direct-action bullet per obligation. A reader must be able to act without reopening the diff. Include a safe exact
    "suggestion"
    or a short code sketch only when it removes doubt. The finding-metadata marker is the last nonblank line: no prose, suggestion fence, or prior-feedback marker may follow it. By default, inline comments are for
    critical
    /
    high
    /
    medium
    anchored findings;
    low
    /
    nit
    findings remain in the top-level summary unless the user or environment lowers
    REVIEW_ANVIL_INLINE_MIN_SEVERITY
    . Ordinary prior-feedback carry-forwards do not produce new inline payloads.
    Classify every source predicate before rendering it. Target behavior and required verification or documentation are author work. Accepted current behavior, allowed implementation boundaries, and explicitly optional follow-ups are no-change boundaries. Source intent outranks modal grammar:
    can
    ,
    could
    , and
    would
    do not make target behavior optional.
    Apply the omission counterfactual only after that classification. Split every source sentence that mixes author work with a no-change boundary into predicates for classification; do not keep an unsplit fallback. If leaving the current code without a target behavior, test, or document change leaves the defect, safety boundary, or reviewer-required verification unresolved, treat that predicate as author work.
    A no-change boundary is not a separate obligation. When accepted current behavior directly constrains a requested change, keep it in the same sentence using
    without changing …
    or
    while keeping … unchanged
    ; do not create a separate action bullet for it. If that sentence would be dense, use short modal prose immediately after the action. Preserve other accepted current behavior or an explicitly optional follow-up as standalone modal prose. Request the smallest new mechanism needed to resolve the failure, but keep each required purpose, result, or safety clause with the action it constrains. Treat source-backed verification or documentation stated to cover, demonstrate, clarify, or make a required boundary clear as author work unless it is explicitly optional. Do not convert acceptable unchanged behavior, an allowed implementation boundary, or an explicitly optional follow-up into mandatory work.
    Before drafting, freeze the exact requested-work prose, the minimum source context needed to resolve antecedents and current-versus-target behavior, and the exact evidence and code fragments that the body may retain from each accepted synthesized finding. Run two independent post-render action-lock auditors from
    references/action-lock-audit.md
    in one parallel wave before writing inline JSON. Give each clean verifier only that frozen source material and each exact complete rendered inline body; do not send unrelated repository or report context. For a passed rewrite, write only the byte-identical audited body to
    .inline.json
    ; any later body edit invalidates the verdict and requires a new audit wave. The exact-source fallback in the next step is exempt and forces COMMENT.
    Validate each auditor's complete per-ID output and combine valid failures from either auditor. Repair only inline bodies with a valid failed verdict, then run two new clean auditors once more. For a first-audit row that is missing, duplicate, malformed, timed out, or otherwise unverifiable, restore the exact source requested-work prose without attempting a repair and force the review event to COMMENT. If either second-audit verdict still fails or is unverifiable, use the same exact-source fallback and COMMENT event. Never omit the finding or a requested predicate to make the audit pass.
  3. Write a sibling
    <report_path>.approval.json
    so the PR-posting helper can choose the GitHub review event (review-only PR runs; for other runs write
    {"event": "COMMENT"}
    or omit the file — the helper defaults to COMMENT):
    json
    {
      "event": "APPROVE | COMMENT",
      "head_sha": "<the HEAD_SHA the preset captured at init/verify-checkout>",
      "adversarial_mode": "off | auto | challenge | targeted | full | strict",
      "approval_allowed": true,
      "reason": "No high/critical in-scope findings; medium-and-lower items are left to the author."
    }
    Include
    "head_sha"
    — the
    HEAD_SHA
    the preset captured at init/verify-checkout time — so the posting helper can verify the approval still matches the reviewed state (it downgrades to COMMENT if the PR head moved mid-run). Include
    "adversarial_mode"
    and set
    "approval_allowed": false
    when approval must be mechanically disabled, including explicit
    adversarial: off
    in a PR run or any run where an action-lock exact-source fallback has been used.
    Use
    APPROVE
    for review-only PR runs when all of these hold:
    approve
    is not
    never
    , at least one reviewer succeeded, no action-lock exact-source fallback has been used, there are no
    critical
    /
    high
    actionable in-scope findings, no
    critical
    /
    high
    in-scope deferred finding needs author action, no prior
    critical
    /
    high
    open or resolved-but-still-present item remains unaddressed, no unresolved
    critical
    /
    high
    adversarial dispute remains, and remaining items are only
    medium
    /
    low
    /
    nit
    findings, suggestions, deferred notes, or out-of-scope follow-ups. Medium-and-lower in-scope findings should still be posted clearly, but the review event is approval: leave those fixes to the author. Use
    COMMENT
    otherwise. Out-of-scope follow-ups do not block approval.
  4. Print the report path as the last output line; the
    .inline.json
    and
    .approval.json
    files are implied by convention.
  5. For out-of-scope follow-ups, write the sibling
    <report_path>.followups.json
    once, after the final round, using the follow-ups schema from §3 "Approving out-of-scope follow-ups" (NOT the
    .approval.json
    schema above). The posting helper deletes it after a successful post, so any consumer (surfacing follow-ups to the user, filing issues for
    auto_approved
    entries after duplicate search) must read it before the post/post-update step — the presets do this.
如果已完成轮次仍低于
rounds
,开始下一个请求轮次;第N+1轮审查包含第N轮提交的新状态。
提前退出收敛(仅
per_fix
模式)
clean
nits_only
轮次即使仍有请求或自适应轮次,也会结束循环 — 进一步轮次会重新审查收敛的代码,主要产生噪声。在运行详情中说明,例如
轮次: 已完成N轮(请求R轮 + 自适应A轮,上限M); 在请求R轮的第N轮后收敛
。(在
commit_mode=none
模式下,多轮 = 同一基线的审查者冗余;无提前退出和自适应延续。)
自适应延续(仅
per_fix
模式)
。完成请求的
rounds
轮次后,仅当
completed_rounds < max_rounds
且所有延续标准都满足时,编排器才可以开始另一轮:
  • 最新一轮是
    material_findings
    ,且产生了至少一个新的重要问题。新问题 = 未在任何先前轮次提出,或复现确认重新检测到先前轮次修复并验证的问题(证据表明修复失败 — 延续存在的核心情况)。未确认或反驳的重新检测和已推迟处理的项目不计入。
  • 最新一轮应用了至少一个已验证的修复提交,或更改了高风险/共享表面,另一轮可能会发现二阶错误。
  • 最新一轮的验证以
    通过
    结束;
    跳过
    未检测到
    预先存在的失败(无新失败)
    失败 → 轮次回退
    对于请求轮次是可接受的,但不足以证明额外自动工作的合理性。
  • 所有预期审查者都成功返回可解析的输出。降级的审查者信号可以完成请求轮次,但不得触发自适应轮次。在自适应轮次中,这是§4之前的硬关卡:任何审查者失败、超时、空输出或无法解析的问题块都会在应用该自适应轮次的修复前停止运行,当设置
    report_path
    时写入失败报告,并阻止improve-PR推送。
  • 剩余风险可能通过另一轮审查/修复收敛。不要因仅低/nit级别反馈、低于
    min_fix_severity
    的建议、已推迟处理的项目、产品决策、新依赖推迟处理、大小上限推迟处理或未修复的重复问题而延长。
在最后一个请求轮次的摘要和自适应轮次摘要(如果运行)中记录延续决策。如果自适应轮次仍有
material_findings
且达到
max_rounds
,则结束并使用调优建议规则;不要在没有更大明确上限的情况下继续延长。
最后一轮后,发出最终报告(输出格式)。如果设置
report_path
  1. 将渲染的PR报告写入该路径(创建父目录)。
  2. 写入同级文件
    <report_path>.inline.json
    :GitHub PR审查评论负载数组,对应同时具有
    file
    line
    的问题 —
    json
    [
      {"path": "src/auth.ts", "line": 50, "side": "RIGHT", "severity": "high", "body": "**刷新在CSRF验证前创建会话**\n\n处理器在检查状态令牌前轮换会话。过时的标签可以使用无效令牌创建新会话。\n\n**修改建议**\n\n- 在轮换会话前检查状态令牌。\n- 拒绝无效令牌,不创建会话。\n- 添加缺失状态令牌的测试。\n\n<!-- review-anvil: id=RAV-RUN3-R2-F001 severity=high area=auth -->"},
      {"path": "src/db.ts", "start_line": 100, "line": 110, "side": "RIGHT", "start_side": "RIGHT", "severity": "medium", "body": "**重试统计在写入成功前记录成功**\n\n重试块在`insert_event`返回前递增`attempts_succeeded`。超时会记录成功,即使未写入任何行。\n\n**修改建议**\n\n- 仅在`insert_event`返回后递增`attempts_succeeded`。\n- 保持超时尝试有资格重试。\n- 添加超时测试。\n\n<!-- review-anvil: id=RAV-RUN3-R2-F002 severity=medium area=db -->", "suggestion": "result = insert_event(payload)\nattempts_succeeded += 1\nreturn result"}
    ]
    单行 →
    {"line": N, "side": "RIGHT"}
    ;范围
    <N>-<M>
    {"start_line": N, "line": M, "side": "RIGHT", "start_side": "RIGHT"}
    。无锚点的问题仅保留在markdown正文中;无锚点问题 →
    []
    。每个已识别的内联正文以自然粗体标题
    **<问题>**
    开头。最后一行必须包含恰好一个
    <!-- review-anvil: id=<完整ID> severity=<严重级别> area=<领域> -->
    标记。标记领域与报告行使用的机器安全领域令牌相同:字母、数字、
    .
    _
    /
    或单个
    -
    分隔符。标题中不得包含可见的ID、严重级别标签或领域标签。读者必须能够仅从可见的
    body
    创建修复。
    为每个内联项包含仅辅助工具使用的
    "severity"
    。发布辅助脚本在调用GitHub前会剥离它,并使用它默认将低/nit级别问题保留为仅摘要。仅当修复是注释行/范围的确切替换时,才包含仅辅助工具使用的
    "suggestion"
    ;辅助脚本会将其转换为GitHub建议围栏块,插入到最终问题元数据标记之前,并在发布前剥离额外的键。仅当满足下一句中的所有安全排除且仍与已验证的锚点和替换匹配时,才保留确切的源建议。不要为设计修复、跨文件编辑、删除行、任何需要判断的内容,或任何锚点/替换/影响范围受到对抗性审查争议的建议包含建议。
    仅辅助工具使用的
    "severity"
    必须与终端标记的严重级别完全匹配;如果它们不一致,辅助脚本会在过滤或发布前中止。存在但无法识别的辅助工具严重级别也会中止;迁移期间可能使用终端标记替代缺失的辅助工具字段。
    对于明确重新引入的
    author-resolved
    问题,在其可见的最终报告问题行或项目符号后立即放置
    <!-- review-anvil: prior_feedback=reintroduced -->
    。其匹配的内联项必须携带仅辅助工具使用的
    "prior_feedback": "reintroduced"
    ;发布辅助脚本会在作者解决抑制前使用它,在GitHub REST请求前剥离JSON字段,并在最终问题元数据标记之前插入隐藏的先前反馈标记,以便后续历史保留处理结果。
    每个符合条件的新
    body
    将与报告行、复现目标和对抗性目标相同的完整问题ID放入最终问题元数据标记中,然后遵循
    references/report-artifacts.md
    中的内联评论语气 — 撰写正文前阅读。保持简短明了:说明代码的行为、由此产生的后果,以及每个源支持的要求义务。将修复视为请求,而非已存在的代码。按内聚的实现义务分组工作,而非按语法;不要拆分受同一规则约束的值。只有作者必须执行的工作才属于
    **修改建议**
    下。将每个权限、例外、豁免或已正确的行为与它限制的操作放在一起,或在该操作后立即使用简短的模态 prose。保留确切的源范围措辞。将源支持的必需测试视为作者工作。对于一个
    critical
    /
    high
    /
    medium
    义务,使用一个简洁的“请”句子。对于两个或更多独立可实现的义务,使用
    **修改建议**
    和每个义务一个直接行动项目符号。读者必须能够无需重新打开差异即可采取行动。仅当消除疑问时,才包含安全的确切
    "suggestion"
    或简短代码草图。问题元数据标记是最后一个非空行:不得有 prose、建议围栏或先前反馈标记跟随它。默认情况下,内联评论用于
    critical
    /
    high
    /
    medium
    级别的锚点问题;
    low
    /
    nit
    级别问题保留在顶级摘要中,除非用户或环境降低
    REVIEW_ANVIL_INLINE_MIN_SEVERITY
    。普通的先前反馈遗留问题不会产生新的内联负载。
    渲染前对每个源谓词进行分类。目标行为和必需的验证或文档是作者工作。接受的当前行为、允许的实现边界和明确可选的后续事项是无变更边界。源意图优于模态语法:
    can
    could
    would
    不会使目标行为可选。
    仅在分类后应用省略反事实。将每个混合作者工作与无变更边界的源句子拆分为谓词进行分类;不要保留未拆分的回退。如果保留当前代码而不进行目标行为、测试或文档变更会留下缺陷、安全边界或审查者要求的验证未解决,则将该谓词视为作者工作。
    无变更边界不是单独的义务。当接受的当前行为直接约束请求的变更时,使用“不更改……”或“保持……不变”将其保留在同一句子中;不要为其创建单独的行动项目符号。如果该句子会很密集,则在行动后立即使用简短的模态 prose。将其他接受的当前行为或明确可选的后续事项保留为独立的模态 prose。请求解决失败所需的最小新机制,但将每个必需的目的、结果或安全条款与它约束的行动放在一起。将源支持的验证或文档(旨在覆盖、演示、澄清或明确必需边界)视为作者工作,除非明确可选。不要将可接受的不变行为、允许的实现边界或明确可选的后续事项转换为强制性工作。
    起草前,冻结确切的请求工作 prose、解决先行词和当前与目标行为所需的最小源上下文,以及每个接受的合成问题中正文可能保留的确切证据和代码片段。写入内联JSON前,从
    references/action-lock-audit.md
    运行两个独立的渲染后行动锁定审计器,并行运行。为每个干净的验证者仅提供该冻结的源材料和每个确切的完整渲染内联正文;不要发送无关的仓库或报告上下文。对于通过重写的,仅将字节相同的审计正文写入
    .inline.json
    ;任何后续正文编辑都会使verdict无效,并需要新的审计浪潮。下一步中的精确源回退豁免,并强制COMMENT。
    验证每个审计器的完整每ID输出,并合并任一审计器的有效失败。仅修复具有有效失败verdict的内联正文,然后再次运行两个新的干净审计器。对于第一次审计中缺失、重复、格式错误、超时或无法验证的行,恢复确切的源请求工作 prose,不尝试修复,并强制审查事件为COMMENT。如果第二次审计的verdict仍然失败或无法验证,使用相同的精确源回退和COMMENT事件。绝不要省略问题或请求的谓词以使审计通过。
  3. 写入同级文件
    <report_path>.approval.json
    ,以便PR发布辅助脚本选择GitHub审查事件(仅适用于只读PR运行;其他运行写入
    {"event": "COMMENT"}
    或省略该文件 — 辅助脚本默认COMMENT):
    json
    {
      "event": "APPROVE | COMMENT",
      "head_sha": "<预设在初始化/verify-checkout时捕获的HEAD_SHA>",
      "adversarial_mode": "off | auto | challenge | targeted | full | strict",
      "approval_allowed": true,
      "reason": "无范围内的高/严重问题;中及以下级别问题留给作者处理。"
    }
    包含
    "head_sha"
    — 预设在初始化/verify-checkout时捕获的
    HEAD_SHA
    — 以便发布辅助脚本验证批准是否仍与审查的状态匹配(如果PR头部在运行中移动,会降级为COMMENT)。当必须机械禁用批准时,包含
    "adversarial_mode"
    并设置
    "approval_allowed": false
    ,包括PR运行中明确的
    adversarial: off
    或任何使用行动锁定精确源回退的运行。
    仅当以下所有条件都满足时,对只读PR运行使用
    APPROVE
    approve
    不是
    never
    ,至少一个审查者成功,未使用行动锁定精确源回退,无
    critical
    /
    high
    级别的可操作范围内问题,无
    critical
    /
    high
    级别的范围内推迟处理问题需要作者行动,无先前的
    critical
    /
    high
    级别的开放或已解决但仍存在的项目未解决,无未解决的
    critical
    /
    high
    级别的对抗性争议,剩余项目仅为
    medium
    /
    low
    /
    nit
    级别问题、建议、推迟处理说明或范围外后续事项。中及以下级别的范围内问题仍应清晰发布,但审查事件为批准:将这些修复留给作者处理。否则使用
    COMMENT
    。范围外后续事项不阻止批准。
  4. 将报告路径作为最后一行输出;
    .inline.json
    .approval.json
    文件由约定隐含。
  5. 对于范围外后续事项,在最后一轮后写入同级文件
    <report_path>.followups.json
    ,使用§3“批准范围外后续事项”中的后续事项模式(不是上述的
    .approval.json
    模式)。发布辅助脚本在成功发布后删除它,因此任何消费者(向用户呈现后续事项、重复搜索后为
    auto_approved
    条目创建问题)必须在发布/发布更新步骤前读取它 — 预设技能会这样做。

Failure handling

故障处理

  • A reviewer fails or times out in a requested round → log
    <agent>: failed (<reason>)
    in the round summary and proceed; no retries except the protocol-only case below. For Bash-dispatched reviewers, failure = wrapper STATUS
    timeout
    /
    empty
    /
    failed
    , reason = tail of
    .err
    ;
    protocol
    follows the next rule. In an adaptive round, any reviewer failure is an abort before fixes from that round are applied.
  • Protocol-only corrective retry: a non-empty response that asks for confirmation, emits only a plan/status update, or otherwise omits the complete fenced findings block is not review output. Bash reviewers surface this as
    STATUS=protocol
    ; detect the same shape directly for Agent-tool reviewers. Re-dispatch that reviewer exactly once on the same snapshot and lens with this prefix:
    PROTOCOL RETRY: Begin the already-authorized read-only review immediately. Do not ask for confirmation or present a plan. Return the completed review now and end with the required fenced findings block.
    Do not answer the confirmation request and do not count the first attempt as a reviewer result. If the retry also violates the protocol, record the reviewer as failed (
    confirmation/plan-only output after corrective retry
    ) and follow the normal requested/adaptive-round failure rules. This is the only content-level retry; do not retry weak, clean, or merely unstructured reviews.
  • A dispatch call — foreground or background — that dies with exit 143 or ends with no
    STATUS=
    line
    in its output was killed by the host tool's timeout before the wrapper could classify — misconfigured dispatch (see §2 "Host tool timeouts"), not a reviewer failure. Fix the dispatch mode (raise the tool timeout or go detached) and re-dispatch that reviewer exactly once; only a second identical death counts as a failed reviewer.
  • All reviewers fail → abort the loop and report. Never carry on with zero findings — that's a misleading clean signal.
  • git commit
    fails (hook, conflict) → surface the error, stop the loop, leave partial fixes in the worktree. Never
    --no-verify
    , never amend earlier commits.
  • On any abort, if
    report_path
    is set, write a failure report to it before stopping
    — the usual header block, a
    ## Failure
    section stating what happened and at which round, plus any completed round summaries. Downstream consumers (
    review-anvil-improve-pr
    's post-update step) depend on the file existing on every exit path, success or failure. Write
    {"event": "COMMENT"}
    to
    .approval.json
    in this case.
  • 请求轮次中审查者失败或超时 → 在轮次摘要中记录
    <agent>: failed (<reason>)
    并继续;除下文的仅协议情况外不重试。对于Bash调度的审查者,失败 = 包装器STATUS
    timeout
    /
    empty
    /
    failed
    ,原因 =
    .err
    的末尾;
    protocol
    遵循下一条规则。在自适应轮次中,任何审查者失败都会在应用该轮次的修复前中止。
  • 仅协议纠正重试:非空响应要求确认、仅发出计划/状态更新,或未以完整的围栏式问题块结尾,不属于审查输出。Bash审查者将其显示为
    STATUS=protocol
    ;直接检测Agent工具审查者的相同形状。使用以下前缀在相同快照和视角下重新调度该审查者恰好一次
    PROTOCOL RETRY: Begin the already-authorized read-only review immediately. Do not ask for confirmation or present a plan. Return the completed review now and end with the required fenced findings block.
    不要回答确认请求,不要将第一次尝试视为审查者结果。如果重试也违反协议,则将审查者记录为失败(
    confirmation/plan-only output after corrective retry
    )并遵循正常的请求/自适应轮次故障规则。这是唯一的内容级重试;不要重试弱、干净或仅非结构化的审查。
  • 前台或后台调度调用以退出码143终止,或输出中
    STATUS=
    ,是在包装器分类前被宿主工具的超时杀死 — 调度配置错误(见§2“宿主工具超时”),而非审查者失败。修复调度模式(提高工具超时或分离调度)并重新调度该审查者恰好一次;只有第二次相同的终止才视为审查者失败。
  • 所有审查者失败 → 中止循环并报告。绝不要在无问题的情况下继续 — 这是误导性的干净信号。
  • git commit
    失败(钩子、冲突) → 显示错误,停止循环,将部分修复留在工作树中。绝不要使用
    --no-verify
    ,绝不要修改先前的提交。
  • 任何中止时,如果设置
    report_path
    ,在停止前向其写入失败报告
    — 通常的标题块、
    ## 故障
    部分说明发生了什么以及在哪一轮,加上任何已完成的轮次摘要。下游消费者(
    review-anvil-improve-pr
    的发布更新步骤)依赖于文件在每个退出路径(成功或失败)都存在。在这种情况下向
    .approval.json
    写入
    {"event": "COMMENT"}

Concurrency

并发

Within a round: parallel (single multi-tool-call message). Between rounds: strictly sequential.
Synthesis-side dispatches — the batched reproduction verifier, every adversary, and each two-auditor action-lock wave — follow the same parallel rule (all agents of a pass launched backgrounded in one message, never serially awaited) and get a hard deadline equal to the effective
reviewer_timeout
(after any >5000-line doubling):
  • Bash dispatches enforce the deadline mechanically: run them under
    run-reviewer.sh
    with that cap.
  • Agent-tool dispatches have no built-in timeout — the source of a production run hanging forever at "awaiting verdicts". Give each dispatch wave exactly one one-shot deadline alarm: a single background
    sleep <cap>
    Bash task launched in the same message as the agents, killed as soon as they all return. When the alarm fires first, salvage every complete per-ID verdict already present in output files and apply the safe failure for anything missing: reproduction verifier failure → Deferred; adversary failure → continue and note; action-lock failure → restore exact source requested-work prose for every unverifiable row and force COMMENT;
    strict
    → COMMENT. Record
    timed out at <cap>s
    in Run Details.
No recurring or polling timers: the harness notifies on completion, so the one-shot alarm above is the only sanctioned wakeup. After the final report is emitted (and its path printed, when
report_path
is set), kill any still-pending alarm — nothing may fire after completion.
一轮内:并行(单个多工具调用消息)。轮次间:严格串行。
合成侧调度 — 批量复现验证者、每个对抗者和每个双审计器行动锁定浪潮 — 遵循相同的并行规则(一次消息中后台启动所有代理,绝不串行等待),并获得等于有效
reviewer_timeout
的硬截止时间(超过5000行时翻倍):
  • Bash调度机械执行截止时间:在
    run-reviewer.sh
    下运行,使用该上限。
  • Agent工具调度无内置超时 — 这是生产运行在“等待verdict”时永远挂起的原因。为每个调度浪潮设置恰好一个一次性截止时间警报:与代理在同一消息中启动的单个后台
    sleep <cap>
    Bash任务,在所有代理返回时杀死。如果警报先触发, salvage输出文件中已存在的每个完整每ID verdict,并对任何缺失的内容应用安全故障:复现验证者失败 → 推迟处理;对抗者失败 → 继续并说明;行动锁定失败 → 为每个无法验证的行恢复确切的源请求工作 prose,并强制COMMENT;
    strict
    → COMMENT。在运行详情中记录
    timed out at <cap>s
无重复或轮询计时器:工具会在完成时通知,因此上述一次性警报是唯一批准的唤醒方式。发出最终报告后(设置
report_path
时打印其路径),杀死任何仍在等待的警报 — 完成后不得触发任何操作。

Reviewer Prompt Template

审查者提示模板

Read
references/reviewer-prompt.md
(next to this SKILL.md; same trusted-root resolution as scripts) at dispatch time.
It defines the per-reviewer lens assignment (the four pillars partition across reviewers — M identical prompts buy redundancy and dedup work, not coverage), the context block (TARGET / PRIOR ROUNDS / SCOPE OF THIS REVIEW / PR REVIEW HISTORY / YOUR LENS), the fixed task block (review principles, severity guide, structured finding keys, the fenced findings-YAML output contract), and the fill-in rules (itemized PRIOR ROUNDS construction;
commit_mode=none
variations). Reviewers return prose findings only — never patches.
When
adversarial
is enabled, normal reviewers still use
reviewer-prompt.md
. When
reproduction
dispatches, the verifier uses
references/reproduction-prompt.md
and receives only the stable candidate finding IDs selected by synthesis. The post-synthesis adversaries use
references/adversarial-prompt.md
and receive the surviving stable candidate finding / would-apply IDs produced by synthesis and reproduction.
调度时阅读
references/reviewer-prompt.md
(与本SKILL.md同目录;与脚本相同的可信根解析)
。它定义了每个审查者的视角分配(四大核心维度在审查者间划分 — M个相同的提示获得冗余和去重工作,而非覆盖范围)、上下文块(TARGET / PRIOR ROUNDS / SCOPE OF THIS REVIEW / PR REVIEW HISTORY / YOUR LENS)、固定任务块(审查原则、严重级别指南、结构化问题键、围栏式问题-YAML输出契约),以及填充规则(逐项PRIOR ROUNDS构建;
commit_mode=none
变体)。审查者仅返回prose问题 — 绝不返回补丁。
启用
adversarial
时,正常审查者仍使用
reviewer-prompt.md
。 调度
reproduction
时,验证者使用
references/reproduction-prompt.md
,仅接收合成选择的稳定候选问题ID。合成后的对抗者使用
references/adversarial-prompt.md
,仅接收合成和复现产生的幸存稳定候选问题/拟应用ID。

Output Format

输出格式

During execution: print
Round 2/3: dispatching 2 codex-exec + 1 claude-exec on PR #42 …
before requested rounds, or
Round 4 (adaptive; requested 3, max 4): dispatching …
for adaptive rounds, then the round summary block (§5) after.
执行期间:请求轮次前打印
第2/3轮:在PR #42上调度2个codex-exec + 1个claude-exec …
,或自适应轮次打印
第4轮(自适应;请求3轮,上限4):调度 …
,然后在轮次后打印轮次摘要块(§5)。

Final report

最终报告

After the last round, emit a fresh top-level report (a new document, not a replacement for the per-round blocks).
The final report is an external-facing decision summary. It must include every finding, but it should read like a scan-friendly index, not a transcript. Do not paste raw reviewer output, full round transcripts, repeated metadata, or paragraph-sized low-priority notes. Put each finding in exactly one focused row or bullet, grouped by severity/priority. Keep the decision, result, scope, and actionable critical/high/medium findings visible. Use progressive disclosure for supporting detail whenever the destination supports it: GitHub uses collapsed
<details>
blocks; other destinations should use their native disclosure controls. If the destination cannot collapse content, post a concise decision summary and preserve the complete report in an attached artifact or stable link. Never hide blockers only in an expandable section. If the report feels too bulky, rewrite and organize it yourself; do not depend on the posting helper to compact or shorten it.
undefined
最后一轮后,发出新的顶级报告(新文档,而非替换每轮块)。
最终报告是面向外部的决策摘要。必须包含每个问题,但应像易于扫描的索引,而非记录。不要粘贴原始审查者输出、完整轮次记录、重复元数据或段落大小的低优先级说明。将每个问题放在恰好一个聚焦的行或项目符号中,按严重级别/优先级分组。保持决策、结果、范围和可操作的critical/high/medium问题可见。只要目标支持,对支持细节使用渐进式披露:GitHub使用折叠的
<details>
块;其他目标应使用其原生披露控件。如果目标无法折叠内容,发布简洁的决策摘要,并将完整报告保留在附加工件或稳定链接中。绝不要仅在可展开部分隐藏阻塞点。如果报告感觉太冗长,自行重写和组织;不要依赖发布辅助脚本压缩或缩短它。
undefined

⚒️ review-anvil report

⚒️ review-anvil报告

Review decision: APPROVE | COMMENT — <one-sentence reason> # review-only PR runs Result: <one sentence: blockers/non-blockers/fixes/verification outcome> Scope: <For PR targets: one sentence summarizing what this PR is trying to change.> Verification: <verify_cmd used, or "none detected" / "skipped"> # per_fix only Checks: off | skipped (no findings needed checking) | <C> concerns checked; <confirmed> confirmed, <refuted> ruled out, <deferred> set aside, <downgraded> lowered in priority Second check: off | <mode>, <A> reviewers; <upheld> kept, <hardened> clarified, <deferred> set aside, <dropped> removed
审查决策: APPROVE | COMMENT — <一句话原因> # 仅只读PR运行 结果: <一句话:阻塞点/非阻塞点/修复/验证结果> 范围: <对于PR目标:一句话总结此PR试图更改的内容。> 验证: <使用的verify_cmd,或"未检测到" / "跳过"> # 仅per_fix模式 检查: 关闭 | 跳过(无需要检查的问题) | <C>个问题已检查; <confirmed>个确认, <refuted>个排除, <deferred>个搁置, <downgraded>个优先级降低 二次检查: 关闭 | <模式>, <A>个审查者; <upheld>个保留, <hardened>个澄清, <deferred>个搁置, <dropped>个删除

Earlier review comments

先前审查评论

<For PR-context runs, list each earlier comment once as open, still present after being marked resolved, fixed, no longer relevant, or intentionally skipped. For
author-resolved
items, count them separately as skipped but omit their individual finding text; retain the original URL and a short plain-language status reason. Actionable carry-forwards affect the review decision even when no new inline comment is needed;
author-resolved
history does not affect the review decision or approval. Keep 1-3 rows visible; for 4+ rows use a collapsed block with summary
Earlier review comments (N items)
. Preserve the exact internal status in the artifact; write the visible explanation in plain language.>
<对于PR上下文运行,将每个先前评论列出一次,标记为开放、标记为已解决后仍存在、已修复、不再相关或故意跳过。 对于
author-resolved
项目,单独计数为跳过,但省略其问题文本;保留原始URL和简短的自然语言状态原因。可操作的遗留问题即使不需要新的内联评论,也会影响审查决策;
author-resolved
历史不影响审查决策或批准。保持1-3行可见;4行以上使用折叠块,摘要为
先前审查评论(N项)
。 在工件中保留确切的内部状态;用自然语言编写可见的解释。>

What I noticed

发现的问题

<Show every confirmed issue once. Critical/high issues go first, then medium, then low/nit. Start with the facts: what the code does and what happens because of it. Inline comments carry supporting evidence and the source-backed requested change. Otherwise, add the smallest supporting fact to what you noticed. If none: "No confirmed problems found.">
ID legend:
RUN
is the observed PR review run,
R
is the immutable origin round,
F
is a finding, and
P
is a plan.
IDPriorityTopicCode locationWhat I noticed
RAV-RUN3-R2-F001highauth
src/auth.ts:42
Refresh creates a session before it checks CSRF validation
<If the table would be hard to read, use grouped bullets instead:>
  • RAV-RUN3-R2-F001 [high] auth
    src/auth.ts:42
    — Refresh creates a session before it checks CSRF validation. (inline)
<details> <summary>Non-blocking low/nit findings</summary>
  • RAV-RUN3-R2-F002 [low] docs — The CLI help could use the same option name.
  • RAV-RUN3-R2-F003 [nit] tests — The duplicate fixture setup can be shared.
</details>
<显示每个已确认的问题一次。critical/high问题优先,然后是medium,最后是low/nit。从事实开始:代码的行为和由此产生的后果。内联评论携带支持证据和源支持的请求变更。否则,为发现的问题添加最小的支持事实。如果无问题:"未发现已确认的问题。">
ID图例:
RUN
是观察到的PR审查运行,
R
是不可变的起源轮次,
F
是问题,
P
是计划。
ID优先级主题代码位置发现的问题
RAV-RUN3-R2-F001highauth
src/auth.ts:42
刷新在CSRF验证前创建会话
<如果表格难以阅读,使用分组项目符号替代:>
  • RAV-RUN3-R2-F001 [high] auth
    src/auth.ts:42
    — 刷新在CSRF验证前创建会话。(内联)
<details> <summary>非阻塞低/nit问题</summary>
  • RAV-RUN3-R2-F002 [low] docs — CLI帮助可以使用相同的选项名称。
  • RAV-RUN3-R2-F003 [nit] tests — 重复的fixture设置可以共享。
</details>

Changes made / Things to try

已做变更 / 建议事项

<For per_fix: focused commit list or "No fixes were made." For review-only: include each thing to try as one short, plain-language behavior change. In external reports, collapse this section when it contains more than 3 items.>
  • <sha>
    <subject> # per_fix only
  • [severity] area<plain-language behavior change>. (
    RAV-RUN3-R2-P001
    ; covers
    RAV-RUN3-R2-F001
    ) # commit_mode=none only
<对于per_fix:聚焦的提交列表或"未做任何修复。"对于仅审查: 将每个建议事项作为一个简短的自然语言行为变更列出。在 外部报告中,当包含超过3项时折叠此部分。>
  • <sha>
    — <主题> # 仅per_fix模式
  • [严重级别] 领域 — <自然语言行为变更>. (
    RAV-RUN3-R2-P001
    ; 涵盖
    RAV-RUN3-R2-F001
    ) # 仅commit_mode=none模式

Set aside / Outside this change

搁置 / 此变更范围外

<Include each item not addressed here in one line. Collapse this section when it contains more than 3 items. Omit it when empty.>
  • RAV-RUN3-R2-F004 [medium] runtime — set aside because the failing path could not be confirmed.
  • RAV-RUN3-R2-F005 [medium] config — set aside after the second check: the fix is too large for a one-line default.
  • [severity] area — follow-up outside this change: <why separate>.
<details> <summary>Run details</summary>
  • Target: <e.g. "PR #42 (feature/auth-rewrite, 12 files, +340/-89)">
  • Run ordinal: <positive observed PR run ordinal | unavailable (local/degraded)>
  • Rounds: <completed> completed (<requested> requested + <adaptive> adaptive, max <max_rounds>); <convergence/adaptive stop note> # productive adaptive-capable runs
  • Rounds: <completed>/<requested> completed; adaptive off; <convergence note> # review-only/exact/no-extra runs
  • Mix: <e.g. "2 codex-exec + 1 claude-exec">
  • Focus: <focus list actually used>
  • Earlier review comments: none | <total> comments; <open>/<still-present>/<fixed>/<not-relevant>/<author-resolved-skipped>/<skipped>
  • Finding counts: <C critical, H high, M medium, L low, N nit; other notes S>
  • Checks: off | skipped | concerns=<C>; confirmed=<confirmed>/ruled-out=<refuted>/set-aside=<deferred>/lowered=<downgraded>; elapsed=<duration>
  • Second check: off | <mode>; reviewers=<A>; kept=<kept>/clarified=<clarified>/set-aside=<deferred>/removed=<removed>; approval changed yes/no
  • Set aside: <D> items; reasons=<reasons>
  • Next time: <one line; see rule below> # omit in review-only
</details>
Reviewed with review-anvil.

`Findings addressed` = post-dedup count of unique findings auto-applied across all rounds.
<将每个未在此处处理的项目放在一行中。当包含超过3项时折叠此部分。空时省略。>
  • RAV-RUN3-R2-F004 [medium] runtime — 搁置,因为无法确认失败路径。
  • RAV-RUN3-R2-F005 [medium] config — 二次检查后搁置:修复对于单行默认值来说太大。
  • [严重级别] 领域 — 此变更范围外的后续事项:<为何分离>.
<details> <summary>运行详情</summary>
  • 目标: <例如 "PR #42(feature/auth-rewrite,12个文件,+340/-89)">
  • 运行序数: <观察到的正PR运行序数 | 不可用(本地/降级)>
  • 轮次: <已完成>已完成(<请求>请求 + <自适应>自适应,上限<max_rounds>); <收敛/自适应停止说明> # 生产环境自适应能力运行
  • 轮次: <已完成>/<请求>已完成; 自适应关闭; <收敛说明> # 仅审查/精确/无额外轮次运行
  • 混合配置: <例如 "2个codex-exec + 1个claude-exec">
  • 聚焦: <实际使用的聚焦列表>
  • 先前审查评论: 无 | <总计>条评论; <开放>/<仍存在>/<已修复>/<不相关>/<作者解决-跳过>/<跳过>
  • 问题计数: <C个critical, H个high, M个medium, L个low, N个nit; 其他说明S>
  • 检查: 关闭 | 跳过 | 问题=<C>; 确认=<confirmed>/排除=<refuted>/搁置=<deferred>/降低=<downgraded>; 耗时=<duration>
  • 二次检查: 关闭 | <模式>; 审查者=<A>; 保留=<kept>/澄清=<clarified>/搁置=<deferred>/删除=<dropped>; 批准是否更改是/否
  • 搁置: <D>项; 原因=<原因>
  • 下次建议: <一句话;见下文规则> # 仅审查模式省略
</details>
Reviewed with review-anvil.

`已处理的问题` = 所有轮次中自动应用的去重后唯一问题计数。

Tuning suggestion rule

调优建议规则

Omit in review-only. Early exit already stops the loop when a round comes back clean, and an adaptive round that converges needs no tuning suggestion. The remaining cases:
  • If every completed round was
    material_findings
    and
    max_rounds == rounds
    , suggest re-enabling adaptive continuation (
    max_rounds = rounds + 1
    ) or setting
    rounds = N + 1
    for the next run.
  • If the adaptive cap was reached and the final round was still
    material_findings
    , suggest increasing
    max_rounds
    by 1 only when the final round applied verified fixes; otherwise suggest resolving Deferred blockers or verification gaps before adding more rounds.
  • If adaptive continuation was blocked by skipped/missing verification, suggest setting a trustworthy
    verify_cmd
    before increasing
    rounds
    .
When the cap that bound was the diff-size-scaled default, name the tier and the exact value to re-run with, e.g.
small-diff adaptive cap (rounds+1=4) reached; re-run with max_rounds: 5 to continue
.
仅审查模式省略。提前退出已在轮次干净时停止循环,自适应轮次收敛时无需调优建议。剩余情况:
  • 如果每个已完成轮次都是
    material_findings
    max_rounds == rounds
    ,建议重新启用自适应延续(
    max_rounds = rounds + 1
    )或下次运行设置
    rounds = N + 1
  • 如果达到自适应上限且最后一轮仍为
    material_findings
    ,仅当最后一轮应用了已验证的修复时,建议将
    max_rounds
    增加1;否则建议在添加更多轮次前解决推迟处理的阻塞点或验证差距。
  • 如果自适应延续因跳过/缺失验证而被阻止,建议在增加
    rounds
    前设置可信的
    verify_cmd
当绑定的上限是差异大小缩放的默认值时,命名层级和重新运行的确切值,例如
小差异自适应上限(rounds+1=4)已达到;使用max_rounds: 5重新运行以继续

Edge Cases

边缘情况

CaseBehavior
Missing reviewer backendValidate only the backends the resolved mix actually names, before round 1. Abort with: "review-anvil requires the
<missing-skill>
skill from the mrshu-skills marketplace. Install via
/plugin install <missing-skill>@mrshu-skills
(Claude Code) or
npx skills add mrshu/agent-skills --skill <missing-skill>
(cross-agent)."
No diff in auto-detected targetAbort: "No target detected — nothing to review." Don't invent work.
Raw diff > ~5000 linesWarn in the round status and continue; tell reviewers they may focus on the most impactful slice; double
reviewer_timeout
(unless the user set it explicitly). For
adversarial: auto
, estimate meaningful changed size after exclusions; very large meaningful diffs select at least
full
, but generated/mechanical churn alone does not force deeper adversarial review.
agents > 8
Reject before round 1 — more dedup work than signal.
rounds = 0
Reject — almost certainly a typo.
max_rounds < rounds
Reject before round 1 — the adaptive cap cannot be below the requested round count.
User-supplied
max_rounds > rounds
with
commit_mode=none
Warn and set
max_rounds=rounds
; read-only extra rounds are explicit redundancy via
rounds
, not adaptive refinement.
adversarial
with
per_fix
Warn and ignore — productive mode verifies real fixes with the build/test gate.
adversarial_rounds > 2
Reject before dispatch — adversarial review is bounded critique, not an open-ended debate.
Reproduction verifier failureKeep consensus findings that did not require reproduction, but move required single-reviewer
medium
+ and deletion/high-risk candidates to Deferred with
We set this aside because the verification check could not be completed.
; never silently promote them.
Adversary failureContinue with the normal synthesized report and note the failure in Run Details; in
strict
, any required adversary failure forces
COMMENT
.
Unparseable findings blockConfirmation/plan-only output follows the one protocol retry above. Otherwise, in requested rounds use substantive review prose as free-form findings with no retry and note
<agent>: unstructured findings (parse failed)
; in adaptive rounds, abort before fixes from that round are applied.
Reviewers contradict each otherSurface both under the same area with reviewers tagged; orchestrator judgment decides the fix; mention the disagreement in the round summary.
Re-runsNot idempotent: a new run reviews the latest state, including the prior run's commits. Surface still-present deferred items under "Deferred from previous runs (still present)".
情况行为
缺失审查者后端第1轮前仅验证解析的混合配置实际命名的后端。中止并提示:"review-anvil需要mrshu-skills市场的
<missing-skill>
技能。通过
/plugin install <missing-skill>@mrshu-skills
(Claude Code)或
npx skills add mrshu/agent-skills --skill <missing-skill>
(跨代理)安装。"
自动检测的目标无差异中止:"未检测到目标 — 无内容可审查。"不要编造工作。
原始差异>约5000行在轮次状态中警告并继续;告知审查者他们可以聚焦最有影响的部分;将
reviewer_timeout
翻倍(除非用户明确设置)。对于
adversarial: auto
,排除后估计有意义的变更大小;非常大的有意义差异至少选择
full
,但仅生成/机械变更不会强制更深的对抗性审查。
agents > 8
第1轮前拒绝 — 去重工作多于信号。
rounds = 0
拒绝 — 几乎肯定是打字错误。
max_rounds < rounds
第1轮前拒绝 — 自适应上限不能低于请求轮次计数。
用户设置
max_rounds > rounds
commit_mode=none
警告并设置
max_rounds=rounds
;只读额外轮次通过
rounds
实现明确冗余,而非自适应优化。
per_fix
模式下设置
adversarial
警告并忽略 — 生产模式通过构建/测试命令验证真实修复。
adversarial_rounds > 2
调度前拒绝 — 对抗性审查是有界批评,而非开放式辩论。
复现验证者失败保留不需要复现的共识问题,但将必需的单审查者
medium
及以上级别和删除/高风险候选问题移至推迟处理,并附带
We set this aside because the verification check could not be completed.
;绝不静默升级它们。
对抗者失败继续使用正常合成的报告,并在运行详情中说明失败;在
strict
模式下,任何必需的对抗者失败强制COMMENT。
无法解析的问题块仅确认/仅计划输出遵循上述的一次协议重试。否则,在请求轮次中使用实质性审查prose作为自由格式问题,不重试,并说明
<agent>: unstructured findings (parse failed)
;在自适应轮次中,应用该轮次的修复前中止。
审查者相互矛盾在同一领域下呈现两者,标记审查者;编排器判断决定修复;在轮次摘要中提及分歧。
重新运行非幂等:新运行审查最新状态,包括先前运行的提交。将仍存在的推迟处理项目显示为"先前运行的推迟处理项目(仍存在)"。

Generated Language

生成语言

Apply
references/asd-ste100-inspired.md
to every generated message.
对每个生成的消息应用
references/asd-ste100-inspired.md