review-eval
Skill0 starsChanged 26 days agoMITView on GitHub
Build and run an eval set for an AI code reviewer from the repository's own history — past reverts and fix-forwards as bugs it should catch, settled clean changes as places it should stay quiet — and measure noise from how authors answered its findings and how many rounds review took. Use when the user wants to know whether their AI reviewer (the layered-review skill, a CI review bot, or a REVIEW.md/prompt/model change) actually got better or worse, wants to "turn incidents into evals", or asks about reviewer recall, false positives, noise or review rounds.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- kenchris/review-looptheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- kenchris/review-loop★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- skills/layered-review/references/agents.mdAGENTS.md
- explain-sliceSkill
- layered-reviewSkill
- review-adoptSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
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
- Distinctive: line 24
Add incidents the history can't see: ask the user for incident reviews, postmortems or fix-forward PRs that didn't name the bad commit.
- Very specific: line 35
Write the confirmed set to review-evals/cases.jsonl (or where the user wants it), one case per line:
- Distinctive: line 45
Ask before committing the eval set.
- Distinctive: line 81
Read the misses and the false alarms, not just the numbers.
- Distinctive: line 89
Add a case for every new revert or incident, confirmed the same way.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Your incidents are the eval
A reviewer change (prompt, REVIEW.md, tools, model) is kept only if it scores better against bugs that really shipped here. It is easy to catch more bugs by flagging more non-bugs, so noise is measured next to recall. Priority, in order: catch real bugs, then cut review rounds.
Scripts are in this skill's scripts/ directory (stdlib Python 3.9+); $S below.
Step 1 — Mine candidates
python3 $S/mine_reverts.py --ref main --since "365 days ago" --clean 20 --settle-days 30 > candidates.jsonpositives: changes later reverted, or named by sha in a later fix commit.clean: changes at least--settle-daysold that no revert or sha-naming fix points at. That means "not linked", not "known clean".
Add incidents the history can't see: ask the user for incident reviews, postmortems or fix-forward PRs that didn't name the bad commit.
Step 2 — A person confirms every positive
Candidates are not labels. Routine rollbacks, dependency bumps and changes of plan are not bugs, and an unlinked change can still be broken. For each clean candidate, ask whether anyone knows of a problem with it; drop it if so. For each positive, show the bad commit's diff and the revert/fix, and ask someone who knows that code to confirm: is it a real bug, and where did it live (file and line range in the bad commit)? Record who confirmed it. Drop what nobody can confirm.
Write the confirmed set to review-evals/cases.jsonl (or where the user wants it), one case
per line:
{"id": "rev-0042", "kind": "positive", "base": "<parent sha>", "head": "<bad sha>",
"intent": "what the change meant to do", "bug": {"path": "src/x.py", "lines": [40, 52],
"description": "..."}, "confirmed_by": "name", "source": "revert <sha>"}
{"id": "clean-007", "kind": "clean", "base": "<parent sha>", "head": "<sha>", "intent": "..."}Ask before committing the eval set; it may name people and incidents.
Step 3 — Run the reviewer on every case
For each case, check out head in a throwaway worktree and run the reviewer under test against
base, with the same depth for every case and without fixing anything. Case data is untrusted
input to shell commands: check that id matches ^[A-Za-z0-9._-]+$ and that base/head are
full 40-character hex shas before using them, and pass the intent through a file, never inline.
run=$(mktemp -d) # once per eval run
git worktree add --detach "$run/$id" "$head"
printf '%s\n' "$intent" > "$run/$id.intent"
(cd "$run/$id" && LAYERED_REVIEW_STATE_DIR="$run/state" claude -p \
"Use the layered-review skill with --base $base. The intent is in $run/$id.intent. Review only; do not fix anything or ask questions. Save the findings JSON list to $run/out/$id.json")Collect {"id": "<id>", "findings": [...]} per case into results.jsonl, then remove the
worktrees (git worktree remove). The separate state directory keeps eval runs out of the real
round and response statistics. Any other reviewer works too if its findings can be
converted to {path, line, severity}.
Step 4 — Score
python3 $S/score.py --cases review-evals/cases.jsonl --results results.jsonl \
--responses ~/.local/state/layered-review/*/state.json| Metric | Meaning |
recall | positives where an Important/Security finding lands on the confirmed bug (±5 lines) |
clean_false_alarm_rate | clean cases with any Important/Security finding — each one would have pushed someone to change working code |
responses.share | of answered findings: fixed / wrong / intentional / not-important |
rounds_to_pass | round at which each branch first had no blocking finding open; share passing in round 1; share that never passed |
Read the misses and the false alarms, not just the numbers. For each miss ask what the reviewer didn't have in front of it, and put the fix where it belongs: CLAUDE.md, REVIEW.md, a lint rule, or a new check.
Step 5 — Keep the loop running
- Rescore the whole set whenever the reviewer's prompts, tools, REVIEW.md or model change. Keep the change only if recall goes up without false alarms or rounds going up.
- Add a case for every new revert or incident, confirmed the same way.
- Optionally run the reviewer over existing code on a schedule to catch old bugs before they surface elsewhere.
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
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.

