review
Reviews a verified change with subagents on two axes, Standards and Spec, then works through the findings that survive.
npx skills
npx skills add JoshuaOliphant/compost --skill review
Works for Codex, Cursor and other harnesses. Use -a <agent> to target one, e.g. -a codex.
Claude Code
/plugin marketplace add JoshuaOliphant/compost
/plugin install compost@compost
Review
A change that passes its tests can still break the repo's rules or quietly miss what the issue asked for. Review catches both before the change reaches compost:finish. Subagents do the reviewing so the reviewer never shares the author's context, and each finding has to survive a skeptic before it costs you a fix. On a diff that changes executable code, the harness's own code review runs alongside them as a second opinion on correctness.
Run this after compost:verify passes on every issue. Nobody needs to ask.
Steps
- Run the review workflow. Run
/compost:review-changeswith{base, head, issue, jev: "${CLAUDE_PLUGIN_ROOT}/scripts/jev.py"}. Leavebaseout to review against the merge-base with the default branch. Leaveheadout to review up toHEAD; pass it to review one issue's commits on a branch that has moved on, such as<merge>^2for an issue landed by a merge. Passissuewhen you know the issue, as the tracker writes its id (42,bd-a1b2.3,group/project#12), since the Spec axis needs its AC-N. The workflow scopes the diff and ranks the changed files by structural risk with Jev'sreview-risk, so reviewers read the riskiest first. It runs a Standards reviewer and a Spec reviewer ascompost:reviewersubagents in parallel (one reviewer on both for a small diff, below); each picks its canon essays, anchors its findings, and grades their severity with Jev (Jev tools). A skeptic told to refute it gets each finding Jev marks worth one: a probable blocker or major, or a call Jev is unsure of. The rest come back marked unverified. When Jev is unavailable, the reviewers grade severity themselves and every blocker and major gets a skeptic, while minor findings skip it. Passskeptics: 3for a branch where a false finding would be expensive; a finding then survives only when most skeptics uphold it.
Every change gets this review, whatever its size. Size picks the path, never whether review runs: a diff of 50 changed lines or fewer (insertions plus deletions from git diff --shortstat) that Jev ranks and finds not structural gets one compost:reviewer on both axes. It tags each finding Standards or Spec and records per axis what it checked; the workflow splits the findings back into the same two results (its path says light). Without Jev's ranking, the diff gets two reviewers. Pass full: true to force two reviewers. That light path is the cheap option; "too small to review" is not a ruling you can make.
Every reviewer, on either path, returns checked beside its findings: what it read, each at a file:line, and on Spec one entry per AC-N with its verdict. Each reviewed axis carries that list in the result. The workflow fails an axis whose reviewer cites no file:line for anything it checked or, on Spec, names some AC-N of the spec in neither a cited entry nor a finding's claim (an AC-N quoted only in a finding's evidence does not count), because an empty findings list with nothing behind it is a reviewer that did not look, not a clean diff. The workflow takes every AC-N in the spec text, so a spec that quotes another issue's AC-N ("keeps #12's AC-3 working") needs it mapped too, or the axis fails; that errs toward incomplete on purpose, and the re-run below can map it or the comment can say why it doesn't apply. A failed axis still returns the findings its reviewer raised, skeptic verdicts and all; take them through step 3 like any others, and keep them when the re-run below misses them.
Running the workflow from this skill is the opt-in it needs: it spawns a handful of agents, not dozens. If the Workflow tool is unavailable (as inside a subagent) or the system denies its call (auto mode can refuse it), do the same by hand, and say in the step 6 comment that the review ran by hand and why: run review-risk yourself (input {"base": ..., "head": ...}), spawn two compost:reviewer agents in one message, one on the Standards axis and one on the Spec axis, with the ranked file list in each prompt and each told to return checked as above, then one skeptic pass over the findings whose skeptic is true, or over every blocker and major when the reviewers left skeptic out. The skeptic pass and the harness code review below are part of the review, not extras to drop on this path. When the diff meets the light criteria above, spawn one agent on both axes instead, told to tag each finding with its axis and return checked per axis, and split its findings by axis before the skeptic pass. A denied call is not a skipped review, and the fallback is this procedure, not another attempt at the workflow tool. If the user themselves declined the call, stop and ask them.
If the workflow reports an empty diff or an unresolvable base, fix that first: commit the work, or pass the right base. If it skipped the Spec axis because no spec was found, say so in the issue comment in step 6. A change reviewed on one axis has been half reviewed.
If complete is false or either axis's status starts with failed:, the review did not happen; problem names each failed axis and why. Fix what the status names (an issue that could not be fetched, a reviewer that did not return) and run the workflow again, or the by-hand fallback above for the failed axis. A reviewer that returned no record of what it checked gets one more run of that axis, by hand, with its prompt naming what the last one left out. A by-hand reviewer whose checked cites no file:line, or skips an AC-N, has not reviewed either. If the axis is still incomplete after that, the step 6 comment and any PR note say the review is incomplete and on which axis, never that it found nothing. Never move on to compost:finish from an incomplete review.
Each axis also returns an unjudged list: findings sent to a skeptic whose skeptics all failed, so nobody tried to refute them. Treat every unjudged finding as a survivor in the steps below.
The result's risk holds the ranked files and a structural flag. When risk.ranked is false, risk.problem says why (no Jev path, Jev unavailable), and structural risk is yours to judge in the section below.
Run the harness's built-in code review too, when the diff changes executable code. Executable means source in a programming language: scripts, hooks, workflows, tests. A diff of only Markdown, prose, or data files has nothing for it to hunt, so skip it and say so, with the reason, in the step 6 comment. Otherwise, alongside the review (while the workflow runs, or while the reviewers do on the by-hand path), invoke the code review skill that ships with the harness you are running in: code-review in Claude Code (not a plugin's skill of a similar name), /review in Codex. It hunts correctness bugs, which neither axis is built to find. Point it at the same range: in Claude Code pass the branch as its target, or nothing to review the working diff, and leave out --fix and --comment, since its findings go through step 3 like the others and nothing is posted before you have checked it. When the harness ships no such skill, or it fails, note that in the issue comment in step 6 and carry on; the two axes are still the review that gates compost:finish.
-
Keep the two axes apart. Read the Standards and Spec survivors side by side. Don't merge them into one ranked list: code can follow every standard and still build the wrong thing, and one axis must not mask the other. Keep the built-in review's findings as a third list for the same reason; it has run its own verification, so treat each as a survivor. Skim the refuted lists too. When a skeptic refuted a blocker with reasoning you can see is wrong, check the code yourself and treat the finding as a survivor if it holds.
-
Verify each survivor against the code before you act on it. A survivor is a claim, not an order. For each one:
- Restate what it asks for in one line, in the domain's terms.
- Open the file at the cited line and check the claim against the code, the tests, and the callers.
- If it asks for something to be "done properly" (configurable, generalised, more layers), grep for a caller that needs it first. No caller means you push back: the extra code is speculative generality, the thing subtract before you add warns against.
- If it contradicts a ruling already logged on the issue, or an ADR, the ruling stands until someone supersedes it. Push back and cite the ruling.
Push back with evidence, not tone: the file:line that shows the reviewer wrong, the test that already covers the case, the caller that doesn't exist. When a finding is right, fix it and say what changed. Skip "good catch" and "you're right"; the fix shows you heard it. When you pushed back and then find you were wrong, say so in one line and fix it.
-
Fix the survivors that hold, one at a time. Blockers first, then the quick fixes, then anything that reshapes code. Fix at the root (fix root causes), and when a fix replaces an interface, replace it: the old code goes in the same change, with no shim left behind. After each fix that changes behaviour, run the tests that cover it. When a Standards survivor is mechanical (a banned API, an import shape, a file in the wrong place), fix the instance and also file an issue for a lint rule, hook, or CI check that would have caught it (make mistakes impossible).
-
Re-verify. Once the fixes are in, run
compost:verifyagain in full: suite, gates, the AC-N map. If the fixes changed behaviour or touched files the first review didn't see, run the review again, the same way step 1 ran it (workflow or by hand), and the built-in review once more when the diff changes executable code. A finding you pushed back on that comes back from a fresh reviewer deserves a second look, not a second refusal by reflex. -
Record the outcome on the issue. Post one comment, headed
Review round <n>(one more than the issue's earlier review comments;compost:implementcounts these for its three-round cap): what each axis and the built-in review found, with what each axis checked (for a clean Spec axis, each AC-N and its verdict), what you fixed (with the commit), what you pushed back on and the evidence, whether the Spec axis and the built-in review ran, and whether the review ran by hand and why. That comment is the ruling logcompost:finishsummarises into the PR.
When the branch is structurally risky
Standards and Spec both judge the change against a reference. Neither asks whether the approach itself was the right one. For a branch that adds a module boundary, a new data flow, a new external dependency, shared or global state, or a change that crosses bounded contexts, have a separate agent judge approach fit. This is opt-in: most issues don't need it.
The trigger is the workflow's risk.structural: run approach fit when it is true, and keep the flagged file names out of the problem statement, since they hint at the mechanism. When risk.ranked is false, decide from the list above by reading the changed files. The flag misses about one structural file in seven, so a branch you can see adds one of those things still gets the judge.
Write a problem statement that describes only the problem, never the solution: what should work differently afterward, or what is broken. Any hint about the mechanism biases the judge toward the code it is about to read. Then spawn one subagent with the prompt in approach fit. It reads the codebase as it was at the base, designs its own approaches before it sees the diff, then compares. Treat its verdict like a survivor from step 3: verify it, and if it names a better approach you agree with, hand the design question to compost:deepen.
For a large or ambiguous change, vet is a further independent pass over the diff and the conversation. Use it when the scope is wide enough that two focused reviewers could miss something between them.
When the user wants to sign off themselves
Some changes the user wants to read with their own eyes. When they say so, follow review-diff. It opens the branch diff in a local browser for inline, merge-request style comments and waits while they review. Their comments are the user's own review: understand each, ask about anything unclear before changing code, then fix, re-verify, and record them on the issue as in steps 4 to 6.
Next moves
compost:finishwhen the review came back complete, no survivors or unjudged findings remain, and verify passes.compost:verifyafter any fix, before you call the review done.compost:diagnosewhen a finding exposes a defect whose cause you can't see from the cited line.compost:deepenwhen approach fit, or a cluster of Standards findings in one module, says the design is the problem.compost:buildwhen a Spec finding shows an AC-N that was never built.