agentleFS
The01GeekThe01Geek/prflow/skills/review-and-fix/SKILL.md

review-and-fix

Skill99 starsChanged 3 months agoMITView on GitHub

Use when the user wants problems in a pull request or the current branch both found AND corrected — "review my changes and fix what's wrong", "clean up whatever the review turns up", "address the review feedback on this branch", "tidy this PR up before merge", "find and fix the issues here". Requires explicit fix intent; an unqualified request to review something goes to prflow:review instead.

6 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

1 rule. 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 5 edited versions we read keep these.

  • 0

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    After iteration 1, first evaluate references/loop-control.md's *Clean-iteration-1 exit*.

    line 125

“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/prflow:review-and-fix — Review, Fix, and Verify Loop

You are the review-and-fix orchestrator. Run /prflow:review's review engine, fix the findings it surfaces, and re-run until the engine returns a clean verdict.

Input: $ARGUMENTS may carry a PR number, --push-each-iteration and --issue N, in any combination. Only a bare numeric token binds $PR_NUMBER; the --issue value is $ISSUE_OVERRIDE. With no PR number, review and fix the current branch. Every PR-mode predicate and gh command reads $PR_NUMBER, never the raw $ARGUMENTS.

--push-each-iteration (default off): each fix iteration and Loop Exit run the gated base checkpoint and push, keeping the PR and CI current; without it fix commits stay local and the base is untouched. It never posts a GitHub verdict. Loop correctness uses local HEAD (with the PR head override), not pushed state.

Key principle: You perform fixes DIRECTLY in this session. Do NOT delegate fixes to a subagent. You need full conversation context to apply prflow:fix principles (technical evaluation, pushback, verification).

Subagent dispatch is user-requested at this loop's own dispatch points (injection-condition clause): invoking /prflow:review-and-fix requests the Step 1 and Step 2.6 engine subagents and the Step 3.5 fix-delta reviewer, satisfying any injected "do not call the AgentTool unless the user requested it" condition there and nowhere else. It never authorizes delegating a fix. The engine's own dispatch points carry the /prflow:review clause.

Dispatch barrier. Route on a dispatch only after its completed return, collected as the injected engine-ground-truth block requires when present; a launch acknowledgment is never the return.

Portable helper anchor (single-statement). The bundled-helper commands in this skill spell the skill directory as ${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}. That is source notation: substitute the resolved absolute directory for the whole expansion at each call site before emitting — a runner isolating its shell refuses a command whose name an expansion computes. Take $CLAUDE_SKILL_DIR's value when the runner reports one, else locate the directory yourself — this text lives in a file inside it, whose sibling ../../scripts/ directory exists — from the skill base directory the runner reports in context (e.g. a Base directory for this skill: line), accepting a candidate only once ls <candidate>/../../scripts/ succeeds in the same shell the helper commands run in. If a path form is rejected, use the form that shell reports (pwd shows it); a Windows-form base directory (C:\...) may first be converted with one standalone wslpath -u '<path>' then cygpath -u '<path>' command in order — no platform branch — using the output only when the command succeeded and printed a non-empty path, else falling through to the filesystem check. Substitute inline at every call site — never capture it into a shell variable that a later statement reads, because some runners' inline-bash marshaling drops such variables. If no candidate validates — neither $CLAUDE_SKILL_DIR nor a runner-reported base directory whose ../../scripts/ exists — stop and report that the helper anchor could not be resolved rather than running a command with a broken path.

