review-anvil-pr

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

review-anvil-pr

review-anvil-pr

Preset that reviews a GitHub PR with the multi-agent loop and posts the result back as a top-level PR comment. The skill orchestrates three steps:
这是一个预设技能,通过多Agent循环审核GitHub PR,并将结果作为顶级PR评论发布。该技能协调以下三个步骤:

Generated Language

生成语言规范

Apply the ASD-STE100-inspired language contract to this preset. Use direct imperatives for internal steps. Use short active declarative sentences in PR comments. Use
**What to change**
only for multiple actions the author must perform; keep no-change constraints in prose. Retain suggestion grammar for low/nit guidance.
  1. scripts/pr-helper.sh init [<locator>]
    — locator parsing or auto-detect from the current branch,
    gh
    preflight (auth + PR reachability), marker UUID + report path setup
  2. The
    review-anvil
    engine in read-only mode (
    commit_mode=none
    )
  3. scripts/pr-helper.sh post <host> <owner> <repo> <n> <marker> <report_path>
    — marker injection, lossless report posting as a PR review /
    gh pr comment
    , race-free URL recovery
为该预设应用受ASD-STE100启发的语言约定。 内部步骤使用直接祈使句。PR评论中使用简短的主动陈述句。仅当作者需要执行多项操作时才使用
**What to change**
;无修改约束以散文形式呈现。低优先级/细枝末节的指导保留建议性语法。
  1. scripts/pr-helper.sh init [<locator>]
    — 解析定位符或从当前分支自动检测,
    gh
    预检查(授权 + PR可达性),标记UUID + 报告路径设置
  2. 以只读模式运行
    review-anvil
    引擎(
    commit_mode=none
  3. scripts/pr-helper.sh post <host> <owner> <repo> <n> <marker> <report_path>
    — 注入标记,将无损报告作为PR审核/
    gh pr comment
    发布,无竞争地恢复URL

Inputs

输入参数

The user may provide a PR locator as the first argument, or omit it entirely:
  • Omitted — the helper runs
    gh pr view --json url
    to detect the PR associated with the currently checked-out branch. The natural "review the PR I'm on" workflow. If no PR is associated with the current branch, the helper aborts with a clear message pointing the user at the explicit-locator forms below.
  • Full GitHub URL
    https://<host>/<owner>/<repo>/pull/<N>
    for github.com or GitHub Enterprise.
  • Slug
    <owner>/<repo>#<N>
    (host defaults to github.com).
Bare integers are rejected by the helper script to prevent wrong-repo misdirection. To target a PR you don't have checked out, pass the URL or slug; to target the PR you're currently on, just omit the locator.
用户可以提供PR定位符作为第一个参数,也可以完全省略:
  • 省略定位符 — 辅助工具运行
    gh pr view --json url
    以检测与当前检出分支关联的PR。这是“审核当前所在PR”的自然工作流。如果当前分支未关联任何PR,辅助工具会中止并给出清晰提示,引导用户使用下文的显式定位符格式。
  • 完整GitHub URL
    https://<host>/<owner>/<repo>/pull/<N>
    ,适用于github.com或GitHub Enterprise。
  • 简短标识(Slug)
    <owner>/<repo>#<N>
    (默认主机为github.com)。
辅助脚本拒绝纯整数定位符,以防止错误指向其他仓库。要审核未检出的PR,请传入URL或简短标识;要审核当前所在的PR,直接省略定位符即可。

How to invoke

调用方式

0. Reject overrides of pinned params

0. 拒绝覆盖固定参数

Pins for this preset:
commit_mode
,
target
,
report_path
,
run_ordinal
. Enforce mechanically — after resolving the helper (step 1), run:
bash
bash <helper-path> check-pins review-anvil-pr "commit_mode,target,report_path,run_ordinal" "$ARGUMENTS"
Non-zero exit means a pinned param was overridden in the args: surface the script's error verbatim and stop. (The engine's prose pin-rejection in "Parsing" remains as the description of the algorithm; the script is the binding layer.)
The pins are non-overridable for safety:
commit_mode
enforces read-only;
target
and
report_path
are mechanically tied to the user's locator; and
run_ordinal
carries the helper's observed PR history into identifier generation. Defense in depth against the engine's prose parser being talked into accepting overrides (e.g. via prompt injection in the focus text).
本预设的固定参数:
commit_mode
target
report_path
run_ordinal
。需强制实施——解析辅助工具后(步骤1),运行:
bash
bash <helper-path> check-pins review-anvil-pr "commit_mode,target,report_path,run_ordinal" "$ARGUMENTS"
非零退出码表示参数中存在对固定参数的覆盖:直接显示脚本的错误信息并停止执行。(引擎在“解析”阶段的文本参数拒绝逻辑作为算法说明保留;脚本是绑定层。)
这些参数不可覆盖是为了安全:
commit_mode
确保只读模式;
target
report_path
与用户提供的定位符机械绑定;
run_ordinal
将辅助工具观察到的PR历史带入标识符生成。这是一种纵深防御,防止引擎的文本解析器被说服接受覆盖(例如通过聚焦文本中的提示注入)。

