open-code-review-loop · v1.4.1 · 2026-08-24 · sha256 17fd799b5e5861a2
open-code-review-loop v1.4.1A
Immutable. This exact content never changes and is served at /api/v1/blob/17fd799b5e5861a2.
--- name: open-code-review-loop description: "Run a bounded OCR-delegation review-fix-re-review loop. Use when the user wants ocr delegate file selection and rules (including open-code-review-delegate phrasing) with a named product reviewer (codex, claude-code, grok-build, or cursor-cli) and a fixer, iterating until validated NO_FINDINGS. Fail closed on missing ocr, missing adapters, skipped files, malformed output, stale evidence, or exhausted rounds." metadata: author: adonis version: "1.4.1" --- # Open Code Review Loop `ocr delegate` is LLM-free: it selects files and resolves rules. Only a validated reviewer result with full OCR coverage may produce `NO_FINDINGS`. OCR never decides that code is clean. ## Fast Path Do these in order. Later references stay closed until a step needs them. 1. Git repository? Otherwise stop. 2. `which ocr` — missing → `MISSING_DEPENDENCIES`. Do not open adapter-contracts / review-contract / fix-contract, and do not install OCR without authorization. Stop before any Reviewer call. 3. Resolve Reviewer/Fixer product IDs, then open **only those product sections** in [adapter-contracts.md](references/adapter-contracts.md). 4. Open [review-contract.md](references/review-contract.md) + [review-schema.json](references/review-schema.json) only in Phase 2. 5. Open [fix-contract.md](references/fix-contract.md) + [fix-schema.json](references/fix-schema.json) only in Phase 4 for independently verified `Fix` rows. 6. Historical `--commit` / `--from/--to` → `HUMAN_GATE` before any fix; do not load the fix contract. ## Trigger and exclusions Use this Skill for an OCR-delegation loop (`ocr delegate` / open-code-review) on a Git workspace with a named product reviewer (`codex`, `claude-code`, `grok-build`, `cursor-cli`) and a fixer until validated `NO_FINDINGS`. Skip one-shot review, non-Git files, commit/push/deploy, and destructive work. > **Wrong skill.** Packet protocol, `.review-handoff`, `review-loop run`, or > a Grok consult → `agentic-review-handoff`. Redirect; do not start > `ocr delegate`. Named path + architecture scan-fix-rescan until no > architecture findings → `architecture-hardening-loop`. Do not claim OCR > `CLEAN`. Do not copy those skills' packet or scanner logic. ## Inputs and defaults Resolve before the first model call: - Repository: current Git root; never infer a broader repo - Target: workspace changes; also OCR `--from/--to` and `--commit` - Reviewer: user-selected product; a real read-only product session - Fixer: current visible host. An external Fixer needs a user-authorized isolated checkout that becomes `$REPO` before round 1 - Paths/excludes: OCR preview; preserve user exclusions every round. Accepted exclusions are `user_exclude` plus reasons the user accepts one by one. OCR-internal exclusions do not prove coverage - Round budget / deadline: 3 rounds (a ceiling, not success permission); 10 minutes per Reviewer/Fixer call - Background: user requirement or none; pass through preview/rule/prompt One named product without roles → that product is Reviewer, current host is Fixer. If the user also says not to ask (`不用问我` / proceed), take those defaults and skip a product-choice question. Missing `ocr` and historical-commit fix still fail closed. Same product in both roles → two independent sessions; Reviewer stays read-only. ## Capability preflight Fast Path already covers Git, `ocr`, and product IDs. Before editing, also inspect installed product help: a binary name does not prove read-only review, structured output, scoped writes, or session recovery. Reviewer inspects without editing. External Fixer: verify the isolated checkout holds the intended snapshot, freeze that Git root as the only `$REPO`, and never review one worktree while fixing another. No isolated target → `HUMAN_GATE` (no patch-transfer protocol). Do not auto-create a worktree. Record allowed source/test paths, prohibited Git/external actions, and explicitly accepted exclusion reasons. Unaccepted reasons (including `unsupported_ext`) are incomplete coverage even if every `reviewable_files` entry was reviewed. Partition sessions by repository, loop ID, role, and canonical product ID — never resume a Reviewer as a Fixer. Adapter cannot satisfy its role → `HUMAN_GATE`. Do not silently substitute another AI or let the Reviewer write the subject. ## Loop contract Freeze before round 1: ```text OCR Review Contract - Repository / target: - Reviewer / session policy: - Fixer / session policy: - Scope / exclusions: - Accepted exclusion reasons: - Background / acceptance checks: - Write boundary: - Round budget: - Per-call deadline: - Git and external actions: none ``` Reviewer owns findings and the clean verdict. Fixer owns source edits and verification. Visible host owns OCR evidence, schema validation, triage, round accounting, and the final result. ### Phase 1: Build current evidence ```bash ROUND_DIR="$(mktemp -d)" python3 <skill-dir>/scripts/build_review_bundle.py \ --repo "$REPO" \ --output "$ROUND_DIR/bundle.json" \ [--from-ref <ref> --to-ref <ref>] \ [--commit <hash>] \ [--exclude <patterns>]... \ [--allow-excluded-reason <reason>] \ [--rule <rule.json>] \ [--background <text> | --background-file <path>] ``` Keep `ROUND_DIR` outside the repo so the next preview cannot select the bundle and permanently drift evidence. `--exclude` may be repeated; the script combines values into OCR's list and keeps that selection every round. `--allow-excluded-reason` is not authority: pass it only after recording the user's explicit acceptance of that exact reason. Zero reviewable files and zero unaccepted exclusions → `CLEAN` with `0/0` coverage. Any unaccepted exclusion (for example `unsupported_ext`) → `UNVERIFIED: INCOMPLETE_COVERAGE`. Do not invoke an AI just to manufacture a verdict. Builder already fail-closes on (do not re-implement; read `scripts/build_review_bundle.py` only if the builder fails): - mid-build `HEAD` / binary-diff / untracked fingerprint drift - missing captured content vs a real zero-byte file (`empty_file: true`) - first-parent merge selection and immutable ref resolution - in-repository output - background argv redaction and a private `0600` snapshot Prefer `--background-file` for non-trivial or sensitive background. Do not commit the bundle. `validate_round.py` recomputes the canonical digest, so editing bundle content while keeping an old `evidence_id` also fails closed. ### Phase 2: Invoke the Reviewer Give the Reviewer the frozen contract, background, whole `bundle.json` (including `evidence_id`), nearby read-only context, non-mutating checks, and the JSON contract from Fast Path step 4. Every `(path, status)` in `reviewable_files` appears exactly once as `reviewed` or `skipped`. Emit only evidence-backed, actionable findings. A fresh `evidence_id` consumes one round; one same-evidence schema correction does not. Drift creates a new ID, so the next Reviewer call consumes another round. A read-only Reviewer timeout is `UNVERIFIED`. Extract the product's final structured object — not prose braces, and not Grok's human-readable `text` field: ```bash python3 <skill-dir>/scripts/extract_product_output.py \ --product "$REVIEWER_PRODUCT" \ --input "$ROUND_DIR/raw-review.json" \ --output "$ROUND_DIR/review.json" \ [--session-id "$RECORDED_SESSION_ID"] ``` The extractor replaces Reviewer identity with host-observed product/session data. Then validate: ```bash python3 <skill-dir>/scripts/validate_round.py \ --bundle "$ROUND_DIR/bundle.json" \ --review "$ROUND_DIR/review.json" \ --output "$ROUND_DIR/validation.json" ``` Malformed output gets one same-session correction. Still invalid → `UNVERIFIED`. Do not reinterpret prose as a verdict. ### Phase 3: Detect evidence drift Rebuild the bundle with the same target and exclusions. Compare `evidence_id`. Equal → the result covers the current snapshot. Different → discard the verdict, record `evidence-drift`, and review the new bundle. Never carry findings or `NO_FINDINGS` across snapshots. ### Phase 4: Triage and fix findings For a valid `FINDINGS` result: 1. Independently open each cited path and verify the evidence. 2. Classify each item as `Fix`, `Reject`, or `Human decision`. 3. Give the Fixer only verified `Fix` rows, target paths, required fix, acceptance check, current evidence ID, and the write boundary. Load the fix contract only now (Fast Path step 5). 4. Extract with `extract_product_output.py`, then `validate_fix_result.py`. One same-session correction for malformed output; a valid result is still only a claim. 5. Fixer re-reads current code and applies the smallest coherent change. 6. Host recomputes Git status/diff, derives actual changed paths, rejects out-of-scope writes, and runs listed checks. Never trust claimed `FIXED`, `changed_paths`, or the Fixer's test summary. 7. Record rejected findings with counter-evidence. Do not edit code to satisfy a known false positive. Fixer does not commit, push, merge, rebase, deploy, send messages, or edit outside the frozen boundary. External Fixer writes only the authorized isolated `$REPO`. Direct writes to the user's original worktree need path-scoped enforcement, not a later diff check; the four documented CLI adapters do not meet that bar. Range/commit review always returns `HUMAN_GATE` before fixing — another writable branch cannot prove those edits against the immutable target. Any source or test edit invalidates the prior bundle, validation, tests, and verdict; return to Phase 1. Fixer timeout or lost delivery after it could have written → recompute the real Git diff and return `UNVERIFIED: DELIVERY_UNKNOWN_WITH_MUTATION`. Do not retry blindly or reset user changes. `FIXED` with unchanged Git/evidence and a still-reproducing finding → `FIXER_NO_MUTATION`. Delivery is known, so allow one same-session correction. A repeated no-mutation result is `UNVERIFIED`, never `CLEAN`. ### Phase 5: Re-review and stop Resume the Reviewer when the product supports reliable session recovery; otherwise start a fresh read-only session with the finding ledger and new bundle. The Fixer never supplies the terminal verdict. - `CLEAN`: validated `NO_FINDINGS` with 100% coverage, zero skipped files, zero unaccepted exclusions, and no drift; **or** the bundle proves `reviewable_files` and `unaccepted_excluded_files` are both empty (no Reviewer invoked). - `HUMAN_GATE`: product decision, writable-target choice, permission, repeated disagreement, or round extension. - `MISSING_DEPENDENCIES`: OCR or a required product capability unavailable before edits. - `UNVERIFIED`: ambiguous delivery, malformed output after one correction, failed checks, repeated drift, or stale required evidence. Round-budget exhaustion is never `CLEAN`. Report the remaining ledger and ask whether to authorize another bounded set of rounds. ## Output contract ```text OCR Review Loop Result - Result: CLEAN | HUMAN_GATE | MISSING_DEPENDENCIES | UNVERIFIED - Repository / target: - Scope / exclusions: - Reviewer / Fixer: - Rounds used / budget: - Final evidence id: - Coverage: <reviewed>/<reviewable>; skipped: <count>; unaccepted excluded: <count> - Fixed / Rejected / Open findings: - Verification: - Sessions / recovery: - Git and external actions: none ``` Reviewer-backed `CLEAN` includes the final `validate_round.py` result and the same-evidence comparison. Zero-file `CLEAN` includes the bundle summary proving both lists empty; no review response exists on that path. Every other state names the exact stop point and does not claim OCR or the AI approved the current code.