review-anvil
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesereview-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 runs, the orchestrator may continue adaptively after the requested rounds until convergence or .
per_fixmax_rounds将代码变更包裹在请求轮次的并行审查子代理 + 编排器应用修复流程中。每一轮流程 =(M个代理从不同视角并行审查)→(你综合并验证审查结果)→(你应用修复、运行构建/测试关卡、提交代码)→ 进入下一轮。在生产环境的运行模式下,编排器可能在请求轮次结束后自适应继续运行,直到代码收敛或达到上限。
per_fixmax_roundsPreset skills
预设技能
This is the engine. Three preset skills in the same plugin pin common configurations; each is a separate whose triggers activation cross-agent.
skills/<name>/SKILL.mddescription| Preset | Pins | Intent |
|---|---|---|
| nothing | Default fix/commit loop, or any custom param combination. |
| | Read-only review — no edits, no commits. |
| | Review a GitHub PR and post the report back as a PR comment (orchestrates |
| | 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.mddescription| 预设技能 | 固定参数 | 用途 |
|---|---|---|
| 无 | 默认修复/提交循环,或任意自定义参数组合。 |
| | 只读审查 — 不编辑、不提交代码。 |
| | 审查GitHub PR并将报告作为PR评论发布(编排 |
| | 优化已检出的PR:在请求轮次中修复并提交代码,同时支持自适应延续,然后推送。目标为分支(而非PR定位符),特意绕过下文的PR目标/per_fix规则。 |
Parameters
参数
Parse the user's free-form args string into:
| Param | Default | Plain-English forms |
|---|---|---|
| | "5 rounds", "three rounds", "do 4 passes" |
| | "max 4 rounds", "allow one extra round", "3 rounds, continue if needed"; "exactly 3 rounds", "only 3 rounds", or "no extra rounds" keeps |
| | "3 agents", "2 reviewers", or a mix like |
| the four pillars (correctness, maintainability, simplicity, production blast-radius) | "focus on async correctness"; an |
| auto-detect | "PR #42", "branch", "uncommitted", "src/auth/", "last 3 commits" |
| | "allow new deps" — auto-apply fixes that introduce new imports/subsystems instead of deferring them |
| | "auto-fix high and above", "fix only critical" — minimum severity for auto-fix; lower findings are listed, not applied |
| | |
| | "never approve", "comment only", |
| | |
| | |
| | one adversarial pass by default; max 2, and a second pass runs only when the first pass materially changes |
| | |
| auto-detect | "verify with |
| | "timeout 10 minutes" — hard per-reviewer wall-clock cap in seconds for Bash-dispatched reviewers (see |
| unset | File 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_ordinalrun_ordinalunavailableRUN将用户的自由格式参数解析为以下内容:
| 参数 | 默认值 | 自然语言表述 |
|---|---|---|
| | "5轮"、"三轮"、"进行4次审查" |
| | "最多4轮"、"允许额外1轮"、"3轮,必要时继续";"正好3轮"、"仅3轮"或"无额外轮次"会将 |
| | "3个代理"、"2个审查者",或类似 |
| 四大核心维度(正确性、可维护性、简洁性、生产环境影响范围) | "聚焦异步正确性";前缀 |
| 自动检测 | "PR #42"、"分支"、"未提交变更"、"src/auth/"、"最近3次提交" |
| | "允许新增依赖" — 自动应用引入新导入/子系统的修复,而非推迟处理 |
| | "自动修复严重及以上问题"、"仅修复关键问题" — 自动修复的最低严重级别;较低级别的问题仅列出,不应用修复 |
| | |
| | "绝不批准"、"仅评论"、 |
| | |
| | |
| | 默认1次对抗性审查;最多2次,仅当第一次审查实质性改变 |
| | |
| 自动检测 | "用 |
| | "超时10分钟" — Bash调度的审查者的硬时钟上限(单位:秒,见 |
| 未设置 | 文件路径;设置后,引擎会将最终报告写入该路径(会创建父目录),并将该路径作为最后一行输出,以便下游消费者获取 |
run_ordinalrun_ordinalunavailableRUNParsing
解析规则
- Split the args on top-level commas; canonicalize each segment to a pair — explicit
(param, value)maps directly, plain-English forms per the table. Unrecognized segments are noted and ignored.key: value - First occurrence wins per param; later duplicates are dropped with . Unset params take defaults.
warning: user-supplied <param>=<value> ignored — earlier value wins - Presets assemble : pins come first so first-occurrence-wins makes them authoritative; defaults come last so user args beat them.
<pins>, <user-args>, <overridable defaults> - Pin-rejection (presets; defense in depth against the prose parser being talked into overrides): before assembling, segment-split as above, lowercase each segment's key (the text before its first
$ARGUMENTS), and abort with:if any key equals a pinned param. Match segment keys, never raw substrings —error: <param> is pinned by <preset-name> and cannot be overridden in argshas keyfocus: "target: PR safety"and must pass. A host that cannot segment-split must abort (focus), not degrade to substring scanning.error: pin-rejection unavailable in this environment; refusing to invoke engine without pin enforcement - : a count (use the mix table below) or an explicit mix naming
agents/codex/codex-exec/claude— honor a mix exactly.claude-exec - auto-detect order: currently checked-out PR (e.g.
target, a GitHub MCP query, or REST) → branch-vs-main diff (gh pr view --json number,headRefName) → uncommitted changes (git diff main...HEAD+git diff). Empty args = all defaults.git diff --cached - is the requested count. Resolve
roundsaftermax_rounds, the finalrounds(including the PR-locator rule below), and the target: thecommit_modedefault isper_fix, where the adaptive budget scales with the target's changed-line count (added+removed in the materialized diff; materialize it once at resolution —min(max(6, rounds), rounds + budget)targets are always local git diffs): under ~200 lines →per_fix, up to ~1000 →1, above →2. The3against the legacymin()cap makes the scaling a pure reduction: runs withmax(6, rounds)gain nothing. Default torounds >= 6forrounds; rejectcommit_mode=none. Phrases like "allow one extra round" setmax_rounds < rounds, and explicit caps likemax_rounds=rounds+1or "up to 4 rounds" set the cap directly. Phrases like "continue if needed" restore the legacymax_rounds: 4cap 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" — forcemax(6, rounds). Do not treatmax_rounds=roundsfocus syntax or severity gates like "fix only critical" as exact-round requests.only: - Adaptive continuation is on by default for . A plain "3 rounds" means
per_fixwithrounds=3betweenmax_roundsand4by 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", or6when the run must stop at the requested count.max_rounds: 3 - If and the user explicitly set
commit_mode=none, warn and collapsemax_rounds > roundstomax_rounds. Extra normal rounds review the same baseline, so useroundsfor reviewer redundancy androundsfor skeptical challenge.adversarial - and
reproduction=autoboth run the selective batched reproduction gate in §3.reproduction=onmay skip dispatch only when there are no candidates.autois allowed for speed, but the round summary and final report must say it was disabled; unconfirmed single-revieweroff+ findings stay in Deferred unless the orchestrator independently reproduced them from code/tests/runtime evidence.medium - applies only when
adversarial. If set withcommit_mode=none, warn and ignore it — productive mode already applies real fixes and gates them with the build/test command. Rejectper_fix; adversarial loops must be bounded.adversarial_rounds > 2means choose the cheapest sufficient adversarial mode after normal synthesis using the default policy below.auto
- 按顶级逗号分割参数;将每个段规范化为对 — 明确的
(参数, 值)直接映射,自然语言表述参考表格。未识别的段会被记录并忽略。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 - 自动检测顺序:当前检出的PR(例如
target、GitHub MCP查询或REST)→ 分支与主分支的差异(gh pr view --json number,headRefName)→ 未提交变更(git diff main...HEAD+git diff)。空参数 = 全部使用默认值。git diff --cached - 是请求的轮次计数。在确定
rounds、最终rounds(包括下文的PR定位符规则)和目标后解析commit_mode:max_rounds模式的默认值为per_fix,其中自适应预算根据目标的变更行数(已具体化差异中的添加+删除行数;在解析时具体化一次 —min(max(6, rounds), rounds + budget)模式的目标始终是本地git差异)缩放:小于约200行 →per_fix,最多约1000行 →1,超过 →2。与旧版3上限的max(6, rounds)使缩放成为纯缩减:min()的运行不会获得额外预算。rounds >= 6模式默认使用commit_mode=none;拒绝rounds。类似“允许额外1轮”的表述会将max_rounds < rounds设为max_rounds,明确的上限如rounds+1或“最多4轮”会直接设置上限。类似“必要时继续”的表述会恢复旧版max_rounds: 4上限,除非与明确上限配对。限制轮次计数的表述 — “正好3轮”、“仅3轮”、“3轮仅”或“无额外轮次” — 会强制max(6, rounds)。不要将max_rounds=rounds聚焦语法或“仅修复关键问题”等严重级别关卡视为精确轮次请求。only: - 模式默认启用自适应延续。单纯的“3轮”意味着
per_fix,rounds=3根据差异大小在4到6之间,因此编排代理可能在第3轮后继续运行,如果§6规则认为有必要进行另一轮。当运行必须在请求的轮次结束时停止,使用“正好3轮”、“仅3轮”、“无额外轮次”或max_rounds。max_rounds: 3 - 如果且用户明确设置
commit_mode=none,则发出警告并将max_rounds > rounds缩减为max_rounds。额外的普通轮次会审查相同的基线,因此使用rounds实现审查者冗余,使用rounds实现质疑性审查。adversarial - 和
reproduction=auto都会运行§3中的选择性批量复现关卡。reproduction=on仅在没有候选问题时可能跳过调度。auto允许以速度为代价,但轮次摘要和最终报告必须说明它已被禁用;未确认的单审查者off及以上级别问题会留在推迟处理中,除非编排器从代码/测试/运行时证据中独立复现了它们。medium - 仅在
adversarial时适用。如果在commit_mode=none模式下设置,则发出警告并忽略 — 生产模式已通过构建/测试命令验证真实修复。拒绝per_fix;对抗性循环必须有界。adversarial_rounds > 2意味着在正常合成后使用默认规则选择最便宜且足够的对抗模式。auto
PR-target / per_fix incompatibility
PR目标 / per_fix不兼容
If is a GitHub PR locator (URL , slug , or "PR #N"), the only valid is . Force it, and warn if the user asked for :
targethttps://<host>/<owner>/<repo>/pull/<N><owner>/<repo>#<N>commit_modenoneper_fixwarning: 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.
如果是GitHub PR定位符(URL 、slug 或“PR #N”),唯一有效的是。强制设置该值,如果用户要求则发出警告:
targethttps://<host>/<owner>/<repo>/pull/<N><owner>/<repo>#<N>commit_modenoneper_fixwarning: 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
提交模式
- (default) — full loop: review → synthesize/reproduce/verify → apply fixes → build/test gate → commit, each round.
per_fix - (review-only) — review → synthesize/reproduce/verify only. No edits, no commits, no staging. Read-only mode may write temporary prompt/reviewer/report artifacts under
noneand the explicit.review-anvil/; it must not modify source files, the index, commits, branches, or remotes. Every normal round reviews the same baseline, soreport_pathbuys reviewer redundancy, not code refinement; the natural default isrounds > 1, and adaptive continuation is disabled by collapsingrounds=1tomax_rounds. Skip Loop Mechanics §4 entirely; the round summary readsrounds; 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.Fixes applied: 0 (review-only)
- (默认) — 完整循环:审查 → 综合/复现/验证 → 应用修复 → 构建/测试关卡 → 提交,每轮执行。
per_fix - (仅审查) — 仅执行审查 → 综合/复现/验证。不编辑、不提交、暂存。只读模式可能在
none和明确的.review-anvil/下写入临时提示/审查者/报告工件;不得修改源文件、索引、提交、分支或远程仓库。每一轮普通审查都会审查相同的基线,因此report_path仅能获得审查者冗余,而非代码优化;自然默认值为rounds > 1,自适应延续通过将rounds=1缩减为max_rounds来禁用。完全跳过循环机制§4;轮次摘要显示rounds;自动修复规则仍会抽象评估,因此问题会被分类为拟应用/建议/推迟处理。可选的对抗性审查是独立的合成后关卡,用于质疑问题的有效性和修复的合理性,而不假装代码已变更。Fixes applied: 0 (review-only)
Posting reports externally
外部发布报告
The engine never posts anywhere. Downstream consumers set , let the engine write a GitHub-ready PR report, and post after it returns — + its is the reference implementation.
report_pathreview-anvil-prpr-helper.shWhen 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报告,然后在引擎返回后发布 — 及其是参考实现。
report_pathreview-anvil-prpr-helper.sh当设置时,优化报告以适应PR时间线读者,而非归档完整性。每轮控制台输出和审查者工件是完整记录;发布的报告是决策摘要加上需要行动的少数问题。自适应延续细节属于运行详情,除非它们改变审查决策;不要将每轮延续推理粘贴到PR报告中。
report_pathExamples
示例
- → 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 Skill review-anvil "5 rounds, 2 codex + 1 claude, focus: async correctness, target: PR #42"- → 3 requested rounds, then at most 1 adaptive round if the continuation policy allows it.
Skill review-anvil "3 rounds, max_rounds: 4" Skill review-anvil "1 round, only: security, target: src/auth/"- → severity gate raised to
Skill review-anvil "fix only critical"; everything else surfaces as suggestions.critical - → normal review first, then adversarial review only if the synthesized findings/fix plans need a validity or proportionality challenge.
Skill review-anvil "target: PR #42, adversarial: auto"
- → 3轮请求轮次,根据差异大小自适应最多4–6轮,2个codex + 1个claude,四大核心维度聚焦,自动检测目标。
Skill review-anvil Skill review-anvil "5 rounds, 2 codex + 1 claude, focus: async correctness, target: PR #42"- → 3轮请求轮次,然后如果延续规则允许,最多1轮自适应轮次。
Skill review-anvil "3 rounds, max_rounds: 4" 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:
| Mix |
|---|---|
| 1 | 1 codex-exec |
| 2 | 1 codex-exec + 1 claude-exec |
| 3 | 2 codex-exec + 1 claude-exec |
| 4 | 2 codex-exec + 2 claude-exec |
| 5 | 3 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 slot).
agents=1当用户给出数量但未指定混合配置时:
| 混合配置 |
|---|---|
| 1 | 1个codex-exec |
| 2 | 1个codex-exec + 1个claude-exec |
| 3 | 2个codex-exec + 1个claude-exec |
| 4 | 2个codex-exec + 2个claude-exec |
| 5 | 3个codex-exec + 2个claude-exec |
| N | 约60/40的codex/claude比例,codex占奇数位 |
原理:在我们的使用中,codex-exec每次调用能发现更多问题,因此占更大比例(包括的情况)。
agents=1Loop Mechanics
循环机制
Run the loop for the requested , then continue adaptively up to
only when §6 allows adaptive continuation. Within a round:
roundsmax_rounds运行请求的轮次,然后仅当§6允许自适应延续时,继续运行至上限。每一轮内:
roundsmax_rounds1. 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 ): fetch the PR's diff via
commit_mode=none(or equivalent MCP/REST). The local worktree is irrelevant — reviewers see the PR as it exists on GitHub.gh pr diff <N> -R <owner>/<repo> - Whenever PR context is available — a PR-locator target, or a preset that supplies it (does, after
review-anvil-improve-pr) — 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.verify-checkout - 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 (ships with
pr-helper.sh history <host> <owner> <repo> <n>; threads, review bodies, and fallback comments are paginated and retried once). Include the status-tagged ledger in every reviewer prompt (PR REVIEW HISTORY block):review-anvil-prthreads,openthreads,resolvedanchors, summary-onlyoutdatedfindings, priorreported/deferreditems, and explicit localreview-dismissedfindings. 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 (suppressed), which also forces the review decision to COMMENT.REVIEW_ANVIL_SKIP_DISMISSED=1 - Note so the round summary can reference the exact baseline (informational-only for PR targets).
git rev-parse HEAD
在轮次开始时捕获目标状态,以便所有审查者看到相同的输入:
- 非PR目标(分支、未提交变更、路径):使用适当的命令具体化差异。
git diff … - PR目标(始终为):通过
commit_mode=none(或等效的MCP/REST)获取PR的差异。本地工作树无关紧要 — 审查者看到的是GitHub上的PR状态。gh pr diff <N> -R <owner>/<repo> - 只要PR上下文可用 — PR定位符目标,或提供PR上下文的预设技能(在
review-anvil-improve-pr后提供) — 同时获取PR标题/正文/基准分支/文件列表,然后用一句话推断PR的预期范围(例如“注释种子的性能优化”、“左侧边栏UX重组”)。将该范围放入每个审查者的提示中。只有当PR引入/回归问题,或直接破坏PR的既定目标时,问题才具有可操作性。明显的、高置信度的预先存在的缺陷可以提及,但必须放在单独的“范围外后续事项”部分 — 绝不能作为当前PR的阻塞点或内联可操作审查评论。verify-checkout - 同样,在调度前收集完整的PR审查历史:当预设技能提供记录(improve-pr在verify-checkout时捕获)时,使用该记录;对于PR定位符目标,通过获取(随
pr-helper.sh history <host> <owner> <repo> <n>提供;线程、审查正文和回退评论会分页并重试一次)。将带有状态标记的记录放入每个审查者的提示中(PR REVIEW HISTORY块):review-anvil-pr线程、open线程、resolved锚点、仅摘要的outdated问题、先前的reported/deferred项目,以及明确的本地review-dismissed问题。待处理的审查不会显示给作者,并被排除。调度前,语义合并具有相同根本原因的条目(摘要措辞通常与其内联评论不同),保留每个源URL和状态;明确的抑制优先,否则保留所有观察到的状态。如果重试后查找失败,则中止而非在没有先前反馈的情况下进行审查 — 除非用户选择降级模式(suppressed),这也会强制审查决策为COMMENT。REVIEW_ANVIL_SKIP_DISMISSED=1 - 记录,以便轮次摘要可以引用确切的基线(仅对PR目标提供信息)。
git rev-parse HEAD
2. Dispatch reviewers in parallel
2. 并行调度审查者
In Claude Code (the primary host)
在Claude Code(主宿主)中
Use the Agent tool for reviewers. Do NOT use via Bash — that path is for non-Claude hosts only.
claude-execclaude -p- : Agent tool,
claude-exec, the assembled Reviewer Prompt assubagent_type: "general-purpose",prompt. The Agent tool streams natively, has norun_in_background: trueceiling, and inherits the session environment.--max-turns - : Bash through the wrapper:
codex-exec, withREVIEW_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. 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.run_in_background: trueprevents reviewer sessions from leaking into later dispatches. The--ephemeralis load-bearing: codex takes its prompt as argv and must not inherit an open stdin — the wrapper passes its stdin through (< /dev/null, which the claude fallback needs), and codex blocking on a never-closing fd 0 is a known hang class from real runs.<&0 - Send all M reviewers in a single message with multiple tool calls. The harness notifies you on completion; do not poll.
为审查者使用Agent工具。不要通过Bash使用 — 该路径仅适用于非Claude宿主。
claude-execclaude -p- :Agent工具,
claude-exec,将组装好的审查者提示作为subagent_type: "general-purpose",prompt。Agent工具原生支持流式传输,没有run_in_background: true上限,并继承会话环境。--max-turns - :通过包装器执行Bash命令:
codex-exec,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是必需的:codex将提示作为argv,不得继承打开的stdin — 包装器传递其stdin(< /dev/null,claude回退需要),codex阻塞在永不关闭的fd 0上是实际运行中已知的挂起类型。<&0 - 在单个消息中发送所有M个审查者,包含多个工具调用。工具会在完成时通知你;不要轮询。
In Codex CLI or other hosts without the Agent tool
在Codex CLI或其他无Agent工具的宿主中
-
: write the assembled prompt to a file, then:
claude-execbashREVIEW_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.mdrestricts the built-in tool set;--toolsauto-approves the listed safe tool uses and is variadic, so the prompt MUST arrive via stdin (the wrapper passes its stdin through).--allowedToolskeeps the fallback non-interactive by denying anything outside the allowed/read-only path. Do not size--permission-mode dontAskto 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;--max-turnsis a runaway backstop that should never bind.100 -
: same validation-enabled wrapper around
codex-exec— stdin fromcodex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/nullhere too./dev/null -
Launch all M wrapper invocations as background shell processes and.
wait
-
:将组装好的提示写入文件,然后执行:
claude-execbashREVIEW_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自动批准列出的安全工具使用,且是可变参数,因此提示必须通过stdin传递(包装器传递其stdin)。--allowedTools通过拒绝允许/只读路径之外的任何操作,使回退模式非交互式。不要根据任务大小设置--permission-mode dontAsk— 任务大小的限制在生产中经常触发(20次已被命中),达到限制的审查者会丢失所有输出。包装器的时钟超时是真正的限制;--max-turns是失控的后备值,不应触发。100 -
:与上述相同的启用验证的包装器,执行
codex-exec— 此处stdin也来自codex exec --ephemeral --sandbox read-only -C <project-dir> '<prompt>' < /dev/null。/dev/null -
启动所有M个包装器调用作为后台shell进程并。
wait
Bash-dispatched reviewers MUST go through run-reviewer.sh
run-reviewer.shBash调度的审查者必须通过run-reviewer.sh
运行
run-reviewer.shEvery shell-dispatched reviewer (codex-exec everywhere; claude-exec outside Claude Code) runs under (next to this SKILL.md). Never background a bare 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:
scripts/run-reviewer.shclaude -p ... > out.md 2>&1run-reviewer.sh <out_file> <timeout_seconds> -- <command> [args...]- Hard wall-clock timeout (, default 600s): TERM at the deadline, KILL 30s later.
reviewer_timeout - Captures exit status; stderr goes to (kept for diagnosis).
<out_file>.err - Prints one classification: |
STATUS=ok|timeout(exit 0, nothing written) |empty(normal-review output did not end with a complete fenced findings block) |protocol(+failed).EXIT_CODE=<n>
Treat any STATUS other than as a failed reviewer (see Failure handling), with the tail of as the reason. gets the one corrective retry defined there before it becomes a failure. Set only for normal reviewer waves; reproduction and adversarial prompts have different output schemas. Reviewer output/prompt files live under ; clean them up after the round's synthesis.
ok.errprotocolREVIEW_ANVIL_REQUIRE_FINDINGS=1.review-anvil/Host tool timeouts must outlive the wrapper. Any host Bash call that can block on a reviewer — the background-and- 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 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 (), never block a foreground call on a reviewer at all. If the host caps tool timeouts below , prefer detached dispatch plus short non-blocking status checks over shrinking the reviewer budget; reducing is a last resort, floored at 300s and forbidden for >5000-line diffs (their timeout is deliberately doubled).
waitreviewer_timeout + 90run_in_backgroundreviewer_timeout + 90reviewer_timeoutResolving the wrapper and files — same trusted-root rule as : 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.
references/pr-helper.shAfter changing the wrapper contract or dispatch examples, run
alongside the reproduction and PR helper tests.
scripts/test-run-reviewer.sh每个shell调度的审查者(所有环境中的codex-exec;Claude Code之外的claude-exec)都在(与本SKILL.md同目录)下运行。绝不要后台运行裸并等待文件 — 在文本模式下,直到最终答案才会打印任何内容,因此挂起的审查者和正常工作的审查者都是0字节文件(一次生产运行为此等待了数分钟)。包装器:
scripts/run-reviewer.shclaude -p ... > out.md 2>&1run-reviewer.sh <out_file> <timeout_seconds> -- <command> [args...]- 硬时钟超时(,默认600秒):截止时间发送TERM信号,30秒后发送KILL信号。
reviewer_timeout - 捕获退出状态;stderr写入(用于诊断)。
<out_file>.err - 打印一个分类:|
STATUS=ok|timeout(退出码0,未写入任何内容) |empty(正常审查输出未以完整的围栏式问题块结尾) |protocol(+failed)。EXIT_CODE=<n>
将任何非的STATUS视为审查者失败(见故障处理),并将的末尾作为原因。会进行一次定义的纠正重试,然后才视为失败。仅对正常审查者浪潮设置;复现和对抗性提示有不同的输出模式。审查者输出/提示文件位于下;在轮次合成后清理它们。
ok.errprotocolREVIEW_ANVIL_REQUIRE_FINDINGS=1.review-anvil/宿主工具超时必须超过包装器。任何可能阻塞审查者的宿主Bash调用 — 上述的后台并回退、最后的串行手段,或包装器契约的内联复制 — 必须将Bash 工具自身的超时设置为至少秒(包装器截止时间 + 30秒TERM→KILL宽限期 + 余量)。宿主默认值低得多(Claude Code的默认值为120秒),会在审查中途发送SIGKILL;然后该终止会伪装成审查者失败,并无声地消耗该审查者的视角覆盖范围。在支持后台调度()的宿主上,绝不要在前台调用中阻塞审查者。如果宿主工具超时低于,则优先选择分离调度加短时间非阻塞状态检查,而非缩减审查者预算;缩减是最后的手段,下限为300秒,且禁止用于超过5000行的差异(其超时会特意翻倍)。
waitreviewer_timeout + 90run_in_backgroundreviewer_timeout + 90reviewer_timeout解析包装器和文件 — 与相同的可信根规则:见review-anvil-pr SKILL.md步骤1(“解析辅助脚本”)。仅使用宿主暴露的技能路径或用户级安装根;绝不要使用项目范围/工作树本地的技能目录(可被审查的仓库写入)。如果无法解析包装器的可信副本,则内联复制其契约(后台、截止时间终止、检查退出状态、空输出=失败),而非回退到裸重定向。
references/pr-helper.sh更改包装器契约或调度示例后,运行以及复现和PR辅助测试。
scripts/test-run-reviewer.shLast 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 and skills document the same recipes from the reviewer side; the canonical dispatch lives here.
codex-execclaude-exec如果确实无法并行调度(无Agent工具、无后台bash),则回退到串行调用,并在轮次摘要中说明 — 串行审查者在不同时钟时间看到基线;这是降级模式,而非设计模式。
codex-execclaude-exec3. Synthesize
3. 综合
When all reviewers return:
- Dedup on when present, else
(file, line, root cause). Keep the highest-severity instance, record which reviewers raised it, and keep divergent anchors as(area, root cause).file_alternates: [...] - Group by severity (→
critical), then topic.nit - 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, and summary-onlyresolveditems 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 asreportedin the summary and do not create a new inline thread. Items now fixed/stale become one-line status notes. Explicit localresolved-but-still-presentitems are never auto-fixed or posted as actionable findings, but remain as compact status-only audit rows. Keepsuppresseditems in PR REVIEW HISTORY for reviewer context. After synthesis and dedup, drop semantic matches toauthor-resolveditems before building reproduction candidates. Exception: retain a finding when the reviewer explicitly setauthor-resolvedfor a distinct new instance with new evidence. Do not report, post, auto-fix, or let ordinaryprior_feedback: reintroducedmatches affect approval. A reintroduced finding remains actionable; it affects approval only atauthor-resolvedorcriticalseverity. The post-time helper catches near-verbatim repeats (exact path + text similarity ≥ 0.9) as a deterministic duplicate-thread backstop.high -
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>andrunare unpadded positive base-10 integers. Encodeorigin-roundfrom an unpadded positive base-10 integer by left-padding only to a minimum width of three digits: encode 1 asordinal, 10 as001, 100 as010, and 1000 as100; do not add any other leading zero. Valid multi-digit examples are1000andRAV-RUN12-R10-F010. Invalid forms includeRAV-R12-P1000,RAV-RUN03-R2-F001,RAV-RUN3-R02-F001,RAV-RUN3-R2-F0001,RAV-RUN0-R2-F001, andRAV-RUN3-R0-F001.RAV-RUN3-R2-F000ID legend:is the observed PR review run,RUNis the immutable origin round,Ris a finding, andFis a plan. Examples areP,RAV-RUN3-R2-F001,RAV-RUN3-R2-P001, andRAV-R2-F001. Cross-round allocation example: in trusted PR run 3, a history finding withRAV-R2-P001keeps that ID. A new round-1 finding receivesid=RAV-RUN1-R2-F007and keeps it when re-raised in round 2. The next new round-2 finding receivesRAV-RUN3-R1-F001. A round-2 plan covering those two current-run findings receivesRAV-RUN3-R2-F002. The matching local/degraded allocation for the same newly allocated items has no history carry-forward:RAV-RUN3-R2-P001,RAV-R1-F001, andRAV-R2-F002. The carriedRAV-R2-P001has no new inline comment. It remains available in history, the report, reproduction, and adversarial review.RAV-RUN1-R2-F007Finding and plan ordinals are independent, run-wide counters namedandnext_finding_ordinal. Both start atnext_plan_ordinal. 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.001A 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 exactvalue supplied inid=; use that complete ID unchanged without advancing a current-run counter. For an actionable history entry that has onlyPR REVIEW HISTORY, use thelegacy=value as a source alias and assign the next canonical ID. Do not assign a new ID to a non-actionable legacy-only entry. Historicallegacy=,RAVF###,RAVW###, andF-###forms are migration/read-boundary aliases only. New findings and plans always use the recipe above.W-###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, andresolvedcarry-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.reported -
Buildafter prior-feedback classification and ID assignment:
REPRODUCTION CANDIDATES- every + finding raised by exactly one reviewer,
medium - every + 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,
medium - every /
criticalfinding whose evidence is mostly inferred from a hunk rather than confirmed from code/runtime context,high - every finding the orchestrator is materially uncertain about after reading the cited files.
- every
-
Whenor
reproduction=autoand candidates exist, dispatch one batched reproduction verifier usingon. 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 returnsreferences/reproduction-prompt.md,confirmed,refuted,unclear, ornarrowedverdicts for the supplied complete canonical finding IDs only, and returns each ID unchanged.downgraded -
Apply reproduction verdicts before auto-fix/reporting:
- and
confirmedfindings may remain actionable, with narrowed wording when supplied.narrowed - findings re-enter the normal severity gates after changing severity.
downgraded - findings are dropped from final Findings (or, if useful for transparency, one-line Deferred notes).
refuted - findings move to Deferred with
unclearRewrite the verifier's reason; do not copy it.We set this aside because <plain-language description of the missing proof>.
-
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 whenapplies 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 (per_fix).We set this aside because the code is still needed — <what> -
If, say so in the round summary and final report. Required reproduction candidates — including single-reviewer
reproduction=off+ 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 withmediumWe set this aside because the needed check was not run. -
/
lowfindings skip verification: they're below the auto-fix gate and surface as suggestions either way.nit
Canonical examples for where reproduction helps and where it must stay out of
the way live in . After changing this
policy or the reproduction prompt, run
alongside the PR helper tests.
references/reproduction-examples.mdscripts/test-reproduction-policy.sh看似合理但错误的问题是LLM审查的主要故障模式,且下游操作成本高昂:虚假的修复提交会污染分支,发布到PR的虚假问题会消耗作者的信任。去重后:
-
先检查先前反馈(编排器判断)。将每个合并的问题与PR REVIEW HISTORY进行语义比较 — 即使措辞不同,相同的根本原因也会被视为匹配。针对当前HEAD重新验证、
open和仅摘要的resolved项目。仍然存在的开放项目是遗留问题,必须保留其对严重级别/批准的影响,但不得创建重复的内联线程;已解决的项目仅表示GitHub讨论已关闭,而非代码已被证明修复。将仍然存在的已解决项目记录为reported在摘要中,且不得创建新的内联线程。现已修复/过时的项目成为单行状态说明。明确的本地resolved-but-still-present项目永远不会被自动修复或作为可操作问题发布,但会保留为紧凑的仅状态审计行。在PR REVIEW HISTORY中保留suppressed项目供审查者参考。合成和去重后,在构建复现候选之前,删除与author-resolved项目的语义匹配项。例外:当审查者明确为具有新证据的不同新实例设置author-resolved时,保留该问题。不报告、不发布、不自动修复,也不要让普通的prior_feedback: reintroduced匹配项影响批准。重新引入的问题仍然具有可操作性;仅在author-resolved或critical严重级别时影响批准。发布时的辅助脚本会捕获近似重复项(精确路径 + 文本相似度≥0.9)作为确定性重复线程的后备。high -
接下来过滤范围/工件(编排器判断)。在复现之前,如果问题是关于存档的设计说明、变更日志、旧迁移示例、生成的 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(or clearly reproduciblehigh), 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.medium - 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 is set, write follow-ups once, after the final round, to — schema in . Automation may file issues only for entries after duplicate search; presets read the file before posting (the helper deletes it afterwards).
report_path<report_path>.followups.jsonreferences/report-artifacts.mdauto_approvedPR范围外的预先存在的问题仍然值得注意,但不得成为内联/阻塞PR问题。对每个范围外后续事项进行分类:
- 自动批准的后续事项 — 当所有以下条件都满足时,创建/排队单独的工作:严重级别为/
critical(或明确可复现的high),错误已从代码/测试/运行时证据中确认,不是产品决策/风格偏好,未在先前PR反馈中跟踪或明确抑制,且修复可与当前PR分离。medium - 需要人工分类 — 当问题真实但严重级别/所有权/产品意图不明确时,仅作为非阻塞后续事项提及。
- 不呈现 — 如果是推测性的、低/nit级别、产品决策、已被驳回/跟踪,或仅通过深入审查无关代码路径才能发现,则丢弃。
当设置时,在最后一轮后将后续事项写入 — 模式位于中。自动化工具在重复搜索后仅可为条目创建问题;预设技能在发布前读取该文件(辅助脚本随后删除它)。
report_path<report_path>.followups.jsonreferences/report-artifacts.mdauto_approvedOptional adversarial review (commit_mode=none
only)
commit_mode=none可选对抗性审查(仅commit_mode=none
)
commit_mode=noneWhen is not , run a bounded post-synthesis gate after
dedup/reproduction and before writing the final report artifacts. Read
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.
adversarialoffreferences/adversarial-prompt.mdAdversarial 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:
| Mode | Dispatch | Intent |
|---|---|---|
| Chosen after synthesis | Selects |
| 1 adversary | Cheap local check over all |
| 2 adversaries | Recommended PR mode: false-positive/scope auditor + fix-plan breaker. Force a deletion skeptic when any would-apply item removes code. |
| 3 adversaries | Adds second-order bug hunting across interacting plans, config, migrations, and tests. |
| Same as | Approval-sensitive: any required adversary failure or unresolved |
Role mapping:
- : one combined adversary using the core prompt plus both the
challengeandfalse-positive-scope-auditorrole additions.fix-plan-breaker - : two adversaries, one
targetedand onefalse-positive-scope-auditor; add/replace with the deletion skeptic behavior fromfix-plan-breakerwhen any would-apply plan removes code.fix-plan-breaker - /
full:strict,false-positive-scope-auditor, andfix-plan-breaker; addsecond-order-bug-hunteronly if the report/approval artifact itself is the risky surface.report-auditor
Default policy:
- Local defaults to
review-anvil-readonly. If the user asks for careful, skeptical, high-confidence, low-noise, or thorough read-only review, the orchestrator should appendoffunless the user explicitly asked for a fast/rough pass.adversarial: auto - defaults to
review-anvil-prbecause GitHub output is public reviewer speech and may include inline comments, one-click suggestions, or an approval event.adversarial: auto - Explicit user input wins: disables the gate; explicit
adversarial: off/challenge/targeted/fulluses that mode. In review-only PR runs, explicitstrictalso forcesadversarial: offto.approval.json; unchallenged LLM review should not satisfy branch protection by accident.{"event": "COMMENT"}
auto- 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 meaningful changed lines or
>1000meaningful files as large, and>20meaningful changed lines,>5000meaningful 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>50, while a huge mechanical rename may stay belowtargetedafter exclusions.full - Use only when approval is disabled/impossible and the result is clean or low/nit-only, has no
off+ inline comments, no GitHub suggestion blocks, nomedium/criticalactionable 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.high - Use for small or self-authored comment-only reviews with material feedback but no suggestion blocks, no high-risk fix plans, and
challenge/approve: never.REVIEW_ANVIL_NO_APPROVE=1 - Use when candidate output includes any
targeted+ inline comment, any GitHub suggestion block, anymedium/criticalactionable/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.high - Use when the meaningful diff is very large or cross-cutting across several subsystems, unless exclusions show it is mostly mechanical/generated churn.
fulladds second-order plan scrutiny without making approval more brittle by itself.full - Use 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, forcestrict. Do not escalate toCOMMENTmerely because branch protection is unknown; usestrictand forcetargetedif approval safety cannot be established.COMMENT
Build would-apply plans from the same concrete fix groups 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
///, and any exact suggestion
blocks that would be emitted. For local non-PR reviews, set
to ; for PR/report-path reviews, set it to the tentative
event/reason. Adversarial reviewers return verdicts against
those complete unchanged IDs using the schema in .
per_fixdeletiondependencynon-localabstractionCANDIDATE APPROVALnot-applicable.approval.jsonadversarial-prompt.mdApply verdicts conservatively:
- only when concrete evidence shows a false positive, dismissed finding, or out-of-scope claim.
drop - when the issue may be real but the proposed fix is harmful, bloated, tech-debt-heavy, too non-local, or disproportionate for this PR.
defer - to harden or simplify the prose fix path while keeping the finding actionable.
modify - when the finding and fix path survive challenge.
uphold
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 , 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.
RAV-RUN3-R2-P001Adversarial review may make the output more conservative. It must never make a
speculative fix more authoritative. It can strip unsafe fields
from , 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.
"suggestion".inline.jsonRun at most passes, capped at 2. A second adversarial pass
runs only when the first pass materially changes + guidance, changes
approval, or rewrites a would-apply plan. Complete target verdicts affect
fix plans, suggestions, and fix prose only; linked complete finding IDs
change only when an independent verdict against that same finding ID refutes or
defers it. With , unresolved adversarial
disputes move the item to Deferred but do not by themselves block ;
unresolved / disputes block . With
, unresolved + disputes keep the item
actionable but force the review event to .
adversarial_roundsmediumPFdisagreement_policy=defermediumAPPROVEcriticalhighAPPROVEdisagreement_policy=commentmediumCOMMENT当不是时,在去重/复现后、写入最终报告工件前运行有界的合成后关卡。调度对抗性审查者前阅读。并行调度所选模式的每个对抗者 — 一个消息,多个后台工具调用,与§2审查者完全相同,遵循并发部分的截止时间规则 — 并在所有对抗者返回或截止时间触发时综合verdict。绝不要在启动下一个对抗者前等待前一个。
adversarialoffreferences/adversarial-prompt.md对抗性审查不是另一个广泛的审查轮次,也不是模拟补丁应用。它攻击候选合成结果:
- 问题有效性 — 误报声明、错误锚点、已驳回的问题、范围外问题、过度严重级别,以及缺失的可达性证据。
- 修复合理性 — 技术上解决问题但造成更多麻烦的建议修复:有害的影响范围、不必要的依赖、臃肿的抽象、未来的技术债务、非本地变更、不安全的删除、脆弱的测试,或未解决根本原因的症状修复。
- 报告安全性 — 不安全的一键GitHub建议、不明确的修复路径、过度自信的批准,以及应推迟处理的可操作评论。
模式:
| 模式 | 调度 | 用途 |
|---|---|---|
| 合成后选择 | 使用以下默认规则选择 |
| 1个对抗者 | 对所有 |
| 2个对抗者 | 推荐的PR模式:误报/范围审计员 + 修复计划质疑者。当任何拟应用项目删除代码时,强制添加删除质疑者。 |
| 3个对抗者 | 添加对交互计划、配置、迁移和测试的二阶错误排查。 |
| 与 | 批准敏感:任何必需的对抗者失败或未解决的 |
角色映射:
- :一个组合对抗者,使用核心提示加上
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,因为GitHub输出是公开的审查者言论,可能包含内联评论、一键建议或批准事件。adversarial: auto - 用户明确输入优先:禁用关卡;明确的
adversarial: off/challenge/targeted/full使用该模式。在只读PR运行中,明确的strict还会强制adversarial: off为.approval.json;未受质疑的LLM审查不应意外满足分支保护要求。{"event": "COMMENT"}
正常合成后的选择:
auto- 首先从审查的快照估计有意义的变更大小。排除生成/供应商/构建工件、锁文件和快照/fixture变更,除非这些文件是审查的产品表面。将行有意义变更或
>1000个有意义文件视为大变更,将>20行有意义变更、>5000个有意义文件或多个交互子系统视为非常大的变更。大小是升级下限,不是唯一信号:小的高风险认证或迁移差异仍可选择>50,而排除后巨大的机械重命名可能仍低于targeted。full - 仅当批准被禁用/不可能且结果干净或仅低/nit级别、没有及以上级别的内联评论、没有GitHub建议块、没有
medium/critical级别的可操作或推迟处理的作者行动项目,且没有拟应用计划涉及删除、依赖、非本地行为或抽象/技术债务风险时,才使用high。对于本地非PR运行,忽略批准条件。off - 对于小的或自作者的仅评论审查,有实质性反馈但无建议块、无高风险修复计划,且/
approve: never时,使用REVIEW_ANVIL_NO_APPROVE=1。challenge - 当候选输出包含任何及以上级别的内联评论、任何GitHub建议块、任何
medium/critical级别的可操作/推迟处理项目、任何拟应用计划涉及删除代码、添加依赖、非本地变更行为、触及认证/安全/数据/架构/迁移/并发/配置,或看起来有抽象/技术债务风险,或开放/已解决的先前PR反馈触及相同文件/根本原因,或差异按有意义变更大小为大变更时,使用high。targeted - 当有意义的差异非常大或跨多个子系统时,使用,除非排除后显示主要是机械/生成变更。
full添加二阶计划审查,本身不会使批准更脆弱。full - 仅当用户明确要求批准敏感行为或确认分支保护/CODEOWNER要求时,使用。如果
strict模式下任何必需的对抗者失败、超时或返回无法解析的输出,则强制strict。不要仅因为分支保护未知就升级到COMMENT;使用strict,如果无法确定批准安全性,则强制targeted。COMMENT
从会提交的相同具体修复组构建拟应用计划。在对抗性调度前,首次组装该修复组时为每个计划分配来源ID;复现结果可能删除或重塑组,但绝不会重新编号幸存的计划或让另一个计划重用其间隙。每个计划列出未更改的涵盖问题ID、模拟的常规提交主题、预期修复路径、风险标签如///,以及任何会发出的确切建议块。对于本地非PR审查,将设置为;对于PR/报告路径审查,将其设置为暂定的事件/原因。对抗性审查者使用中的模式针对这些完整未更改的ID返回verdict。
per_fixdeletiondependencynon-localabstractionCANDIDATE APPROVALnot-applicable.approval.jsonadversarial-prompt.md保守应用verdict:
- 仅当具体证据显示错误阳性、已驳回的问题或范围外声明时,才。
drop - 当问题可能真实但建议修复有害、臃肿、技术债务沉重、过于非本地或与PR不成比例时,。
defer - 以强化或简化 prose 修复路径,同时保持问题的可操作性。
modify - 当问题和修复路径经受住挑战时,。
uphold
通用不确定性不会推迟问题。对抗者必须引用代码、配置、测试、运行时行为、状态感知的PR反馈或PR范围证据。对抗者不得创建新的可操作问题。如果他们在攻击计划(如)时注意到新问题,仅将其记录为二阶计划风险或后续事项;除非编排器运行单独的正常审查/验证轮次,否则它仍处于推迟处理状态。
RAV-RUN3-R2-P001对抗性审查可能使输出更保守。绝不能使推测性修复更具权威性。它可以从中删除不安全的字段、将项目移至推迟处理、强化/简化修复 prose,或降级批准。绝不能从未经验证的对抗性想法创建补丁、提交或最终可操作问题。
.inline.json"suggestion"最多运行次审查,上限为2。仅当第一次审查实质性改变及以上级别的指导意见、更改批准或重写拟应用计划时,才进行第二次对抗性审查。完整的目标verdict仅影响修复计划、建议和修复 prose;链接的完整问题ID仅当针对同一问题ID的独立verdict反驳或推迟处理时才会改变。使用时,未解决的级别对抗性争议会将项目移至推迟处理,但本身不会阻止;未解决的/级别争议会阻止。使用时,未解决的及以上级别争议会保持项目的可操作性,但强制审查事件为。
adversarial_roundsmediumPFdisagreement_policy=defermediumAPPROVEcriticalhighAPPROVEdisagreement_policy=commentmediumCOMMENT4. Apply fixes
4. 应用修复
Skip entirely when (the policy below is still evaluated in the abstract for the report).
commit_mode=noneOtherwise read before making any edit: it defines the conventional-commit fix-group style, the auto-fix proportionality rules (severity gate >= ; no new dependencies without ; per-round size cap; noise is deferred with a reason, never silently dropped), and the build/test gate ( resolution, baseline run, fix-forward-or-revert, revert-failure escalation). The invariant: a round never ends with the build/test gate newly red.
references/fix-application.mdmin_fix_severityallow_new_depsverify_cmd当时完全跳过(下文规则仍会抽象评估用于报告)。
commit_mode=none否则,在进行任何编辑前阅读:它定义了常规提交修复组风格、自动修复合理性规则(严重级别关卡≥;无时不添加新依赖;每轮大小上限;噪声会附带原因推迟处理,绝不静默丢弃),以及构建/测试关卡(解析、基线运行、修复前进或回退、回退失败升级)。不变量:轮次永远不会以构建/测试关卡新变红结束。
references/fix-application.mdmin_fix_severityallow_new_depsverify_cmd5. Round summary
5. 轮次摘要
Append to running output:
undefined追加到运行输出:
undefinedRound 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 , start the next requested round;
round N+1 reviews the new state including round N's commits.
roundsEarly exit on convergence ( only). A or
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. . (In , multi-round = reviewer
redundancy over the same baseline; no early exit and no adaptive continuation.)
per_fixcleannits_onlyRounds: N completed (R requested + A adaptive, max M); converged after round N of R requestedcommit_mode=noneAdaptive continuation ( only). After the requested are
complete, the orchestrator may start one more round only while
and all continuation criteria hold:
per_fixroundscompleted_rounds < max_rounds- The latest round was 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.
material_findings - 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, andpre-existing failures (no new)are acceptable for requested rounds but not strong enough to justify extra automatic work.failed → round reverted - 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
is set, and prevents improve-PR pushes.
report_path - The remaining risk is likely to converge with another review/fix pass. Do not
extend for low/nit-only feedback, suggestions below , items already Deferred, product decisions, new-dependency deferrals, size-cap deferrals, or repeated findings that were not fixed.
min_fix_severity
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
and hits , finish and use the tuning suggestion
rule; do not keep extending without a larger explicit cap.
material_findingsmax_roundsAfter the final round, emit the Final Report (Output Format). If is set:
report_path-
Write the rendered PR report there (creating parent dirs).
-
Write a sibling: an array of GitHub PR review comment payloads for findings with both
<report_path>.inline.jsonandfile—linejson[ {"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 →; range{"line": N, "side": "RIGHT"}→<N>-<M>. Findings without anchors stay in the markdown body only; no anchored findings →{"start_line": N, "line": M, "side": "RIGHT", "start_side": "RIGHT"}. Start each identified inline body with the natural bold title[]. End it with exactly one**<finding>**marker on its own final line. The marker area is the same machine-safe area token used by the report row: letters, digits,<!-- review-anvil: id=<complete-id> severity=<severity> area=<area> -->,.,_, 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-alone.bodyInclude helper-onlyfor 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"severity"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."suggestion"The helper-onlymust 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."severity"For an explicitly reintroducedfinding, placeauthor-resolvedimmediately after its visible final-report finding row or bullet. Its matching inline item must carry helper-only<!-- review-anvil: 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."prior_feedback": "reintroduced"Each eligible newputs 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 inbody— 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 underreferences/report-artifacts.md. 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**What to change**/critical/highobligation, use one concisemediumsentence. For two or more independently implementable obligations, usePleaseand one direct-action bullet per obligation. A reader must be able to act without reopening the diff. Include a safe exact**What to change**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"suggestion"/critical/highanchored findings;medium/lowfindings remain in the top-level summary unless the user or environment lowersnit. Ordinary prior-feedback carry-forwards do not produce new inline payloads.REVIEW_ANVIL_INLINE_MIN_SEVERITYClassify 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, andcoulddo not make target behavior optional.wouldApply 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 usingorwithout changing …; 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.while keeping … unchangedBefore 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 fromin 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 toreferences/action-lock-audit.md; 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..inline.jsonValidate 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. -
Write a siblingso the PR-posting helper can choose the GitHub review event (review-only PR runs; for other runs write
<report_path>.approval.jsonor omit the file — the helper defaults to COMMENT):{"event": "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— 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). IncludeHEAD_SHAand set"adversarial_mode"when approval must be mechanically disabled, including explicit"approval_allowed": falsein a PR run or any run where an action-lock exact-source fallback has been used.adversarial: offUsefor review-only PR runs when all of these hold:APPROVEis notapprove, at least one reviewer succeeded, no action-lock exact-source fallback has been used, there are nonever/criticalactionable in-scope findings, nohigh/criticalin-scope deferred finding needs author action, no priorhigh/criticalopen or resolved-but-still-present item remains unaddressed, no unresolvedhigh/criticaladversarial dispute remains, and remaining items are onlyhigh/medium/lowfindings, 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. Usenitotherwise. Out-of-scope follow-ups do not block approval.COMMENT -
Print the report path as the last output line; theand
.inline.jsonfiles are implied by convention..approval.json -
For out-of-scope follow-ups, write the siblingonce, after the final round, using the follow-ups schema from §3 "Approving out-of-scope follow-ups" (NOT the
<report_path>.followups.jsonschema above). The posting helper deletes it after a successful post, so any consumer (surfacing follow-ups to the user, filing issues for.approval.jsonentries after duplicate search) must read it before the post/post-update step — the presets do this.auto_approved
如果已完成轮次仍低于,开始下一个请求轮次;第N+1轮审查包含第N轮提交的新状态。
rounds提前退出收敛(仅模式)。或轮次即使仍有请求或自适应轮次,也会结束循环 — 进一步轮次会重新审查收敛的代码,主要产生噪声。在运行详情中说明,例如。(在模式下,多轮 = 同一基线的审查者冗余;无提前退出和自适应延续。)
per_fixcleannits_only轮次: 已完成N轮(请求R轮 + 自适应A轮,上限M); 在请求R轮的第N轮后收敛commit_mode=none自适应延续(仅模式)。完成请求的轮次后,仅当且所有延续标准都满足时,编排器才可以开始另一轮:
per_fixroundscompleted_rounds < max_rounds- 最新一轮是,且产生了至少一个新的重要问题。新问题 = 未在任何先前轮次提出,或复现确认重新检测到先前轮次修复并验证的问题(证据表明修复失败 — 延续存在的核心情况)。未确认或反驳的重新检测和已推迟处理的项目不计入。
material_findings - 最新一轮应用了至少一个已验证的修复提交,或更改了高风险/共享表面,另一轮可能会发现二阶错误。
- 最新一轮的验证以结束;
通过、跳过、未检测到和预先存在的失败(无新失败)对于请求轮次是可接受的,但不足以证明额外自动工作的合理性。失败 → 轮次回退 - 所有预期审查者都成功返回可解析的输出。降级的审查者信号可以完成请求轮次,但不得触发自适应轮次。在自适应轮次中,这是§4之前的硬关卡:任何审查者失败、超时、空输出或无法解析的问题块都会在应用该自适应轮次的修复前停止运行,当设置时写入失败报告,并阻止improve-PR推送。
report_path - 剩余风险可能通过另一轮审查/修复收敛。不要因仅低/nit级别反馈、低于的建议、已推迟处理的项目、产品决策、新依赖推迟处理、大小上限推迟处理或未修复的重复问题而延长。
min_fix_severity
在最后一个请求轮次的摘要和自适应轮次摘要(如果运行)中记录延续决策。如果自适应轮次仍有且达到,则结束并使用调优建议规则;不要在没有更大明确上限的情况下继续延长。
material_findingsmax_rounds最后一轮后,发出最终报告(输出格式)。如果设置:
report_path-
将渲染的PR报告写入该路径(创建父目录)。
-
写入同级文件:GitHub PR审查评论负载数组,对应同时具有
<report_path>.inline.json和file的问题 —linejson[ {"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>。无锚点的问题仅保留在markdown正文中;无锚点问题 →{"start_line": N, "line": M, "side": "RIGHT", "start_side": "RIGHT"}。每个已识别的内联正文以自然粗体标题[]开头。最后一行必须包含恰好一个**<问题>**标记。标记领域与报告行使用的机器安全领域令牌相同:字母、数字、<!-- review-anvil: id=<完整ID> severity=<严重级别> area=<领域> -->、.、_或单个/分隔符。标题中不得包含可见的ID、严重级别标签或领域标签。读者必须能够仅从可见的-创建修复。body为每个内联项包含仅辅助工具使用的。发布辅助脚本在调用GitHub前会剥离它,并使用它默认将低/nit级别问题保留为仅摘要。仅当修复是注释行/范围的确切替换时,才包含仅辅助工具使用的"severity";辅助脚本会将其转换为GitHub建议围栏块,插入到最终问题元数据标记之前,并在发布前剥离额外的键。仅当满足下一句中的所有安全排除且仍与已验证的锚点和替换匹配时,才保留确切的源建议。不要为设计修复、跨文件编辑、删除行、任何需要判断的内容,或任何锚点/替换/影响范围受到对抗性审查争议的建议包含建议。"suggestion"仅辅助工具使用的必须与终端标记的严重级别完全匹配;如果它们不一致,辅助脚本会在过滤或发布前中止。存在但无法识别的辅助工具严重级别也会中止;迁移期间可能使用终端标记替代缺失的辅助工具字段。"severity"对于明确重新引入的问题,在其可见的最终报告问题行或项目符号后立即放置author-resolved。其匹配的内联项必须携带仅辅助工具使用的<!-- review-anvil: prior_feedback=reintroduced -->;发布辅助脚本会在作者解决抑制前使用它,在GitHub REST请求前剥离JSON字段,并在最终问题元数据标记之前插入隐藏的先前反馈标记,以便后续历史保留处理结果。"prior_feedback": "reintroduced"每个符合条件的新将与报告行、复现目标和对抗性目标相同的完整问题ID放入最终问题元数据标记中,然后遵循body中的内联评论语气 — 撰写正文前阅读。保持简短明了:说明代码的行为、由此产生的后果,以及每个源支持的要求义务。将修复视为请求,而非已存在的代码。按内聚的实现义务分组工作,而非按语法;不要拆分受同一规则约束的值。只有作者必须执行的工作才属于references/report-artifacts.md下。将每个权限、例外、豁免或已正确的行为与它限制的操作放在一起,或在该操作后立即使用简短的模态 prose。保留确切的源范围措辞。将源支持的必需测试视为作者工作。对于一个**修改建议**/critical/high义务,使用一个简洁的“请”句子。对于两个或更多独立可实现的义务,使用medium和每个义务一个直接行动项目符号。读者必须能够无需重新打开差异即可采取行动。仅当消除疑问时,才包含安全的确切**修改建议**或简短代码草图。问题元数据标记是最后一个非空行:不得有 prose、建议围栏或先前反馈标记跟随它。默认情况下,内联评论用于"suggestion"/critical/high级别的锚点问题;medium/low级别问题保留在顶级摘要中,除非用户或环境降低nit。普通的先前反馈遗留问题不会产生新的内联负载。REVIEW_ANVIL_INLINE_MIN_SEVERITY渲染前对每个源谓词进行分类。目标行为和必需的验证或文档是作者工作。接受的当前行为、允许的实现边界和明确可选的后续事项是无变更边界。源意图优于模态语法:、can和could不会使目标行为可选。would仅在分类后应用省略反事实。将每个混合作者工作与无变更边界的源句子拆分为谓词进行分类;不要保留未拆分的回退。如果保留当前代码而不进行目标行为、测试或文档变更会留下缺陷、安全边界或审查者要求的验证未解决,则将该谓词视为作者工作。无变更边界不是单独的义务。当接受的当前行为直接约束请求的变更时,使用“不更改……”或“保持……不变”将其保留在同一句子中;不要为其创建单独的行动项目符号。如果该句子会很密集,则在行动后立即使用简短的模态 prose。将其他接受的当前行为或明确可选的后续事项保留为独立的模态 prose。请求解决失败所需的最小新机制,但将每个必需的目的、结果或安全条款与它约束的行动放在一起。将源支持的验证或文档(旨在覆盖、演示、澄清或明确必需边界)视为作者工作,除非明确可选。不要将可接受的不变行为、允许的实现边界或明确可选的后续事项转换为强制性工作。起草前,冻结确切的请求工作 prose、解决先行词和当前与目标行为所需的最小源上下文,以及每个接受的合成问题中正文可能保留的确切证据和代码片段。写入内联JSON前,从运行两个独立的渲染后行动锁定审计器,并行运行。为每个干净的验证者仅提供该冻结的源材料和每个确切的完整渲染内联正文;不要发送无关的仓库或报告上下文。对于通过重写的,仅将字节相同的审计正文写入references/action-lock-audit.md;任何后续正文编辑都会使verdict无效,并需要新的审计浪潮。下一步中的精确源回退豁免,并强制COMMENT。.inline.json验证每个审计器的完整每ID输出,并合并任一审计器的有效失败。仅修复具有有效失败verdict的内联正文,然后再次运行两个新的干净审计器。对于第一次审计中缺失、重复、格式错误、超时或无法验证的行,恢复确切的源请求工作 prose,不尝试修复,并强制审查事件为COMMENT。如果第二次审计的verdict仍然失败或无法验证,使用相同的精确源回退和COMMENT事件。绝不要省略问题或请求的谓词以使审计通过。 -
写入同级文件,以便PR发布辅助脚本选择GitHub审查事件(仅适用于只读PR运行;其他运行写入
<report_path>.approval.json或省略该文件 — 辅助脚本默认COMMENT):{"event": "COMMENT"}json{ "event": "APPROVE | COMMENT", "head_sha": "<预设在初始化/verify-checkout时捕获的HEAD_SHA>", "adversarial_mode": "off | auto | challenge | targeted | full | strict", "approval_allowed": true, "reason": "无范围内的高/严重问题;中及以下级别问题留给作者处理。" }包含— 预设在初始化/verify-checkout时捕获的"head_sha"— 以便发布辅助脚本验证批准是否仍与审查的状态匹配(如果PR头部在运行中移动,会降级为COMMENT)。当必须机械禁用批准时,包含HEAD_SHA并设置"adversarial_mode",包括PR运行中明确的"approval_allowed": false或任何使用行动锁定精确源回退的运行。adversarial: off仅当以下所有条件都满足时,对只读PR运行使用:APPROVE不是approve,至少一个审查者成功,未使用行动锁定精确源回退,无never/critical级别的可操作范围内问题,无high/critical级别的范围内推迟处理问题需要作者行动,无先前的high/critical级别的开放或已解决但仍存在的项目未解决,无未解决的high/critical级别的对抗性争议,剩余项目仅为high/medium/low级别问题、建议、推迟处理说明或范围外后续事项。中及以下级别的范围内问题仍应清晰发布,但审查事件为批准:将这些修复留给作者处理。否则使用nit。范围外后续事项不阻止批准。COMMENT -
将报告路径作为最后一行输出;和
.inline.json文件由约定隐含。.approval.json -
对于范围外后续事项,在最后一轮后写入同级文件,使用§3“批准范围外后续事项”中的后续事项模式(不是上述的
<report_path>.followups.json模式)。发布辅助脚本在成功发布后删除它,因此任何消费者(向用户呈现后续事项、重复搜索后为.approval.json条目创建问题)必须在发布/发布更新步骤前读取它 — 预设技能会这样做。auto_approved
Failure handling
故障处理
- A reviewer fails or times out in a requested round → log in the round summary and proceed; no retries except the protocol-only case below. For Bash-dispatched reviewers, failure = wrapper STATUS
<agent>: failed (<reason>)/timeout/empty, reason = tail offailed;.errfollows the next rule. In an adaptive round, any reviewer failure is an abort before fixes from that round are applied.protocol - 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 ; detect the same shape directly for Agent-tool reviewers. Re-dispatch that reviewer exactly once on the same snapshot and lens with this prefix:
STATUS=protocolDo 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 (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.) 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.confirmation/plan-only output after corrective retry - A dispatch call — foreground or background — that dies with exit 143 or ends with no 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.
STATUS= - All reviewers fail → abort the loop and report. Never carry on with zero findings — that's a misleading clean signal.
- fails (hook, conflict) → surface the error, stop the loop, leave partial fixes in the worktree. Never
git commit, never amend earlier commits.--no-verify - On any abort, if is set, write a failure report to it before stopping — the usual header block, a
report_pathsection stating what happened and at which round, plus any completed round summaries. Downstream consumers (## Failure's post-update step) depend on the file existing on every exit path, success or failure. Writereview-anvil-improve-prto{"event": "COMMENT"}in this case..approval.json
- 请求轮次中审查者失败或超时 → 在轮次摘要中记录并继续;除下文的仅协议情况外不重试。对于Bash调度的审查者,失败 = 包装器STATUS
<agent>: failed (<reason>)/timeout/empty,原因 =failed的末尾;.err遵循下一条规则。在自适应轮次中,任何审查者失败都会在应用该轮次的修复前中止。protocol - 仅协议纠正重试:非空响应要求确认、仅发出计划/状态更新,或未以完整的围栏式问题块结尾,不属于审查输出。Bash审查者将其显示为;直接检测Agent工具审查者的相同形状。使用以下前缀在相同快照和视角下重新调度该审查者恰好一次:
STATUS=protocol不要回答确认请求,不要将第一次尝试视为审查者结果。如果重试也违反协议,则将审查者记录为失败(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终止,或输出中无行,是在包装器分类前被宿主工具的超时杀死 — 调度配置错误(见§2“宿主工具超时”),而非审查者失败。修复调度模式(提高工具超时或分离调度)并重新调度该审查者恰好一次;只有第二次相同的终止才视为审查者失败。
STATUS= - 所有审查者失败 → 中止循环并报告。绝不要在无问题的情况下继续 — 这是误导性的干净信号。
- 失败(钩子、冲突) → 显示错误,停止循环,将部分修复留在工作树中。绝不要使用
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 (after any >5000-line doubling):
reviewer_timeout- Bash dispatches enforce the deadline mechanically: run them under with that cap.
run-reviewer.sh - 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 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;
sleep <cap>→ COMMENT. Recordstrictin Run Details.timed out at <cap>s
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 is set), kill any still-pending alarm — nothing may fire after completion.
report_path一轮内:并行(单个多工具调用消息)。轮次间:严格串行。
合成侧调度 — 批量复现验证者、每个对抗者和每个双审计器行动锁定浪潮 — 遵循相同的并行规则(一次消息中后台启动所有代理,绝不串行等待),并获得等于有效的硬截止时间(超过5000行时翻倍):
reviewer_timeout- Bash调度机械执行截止时间:在下运行,使用该上限。
run-reviewer.sh - Agent工具调度无内置超时 — 这是生产运行在“等待verdict”时永远挂起的原因。为每个调度浪潮设置恰好一个一次性截止时间警报:与代理在同一消息中启动的单个后台Bash任务,在所有代理返回时杀死。如果警报先触发, salvage输出文件中已存在的每个完整每ID verdict,并对任何缺失的内容应用安全故障:复现验证者失败 → 推迟处理;对抗者失败 → 继续并说明;行动锁定失败 → 为每个无法验证的行恢复确切的源请求工作 prose,并强制COMMENT;
sleep <cap>→ COMMENT。在运行详情中记录strict。timed out at <cap>s
无重复或轮询计时器:工具会在完成时通知,因此上述一次性警报是唯一批准的唤醒方式。发出最终报告后(设置时打印其路径),杀死任何仍在等待的警报 — 完成后不得触发任何操作。
report_pathReviewer Prompt Template
审查者提示模板
Read (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; variations). Reviewers return prose findings only — never patches.
references/reviewer-prompt.mdcommit_mode=noneWhen is enabled, normal reviewers still use .
When dispatches, the verifier uses
and receives only the stable candidate
finding IDs selected by synthesis. The post-synthesis adversaries use
and receive the surviving stable candidate
finding / would-apply IDs produced by synthesis and reproduction.
adversarialreviewer-prompt.mdreproductionreferences/reproduction-prompt.mdreferences/adversarial-prompt.md调度时阅读(与本SKILL.md同目录;与脚本相同的可信根解析)。它定义了每个审查者的视角分配(四大核心维度在审查者间划分 — M个相同的提示获得冗余和去重工作,而非覆盖范围)、上下文块(TARGET / PRIOR ROUNDS / SCOPE OF THIS REVIEW / PR REVIEW HISTORY / YOUR LENS)、固定任务块(审查原则、严重级别指南、结构化问题键、围栏式问题-YAML输出契约),以及填充规则(逐项PRIOR ROUNDS构建;变体)。审查者仅返回prose问题 — 绝不返回补丁。
references/reviewer-prompt.mdcommit_mode=none启用时,正常审查者仍使用。
调度时,验证者使用,仅接收合成选择的稳定候选问题ID。合成后的对抗者使用,仅接收合成和复现产生的幸存稳定候选问题/拟应用ID。
adversarialreviewer-prompt.mdreproductionreferences/reproduction-prompt.mdreferences/adversarial-prompt.mdOutput Format
输出格式
During execution: print before requested rounds, or for adaptive rounds, then the round summary block (§5) after.
Round 2/3: dispatching 2 codex-exec + 1 claude-exec on PR #42 …Round 4 (adaptive; requested 3, max 4): dispatching …执行期间:请求轮次前打印,或自适应轮次打印,然后在轮次后打印轮次摘要块(§5)。
第2/3轮:在PR #42上调度2个codex-exec + 1个claude-exec …第4轮(自适应;请求3轮,上限4):调度 …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 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.
<details>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 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; history does not affect the review decision or approval. Keep 1-3 rows visible; for
4+ rows use a collapsed block with summary .
Preserve the exact internal status in the artifact; write the visible
explanation in plain language.>
author-resolvedauthor-resolvedEarlier review comments (N items)<对于PR上下文运行,将每个先前评论列出一次,标记为开放、标记为已解决后仍存在、已修复、不再相关或故意跳过。
对于项目,单独计数为跳过,但省略其问题文本;保留原始URL和简短的自然语言状态原因。可操作的遗留问题即使不需要新的内联评论,也会影响审查决策;历史不影响审查决策或批准。保持1-3行可见;4行以上使用折叠块,摘要为。
在工件中保留确切的内部状态;用自然语言编写可见的解释。>
author-resolvedauthor-resolved先前审查评论(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: is the observed PR review run, is the immutable origin round, is a finding, and is a plan.
RUNRFP| ID | Priority | Topic | Code location | What I noticed |
|---|---|---|---|---|
| RAV-RUN3-R2-F001 | high | auth | | 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 — Refresh creates a session before it checks CSRF validation. (inline)
src/auth.ts:42
- 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.
<显示每个已确认的问题一次。critical/high问题优先,然后是medium,最后是low/nit。从事实开始:代码的行为和由此产生的后果。内联评论携带支持证据和源支持的请求变更。否则,为发现的问题添加最小的支持事实。如果无问题:"未发现已确认的问题。">
ID图例: 是观察到的PR审查运行,是不可变的起源轮次,是问题,是计划。
RUNRFP| ID | 优先级 | 主题 | 代码位置 | 发现的问题 |
|---|---|---|---|---|
| RAV-RUN3-R2-F001 | high | auth | | 刷新在CSRF验证前创建会话 |
<如果表格难以阅读,使用分组项目符号替代:>
- RAV-RUN3-R2-F001 [high] auth — 刷新在CSRF验证前创建会话。(内联)
src/auth.ts:42
- RAV-RUN3-R2-F002 [low] docs — CLI帮助可以使用相同的选项名称。
- RAV-RUN3-R2-F003 [nit] tests — 重复的fixture设置可以共享。
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.>
- — <subject> # per_fix only
<sha> - [severity] area — <plain-language behavior change>. (; covers
RAV-RUN3-R2-P001) # commit_mode=none onlyRAV-RUN3-R2-F001
<对于per_fix:聚焦的提交列表或"未做任何修复。"对于仅审查:
将每个建议事项作为一个简短的自然语言行为变更列出。在
外部报告中,当包含超过3项时折叠此部分。>
- — <主题> # 仅per_fix模式
<sha> - [严重级别] 领域 — <自然语言行为变更>. (; 涵盖
RAV-RUN3-R2-P001) # 仅commit_mode=none模式RAV-RUN3-R2-F001
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>.
- 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
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 — 二次检查后搁置:修复对于单行默认值来说太大。
- [严重级别] 领域 — 此变更范围外的后续事项:<为何分离>.
- 目标: <例如 "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>项; 原因=<原因>
- 下次建议: <一句话;见下文规则> # 仅审查模式省略
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 and
material_findings, suggest re-enabling adaptive continuation (max_rounds == rounds) or settingmax_rounds = rounds + 1for the next run.rounds = N + 1 - If the adaptive cap was reached and the final round was still
, suggest increasing
material_findingsby 1 only when the final round applied verified fixes; otherwise suggest resolving Deferred blockers or verification gaps before adding more rounds.max_rounds - If adaptive continuation was blocked by skipped/missing verification, suggest
setting a trustworthy before increasing
verify_cmd.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增加1;否则建议在添加更多轮次前解决推迟处理的阻塞点或验证差距。max_rounds - 如果自适应延续因跳过/缺失验证而被阻止,建议在增加前设置可信的
rounds。verify_cmd
当绑定的上限是差异大小缩放的默认值时,命名层级和重新运行的确切值,例如。
小差异自适应上限(rounds+1=4)已达到;使用max_rounds: 5重新运行以继续Edge Cases
边缘情况
| Case | Behavior |
|---|---|
| Missing reviewer backend | Validate only the backends the resolved mix actually names, before round 1. Abort with: "review-anvil requires the |
| No diff in auto-detected target | Abort: "No target detected — nothing to review." Don't invent work. |
| Raw diff > ~5000 lines | Warn in the round status and continue; tell reviewers they may focus on the most impactful slice; double |
| Reject before round 1 — more dedup work than signal. |
| Reject — almost certainly a typo. |
| Reject before round 1 — the adaptive cap cannot be below the requested round count. |
User-supplied | Warn and set |
| Warn and ignore — productive mode verifies real fixes with the build/test gate. |
| Reject before dispatch — adversarial review is bounded critique, not an open-ended debate. |
| Reproduction verifier failure | Keep consensus findings that did not require reproduction, but move required single-reviewer |
| Adversary failure | Continue with the normal synthesized report and note the failure in Run Details; in |
| Unparseable findings block | Confirmation/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 |
| Reviewers contradict each other | Surface both under the same area with reviewers tagged; orchestrator judgment decides the fix; mention the disagreement in the round summary. |
| Re-runs | Not 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市场的 |
| 自动检测的目标无差异 | 中止:"未检测到目标 — 无内容可审查。"不要编造工作。 |
| 原始差异>约5000行 | 在轮次状态中警告并继续;告知审查者他们可以聚焦最有影响的部分;将 |
| 第1轮前拒绝 — 去重工作多于信号。 |
| 拒绝 — 几乎肯定是打字错误。 |
| 第1轮前拒绝 — 自适应上限不能低于请求轮次计数。 |
用户设置 | 警告并设置 |
| 警告并忽略 — 生产模式通过构建/测试命令验证真实修复。 |
| 调度前拒绝 — 对抗性审查是有界批评,而非开放式辩论。 |
| 复现验证者失败 | 保留不需要复现的共识问题,但将必需的单审查者 |
| 对抗者失败 | 继续使用正常合成的报告,并在运行详情中说明失败;在 |
| 无法解析的问题块 | 仅确认/仅计划输出遵循上述的一次协议重试。否则,在请求轮次中使用实质性审查prose作为自由格式问题,不重试,并说明 |
| 审查者相互矛盾 | 在同一领域下呈现两者,标记审查者;编排器判断决定修复;在轮次摘要中提及分歧。 |
| 重新运行 | 非幂等:新运行审查最新状态,包括先前运行的提交。将仍存在的推迟处理项目显示为"先前运行的推迟处理项目(仍存在)"。 |
Generated Language
生成语言
Apply to every generated message.
references/asd-ste100-inspired.md对每个生成的消息应用。
references/asd-ste100-inspired.md