1. Resolve the helper script

1. 解析辅助脚本

The script lives at
./scripts/pr-helper.sh
relative to this SKILL.md. That is the only authoritative resolution rule.
To find the absolute path:
  1. If the host exposes the loaded SKILL.md's path (Claude Code via
    ${CLAUDE_PLUGIN_ROOT}/skills/review-anvil-pr/scripts/pr-helper.sh
    , or any agent that surfaces the skill's filesystem location to the model), use that and stop.
  2. Otherwise, fall back to user-level skill install paths only:
    • ~/.claude/skills/review-anvil-pr/scripts/pr-helper.sh
      (Claude Code via
      npx skills add
      )
    • The home-directory skill root for the current host as
      vercel-labs/skills
      documents it (
      npx skills list
      shows the configured location).
    Do not search project-scoped or worktree-local skill directories (e.g.
    <project>/.claude/skills/...
    ,
    <reviewed-repo>/.codex/skills/...
    , etc.) — those paths are writable by the contents of the repository being reviewed. An adversarial PR could plant a malicious
    pr-helper.sh
    inside such a directory and weaponize the wrapper into arbitrary shell execution. The script must come from a trusted install root outside the reviewed worktree.
  3. Verify the file exists before running it — if no candidate from the trusted set above resolves, abort with
    error: review-anvil-pr/scripts/pr-helper.sh not found in any trusted skill root; reinstall via 'npx skills add mrshu/agent-skills --skill review-anvil-pr'
    .
The primary contract is "the script is
./scripts/pr-helper.sh
relative to this SKILL.md." When the host doesn't expose that path, the user-level fallback is a recovery mechanism — but it is not a substitute for the host exposing skill-file paths, and project-scoped paths must never be searched.
脚本位于相对于本SKILL.md的
./scripts/pr-helper.sh
,这是唯一权威的解析规则。
要获取绝对路径:
  1. 如果宿主暴露已加载SKILL.md的路径(如Claude Code通过
    ${CLAUDE_PLUGIN_ROOT}/skills/review-anvil-pr/scripts/pr-helper.sh
    ,或任何向模型公开技能文件系统位置的Agent),直接使用该路径并停止。
  2. 否则,仅回退到用户级技能安装路径
    • ~/.claude/skills/review-anvil-pr/scripts/pr-helper.sh
      (Claude Code通过
      npx skills add
      安装)
    • 当前宿主的主目录技能根目录,如
      vercel-labs/skills
      文档所述(
      npx skills list
      可显示配置位置)。
    请勿搜索项目范围或工作树本地的技能目录(例如
    <project>/.claude/skills/...
    <reviewed-repo>/.codex/skills/...
    等)——这些路径可被待审核仓库的内容写入。恶意PR可能在这类目录中植入恶意
    pr-helper.sh
    ,进而利用包装器执行任意shell命令。脚本必须来自待审核工作树之外的可信安装根目录。
  3. 运行前验证文件是否存在——如果上述可信路径中均无法找到该文件,中止并提示:
    error: review-anvil-pr/scripts/pr-helper.sh not found in any trusted skill root; reinstall via 'npx skills add mrshu/agent-skills --skill review-anvil-pr'
核心约定是“脚本位于本SKILL.md相对路径下的
./scripts/pr-helper.sh
”。当宿主不暴露该路径时,用户级回退是一种恢复机制——但不能替代宿主暴露技能文件路径的功能,且绝不能搜索项目范围的路径。

2. Init

2. 初始化