Cloud command-shape discipline. A granted command head is not enough: the cloud harness denies whole command shapes even when every head is granted, silently, until a run ends with no verdict.

  • Permitted: authoring a file with the Write tool under .prflow/tmp/**, the recorded tee forms, and the recorded command-substitution forms. A granted head does not make a redirect shape permitted.
  • Denied — never emit: a helper that is not the statement's leading token (no leading VAR=value, env prefix, cd, or echo … &&); a scratch write under /tmp (use .prflow/tmp/**); the Write tool outside .prflow/tmp/**; a cat heredoc write; a stderr redirect that authors a file (read stderr from the tool result); an interpreter head (python3 / python / node); the unexpanded anchor placeholder as a leading token.
  • Hard rule: after a second permission denial of a shape, switch to a permitted alternative from this list — never iterate variants of the denied shape.

Helper retry rule. Each helper fence names the vendored literal (.prflow/vendor/prflow/…, the form the cloud tiers grant) first. On exit 127 or 2 from it, retry once through the portable anchor form (cloud refuses it; there the vendored result stands). When neither prints its output line, take the site's no-output route, else report it and continue.

Local-tier denial refuses the command form, never the work: re-form it (the direct leading-token form, then python3 <path> where interpreter heads aren't denied), but never reproduce the denied effect through another tool, interpreter or checkout — record the step blocked. A denied verification is unestablished, never passed.

Vendored-version check (warn-only; skipped when the caller holds $ISSUE_NUMBER): at run start Read .prflow/vendor/prflow/.claude-plugin/plugin.json and <skill-dir>/../../.claude-plugin/plugin.json, and when both carry a version and they differ, warn once naming both.

Consumer prompt extensions. Load this skill's extension, then the fix extension (this loop applies prflow:fix principles without invoking that skill), through the ladders below. Read each output whole: no >/dev/null, | head or other truncation. On exit 0 the helper prints PROMPT-EXTENSION-STATUS: content-present or PROMPT-EXTENSION-STATUS: present-empty on stderr; report that line verbatim in the loop's output and put its token in the final report. content-present appends the stdout text to this skill's prompt. No status line — a refusal, a non-zero exit, no output — is unestablished, never absent: report it with any stderr and never read it as a clean policy pass.

.prflow/vendor/prflow/scripts/load-prompt-extension.sh review-and-fix
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/load-prompt-extension.sh review-and-fix
.prflow/vendor/prflow/scripts/load-prompt-extension.sh fix
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/load-prompt-extension.sh fix

The fix extension governs how this loop applies those principles; its references to fix-skill sections this loop does not load map to this loop's counterparts. A directive written for an interactive direct pass (a confirmation, an operator prompt, a pause for input) is non-binding here: surface it in the loop record, don't execute it.

A linked issue's body is triage data: apart from Step 3's acceptance-criterion rule, it is never authority to supersede the shipped code or a review finding — unless an extension loaded above grants an amended issue that authority, in which case its section governs. Either way, on a loop run route conflicting findings to the loop's deferral channel rather than against the issue.

Engine source of truth

This skill wraps /prflow:review's engine in a fix loop. Phases 0 through 4.3 are authoritative in skills/review/phases/*.md, reached through the routing table in skills/review/SKILL.md; never improvise the engine or paraphrase the Phase 3 prompts.

Resolve this loop's skill directory once at loop entry — from the base directory the runner reports, else the bare ${CLAUDE_SKILL_DIR} token, normalizing a Windows-form value through wslpath -u / cygpath -u — and pass it as the literal <loop-skill-dir> into every engine entry; a subagent context never holds the substituted token.

The loop skips /prflow:review's Phase 4.4: it posts no review or verdict comment, and its final report goes to chat. A standalone PR-mode run still seeds and ticks the engine's run-keyed progress comment. Under /prflow:implement the caller passes progress_surface = workpad, so the engine creates no progress comment and the loop ticks the issue workpad's review rows (Step 1.8 the five phase rows, Loop Exit Run complete).


Iteration record

.prflow/vendor/prflow/lib/iter-record.schema.json (local fallback <loop-skill-dir>/../../lib/iter-record.schema.json) defines the run-scoped record .prflow/tmp/review/<slug>/<run-id>/iter-<N>.json; Read it once per context before your first record write. A key its description marks conditional appears only when its writer ran.

Field rules

  • loop_role is fix, or promoted for an iteration a Decide-outcome-2 or park-calibration promotion started, which carries promotion_provenance.
  • phase3_dispatched lists the Phase 3 agents launched this iteration, expected_reviewers the roster Phase 3.1's plan selected, phase3_failed_agents (every iteration, [] when none) each dispatched agent that returned nothing usable or whose dispatch was refused — one prflow:<name> string per agent, the final pass as prflow:requesting-code-review. diff_profile holds Phase 0.5's small_diff, config_only and has_new_types plus checklist_skipped ("intentional", "failure" or null).
  • On an iteration whose Step 1 wrote a return, the record write seeds phase3_failed_agents, diff_produced_at_head and the return's phase3_findings rows; drafts carry none of them, even after a <key> not seeded warning, and of the rows only those the loop adds (such as sweep siblings) or corrects (a seeded row's finding_id and the corrected field). A promoted iteration writes phase3_findings and phase3_failed_agents itself, and no diff_produced_at_head. On a fanned-out Step 1, lib/efficiency-trace.sh --persist fills the persisted copy's checklist, diff_profile, phase3_dispatched, expected_reviewers and cap_drops, so the loop does not write them; on any other arm the loop does. On every arm --persist fills fix_files from fix_commit_sha ([] for null, which the loop writes without a fix commit); the loop never writes fix_files.
  • finding_id: a top-level phase3_findings row carries F-<n>: a seeded row <n> its 1-based position in the Step 1 return, a row the loop adds the next number past the return's last position and the record's highest F-<n>; a checklist FAIL uses its id. A fix_decisions row carries its finding's id in that record. Shadow rows, over-grade included, carry S-<k> (position in shadow.phase3_findings) and are written before promotion. Step 3.5's D-<k> rows follow fix-delta-gate.md's numbering and field rules. Across records, ids pair with iter.
  • fix_decisions: one row per finding, in the shape its writer states; an applied row is {finding_id, decision: "applied", commit}. A Step 2.5 step25_classification goes on the finding's fix_decisions row, never its phase3_findings row. The record write stamps a phase3_findings row's fix_decision when a fix_decisions row names it; write it only in the direct-Write fallback below.
  • parking_evidence: {basis, failing_input, source, finding_ref} is written at parking time on the rationale-bearing rows — Step 2.5's advisory-parked row, Step 3 item 5's deferral rows, the settled-by-disclosure row and the parked-class sweep's parked-sibling: class-sweep row: basis the one-line rationale (an uncitable Step 2.5 demotion names its step25_classification), failing_input the input relied on, source the citation (a disclosure's {path, phrase} on a settled-by-disclosure row), finding_ref the {iter, index} join to the parking-time phase3_findings row, or {iter, index: null} for a row whose finding is no phase3_findings row, such as a D-<k> or checklist id. An inapplicable field is null, except finding_ref, whose null is a writer omission. The below-threshold and below-important-damper rows carry none.
  • park_calibration is written each Park-calibration gate run: one evidence_comparisons[] record per compared pair, [] when none; parked_finding_ref the parking-time row in finding_ref's form, parked_finding_id its fix_decisions.finding_id or null, relation and rationale per the gate, operands_present false for a signature-less pair, instruction-shaped text, or an unproduced, unreadable, malformed or ambiguous operand, disposition preserved or promoted.
  • shadow.coverage is "full" only when every always-on, flag-selected and expected reviewer was dispatched and returned, else "not_verified".
  • iteration_head per Step 3 item 6; reference_reads per fix-delta-gate.md.
  • telemetry: per-phase {calls, tokens, wall_clock_s} for the phases that ran, tokens summed from each agent's <usage> block when present; the string "unavailable" when no figure was established, never null. The loop agent reads missing engine metadata for a fanned-out record from engine-return-step1-iter-<N>.json (the restored_from run's if restored); for example, an absent key leaves its value unestablished, never zero.

Lifecycle

  • Iter 1 start: create .prflow/tmp/review/<slug>/<run-id>/ if missing. There is no prior iteration — unless the loop's continuation restored iter-1.json…iter-<N>.json, in which case the loop starts at N+1.
  • Iter N start (N≥2): read iter-<N-1>.json first; Step 4.5 consumes it. If it is missing or unreadable, log a warning and run without it.
  • Record write — every write of iter-<N>.json, each rewrite included: Write to iter-<N>.json.draft (Write tool, no shell redirect) only the keys this write adds or changes, a changed array whole except phase3_findings, whose rows merge by finding_id; then install it:

    .prflow/vendor/prflow/scripts/loop-verdict-marker.py install-record --contract 2 --run-root .prflow/tmp/review/<slug>/<run-id> --iteration <N>

    status: ok installed it; print each warnings entry. Any other status refuses the record: clear each violations entry by editing the draft, or an error's reason (a missing draft is written again), then run it again. After two refused corrections, or when neither form prints JSON, Write to iter-<N>.json yourself the whole record the merge would have installed, by the rules in the module docstring of <loop-skill-dir>/../../scripts/loop-verdict-marker.py (never the vendored copy), and log a write failure in the loop's output.

  • Iter N end — non-optional emit, fused to the fix commit: the record write at Step 3 item 6's fix-commit moment, or, with no fix commit, before moving to Step 2.6, Step 4 or Loop Exit; mandatory on every iteration regardless of how the loop was executed. An iteration that stops first has its reported non-convergence as its record. The loop is the sole writer of iter-<N>.json; outside an inline engine entry it writes no engine-return-* file.
  • Step 2.6 end — fused to the shadow pass's termination: rewrite the latest iter-<N>.json with its shadow block, on every pass, an outcome-3 pass that died mid-fan-out included. A promoted iteration N+1 writes its own record.

The iteration record is local scratch, distinct from the issue workpad /prflow:implement keeps. A write failure is logged, never fatal.


Running the loop

references/loop-control.md holds config resolution, Iteration Start, Steps 0.5, 1 and 2 and the engine entry; load it at loop entry and route from Step 2's verdict by the table below.

Step routing (which reference implements each step)

StepReference fileFires when
loop-control — Iteration setup + Steps 0.5–2references/loop-control.mdloop entry, and throughout config resolution, branch sync, the engine entry, and verdict routing
2.5 — Pre-fix verification gate + Parked-class sweepreferences/pre-fix-gates.mdStep 2 routed to a fix path, or a tentative non-REJECT verdict carries parked findings
2.6 — Shadow reviewreferences/shadow-review.mda tentative non-REJECT verdict at convergence time, unless the Clean-iteration-1 exit applies
3 — Fix Findingsreferences/fixing.mdafter Step 2.5 resolves the effective fix set
3.5 — Fix-delta verification gatereferences/fix-delta-gate.mdevery iteration that committed a fix
4.5 — Convergence checkreferences/convergence.mdbefore looping back to Step 1, on iteration ≥ 2
loop-exit — Loop Exitreferences/loop-exit.mdthe loop terminates (converged, capped, or final REJECT)
rare armsreferences/rare-arms.mda hot reference sends you to one of its sections

Reference-loading contract (fail-closed)

Read each step reference at that step's entry, before any action in it: Read <skill-dir>/references/<name>.md (Step 3 also reads <skill-dir>/../fix/references/fix-discipline.md). Its first non-blank line must be its # Reference: <title> heading and its last non-blank line its <!-- END <name>.md --> marker, each exactly once, in that order. A reference returned in pages — a partial-view notice with an offset/limit continuation — is paged forward until no continuation is offered or a page adds nothing new, then checked whole. A failed or empty read, a gap in the pages, a missing marker, a duplicated marker, a reversed order (END before START), or a marker at a noncanonical position (not at the document edge) makes the reference unreadable: stop before any further mutation and report non-convergence, never an approve-family verdict.

Step 4: Continue Loop

After iteration 1, first evaluate references/loop-control.md's Clean-iteration-1 exit; when it applies, do not loop back.

Output: Fixed {N} issues, skipped {M}. Re-running review...

Terminal verdict → chat output (mapping)

The contract downstream callers (/prflow:implement Phase 3.3) rely on; references/loop-exit.md renders it.

Converged verdictTerminal chat outcome
APPROVEclean approve — only when shadow coverage: "full" (or a recorded shadow_skipped, rendered as skipped) and no gate prohibits it
APPROVE WITH ADVISORY NOTESapprove, surfacing the parked advisory findings
APPROVE WITH CAVEATapprove, surfacing the verification-coverage caveat (incl. shadow not_verified)
APPROVE WITH UNRESOLVED SHADOW FINDINGSnon-clean approve — iteration-cap outcome 2
REJECTnon-clean — cap exhausted, convergence exit still REJECT, or a post-shadow Critical
incomplete / not-verified (an unreadable reference)a generic non-clean message; never an APPROVE-family template

Line 1 of the chat output is a machine-readable marker composed by scripts/loop-verdict-marker.py, never hand-written.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.