一键导入
review-and-fix
Use when you need findings on a PR or current branch to be auto-applied, not just reported.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when you need findings on a PR or current branch to be auto-applied, not just reported.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Stage B of /devflow-weekly: given the bundled context of every occurrence PR for one recurring pattern, re-derive the root cause, make the intervention edits in the working tree, and return the touched paths + PR title + PR body as JSON. Invoked as a subagent on a branch the orchestrator already created.
Run the weekly devflow self-improvement loop locally: scan freshly-merged watched-author PRs, write per-PR retrospective entries (LLM only for PRs that fail the mechanical clean-gate), derive recurring patterns, and open one human-reviewed intervention PR per actionable pattern. Use when running the weekly devflow retrospective + audit.
Use when setting up external documentation for the first time, performing a comprehensive documentation refresh, or when large portions of internal docs need corresponding external docs created.
Use when setting up internal documentation for the first time, when the docs directory is empty or poorly organized, or when a codebase has no structured developer documentation yet.
Use when a PR has customer-visible changes (new features, bug fixes, UI changes) that need a release note entry, or when finalizing a branch before merge.
Use when internal documentation has been updated and external customer-facing docs need to be aligned, or when checking for outdated, missing, or confidential content in external docs.
| name | review-and-fix |
| description | Use when you need findings on a PR or current branch to be auto-applied, not just reported. |
| argument-hint | pr-number |
You are the review-and-fix orchestrator. Run /devflow:review's review engine, fix the findings it surfaces, and re-run until the engine returns a clean verdict.
Input: Optional PR number as $ARGUMENTS. If omitted, review and fix the current branch.
Key principle: You perform fixes DIRECTLY in this session. Do NOT delegate fixes to a subagent. You need full conversation context to apply superpowers:receiving-code-review principles (technical evaluation, pushback, verification).
/devflow:review and read the report; auto-fixing prose adds churn for little value./devflow:review instead; this skill commits fixes between iterations.--request-changes merge block as a side effect — this skill is silent on GitHub by design. Run /devflow:review <PR> afterward (or instead) to post the verdict as a blocking review.This skill wraps /devflow:review's four-phase engine in a fix loop. Phases 0 through 4.3 — setup, diff classification, checklist generation (including >10-file batching and Phase 1.5 dedup), checklist verification (including lite-mode partition), review agents (including the exact per-agent prompts and the defect_signature contract), and aggregation — live in /devflow:review's SKILL.md and are authoritative. Read them on every Step 1; never improvise the engine or paraphrase the Phase 3 prompts. Drift between the two skills is the single biggest cause of /devflow:review-and-fix missing findings that /devflow:review caught.
This skill skips /devflow:review's Phase 4.4 entirely — no GitHub post. The final report is emitted to chat only; the human reviewer decides whether to convert it into a formal merge signal by running /devflow:review <PR> separately (which performs an independent re-review and posts the result). It also adds:
.devflow/review/<slug>/iter-<N>.json) that carries checklist verdicts, findings, fix decisions, and convergence inputs across iterations.## Coverage section in the final report aggregating per-iter finding counts, shadow agreement, and Phase 1.1.5 cap drops (see Loop Exit → Coverage).Maintainer rule. Engine changes belong in /devflow:review's SKILL.md; this file should only touch the loop wrapper, the workpad, the fix-delta handoff (Step 0.9), the Step 2.5 verification gate, the Step 2.6 shadow review, the fix step, the convergence check, the telemetry summary, or Loop Exit's chat output. Violating the letter of these phases is violating the spirit — even when a paraphrase looks faithful, the downstream agents are calibrated to /devflow:review's exact wording.
The orchestrator persists per-iteration state under .devflow/review/<slug>/iter-<N>.json (relative to the repo root). <slug> is pr-<N> in PR mode or the sanitized current branch name in branch mode. <N> is the iteration number, starting at 1.
The same directory also contains .devflow/review/<slug>/diff.patch — the cached full diff written by Phase 0.2 of /devflow:review on every iteration (overwritten if it already exists). Phase 3 agents Read this file directly instead of re-running gh pr diff / git diff 4–5 times in parallel. See /devflow:review's Phase 0.2 for the write logic.
Important. The .devflow/ directory is ephemeral working state — it should be listed in .gitignore. This skill does NOT add the entry itself (that is a repo-level concern); flag missing .gitignore coverage in the chat output if .devflow/ is not already ignored.
{
"iter": 1,
"started_at": "2026-05-16T20:45:00Z",
"fix_commit_sha": "abc1234",
"fix_files": ["src/example_pkg/foo.py", "tests/test_foo.py"],
"checklist": [
{
"id": "VC-1",
"claim": "...",
"file": "src/example_pkg/foo.py",
"verification_mode": "lite",
"claim_signature": "api_contract:foo.py:spdx-header-present",
"verdict": "PASS",
"evidence": "...",
"reused_from_iter_prev": false
}
],
"phase3_findings": [
{
"agent": "pr-review-toolkit:code-reviewer",
"severity": "Critical",
"description": "...",
"defect_signature": {"file": "src/example_pkg/foo.py", "line_range": [42, 47], "kind": "null_deref"},
"corroboration_count": 2,
"step25_classification": "codebase | web_confirmed | web_refuted | web_inconclusive | over_budget",
"fix_decision": "applied | pushed_back | deferred | advisory"
}
],
"fix_decisions": [
{"finding_id": "F-3", "decision": "applied", "commit": "abc1234"},
{
"finding_id": "F-7",
"decision": "pushed_back",
"source_file": "src/example_pkg/foo.py",
"claim_text": "function returns None when input is empty",
"skip_category": "claim-quality",
"evidence": "lines 200-220 of foo.py show the empty-input branch raises ValueError instead"
},
{
"finding_id": "F-9",
"decision": "deferred",
"source_file": "src/example_pkg/bar.py",
"claim_text": "race condition in concurrent writer",
"skip_category": "already-tracked",
"evidence": "#42"
},
{
"finding_id": "F-11",
"decision": "deferred",
"source_file": "src/example_pkg/baz.py",
"claim_text": "preexisting style violation on line 88",
"skip_category": "out-of-scope",
"evidence": "git blame shows line 88 unchanged by this PR (last touched in commit 9abcdef, three months ago)"
},
{
"finding_id": "F-13",
"decision": "deferred",
"source_file": "src/example_pkg/qux.py",
"claim_text": "log message is slightly imprecise about which retry attempt failed",
"skip_category": "uncategorized",
"evidence": "real but minor wording nit; not worth a fix-loop iteration"
},
{
"finding_id": "F-15",
"decision": "advisory",
"source_file": "src/example_pkg/quux.py",
"claim_text": "claim about a specific Postgres lock mode behavior",
"skip_category": "advisory-parked",
"evidence": "Step 2.5 demoted this finding after WebFetch verification; refuted by https://www.postgresql.org/docs/current/explicit-locking.html"
}
],
"convergence_inputs": {
"fixes_applied": 4,
"fix_diff_lines": 22,
"new_corroborated_critical_count": 0
},
"cap_drops": {
"count": 0,
"by_category": {}
},
"shadow": {
"ran_at": null,
"verdict": null,
"phase3_findings": [],
"phase2_fails": [],
"comparison": {
"shadow_total": 0,
"overlap_with_iter_N": 0,
"new": 0,
"new_critical": 0,
"new_important": 0
},
"promoted_to_iter_next": false
},
"telemetry": {
"phase_0": {"calls": 0, "tokens": 0, "wall_clock_s": 1.2},
"phase_0_5": {"calls": 0, "tokens": 0, "wall_clock_s": 0.3},
"phase_1": {"calls": 2, "tokens": 9400, "wall_clock_s": 28},
"phase_1_5": {"calls": 1, "tokens": 3100, "wall_clock_s": 11},
"phase_2": {"calls": 27,"tokens": 95000, "wall_clock_s": 220},
"phase_3": {"calls": 5, "tokens": 48000, "wall_clock_s": 180},
"step_2_5": {"calls": 0, "tokens": 0, "wall_clock_s": 4, "webfetches": 2},
"step_2_6": {"calls": 0, "tokens": 0, "wall_clock_s": 0},
"phase_4_x": {"calls": 0, "tokens": 0, "wall_clock_s": 1}
}
}
cap_drops is populated from /devflow:review's Phase 1.1.5 output (see that skill's Phase 1.1.5 for the shape — count is the total dropped at the 100-item cap, by_category is the per-category breakdown). The Coverage section in the final report reads this.
shadow is populated by Step 2.6 (the shadow review pass). It is only present on the workpad of the iter that triggered the shadow — typically the iter with the tentative non-REJECT verdict. Promoted-shadow iters (when the shadow surfaces new findings and triggers iter N+1 → Step 2.5) have their own workpad without a shadow block of their own unless they too produce a non-REJECT verdict that triggers another shadow.
iter-<N-1>.json. The fix-delta handoff (Step 0.9) and convergence check both consume it. If the file is missing or unreadable, log a warning and continue without the handoff optimizations (Phase 1 generator runs without the prior-checklist variance-recovery block; Phase 2.0.5 reuses nothing; Phase 3 runs without prior-findings context). Phase 1+2+3 still run — they always do.iter-<N>.json with everything collected during the iteration before looping back to Step 1.shadow block to the latest iter's workpad (re-writing iter-<N>.json with the shadow result included). If the shadow promotes new findings into iter (N+1), iter (N+1) is a normal iter from a lifecycle standpoint — it will write its own iter-<N+1>.json per the regular end-of-iter rule.The workpad is best-effort and informational. A write failure should not abort the loop — log it and continue.
Execute this loop with a maximum of 4 iterations.
Output: Review iteration {N}/4...
If N ≥ 2: read iter-<N-1>.json from the workpad before proceeding.
On iteration 1, skip this step — there is no prior iteration to hand off from. Proceed directly to Step 1.
On iterations N ≥ 2, prepare the iter-(N-1) state Phase 1, Phase 2, and Phase 3 of the engine will consume. Phase 1+2 always re-run; this step does NOT skip them. The earlier version of this gate did skip Phase 1+2 wholesale when the fix commit didn't intersect the prior checklist's files, and that turned out to be the primary false-pass mechanism for this skill — see the rationale block below.
Why this step is a handoff, not a skip gate. The user's framing, which is load-bearing: iterations exist for two distinct reasons that need different responses.
This step's job is to compute and stage the inputs both Phase 1 and Phase 2 need; it does not decide whether to run them.
Compute:
Fix-files set (fix_files). The files modified by iter-(N-1)'s fix commit. Prefer the value Step 3.7 already wrote to iter-(N-1)'s workpad (the fix_files field); the workpad is being loaded anyway for prior_checklist and prior_phase3_findings, so no extra cost. If the field is absent (older workpad, partial write), recompute:
git diff --name-only ${PREV_FIX_COMMIT}~1 ${PREV_FIX_COMMIT}
where ${PREV_FIX_COMMIT} is the fix_commit_sha recorded in iter-<N-1>.json. If iter-<N-1>.json itself is missing or unreadable, the lifecycle note (see "Persistent workpad → Lifecycle" above) already covers this: skip the handoff optimizations entirely (Phase 1 runs without the prior-checklist variance-recovery block; Phase 2.0.5 reuses nothing; Phase 3 runs without prior-findings context) and proceed to Step 1. Do not attempt partial recovery from HEAD~1 — without the prior checklist, fix_files alone has no downstream consumer.
Prior checklist (prior_checklist). The full checklist array from iter-<N-1>.json, including each item's claim_signature and verdict.
Prior Phase 3 findings (prior_phase3_findings). The full phase3_findings array from iter-<N-1>.json, including each finding's defect_signature and the matching fix_decisions entry (so Phase 3 can see which were applied vs. pushed back vs. deferred).
Pass these into Step 1:
prior_checklist (variance-recovery mode — see /devflow:review's Phase 1.2 conditional block).prior_checklist and fix_files for narrow per-item reuse (see /devflow:review's Phase 2.0.5).prior_phase3_findings labeled "already considered" (see /devflow:review's Phase 3.1 conditional block).Log: Fix-delta handoff: iter-{N-1} fix touched {len(fix_files)} file(s) ({names}); passing prior checklist ({len(prior_checklist)} items) and prior Phase 3 findings ({len(prior_phase3_findings)}) into Phase 1+2+3 for narrow reuse and variance recovery.
Mandatory and authoritative. Use Glob with pattern **/devflow/skills/review/SKILL.md to locate /devflow:review's SKILL.md, then Read it in full. Execute its Phases 0 through 4.3 verbatim — do not improvise the Phase 3 agent prompts, do not skip the Phase 1 >10-file batching, do not substitute your own verdict criteria. This skill deliberately does not contain a paraphrase of those phases; if you cannot read /devflow:review's SKILL.md, error out (see Error Handling).
Why path-based loading, not Skill: "devflow:review". The Skill tool executes a skill end-to-end; it would run /devflow:review's Phase 4.4 (formal GitHub post) before this loop has converged, defeating the deferred-post design. We need /devflow:review's phases as a procedure read inline, not as an opaque invocation. The path-coupling that follows is the price of that: the glob assumes the plugin layout <plugin-root>/skills/<skill-name>/SKILL.md (per the agentskills.io convention) — ** absorbs depth changes, but the skills/review/ sub-path is load-bearing. If that layout ever changes, update the glob pattern here and in the "Engine sharing" paragraph at the top of /devflow:review's SKILL.md.
When iter N≥2, hand off the fix_files, prior_checklist, and prior_phase3_findings computed in Step 0.9 into the engine's Phase 1 (generator variance-recovery prompt block), Phase 2 (narrow-reuse — Phase 2.0.5), and Phase 3 (prior-findings context block). Phase 1+2 always run; their outputs may be smaller because Phase 2.0.5 reuses some prior verdicts, but the phases themselves do not skip.
Skip /devflow:review's Phase 4.4 (formal GitHub review posting). The fix loop is silent on GitHub by design — the final report is emitted to chat only at Loop Exit. A human who wants a formal merge signal runs /devflow:review <PR> separately.
Red flags — STOP and run Glob+Read if you're about to:
Every drift incident this skill has had traces to one of those rationalizations. Violating the letter of /devflow:review's phases is violating the spirit, even when the paraphrase reads correct.
The engine produces, for this iteration: a verdict in {APPROVE, APPROVE WITH CAVEAT / APPROVE with notes, REJECT} plus a markdown report. Phase 0.5 flags (small_diff, config_only, has_new_types, engine_self_modifying, checklist_skipped) apply unchanged. The fix loop's iteration cap is still max 4 — Phase 0.5 only scales agent dispatch, not the loop.
APPROVE. Go to Step 2.6: Shadow review before exiting the loop.APPROVE WITH ADVISORY NOTES. Go to Step 2.6: Shadow review.APPROVE WITH CAVEAT. Go to Step 2.6: Shadow review.Before applying any fixes, classify each Critical or Important/Major finding from Phase 3 (the existing review agents). The goal is to keep the loop from auto-applying confidently-stated-but-wrong fixes; LLM verbalized confidence is poorly calibrated, especially on claims about external tool/framework behavior. Phase 2 checklist FAILs and findings raised by ≥2 Phase 3 agents are corroborated — pass them straight to Step 3. The gate targets the remaining single-source findings.
For each Critical/Important finding raised by exactly one Phase 3 agent:
Classify the claim:
@/syntax must be quoted in claude-code-action"). Run web verification.Web verification (up to a per-iteration cap of 5 WebFetches; remaining external-tool claims that don't fit the budget become advisory):
site:docs.github.com id-token permission job level) over generic web search.refuted by {url} tag. Do NOT auto-fix. Also append a line to the workpad's Devflow Reflection section: verified false positive — {claim text} — refuted by {url} to build the evidence trail. The finding still surfaces in this iteration's ## Advisory Findings section so the human reviewer can override if the docs were wrong about the codebase. (Earlier versions of this skill dropped refuted findings entirely; that hid user-visible evidence and was a primary drift mechanism vs. /devflow:review.)Add an ## Advisory Findings section to the iteration's report listing every advisory finding verbatim (the original agent's claim plus a one-line reason: refuted by {url}, inconclusive after web verification, or over verification budget). Advisory findings:
### Pre-mapping: Step-3-evaluated REJECT downgrade section has to evaluate; the gate's qualifying skip_category set deliberately does not include advisory-parked because advisory findings can't reach the gate as triggers in the first place.fix_decisions of the form {finding_id, decision: "advisory", source_file, claim_text, skip_category: "advisory-parked", evidence: <one-line demotion reason>}. This keeps the workpad's fix_decisions array the single source of truth for every per-finding outcome (applied / pushed_back / deferred / advisory) — Step 3 item 7 will then only need to write rows for the applied / pushed_back / deferred decisions it sees, since advisory rows are already present.Agreement heuristic. Two findings agree when they describe the same defect (same root cause + same affected file/line span); identical wording is not required. Use your own judgment; do not invoke a subagent for this.
When WebFetch/WebSearch are unavailable (older workflow, local invocation with restricted tools), skip the web step: external-tool claims that cannot be verified are demoted to advisory directly. The gate still provides value via the cross-agent corroboration filter.
Run a structurally-independent re-review before declaring convergence. Only triggers when the loop's tentative final verdict is non-REJECT (APPROVE, APPROVE WITH ADVISORY NOTES, APPROVE WITH CAVEAT / APPROVE with notes) — either from Step 2 on the current iteration, or from Step 4.5's early-exit convergence path. REJECT verdicts skip this step and go straight to Loop Exit.
Why a shadow pass. Iterations inside the fix loop share state — the orchestrator's context window carries prior findings, fix decisions, and pushback history forward. That state biases what the engine looks for and what it accepts as "already considered." The shadow pass is the loop's audit: a fresh engine context with no knowledge of the iter history runs the same engine and we compare. This matches what users already do manually today (/devflow:review <PR> after /devflow:review-and-fix); doing it inside the loop costs the same and feeds the result into one more iteration if the shadow disagrees, instead of leaving it to the human.
Iteration accounting. The shadow pass itself is NOT counted toward the max-4 iteration cap — it's a verification pass on the final iter's state, not a fix iteration. A promoted iter (one started because the shadow surfaced new findings — see outcome #2 below) DOES count toward the cap, because it runs Step 2.5 + Step 3 + Step 4 + Step 4.5 from the fix-loop side even though it skips Phase 1+2.
Use the Agent tool (NOT the Skill tool) with subagent_type: "general-purpose". The subagent's fresh context window is the structural guarantee: it has no access to the orchestrator's prior findings, workpad, fix decisions, or pushback history. We dispatch the engine inline as a procedure read from SKILL.md — not via the Skill tool — because Skill runs a skill end-to-end and would execute /devflow:review's Phase 4.4 before the shadow can be intercepted; we need the phases as steps the subagent walks through itself so it can stop before Phase 4.4. This mirrors the Step 1 pattern in this file.
Prompt:
You are running a shadow code-review pass for /devflow:review-and-fix's convergence audit. Your fresh context window is the structural guarantee — do NOT consult any prior conversation, workpad, or fix history; everything you need is in /devflow:review's SKILL.md and the diff itself.
1. Use `Glob` with pattern `**/devflow/skills/review/SKILL.md` to locate /devflow:review's SKILL.md. Read it in full.
2. Execute its Phases 0 through 4.3 verbatim against {PR <N> | the current branch}. Do not improvise the Phase 3 agent prompts; do not skip the Phase 1 >10-file batching; do not substitute your own verdict criteria.
3. DO NOT execute Phase 4.4 (no `gh pr review` / `gh pr comment` / no formal GitHub post). This is an internal shadow pass and must produce zero side effects on the PR. /devflow:review's Phase 4.4 only runs in PR mode anyway, but be explicit: if invoked in PR mode, stop after Phase 4.3.
4. Return your output as a single JSON object in a ```json code fence with these keys:
- "verdict": one of APPROVE / "APPROVE with notes" / "APPROVE WITH CAVEAT" / "APPROVE WITH ADVISORY NOTES" / REJECT
- "report": the full markdown report from /devflow:review's Phase 4.1
- "phase3_findings": the array of Phase 3 findings with `defect_signature` blocks
- "phase2_fails": the array of Phase 2 checklist items with verdict FAIL or INCONCLUSIVE (empty if Phase 1+2 were skipped)
When the subagent returns, parse out shadow_verdict, shadow_phase3_findings, and shadow_phase2_fails.
Compare shadow's findings to the loop's last iter's findings (the workpad's iter-<N>.json from the loop's most recent fix iteration — N is the iteration that produced the tentative final verdict, not counting the shadow itself):
A shadow finding is new iff no finding in the last iter's phase3_findings matches it under /devflow:review's Phase 3.2 defect_signature corroboration rule (same file + overlapping line_range + identical kind). See that section for the canonical definition — do not paraphrase it here.
Apply the same comparison to shadow_phase2_fails against the last iter's checklist (matching on claim_signature where available, else on (source_file, claim text)).
Three outcomes:
Shadow's findings are a subset of (or equal to) the loop's last iter's findings AND shadow_verdict is non-REJECT → genuine convergence. Record the shadow result in the workpad (see "Shadow workpad record" below) and proceed to Loop Exit with the tentative final verdict unchanged.
Shadow surfaces any new Critical or Important Phase 3 finding, OR any new Phase 2 FAIL, OR shadow_verdict is REJECT → the loop has not converged. Promote the shadow's new findings into a new iteration:
iter-<N+1>.json workpad at end-of-iter per the regular Persistent workpad → Lifecycle rule. Its iter field is N+1; it does NOT overload iter-N's workpad.prior_phase3_findings (Step 2.5's classification needs it to evaluate shadow's findings against what's already been considered); skip the fix_files and prior_checklist computation — Phase 1+2 are skipped for promoted iters, so those staged values have no downstream consumer.REJECT if any of shadow's new findings is Critical.APPROVE WITH UNRESOLVED SHADOW FINDINGS otherwise (Important-only).## Unresolved Shadow Findings section.Shadow returns a malformed or empty response, or the subagent errors → record the failure in the workpad, note it in chat (Shadow review pass failed: {reason}. Proceeding to Loop Exit with the loop's tentative verdict — shadow agreement not verified.), and proceed to Loop Exit. Do not retry; do not block the loop on a shadow failure.
After Step 2.6 completes (regardless of outcome), append a shadow block to the last iter's workpad file (iter-<N>.json):
"shadow": {
"ran_at": "2026-05-17T12:34:00Z",
"verdict": "APPROVE",
"phase3_findings": [/* the parsed array */],
"phase2_fails": [/* the parsed array */],
"comparison": {
"shadow_total": X,
"overlap_with_iter_N": Y,
"new": Z,
"new_critical": Z_crit,
"new_important": Z_imp
},
"promoted_to_iter_next": true | false
}
The Coverage section in the final report (Loop Exit) reads this block.
The shadow pass roughly doubles the cost of a converging run — one full engine pass that doesn't lead to fixes when it agrees. This is intentional:
/devflow:review after /devflow:review-and-fix); net cost is zero in their workflow and shadow agreement is now mechanical rather than a separate session.Apply the superpowers:receiving-code-review principles. After Step 2.5, the findings reaching Step 3 are: Phase 2 checklist FAILs, corroborated Phase 3 findings, confirmed-by-web findings, and codebase-claim findings. Refuted and inconclusive findings have been demoted to advisory and are not in this list; they stay parked.
Read all findings without reacting. Understand the full picture before fixing anything.
Evaluate each finding technically:
Fix one issue at a time. After each fix, verify the surrounding code still makes sense.
Run tests after all fixes. Check CLAUDE.md, README, or project configuration for the project's test and lint commands. If tests fail, fix the test failures before continuing.
Track pushbacks. For each finding you skipped (whether checklist FAIL or Phase 3 finding), record a structured entry: {source_file, claim_text, skip_category, evidence}. skip_category MUST be one of the values defined in the skip_category enum (authoritative) block below — this is the single source of truth for the enum, referenced by both this step and the Loop Exit Pre-mapping gate. Adding a new category requires editing only this block; both consumers read from it.
skip_category enum (authoritative)| Value | Meaning | Required evidence | Pre-mapping gate: qualifies for REJECT downgrade? |
|---|---|---|---|
claim-quality | Verifier evidence is correct in form but the underlying code is fine (e.g. the verifier oversimplified a branch the code handles correctly). | Cite the source span proving the code is correct. | Yes |
out-of-scope | The flagged lines are pre-existing code unmodified by this PR's diff, or belong to a separate concern from what this PR is doing. | Cite git blame / git log -S or the diff to prove the lines are not in this PR. | Yes |
already-tracked | A separate issue or PR addresses the underlying defect. | Cite the issue/PR number. | Yes |
uncategorized | None of the above fit cleanly. Use for "polish," "defer," "minor," "low priority," or any real-but-unfixed defect. | Free text describing why it wasn't fixed in-loop. | No — keeps the REJECT. The three named categories describe false-positive REJECTs; uncategorized describes a real defect that was simply not fixed. |
advisory-parked | Written by Step 2.5 at demotion time (not by this step). Marks a finding that web-verification refuted or could not confirm. | Demotion reason (e.g. refuted by {url}, inconclusive after web verification, over verification budget). | N/A — advisory findings are not REJECT triggers; they cannot reach the gate as triggers in the first place. |
Drift rule. If a future edit adds a sixth value, add a row above AND verify the Pre-mapping gate's reference to this table still makes sense — the gate uses the "qualifies for downgrade?" column verbatim and assumes nothing else.
A skip recorded with skip_category set to a value not in this enum (typo, missing field, etc.) is treated as missing-category and the gate keeps the REJECT.
If the same (source_file, claim_text) pair was also skipped in the previous iteration, escalate to the user: "Finding persists after pushback: {claim}. Manual review needed." and stop the loop.
Commit fixes before re-running the review:
git add -A && git commit -m "fix: address review findings (iteration {N})"
This ensures the next review iteration sees the updated code in the diff. Capture the resulting SHA (git rev-parse HEAD) and write it to the iter-N workpad as fix_commit_sha — Step 0.9 of iter-(N+1) reads it.
Persist the workpad. Before looping, write iter-<N>.json with: fix_commit_sha, fix_files (git diff --name-only HEAD~1 HEAD), the iter-N checklist + verdicts (each item flagged reused_from_iter_prev: true|false to record whether Phase 2.0.5's narrow-reuse path was taken), Phase 3 findings (each with defect_signature, step25_classification, and the matching fix_decision so iter-(N+1)'s Phase 3 handoff has the full record), fix_decisions (one entry per finding using the shape shown in the workpad schema example: applied entries carry {finding_id, decision, commit}; pushed_back / deferred entries carry the structured pushback fields {source_file, claim_text, skip_category, evidence} from Step 3 item 5 where skip_category is one of the values in the skip_category enum (authoritative) table; advisory entries — written by Step 2.5 at demotion time, not here — carry skip_category: "advisory-parked" plus the demotion evidence), convergence_inputs, cap_drops (from /devflow:review's Phase 1.1.5 output — see that skill for the shape), and telemetry (best-effort — see Loop Exit). The shadow block, if any, is appended later by Step 2.6 and is not populated here.
Output: Fixed {N} issues, skipped {M}. Re-running review...
Before looping back to Step 1, evaluate whether iter N+1 is likely to be a no-op. If it is, exit the loop early with iter N's current state. Convergence check is inactive on the iter-1 → iter-2 transition (no previous iteration to compare against). Starting at the iter-2 → iter-3 decision, check all three:
git diff HEAD~{commits_this_iter}..HEAD --shortstat)If all three hold → exit the loop early. The remaining unresolved findings (skipped via pushback in Step 3, or advisory from Step 2.5) are the final output of the run; iterating further wouldn't change them. Use iter N's current verdict as the tentative final verdict and proceed to Step 2.6: Shadow review before Loop Exit (the shadow pass still runs on early-exit convergence — it's the "loop is stuck" detector confirming the stop is genuine). Output: Converged after iteration N — fewer than 3 small fixes applied and no new findings; running shadow review before final verdict.
If any condition fails → loop back to Step 1 for iter N+1.
Note: convergence is not a way around an unresolved REJECT. If iter N's verdict is REJECT due to stuck/pushed-back findings, the shadow pass and Loop Exit's verdict flow still fire (a REJECT-on-convergence-exit goes straight to Loop Exit; Step 2.6 only runs when the tentative verdict is non-REJECT). Early exit just means "iterating won't help" — the human gate still applies.
Run this step BEFORE the REJECT downgrade gate below. It does two things: enforces a widens-surface guard on Yes-downgrade skips, and emits a structured manifest that downstream callers (currently /implement Phase 4.0.5) can consume to file follow-up issues and inject the Scope-Acknowledged Findings block into the PR body.
Widens-surface guard. Walk every fix_decisions entry in the final iter's workpad whose skip_category reads Yes in the enum table (Step 3, item 5 — currently claim-quality, out-of-scope, already-tracked). For each candidate, join to its Phase 3 finding via finding_id to obtain defect_signature.file and defect_signature.line_range, then read the cached diff (.devflow/review/<slug>/diff.patch) and check whether any non-comment hunk in the diff overlaps that file within ±10 lines of the line range. If overlap is detected, the skip is disqualified for the downgrade gate — append a bullet to the workpad's Devflow Reflection (widens-surface guard rejected skip for finding {finding_id}: PR diff overlaps {file}:{lines}) and treat the finding as a non-skipped REJECT trigger for the gate that runs next. This catches the "refactor around a pre-existing bug, then defer the bug" pattern: the bug's lines weren't touched in isolation, but the surrounding code changed in a way that widens reliance on the broken behavior.
Deferrals manifest. After the guard runs, emit .devflow/review/<slug>/deferrals.json containing every surviving Yes-downgrade skip (i.e. claim-quality / out-of-scope / already-tracked entries that the widens-surface guard did not disqualify). The manifest is written regardless of whether the downgrade gate ultimately fires; claim-quality and already-tracked skips on non-REJECT runs are still legitimate deferrals worth tracking for the verdict matcher. If zero entries survive, omit the file entirely.
Schema:
{
"schema_version": 1,
"pr_branch": "<current branch>",
"base_branch": "<base_branch from .github/project-config.yml; if absent, the repo default branch via `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`, falling back to `main`>",
"generated_at": "<ISO 8601 UTC>",
"deferrals": [
{
"agent": "<from phase3_findings.agent>",
"severity": "<Critical | Important | Suggestion>",
"file": "<from defect_signature.file>",
"line_range": [<start>, <end>],
"symbol": "<best-effort, see below>",
"kind": "<from defect_signature.kind>",
"summary": "<verbatim from phase3_findings.description>",
"category": "<one of: out-of-scope, already-tracked, claim-quality>",
"explanation": "<verbatim from fix_decisions.evidence>"
}
]
}
symbol is best-effort: scan the finding's description for the first backtick-quoted identifier; if none, leave empty string. Downstream matchers (the /devflow:review verdict engine) fall back to line_range + summary similarity when symbol is absent.
This step writes the artifact and applies the guard. It does NOT file follow-up issues, mutate the PR body, or touch GitHub — those are /implement Phase 4.0.5's responsibility. /devflow:review-and-fix is silent on GitHub by design and stays so. When the caller is standalone /devflow:review-and-fix (no orchestrator wrapping it), the manifest is still written but no consumer reads it — that's fine; it's informational state on disk and useful for debugging.
If the engine's final verdict is REJECT AND every REJECT trigger (checklist FAILs and Critical Phase 3 findings) was Step-3-skipped with a skip_category whose "qualifies for REJECT downgrade?" column in the skip_category enum (authoritative) table (Step 3, item 5) reads Yes AND survived the widens-surface guard above, downgrade the final verdict to APPROVE WITH CAVEAT and surface each trigger in the report's ## Downgraded Findings section with its category label and evidence.
The gate consults that table directly — it does not maintain its own list. If a future edit adds a sixth skip_category, mark its downgrade-eligibility in the table row and the gate picks it up automatically. One trigger whose category reads "No" (or "N/A", or whose category isn't in the table at all) keeps the REJECT. Similarly, any REJECT trigger that was NOT skipped at all (i.e. the orchestrator addressed it in Step 3 but the post-fix engine re-run still rejects) keeps the REJECT; the downgrade gate is for false-positive REJECTs, not for unfinished work. A trigger whose skip was disqualified by the widens-surface guard above keeps the REJECT for the same reason — the guard found that this PR widens reliance on the deferred bug, so the bug is no longer "pre-existing and unrelated" for review purposes.
The fix loop is silent on GitHub by design — it does NOT post a gh pr review or gh pr comment for any verdict. The final report (including any ## Advisory Findings, ## Coverage, and ## Unresolved Shadow Findings sections) is emitted to chat only. A human who wants a formal --request-changes / --approve / --comment review on the PR runs /devflow:review <PR> separately; that skill performs an independent re-review and posts the result via its own Phase 4.4.
Map the final verdict to the chat line that precedes the full report:
Review passed after {N} iteration(s) (shadow agreed). All checks approved.Review passed after {N} iteration(s) (shadow agreed) with {M} advisory finding(s) parked for human review. See report.Review passed after {N} iteration(s) (shadow agreed) with caveats. See report.Review converged after {N} iteration(s) but a final shadow pass surfaced {K} new Important finding(s) that the loop could not address within the iteration cap. See report.Review still has findings after {N} iteration(s). Remaining issues require manual review: followed by the list of unresolved findings. Then append the formal-merge-signal hint, conditional on mode:
$ARGUMENTS is a PR number): To post this verdict as a formal merge signal (e.g. a blocking --request-changes review), run \/devflow:review {PR_NUMBER}` — it performs an independent re-review and posts the result.`To post this verdict as a formal merge signal once a PR exists, push the branch and open a PR, then run \/devflow:review ` — it performs an independent re-review and posts the result.`Inject a ## Coverage section into the final report, positioned between the engine report's ## Code Review Findings and ## Verdict Criteria sections (those headings come from /devflow:review's Phase 4.1 template). The section reports run-level coverage so the human reader can see how exhaustive the engine was and where it cut corners.
Compute by reading every iter-<K>.json workpad (plus the appended shadow block, if any) and rendering:
## Coverage
### Per-iteration finding counts
| Iter | Phase 3 findings | Critical | Important | Suggestion | Phase 2 FAILs | Phase 2 INCONCLUSIVE |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | 7 | 1 | 3 | 3 | 2 | 0 |
| 2 | 4 | 0 | 2 | 2 | 0 | 1 |
| ... | | | | | | |
### Shadow agreement
Shadow pass raised X findings; Y were already in iter N (overlap = Y/X); Z were new (Z_crit Critical, Z_imp Important). {If Z > 0: "The loop promoted them into iter (N+1); this report reflects the post-promotion state."} {If Z == 0: "Genuine convergence — shadow agreed with the loop."} {If shadow did not run (e.g. REJECT verdict): "Shadow pass did not run — final verdict was REJECT before convergence."}
### Phase 1.1.5 cap drops
Phase 1.1.5 dropped M items at the 100-item cap (categories: dependency_interaction: K1, api_contract: K2, ...). {Omit this subsection entirely if M == 0 across all iters.}
If a workpad is missing or unreadable, omit the corresponding row and append a one-line note: Iter K workpad unreadable; coverage row omitted. Coverage rendering never blocks the final verdict.
Coverage and the Run telemetry summary (below) both consume the per-iter workpads. Read each iter-<K>.json once into memory at Loop Exit and render both sections from the same in-memory array — do not re-open files.
After the verdict line, print a compact telemetry table to chat (informational only — best-effort). Aggregate across all iterations by reading every iter-<K>.json workpad and summing per-phase counts.
For each agent invocation during the run, record:
agent_call_count — increment by 1 per Agent / Task tool call.total_tokens — parse the usage.total_tokens value from each agent's tool-result <usage> block when present. If the value is missing, skip silently (do not block).wall_clock_s — measure elapsed time between phase enter and phase exit using the orchestrator's clock.Phase boundaries (matching the workpad schema): phase_0, phase_0_5, phase_1, phase_1_5, phase_2, phase_3, step_2_5, step_2_6 (shadow pass), phase_4_x (covers Phase 4.1–4.3 + Loop Exit final-report emission).
Render as:
## Run telemetry
| Phase | Iter | Calls | Tokens | Wall-clock |
| --- | --- | --- | --- | --- |
| Phase 1 | 1 | 2 | ~9.4k | 28s |
| Phase 1.5 | 1 | 1 | ~3.1k | 11s |
| Phase 2 | 1 | 39 | ~140k | 4m12s |
| Phase 3 | 1 | 5 | ~48k | 3m00s |
| Phase 2 | 2 | 27 | ~95k | 3m40s |
| ... | | | | |
| **Total** | | 52 | ~310k | 11m05s |
Notes:
<usage> blocks). Mark with ~ to signal estimation.gh pr review from inside the loop — this skill is silent on GitHub by design; the user runs /devflow:review <PR> separately for a formal merge signal.