bash
bash <helper-path> init "<locator>"     # explicit form
bash <helper-path> init                 # auto-detect from current branch
If the user supplied a locator (URL or
<owner>/<repo>#<N>
slug), pass it as the argument. If they didn't, invoke
init
with no argument — the script will run
gh pr view --json url
to find the PR associated with the currently checked-out branch and use that as the locator. The script aborts with a clear message if no PR is found.
On success, the script prints these KEY=VALUE lines on stdout:
HOST=github.com
OWNER=acme
REPO=widgets
N=137
RUN_ORDINAL=3
HEAD_SHA=<the PR head commit at review time>
MARKER=<uuidv4>
REPORT_PATH=<absolute-path>/.review-anvil/final-report-<uuidv4>.md
TITLE=<PR title>
If the locator was auto-detected, the script also prints
auto-detected PR: <url>
to stderr before the KEY=VALUE block, so the agent can echo that to the user before proceeding.
Capture all values, including
RUN_ORDINAL
. Echo to the user:
review target: $HOST/$OWNER/$REPO#$N — $TITLE
.
On non-zero exit, surface the script's stderr verbatim and stop. Do not dispatch reviewers.
bash
bash <helper-path> init "<locator>"     # 显式形式
bash <helper-path> init                 # 从当前分支自动检测
如果用户提供了定位符(URL或
<owner>/<repo>#<N>
简短标识),将其作为参数传入。如果未提供,则不带参数调用
init
——脚本会运行
gh pr view --json url
查找与当前检出分支关联的PR并将其作为定位符。如果未找到PR,脚本会中止并给出清晰提示。
成功时,脚本会在标准输出打印以下KEY=VALUE行:
HOST=github.com
OWNER=acme
REPO=widgets
N=137
RUN_ORDINAL=3
HEAD_SHA=<审核时的PR头部提交哈希>
MARKER=<uuidv4>
REPORT_PATH=<绝对路径>/.review-anvil/final-report-<uuidv4>.md
TITLE=<PR标题>
如果定位符是自动检测的,脚本还会在标准错误输出打印
auto-detected PR: <url>
,以便Agent在继续前告知用户。
捕获所有值,包括
RUN_ORDINAL
。向用户回显:
review target: $HOST/$OWNER/$REPO#$N — $TITLE
如果非零退出,直接显示脚本的标准错误信息并停止,不启动审核器。

3. Activate the engine

3. 激活引擎

Activate the
review-anvil
skill with this argument string (extra user args go between the pinned params and the rounds default):
commit_mode: none, target: <locator>, report_path: <REPORT_PATH>, run_ordinal: <RUN_ORDINAL>, <extra-user-args>, adversarial: auto, rounds: 1
The user may override
rounds:
or
adversarial:
in their args (they are defaults, not pins). They cannot override the observed value of
run_ordinal
, or the
commit_mode
,
target
, and
report_path
pins; the step-0 segment-rejection above blocks override attempts.
RUN_ORDINAL
comes from the
init
preflight. When it is a positive integer, the engine includes the corresponding
RUN
segment in new provenance IDs. The value
unavailable
makes the engine emit IDs without the
RUN
segment; degraded history must not invent a run number.
The engine's default
reproduction: auto
runs before adversarial review and reproduces uncertain material findings in one batched confidence pass. The user may pass
reproduction: off
for speed, but unreproduced single-reviewer
medium
+ findings, deletion/high-risk findings, and orchestrator-uncertain findings must stay Deferred rather than becoming inline/actionable PR comments.
The default
adversarial: auto
lets the engine choose
off
,
challenge
,
targeted
, or
strict
after normal synthesis. The user may also pass
adversarial: off|challenge|targeted|full|strict
. Adversarial review stays read-only: it attacks candidate findings and would-apply plans before the report is posted, so false positives can be dropped and harmful/bloated/tech-debt-heavy fixes can be deferred instead of turned into inline comments. Unresolved
critical
/
high
adversarial disputes and
disagreement_policy=comment
material disputes force the review event to
COMMENT
rather than
APPROVE
. If the user explicitly passes
adversarial: off
, the engine must write
{"event":"COMMENT","adversarial_mode":"off", "approval_allowed":false}
to
.approval.json
; unchallenged LLM review should not satisfy branch protection by accident.
Provide
$HEAD_SHA
to the engine for its
.approval.json
head_sha
field — the posting helper uses it to downgrade a stale APPROVE (PR head moved mid-run) to a COMMENT.
The engine runs the review loop, writes the final report to
<REPORT_PATH>
(on failure paths too), and prints that path on its last output line. Before posting, if
<REPORT_PATH>.followups.json
exists, read it and surface its entries to the user (the helper deletes it after a successful post;
auto_approved
entries are the only ones automation may file issues for, after a duplicate search).
使用以下参数字符串激活
review-anvil
技能(额外用户参数放在固定参数和默认轮次数之间):
commit_mode: none, target: <locator>, report_path: <REPORT_PATH>, run_ordinal: <RUN_ORDINAL>, <extra-user-args>, adversarial: auto, rounds: 1
用户可以在参数中覆盖
rounds:
adversarial:
(它们是默认值,不是固定参数)。但不能覆盖
run_ordinal
的观测值,也不能覆盖
commit_mode
target
report_path
这些固定参数;步骤0的参数拒绝逻辑会阻止覆盖尝试。
RUN_ORDINAL
来自初始化预检查。当它是正整数时,引擎会在新的溯源ID中包含对应的
RUN
段。如果值为
unavailable
,引擎会生成不带
RUN
段的ID;历史信息缺失时不得编造运行编号。
引擎默认的
reproduction: auto
会在对抗性审核前运行,并在一次批量置信度检查中重现不确定的重要发现。用户可以传入
reproduction: off
以提高速度,但未重现的单审核员
medium
+级别发现、删除/高风险发现以及编排器不确定的发现必须保持“延迟处理”状态,而不能转化为内联/可操作的PR评论。
默认的
adversarial: auto
让引擎在正常合成后选择
off
challenge
targeted
strict
模式。用户也可以传入
adversarial: off|challenge|targeted|full|strict
。 对抗性审核保持只读:它会在报告发布前攻击候选发现和拟应用的修复方案,从而可以删除误报,并将有害/冗余/技术债务沉重的修复方案延迟处理,而不是转化为内联评论。未解决的
critical
/
high
级别对抗性争议以及
disagreement_policy=comment
的重要争议会将审核事件强制设为
COMMENT
而非
APPROVE
。如果用户明确传入
adversarial: off
,引擎必须向
.approval.json
写入
{"event":"COMMENT","adversarial_mode":"off","approval_allowed":false}
;未经过挑战的LLM审核不应意外满足分支保护要求。
$HEAD_SHA
提供给引擎,用于
.approval.json
head_sha
字段——发布辅助工具会使用它将运行期间PR头部发生变化的过期APPROVE降级为COMMENT。
引擎运行审核循环,将最终报告写入
<REPORT_PATH>
(失败路径也会写入),并在最后一行输出该路径。发布前,如果
<REPORT_PATH>.followups.json
存在,读取并向用户展示其中的条目(辅助工具成功发布后会删除该文件;只有
auto_approved
条目可在重复搜索后由自动化工具提交议题)。

