fix-verify-loop

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Fix-Verify Loop

Fix-Verify Loop

fix-verify-loop is a bounded resolver. Input: confirmed P0/P1 findings. Output: staged code where each listed finding is resolved, OR an escalation list of findings it could not resolve in 2 attempts.
It verifies ONLY per-finding resolution. Regression detection, finding new issues, and reviewing the diff as a whole are explicitly NOT its job — those belong to whoever reviews the diff next (caller's choice).
fix-verify-loop 是一个受限 resolver。输入:已确认的P0/P1问题。输出:已暂存的代码(其中列出的每个问题均已解决),或包含两次尝试后仍无法解决的问题的升级列表。
它仅验证单个问题的解决情况。回归检测、发现新问题以及整体审查差异明确不属于它的职责——这些工作属于下一位审查差异的人员(由调用方选择)。

When to use

使用场景

After a two-pass-review (or any review) produces confirmed P0/P1 findings that need fixing. Also after test failures that need code or test fixes.
在两轮审查(或任何审查)产生需要修复的已确认P0/P1问题之后使用。也可用于需要修复代码或测试的测试失败场景。

Protocol

协议

Input

输入

  • Findings: confirmed P0/P1 findings conforming to the Output Schema below
  • Artifact paths: files to fix
  • Criteria: the original criteria the fix must satisfy
Intake filter: Only process findings where
verdict = "confirmed"
and
severity in ["P0", "P1"]
. Ignore P2/P3 findings — they are out of scope. Note: findings with
verdict: "confirmed"
are accepted regardless of source — the caller is responsible for confirmation quality (e.g., an orchestrator may set this as an escape hatch for review findings that have no verifier pass).
Pre-gate (findings without an independent verifier pass): A finding requires a verifier pre-gate BEFORE Round 1 if it has not been verifier-validated. Detect via:
  • evidence
    field is null or missing, OR
  • evidence
    field starts with "Orchestrator-confirmed".
Confidence is the reviewer or verifier's honest signal — it does not by itself trigger pre-gate. Pre-gate's job is to catch findings that haven't been independently verified, not findings that the verifier already vouched for at low confidence.
For these findings, run this pre-gate first:
  1. Spawn the
    verifier
    agent with: Artifact = the finding's file (or surrounding context), Findings = the single finding, Criteria = "is this finding real?".
  2. If verifier returns
    rejected
    → adds to
    dropped
    bucket → drop the finding from fix-verify-loop. Skip to next finding.
  3. If verifier returns
    confirmed
    or
    demoted
    (still real) → proceed to Round 1 normally.
  4. If verifier output is inconclusive (no parseable verdict) → treat as a failed attempt. Proceed to Round 1 anyway (this consumes one of the two attempts; see inconclusive rule below).
Findings that pass the intake filter and either don't trigger the pre-gate or pass it proceed to Round 1.
  • 问题:符合下方输出 Schema的已确认P0/P1问题
  • 工件路径:需要修复的文件
  • 判定标准:修复必须满足的原始标准
准入过滤:仅处理
verdict = "confirmed"
severity in ["P0", "P1"]
的问题。忽略P2/P3级问题——它们超出范围。注意:无论来源如何,
verdict: "confirmed"
的问题都会被接受——调用方负责确认质量(例如,编排器可能将此作为审查问题的逃生通道,这些问题没有验证器通过记录)。
预检查(无独立验证器通过的问题):如果问题未经过验证器验证,则在第一轮之前需要进行预检查。通过以下方式检测:
  • evidence
    字段为null或缺失,或者
  • evidence
    字段以"Orchestrator-confirmed"开头。
置信度是审查者或验证者的真实信号——它本身不会触发预检查。预检查的作用是捕获未经过独立验证的问题,而不是验证者已低置信度认可的问题。
对于这些问题,先运行以下预检查:
  1. 启动
    verifier
    agent,参数为:Artifact = 问题对应的文件(或上下文),Findings = 单个问题,Criteria = "这个问题是否真实存在?"。
  2. 如果验证者返回
    rejected
    → 加入
    dropped
    桶 → 将问题从fix-verify-loop中移除。跳过至下一个问题。
  3. 如果验证者返回
    confirmed
    demoted
    (仍然真实存在) → 正常进入第一轮。
  4. 如果验证者输出无结论(无法解析的verdict) → 视为尝试失败。仍进入第一轮(这会消耗两次尝试中的一次;见下方无结论规则)。
通过准入过滤且未触发预检查或通过预检查的问题进入第一轮。

Per-finding loop

单个问题循环

Process findings sequentially, one at a time. Do not batch. For each finding, run Round 1; if not resolved, run Round 2; if still not resolved, escalate. Round 1 and Round 2 mirror each other in shape — same fix-then-verify dispatch, same verifier question.
Include these rules in every fix-subagent brief:
  • Keep Git mutations scoped to assigned files: never run
    git stash
    ,
    git checkout -- .
    ,
    git reset
    , or another command that changes the whole tree.
  • Scope every Git read to assigned paths.
  • Read a committed baseline without changing shared state with
    git show HEAD:<path>
    .
按顺序逐个处理问题,不批量处理。针对每个问题,运行第一轮;如果未解决,运行第二轮;如果仍未解决,则升级处理。第一轮和第二轮流程一致——都是先修复再验证,验证的问题相同。
在每个修复子代理的任务说明中包含以下规则:
  • Git变更仅限指定文件:绝不运行
    git stash
    git checkout -- .
    git reset
    或其他会修改整个代码树的命令。
  • 所有Git读取操作仅限指定路径。
  • 使用
    git show HEAD:<path>
    读取已提交的基线,不修改共享状态。

Preconditions — pre-staged hunk check

前置条件 — 预暂存代码块检查

This check fires in Round 1 only, AFTER the fix subagent declares
files_changed
and BEFORE staging. The fix subagent doesn't know what files it will touch until it runs, so the Round 1 order is: spawn fix → check pre-staged hunks → stage → verify. In Round 2, any pre-existing staged content is from Round 1's prior attempt and not user-authored — the check would fire spuriously, so we skip it. Round 2 order is: spawn fix → stage → verify.
Before staging (Round 1 only):
  • Run
    git diff --staged -- <files the fix will touch>
    (the
    files_changed
    returned by the fix subagent).
  • If non-empty (pre-existing staged hunks exist in those files):
    • Inspect the hunks. Form a heuristic judgment:
      • No overlap with the fix's likely lines, hunks small, look unrelated → recommend "Commit pre-existing first"
      • Overlap with the fix's lines, OR hunks large/sprawling → recommend "Stash pre-existing"
      • Hunks clearly continue the fix's logical change → recommend "Proceed (treat as part of this fix)"
    • Use the
      AskUserQuestion
      tool with options "Commit pre-existing first", "Stash pre-existing", "Proceed (treat as part of this fix)". Include a one-line summary of what was found (e.g., "3 hunks in auth.js totaling 18 lines, no overlap with fix's edits"). Surface the heuristic recommendation as the first option labeled "(Recommended)".
此检查仅在第一轮触发,在修复子代理声明
files_changed
之后、暂存之前。修复子代理在运行前不知道会修改哪些文件,因此第一轮的顺序是:启动修复 → 检查预暂存代码块 → 暂存 → 验证。在第二轮中,任何已存在的暂存内容来自第一轮的尝试,而非用户编写——检查会误触发,因此跳过。第二轮顺序是:启动修复 → 暂存 → 验证。
暂存前(仅第一轮):
  • 运行
    git diff --staged -- <files the fix will touch>
    (修复子代理返回的
    files_changed
    )。
  • 如果结果非空(这些文件中存在已预暂存的代码块):
    • 检查代码块,形成启发式判断:
      • 与修复可能修改的行无重叠,代码块小,看起来无关 → 建议"先提交已预暂存的内容"
      • 与修复的行有重叠,或代码块大/分散 → 建议"暂存已预暂存的内容"
      • 代码块明显延续修复的逻辑变更 → 建议"继续(视为本次修复的一部分)"
    • 使用
      AskUserQuestion
      工具,选项为"先提交已预暂存的内容"、"暂存已预暂存的内容"、"继续(视为本次修复的一部分)"。附上一行发现内容的摘要(例如,"auth.js中有3个代码块共18行,与修复编辑无重叠")。将启发式建议作为第一个选项标注"(推荐)"。

Round 1 — Fix + Verify

第一轮 — 修复 + 验证

  1. Fix. Spawn a fix subagent (Opus). Subagent receives: the finding (full schema), the affected file path(s), the criterion it violates. Subagent edits the working tree and returns
    { files_changed: [paths], summary: string, concerns: [string] | null }
    .
  2. Pre-staging check. Run the Preconditions check on
    files_changed
    .
  3. Stage.
    git add <files_changed>
    — do NOT commit. The user decides when to commit.
  4. Verify. Spawn the
    verifier
    agent with:
    • Artifact: the staged diff scoped to this finding's files (
      git diff --staged -- <files_changed>
      )
    • Findings: the original finding being fixed (single)
    • Criteria: ONLY "is this finding resolved?"
    • Output contract: "Return a ReviewOutput envelope (see Output Schema) with a verdict on the single finding."
  5. Decide. Map the verifier's verdict on the finding:
    • confirmed
      → still real and still in scope (P0/P1) → not resolved → proceed to Round 2.
    • rejected
      → not a real issue → adds to
      resolved
      bucket → done.
    • demoted
      → check the new severity:
      • new severity in [P0, P1] → still in fix-verify-loop scope → proceed to Round 2.
      • new severity in [P2, P3] → out of fix-verify-loop scope → adds to
        demoted
        bucket → done (the issue exists at lower severity; hand-off implicit).
    • Inconclusive (the verifier subagent fails to return a parseable ReviewOutput — crash, malformed output, no verdict on the finding) → counts as a failed attempt. Proceed to Round 2. No retry loop.
  1. 修复。启动修复子代理(Opus)。子代理接收:完整Schema的问题、受影响的文件路径、违反的判定标准。子代理编辑工作树并返回
    { files_changed: [paths], summary: string, concerns: [string] | null }
  2. 预暂存检查。对
    files_changed
    运行前置条件检查。
  3. 暂存。运行
    git add <files_changed>
    — 不提交。由用户决定何时提交。
  4. 验证。启动
    verifier
    agent,参数为:
    • Artifact:针对此问题文件的暂存差异(
      git diff --staged -- <files_changed>
    • Findings:待修复的原始问题(单个)
    • Criteria:仅为"这个问题是否已解决?"
    • Output contract:"返回一个ReviewOutput信封(见Output Schema),包含对单个问题的verdict。"
  5. 决策。根据验证者对问题的verdict进行处理:
    • confirmed
      → 问题仍然真实存在且在范围内(P0/P1) → 未解决 → 进入第二轮
    • rejected
      → 不是真实问题 → 加入
      resolved
      桶 → 完成
    • demoted
      → 检查新的严重程度:
      • 新严重程度为[P0, P1] → 仍在fix-verify-loop范围内 → 进入第二轮
      • 新严重程度为[P2, P3] → 超出fix-verify-loop范围 → 加入
        demoted
        桶 → 完成(问题仍存在但严重程度较低;隐含移交)。
    • 无结论(验证子代理未能返回可解析的ReviewOutput——崩溃、格式错误的输出、无问题verdict) → 视为尝试失败。进入第二轮。无重试循环。

Round 2 — Fix + Verify

第二轮 — 修复 + 验证

Same shape as Round 1. The only difference is the fix subagent gets Round 1 context.
  1. Fix. Spawn another fix subagent with full Round 1 context (what was attempted, why it didn't work, the verifier's evidence). Subagent returns
    { files_changed: [paths], summary: string, concerns: [string] | null }
    .
  2. Stage.
    git add <files_changed>
    . (No pre-staging check in Round 2 — see Preconditions for why.)
  3. Verify. Same dispatch as Round 1 — verifier asked "is this finding resolved?" on the single finding.
  4. Decide. Map the verifier's verdict on the finding:
    • confirmed
      → still real and still in scope (P0/P1) → not resolved → adds to
      escalated
      bucket → escalate (do not attempt Round 3).
    • rejected
      → not a real issue → adds to
      resolved
      bucket → done.
    • demoted
      → check the new severity:
      • new severity in [P0, P1] → still in fix-verify-loop scope → adds to
        escalated
        bucket → escalate.
      • new severity in [P2, P3] → out of fix-verify-loop scope → adds to
        demoted
        bucket → done (the issue exists at lower severity; hand-off implicit).
    • Inconclusive (the verifier subagent fails to return a parseable ReviewOutput) → counts as a failed attempt → adds to
      escalated
      bucket → escalate. No retry loop.
与第一轮流程一致。唯一区别是修复子代理会获得第一轮的上下文。
  1. 修复。启动另一个修复子代理,提供完整的第一轮上下文(尝试了什么、为什么失败、验证者的证据)。子代理返回
    { files_changed: [paths], summary: string, concerns: [string] | null }
  2. 暂存。运行
    git add <files_changed>
    。(第二轮无预暂存检查——原因见前置条件。)
  3. 验证。与第一轮调度相同——验证者被问及"这个问题是否已解决?"(针对单个问题)。
  4. 决策。根据验证者对问题的verdict进行处理:
    • confirmed
      → 问题仍然真实存在且在范围内(P0/P1) → 未解决 → 加入
      escalated
      桶 → 升级处理(不尝试第三轮)。
    • rejected
      → 不是真实问题 → 加入
      resolved
      桶 → 完成
    • demoted
      → 检查新的严重程度:
      • 新严重程度为[P0, P1] → 仍在fix-verify-loop范围内 → 加入
        escalated
        桶 → 升级处理
      • 新严重程度为[P2, P3] → 超出fix-verify-loop范围 → 加入
        demoted
        桶 → 完成(问题仍存在但严重程度较低;隐含移交)。
    • 无结论(验证子代理未能返回可解析的ReviewOutput) → 视为尝试失败 → 加入
      escalated
      桶 → 升级处理。无重试循环。

Escalation

升级处理

If Round 2 still has the finding unresolved:
  • STOP. Do not attempt Round 3.
  • Present to the user in this shape (derive the staged line via
    git diff --staged --stat -- <files_changed>
    ):
    **Escalated — finding not resolved after 2 attempts:**
    - Finding: [ID — title]
    - Attempted: [Round 1 summary] → [Round 2 summary]
    - Still unresolved: [verifier's evidence | verifier inconclusive]
    - Currently staged: [e.g. "R2's changes to auth.js, +12/-4 lines" | nothing staged]
    Then use the
    AskUserQuestion
    tool with options: "Manual fix", "Try a different approach", "Defer this finding", "Discard R2 changes and revert". Recommended: "Defer this finding".
After all findings are processed, return a
FixVerifyLoopOutput
envelope with four buckets:
  • resolved: finding IDs marked done in Round 1 or Round 2 (with the staged files)
  • escalated: findings that hit Round 2 without resolution, with attempt summaries
  • dropped: findings the pre-gate verifier rejected as not-real
  • demoted: findings demoted to P2/P3 by the verifier (out of fix-verify-loop scope)
Bucket assignment by verdict path:
  • Pre-gate
    rejected
    dropped
  • Pre-gate
    confirmed
    or
    demoted
    → proceed to Round 1
  • R1
    rejected
    resolved
  • R1
    confirmed
    (still real, P0/P1) → proceed to Round 2
  • R1
    demoted
    to [P0, P1] → proceed to Round 2
  • R1
    demoted
    to [P2, P3] →
    demoted
  • R2
    rejected
    resolved
  • R2
    confirmed
    (still real, P0/P1) →
    escalated
  • R2
    demoted
    to [P0, P1] →
    escalated
  • R2
    demoted
    to [P2, P3] →
    demoted
如果第二轮后问题仍未解决:
  • 停止。不尝试第三轮。
  • 以以下形式呈现给用户(通过
    git diff --staged --stat -- <files_changed>
    生成暂存行):
    **升级处理 — 两次尝试后问题仍未解决:**
    - 问题:[ID — 标题]
    - 尝试内容:[第一轮摘要] → [第二轮摘要]
    - 仍未解决:[验证者的证据 | 验证无结论]
    - 当前暂存内容:[例如 "R2对auth.js的修改,+12/-4行" | 无暂存内容]
    然后使用
    AskUserQuestion
    工具,选项为:"手动修复"、"尝试其他方法"、"推迟此问题"、"丢弃R2修改并回滚"。推荐选项:"推迟此问题"。
所有问题处理完成后,返回一个
FixVerifyLoopOutput
信封,包含四个桶:
  • resolved:在第一轮或第二轮标记为完成的问题ID(包含暂存文件)
  • escalated:两轮尝试后仍未解决的问题,包含尝试摘要
  • dropped:预检查验证者判定为不真实的问题
  • demoted:被验证者降级为P2/P3的问题(超出fix-verify-loop范围)
根据verdict路径分配桶:
  • 预检查
    rejected
    dropped
  • 预检查
    confirmed
    demoted
    → 进入第一轮
  • 第一轮
    rejected
    resolved
  • 第一轮
    confirmed
    (仍然真实,P0/P1) → 进入第二轮
  • 第一轮
    demoted
    至[P0, P1] → 进入第二轮
  • 第一轮
    demoted
    至[P2, P3] →
    demoted
  • 第二轮
    rejected
    resolved
  • 第二轮
    confirmed
    (仍然真实,P0/P1) →
    escalated
  • 第二轮
    demoted
    至[P0, P1] →
    escalated
  • 第二轮
    demoted
    至[P2, P3] →
    demoted

Rules

规则

  • Max 2 attempts. Never loop beyond Round 2.
  • Scoped fixes. Fix subagents must NOT edit files outside the scope of their finding without user approval. If a fix requires additional files, the subagent must FIRST return
    { needs_scope_expansion: true, additional_files: [paths], justification: string }
    instead of making edits. The parent then uses the
    AskUserQuestion
    tool with options: "Approve expanded scope", "Reject — fix within original scope only", "Defer this finding". Recommended: "Approve expanded scope" (include the justification and file list). On approval, re-dispatch the subagent with expanded scope. Additional files are included in verification.
  • Always verify. Every fix gets the verifier-on-one-question check. Don't skip — the verifier agent is the only verification mechanism this skill uses.
  • Test failures. Determine if it's a code bug or test bug first, then fix the right one. This judgment happens during the fix subagent's work — the subagent inspects the failure and the test, decides which is wrong, and fixes the right one. The skill itself does not branch on this; it's part of the fix subagent's task.

  • 最多2次尝试。绝不循环超过第二轮。
  • 范围限定修复。修复子代理不得在未经用户批准的情况下编辑问题范围外的文件。如果修复需要额外文件,子代理必须先返回
    { needs_scope_expansion: true, additional_files: [paths], justification: string }
    ,而不是直接修改。父代理随后使用
    AskUserQuestion
    工具,选项为:"批准扩展范围"、"拒绝——仅在原范围内修复"、"推迟此问题"。推荐选项:"批准扩展范围"(包含理由和文件列表)。批准后,重新调度子代理并扩展范围。额外文件会包含在验证中。
  • 始终验证。每个修复都要经过验证者的单一问题检查。不得跳过——验证者agent是此skill唯一的验证机制。
  • 测试失败。首先确定是代码bug还是测试bug,然后修复正确的部分。此判断在修复子代理的工作中完成——子代理检查失败情况和测试,判断哪部分有问题,并修复正确的部分。skill本身不会在此分支处理;这是修复子代理任务的一部分。

Output Schema

Output Schema

FixVerifyLoopOutput

FixVerifyLoopOutput

The skill returns this envelope after all findings are processed:
{
  resolved: [Finding.id, ...],            // fixed in R1 or R2
  escalated: [{                           // could not be fixed in 2 attempts
    id: Finding.id,
    attempts: [string, string],           // R1 + R2 summaries
    evidence: string | null,              // verifier's evidence (null if R2 was inconclusive)
    staged_summary: string                // e.g., "R2's changes to auth.js, +12/-4 lines"
  }, ...],
  dropped: [{                             // pre-gate verifier rejected as not-real
    id: Finding.id,
    reason: string                        // verifier's rejection evidence
  }, ...],
  demoted: [{                             // demoted to P2/P3 (out of scope)
    id: Finding.id,
    new_severity: "P2" | "P3",
    evidence: string                      // verifier's demotion reasoning
  }, ...]
}
<!-- source: references/finding-schema.md -->
所有问题处理完成后,skill返回此信封:
{
  resolved: [Finding.id, ...],            // 在R1或R2中修复
  escalated: [{                           // 两次尝试后仍无法修复
    id: Finding.id,
    attempts: [string, string],           // R1 + R2摘要
    evidence: string | null,              // 验证者的证据(如果R2无结论则为null)
    staged_summary: string                // 例如 "R2对auth.js的修改,+12/-4行"
  }, ...],
  dropped: [{                             // 预检查验证者判定为不真实
    id: Finding.id,
    reason: string                        // 验证者的拒绝证据
  }, ...],
  demoted: [{                             // 降级为P2/P3(超出范围)
    id: Finding.id,
    new_severity: "P2" | "P3",
    evidence: string                      // 验证者的降级理由
  }, ...]
}
<!-- source: references/finding-schema.md -->

Finding

Finding

Finding {
  id: sequential number starting from 1,
  severity: "P0" | "P1" | "P2" | "P3",
  title: short title,
  body: detailed explanation with evidence,
  file: file path or null for global issues,
  line_start: number or null,
  line_end: number or null,
  confidence: 0.0-1.0,
  criterion: what was violated,
  verdict: "confirmed" | "demoted" | "rejected" | null,
  evidence: reasoning for verdict | null
}
Finding {
  id: 从1开始的连续编号,
  severity: "P0" | "P1" | "P2" | "P3",
  title: 简短标题,
  body: 包含证据的详细说明,
  file: 文件路径或全局问题为null,
  line_start: 数字或null,
  line_end: 数字或null,
  confidence: 0.0-1.0,
  criterion: 违反的标准,
  verdict: "confirmed" | "demoted" | "rejected" | null,
  evidence: verdict的理由 | null
}

ReviewOutput

ReviewOutput

Findings are wrapped in a
ReviewOutput
envelope:
ReviewOutput {
  schema_version: "v1",
  findings: Finding[],
  checks_run: string[]
}
问题被包裹在
ReviewOutput
信封中:
ReviewOutput {
  schema_version: "v1",
  findings: Finding[],
  checks_run: string[]
}

Severity calibration

严重程度校准

  • P0 — Must fix: breaks functionality, security breach, data loss, or violates criteria
  • P1 — Fix before shipping: correct but incomplete, fragile, or reliability risk
  • P2 — Should fix: quality issue, code smell, not blocking
  • P3 — Nice to have: observation, style, minor improvement
  • P0 — 必须修复:破坏功能、安全漏洞、数据丢失或违反标准
  • P1 — 发布前修复:正确但不完整、脆弱或存在可靠性风险
  • P2 — 应该修复:质量问题、代码异味、不阻塞
  • P3 — 锦上添花:观察结果、风格问题、小改进

Field notes

字段说明

  • confidence
    — 1.0 means certain, below 0.5 means you're guessing. Be honest.
  • criterion
    — required for P0/P1 findings. Name the specific criterion violated.
  • verdict
    — populated by the verifier in two-pass review. Set to
    null
    when producing findings directly.
  • evidence
    — verifier's reasoning for the verdict. Set to
    null
    when producing findings directly.
  • checks_run
    — list every criterion evaluated, file path checked, or acceptance criterion verified. For ACs, use
    AC-NNN-XX: PASS — [evidence]
    or
    AC-NNN-XX: FAIL — [reason]
    .
  • confidence
    — 1.0表示确定,低于0.5表示猜测。请如实填写。
  • criterion
    — P0/P1问题必填。指明违反的具体标准。
  • verdict
    — 由验证者在两轮审查中填写。直接生成问题时设为
    null
  • evidence
    — 验证者对verdict的理由。直接生成问题时设为
    null
  • checks_run
    — 列出所有评估的标准、检查的文件路径或验证的验收标准。对于验收标准,使用
    AC-NNN-XX: PASS — [证据]
    AC-NNN-XX: FAIL — [理由]
    。",