4. Post

4. 发布

bash
bash <helper-path> post "$HOST" "$OWNER" "$REPO" "$N" "$MARKER" "$REPORT_PATH"
The script chooses the GitHub review event from
<REPORT_PATH>.approval.json
(
APPROVE
or
COMMENT
; default
COMMENT
if absent) and then posts the report:
  • Approval / hybrid review. If the decision is
    APPROVE
    , the helper submits a GitHub approval review. If
    <REPORT_PATH>.inline.json
    is non-empty, its comments are included as non-blocking findings or suggestions; by default the helper posts
    critical
    /
    high
    /
    medium
    inline comments and leaves lower-severity items in the top-level body unless
    REVIEW_ANVIL_INLINE_MIN_SEVERITY
    is lowered. Otherwise the approval has only the top-level body. Use this when there are no
    critical
    /
    high
    actionable in-scope findings; medium-and-lower issues are posted but left to the author. If GitHub rejects the approval (most commonly: you cannot approve your own PR), the helper downgrades to a comment review, appends a note to the report explaining the downgrade, and keeps cascading down to the top-level fallback — a failed approval never costs the report. An unexpected or malformed
    approval.json
    likewise defaults to
    COMMENT
    , never to
    APPROVE
    .
  • Comment review. If the decision is
    COMMENT
    and
    <REPORT_PATH>.inline.json
    exists and is non-empty, the script assembles a PR review payload (
    {event: COMMENT, body: <report>, comments: [...]}
    ) and submits it via
    gh api /repos/{O}/{R}/pulls/{N}/reviews
    . This produces ONE review event in the PR timeline with a top-level summary body AND inline review comments anchored to specific files+lines — the native GitHub review UX. The API response's
    html_url
    is used directly (no marker lookup needed).
  • Top-level fallback. If the decision is
    COMMENT
    and
    <REPORT_PATH>.inline.json
    is absent or empty (no findings had
    file
    +
    line
    ), or if the PR-review API call fails (most common cause: reviewer-supplied line numbers aren't in the PR's diff), the script falls back to
    gh pr comment --body-file <REPORT_PATH>
    and recovers the URL via paginated marker lookup with one retry for read-after-write lag.
In all paths, the marker UUID is prepended to the report body (idempotently — retries don't stack markers) before posting, so URL recovery remains possible even on the fallback path. An
APPROVE
decision is additionally checked against the PR's current head SHA and downgraded to
COMMENT
if the PR moved since the review.
GitHub comment shape. The engine is expected to write a concise PR-summary report that includes every finding once. Decision-critical content stays visible: review decision, result, scope, and actionable findings. Audit-heavy content uses native GitHub
<details>
blocks by default: Run details are always collapsed; prior-feedback, would-apply, deferred/out-of-scope, and low/nit sections collapse when they grow beyond the engine's thresholds. The helper posts that report body as written and preserves the expandable content; it does not delete, summarize, or shorten generated prose before submitting it to GitHub. If GitHub rejects an unusually large payload, posting fails with the report left at
<REPORT_PATH>
; the running agent should rewrite the report with the same findings, rationale, and actionable detail in a better organized form, then retry posting. Do not silently drop rationale.
Inline comment shape. Before submitting a PR review, the helper filters
<REPORT_PATH>.inline.json
. Inline comments default to
critical
/
high
/
medium
findings (
REVIEW_ANVIL_INLINE_MIN_SEVERITY=medium
); lower-severity findings remain in the top-level summary. Each new body has a natural bold title and ends with hidden
id
,
severity
, and
area
metadata. The helper strips helper-only JSON fields before calling GitHub, inserts any safe exact suggestion and reintroduced-prior-feedback marker before the finding metadata, and keeps the finding marker as the final line.
The helper-only
"severity"
must match the terminal marker severity exactly; the helper aborts before filtering or posting when they disagree. A present but unrecognized helper severity also aborts; an absent helper field may use the terminal marker during migration.
Prior-feedback continuity. Before review, the engine fetches every root review thread with open/resolved/outdated state plus findings from earlier review-anvil review bodies and fallback comments. Reviewers must account for every ledger item; GitHub
resolved
means only that the discussion closed, not that the code was proven fixed. Immediately before posting, the helper refreshes this paginated history and suppresses an exact canonical finding ID on the same path even when its prose changed. Different canonical IDs remain distinct. When one side has no comparable canonical ID, legacy path-and-text matching remains available. The finding stays in a status-labeled
Prior PR feedback
report section, so open and resolved-but-still-present findings remain visible and affect the decision without creating duplicate conversations. Explicit local suppressions from
$REVIEW_ANVIL_DISMISSALS
remain categorical. If history cannot be fetched after retry, posting aborts rather than publishing a review that ignores prior feedback.
Only the PR author resolving a GitHub review thread creates
author-resolved
status. This requires the API-confirmed
resolvedBy
identity to match the PR author; ordinary thread resolution remains
resolved
and is revalidated.
Scope discipline. The posted review should separate actionable in-scope findings from obvious pre-existing issues. Findings unrelated to the PR's stated purpose should appear, at most, under "Out-of-scope follow-ups" as separate-PR work and should not be emitted as inline actionable comments. Follow-ups are auto-approved only when they are confirmed, high-confidence
critical
/
high
(or clearly reproducible
medium
), not product/style decisions, not already tracked/dismissed, and separable from the current PR; ambiguous ones remain
needs_triage
.
Cleanup on success. After a successful post (comment or approval), the helper removes
<REPORT_PATH>
,
<REPORT_PATH>.inline.json
,
<REPORT_PATH>.approval.json
, and
<REPORT_PATH>.followups.json
, and attempts to
rmdir
the parent directory (succeeds only if empty — concurrent runs are unaffected). On any abort (
die
), the artifacts are left in place so the user can inspect or post manually.
bash
bash <helper-path> post "$HOST" "$OWNER" "$REPO" "$N" "$MARKER" "$REPORT_PATH"
脚本会从
<REPORT_PATH>.approval.json
中选择GitHub审核事件类型(
APPROVE
COMMENT
;如果不存在则默认
COMMENT
),然后发布报告:
  • 批准/混合审核。如果决策是
    APPROVE
    ,辅助工具会提交GitHub批准审核。如果
    <REPORT_PATH>.inline.json
    非空,其中的评论会作为非阻塞性发现或建议包含在内;默认情况下,辅助工具会发布
    critical
    /
    high
    /
    medium
    级别的内联评论,低严重级别的条目保留在顶级正文中,除非降低
    REVIEW_ANVIL_INLINE_MIN_SEVERITY
    的值。否则批准仅包含顶级正文。当没有
    critical
    /
    high
    级别的可操作范围内发现时使用此模式;中低级问题会发布但由作者自行处理。如果GitHub拒绝批准(最常见原因:无法批准自己的PR),辅助工具会降级为评论审核,在报告末尾添加说明解释降级原因,并继续回退到顶级备选方案——批准失败绝不会导致报告丢失。意外或格式错误的
    approval.json
    同样默认使用
    COMMENT
    ,绝不会使用
    APPROVE
  • 评论审核。如果决策是
    COMMENT
    <REPORT_PATH>.inline.json
    存在且非空,脚本会组装PR审核负载(
    {event: COMMENT, body: <report>, comments: [...]}
    )并通过
    gh api /repos/{O}/{R}/pulls/{N}/reviews
    提交。这会在PR时间线中生成一个审核事件,包含顶级摘要正文以及锚定到特定文件+行的内联审核评论——这是GitHub原生的审核用户体验。API响应的
    html_url
    会直接使用(无需标记查找)。
  • 顶级备选方案。如果决策是
    COMMENT
    <REPORT_PATH>.inline.json
    不存在或为空(没有带
    file
    +
    line
    的发现),或者PR审核API调用失败(最常见原因:审核员提供的行号不在PR的差异中),脚本会回退到
    gh pr comment --body-file <REPORT_PATH>
    ,并通过分页标记查找恢复URL,针对读写延迟进行一次重试。
在所有路径中,标记UUID会被前置到报告正文(幂等——重试不会叠加标记),以便即使在回退路径下也能恢复URL。
APPROVE
决策还会与PR当前的头部SHA进行检查,如果审核期间PR发生变化,会降级为
COMMENT
GitHub评论格式。引擎应编写简洁的PR摘要报告,每个发现仅出现一次。决策关键内容保持可见:审核决策、结果、范围和可操作发现。审计相关内容默认使用GitHub原生的
<details>
块:运行详情始终折叠;当prior-feedback、would-apply、deferred/out-of-scope以及low/nit部分超过引擎阈值时会折叠。辅助工具按原样发布报告正文,保留可展开内容;提交到GitHub前不会删除、总结或缩短生成的文本。如果GitHub拒绝异常大的负载,发布会失败,报告保留在
<REPORT_PATH>
;运行中的Agent应重新组织报告,保留相同的发现、理由和可操作细节,然后重试发布。不得静默丢弃理由。
内联评论格式。提交PR审核前,辅助工具会过滤
<REPORT_PATH>.inline.json
。内联评论默认包含
critical
/
high
/
medium
级别的发现(
REVIEW_ANVIL_INLINE_MIN_SEVERITY=medium
);低严重级别的发现保留在顶级摘要中。每个新正文都有一个自然的粗体标题,并以隐藏的
id
severity
area
元数据结尾。辅助工具在调用GitHub前会删除仅辅助工具使用的JSON字段,在发现元数据前插入任何安全的精确建议和重新引入的prior-feedback标记,并将发现标记作为最后一行。
仅辅助工具使用的
"severity"
必须与终端标记的严重级别完全匹配;如果不匹配,辅助工具会在过滤或发布前中止。 存在但无法识别的辅助工具严重级别也会导致中止;迁移期间如果缺少辅助工具字段,可以使用终端标记的严重级别。
历史反馈连续性。审核前,引擎会获取所有处于打开/已解决/已过时状态的根审核线程,以及来自早期review-anvil审核正文和备选评论的发现。审核员必须考虑所有记录项;GitHub的
resolved
仅表示讨论已关闭,不代表代码已被证明修复。发布前,辅助工具会刷新此分页历史,并抑制同一路径上的完全相同的规范发现ID,即使其文本已更改。不同的规范ID保持区分。当某一方没有可比较的规范ID时,仍可使用传统的路径和文本匹配。发现会保留在标记状态的
Prior PR feedback
报告部分,因此打开和已解决但仍存在的发现保持可见并影响决策,不会创建重复对话。来自
$REVIEW_ANVIL_DISMISSALS
的显式本地抑制仍然是绝对的。如果重试后仍无法获取历史,发布会中止,而不是发布忽略历史反馈的审核。
只有PR作者解决GitHub审核线程才会创建
author-resolved
状态。这需要API确认的
resolvedBy
身份与PR作者匹配;普通线程解决仍为
resolved
并会重新验证。
范围约束。发布的审核应将可操作的范围内发现与明显的预先存在的问题分开。与PR声明目的无关的发现最多应出现在“Out-of-scope follow-ups”下作为单独PR的工作,不应作为内联可操作评论发出。只有当后续任务被确认是高置信度的
critical
/
high
级别(或清晰可重现的
medium
级别)、不是产品/风格决策、未被跟踪/驳回且可与当前PR分离时,才会自动批准;模糊的后续任务保持
needs_triage
状态。
成功后的清理。成功发布(评论或批准)后,辅助工具会删除
<REPORT_PATH>
<REPORT_PATH>.inline.json
<REPORT_PATH>.approval.json
<REPORT_PATH>.followups.json
,并尝试删除父目录(仅当目录为空时成功——不影响并发运行)。任何中止(
die
)时,工件会保留在原地,以便用户检查或手动发布。

5. Report back

5. 向用户反馈

Surface the URL (or
posted (URL unavailable)
) to the user. If the helper script exited non-zero from
post
, surface its stderr; the report still exists on disk at
<REPORT_PATH>
for manual posting.
向用户展示URL(或
posted (URL unavailable)
)。如果辅助工具在
post
步骤中非零退出,显示其标准错误信息;报告仍保存在磁盘的
<REPORT_PATH>
中,可手动发布。

Examples

示例

  • "Review the PR I'm on and post the result back." — user is checked out on a PR branch. Agent invokes
    init
    with no locator; helper detects the PR via
    gh pr view
    .
  • "Review https://github.com/acme/widgets/pull/137 with a focus on security." — explicit URL locator; extra arg
    focus: security
    flows through to the engine.
  • "Review acme/widgets#42 and use 2 rounds of reviewer redundancy." — slug locator;
    rounds: 2
    overrides the preset's
    rounds: 1
    default.
  • "Review acme/widgets#42 with adversarial: targeted." — force targeted adversarial review after normal synthesis.
  • "Review acme/widgets#42 with adversarial: off." — skip adversarial review and post COMMENT-only feedback.
  • “审核我当前所在的PR并发布结果。” — 用户已检出PR分支。Agent不带定位符调用
    init
    ;辅助工具通过
    gh pr view
    检测PR。
  • “审核https://github.com/acme/widgets/pull/137,重点关注安全性。” — 显式URL定位符;额外参数
    focus: security
    传递给引擎。
  • “审核acme/widgets#42,使用2轮审核员冗余。” — 简短标识定位符;
    rounds: 2
    覆盖预设的
    rounds: 1
    默认值。
  • “审核acme/widgets#42,使用adversarial: targeted模式。” — 在正常合成后强制进行针对性对抗性审核。
  • “审核acme/widgets#42,使用adversarial: off模式。” — 跳过对抗性审核,仅发布COMMENT反馈。

Constraints

约束条件

  • Requires
    gh
    ,
    uuidgen
    ,
    jq
    (a real binary — gh's
    --jq
    is built-in gojq and doesn't count), and
    uv
    (preferred; falls back to
    python3
    ) for PR-feedback history handling.
    init
    preflights all of these so a missing dependency fails before the expensive review, not after.
  • Environment switches honored by the helper:
    REVIEW_ANVIL_NO_APPROVE=1
    (never submit an approval),
    REVIEW_ANVIL_SKIP_DISMISSED=1
    (legacy name: skip the full PR-history lookup for hosts without GraphQL access — degraded mode that also forces COMMENT),
    REVIEW_ANVIL_DISMISSALS=<path>
    (local-suppressions file, default
    ~/.review-anvil/dismissed-findings.json
    ; record entries with
    pr-helper.sh dismiss <host> <owner> <repo> <n> <path> <pattern> [<reason>]
    ),
    REVIEW_ANVIL_INLINE_MIN_SEVERITY=<critical|high|medium|low|nit>
    (minimum severity posted inline; default
    medium
    ), and
    REVIEW_ANVIL_ENABLE_SUGGESTIONS=0
    (disable helper-added GitHub suggestion blocks).
  • An
    APPROVE
    decision submits a real GitHub approval from your authenticated
    gh
    account.
    It counts toward branch-protection required reviews and reads to collaborators as your judgment — while the gate behind it is the engine's LLM classification. If that posture isn't acceptable for a repo or org, pass
    approve: never
    (or "never approve" / "comment only") and the run always posts plain
    COMMENT
    reviews.
    REQUEST_CHANGES
    is deliberately unsupported: blocking someone's merge on LLM judgment is a different risk class from commenting or approving.
  • What lands on the PR has passed the engine's reproduction/verification gates: uncertain
    medium
    + findings are reproduced against the actual code before posting. When a finding cannot be confirmed, the report says what proof is missing and that it was set aside, rather than presenting it as an actionable review comment. False positives posted to a colleague's PR burn trust — the engine treats precision as the product.
  • When
    adversarial:
    is enabled, the posted report should include only the final verdict summary and survivor findings. The adversarial transcript stays out of GitHub; its effects are folded into dropped findings, deferred disproportionate fixes, hardened fix paths, stripped suggestion blocks, and approval downgrades.
  • Read-only by design — the PR's branch may not be checked out locally, and pushing fix commits to a PR you don't own is rarely the intent. If you want to fix-and-commit on a PR you have checked out, activate
    review-anvil
    directly with
    target: branch
    (your checked-out PR branch) and
    commit_mode=per_fix
    — the local working tree becomes the source of truth and the diff against the merge base is unambiguous.
  • Supports github.com and GitHub Enterprise — the script extracts the host from the URL and sets
    GH_HOST
    internally for all
    gh
    invocations.
  • Bare-integer PR locators are rejected — pass a URL or
    <owner>/<repo>#<N>
    slug to be unambiguous about repo identity.
  • 需要
    gh
    uuidgen
    jq
    (真实二进制文件——gh内置的
    --jq
    是gojq,不满足要求)以及
    uv
    (首选;回退到
    python3
    )来处理PR反馈历史。
    init
    预检查所有这些依赖,因此缺失的依赖会在昂贵的审核前失败,而不是之后。
  • 辅助工具支持的环境变量:
    REVIEW_ANVIL_NO_APPROVE=1
    (从不提交批准)、
    REVIEW_ANVIL_SKIP_DISMISSED=1
    (旧名称:为无GraphQL访问权限的宿主跳过完整PR历史查找——降级模式,同时强制使用COMMENT)、
    REVIEW_ANVIL_DISMISSALS=<path>
    (本地抑制文件,默认
    ~/.review-anvil/dismissed-findings.json
    ;使用
    pr-helper.sh dismiss <host> <owner> <repo> <n> <path> <pattern> [<reason>]
    记录条目)、
    REVIEW_ANVIL_INLINE_MIN_SEVERITY=<critical|high|medium|low|nit>
    (内联发布的最低严重级别;默认
    medium
    )、
    REVIEW_ANVIL_ENABLE_SUGGESTIONS=0
    (禁用辅助工具添加的GitHub建议块)。
  • APPROVE
    决策会从您已认证的
    gh
    账户提交真实的GitHub批准。
    它会计入分支保护所需的审核次数,并向协作者传达您的判断——而背后的依据是引擎的LLM分类。如果这种方式在某个仓库或组织中不可接受,请传入
    approve: never
    (或“never approve”/“comment only”),运行将始终发布普通的
    COMMENT
    审核。
    REQUEST_CHANGES
    被故意不支持:基于LLM判断阻止他人合并属于不同的风险类别,不同于评论或批准。
  • 发布到PR的内容已通过引擎的重现/验证关卡:不确定的
    medium
    +级别发现会在发布前针对实际代码进行重现。当发现无法确认时,报告会说明缺少的证据以及该发现已被搁置,而不是将其作为可操作的审核评论呈现。向同事的PR发布误报会损害信任——引擎将精确性视为核心目标。
  • 当启用
    adversarial:
    模式时,发布的报告应仅包含最终结论摘要和留存的发现。对抗性记录不会出现在GitHub上;其效果体现在删除的发现、延迟处理的过度修复、强化的修复路径、移除的建议块以及批准降级中。
  • 设计为只读模式——PR分支可能未在本地检出,向不属于您的PR推送修复提交很少是用户的意图。如果您想在已检出的PR上进行修复并提交,请直接激活
    review-anvil
    ,使用
    target: branch
    (您已检出的PR分支)和
    commit_mode=per_fix
    ——本地工作树成为数据源,与合并基准的差异明确无误。
  • 支持github.com和GitHub Enterprise——脚本从URL中提取主机,并在所有
    gh
    调用内部设置
    GH_HOST
  • 拒绝纯整数PR定位符——传入URL或
    <owner>/<repo>#<N>
    简短标识以明确仓库身份。

Recovery: orphaned artifacts

恢复:孤立工件

If the orchestrator dies between the engine finishing and the post step, the artifacts remain under
.review-anvil/
(self-gitignored — they can't dirty the worktree or end up in commits). Re-run step 4's
post
with the captured values to publish them: the helper's head-SHA check downgrades a stale APPROVE if the PR moved in the meantime, and the marker lookup prevents double posts if a previous attempt partially succeeded. Leftovers from runs you don't want to publish can simply be deleted.
如果编排器在引擎完成和发布步骤之间崩溃,工件会保留在
.review-anvil/
下(自动被git忽略——不会污染工作树或进入提交)。使用捕获的值重新运行步骤4的
post
即可发布:辅助工具的头部SHA检查会在PR发生变化时将过期的APPROVE降级为COMMENT,标记查找会防止之前部分成功的尝试导致重复发布。对于不想发布的运行残留文件,直接删除即可。

Pairing

配对

This preset depends on the
review-anvil
engine being available in the same agent. Both skills ship in the same plugin and should be installed together (
npx skills add mrshu/agent-skills --skill review-anvil --skill review-anvil-pr
, or just
--all
).
本预设依赖于同一Agent中可用的
review-anvil
引擎。两个技能在同一插件中发布,应一起安装(
npx skills add mrshu/agent-skills --skill review-anvil --skill review-anvil-pr
,或直接使用
--all
)。