A review ledger per pull request that refuses unchecked review claims.
It refuses a finding without a source, a withdrawal without evidence, a verdict before the gates have finished and every changed file has been read, and a post without a named person. It does not review code and calls no model: an agent or a person does the review, reviewproof does the bookkeeping. Built for AI-assisted review over several rounds on GitHub and GitLab; it works for people too.
~/.reviewproof), so a review
never touches the reviewed repository. No token is written to disk. Open the diagram
Each rule closes one way an AI review goes wrong: a finding nobody can trace, a file nobody opened, a verdict while the tests still run, a round-1 finding quietly dropped in round 2, a note posted before a person looked at it.
Each finding needs a severity, a source (a rule, a design, legacy code or other, with a reference) and a place
file:line, checked at the round's head and stored as file:line@sha. A missing field, a file that does
not exist at the head or a line past its end is refused.
In the next round every open finding needs a status: verified, reopened at a place in the new head,
or withdrawn. Withdrawing needs evidence holding a file:line@sha or a URL; “the author disagrees” is
not evidence.
No verdict while a gate is unfinished, a changed file is unread or a carried finding has no status. Reads are measured: in
Claude Code a hook on the Read tool records each file and line range the agent opened. pass is also refused while
a blocking finding is open or a gate failed or was skipped, and a summary with hedge words (probably, seems, might) is refused.
The person reads the draft and runs reviewproof post --approved-by <name> in their own terminal. It refuses
to run inside Claude Code, and the plugin's hook stops the agent from running it. The posted comment is read back and compared
with the draft.
Run inside a checkout at the head of the pull request. The agent (or you) does the review; reviewproof keeps the ledger.
$ reviewproof start o/r#12 # round 1 (a URL or gitlab:g/r!7 also work) $ reviewproof diff # prints the round diff, counts the files read $ reviewproof gate run tests -- npm test # no shell; the log is kept, a rerun is attempt 2 $ reviewproof gate skip e2e --reason "needs a staging server" $ reviewproof add findings.json # sourced findings, linted $ reviewproof status # what still blocks a verdict $ reviewproof verdict not-yet --summary "Two findings open; tests pass." $ reviewproof draft # writes the note and prints it
Severity: blocking, major, minor. Source kind: rule, design,
legacy, other.
[
{
"severity": "major",
"source": { "kind": "rule", "ref": "CONTRIBUTING.md#error-handling" },
"at": "src/api/client.ts:88",
"title": "Network errors are swallowed",
"body": "The catch block returns null, which callers read as 'not found'."
}
]
Run start again: every finding still open needs a status before the next verdict.
$ reviewproof start o/r#12 $ reviewproof mark F1-1 verified $ reviewproof mark F1-2 reopened --at src/api/client.ts:91 $ reviewproof mark F1-3 withdrawn --evidence "src/api/client.ts:40@3f9c2ab handles it"
The agent stops at the draft. You read it and post from your own terminal, not from the agent. post sends the draft as
a comment, reads it back, compares it with the draft and stores the comment's id and URL.
$ reviewproof post --approved-by <name>
Other commands: read <file> [--lines a-b] counts a file read elsewhere, skip <file> --reason R
leaves a changed file out of coverage, export --sarif [--out FILE] writes the latest round as SARIF 2.1.0 for
code-scanning tools.
The ledger is locked per pull request while a command changes it, so commands run at the same time are safe: none loses another's change, and a gate's log is never overwritten.
Start each gate as its own background command right after start, and review while they run.
status shows a gate still running as missing.
Split a large diff among helper agents, one group of files each. Their Reads count, each recorded with the agent's id. The main
session reads the code behind every major or blocking candidate itself before add.
One checkout (a git worktree) and one agent per pull request. Each pull request has its own ledger, so they never wait for each other.
Other tools cover parts of this. A survey in November 2026 found none that refuses the claims above.
| AI reviewers | Copilot code review, CodeRabbit, Cursor Bugbot, Claude Code Review, Greptile. They review the code and carry findings across rounds, but they can resolve or drop a finding on their own. |
|---|---|
| “Viewed” marks | Reviewable, Gerrit, GitHub “Viewed”. Files are marked reviewed, but a person declares it; nothing measures what was read. |
| reviewproof | Finds no bugs and calls no model, so it works with any agent, or a person. It adds the refusals: no finding without a source, no withdrawal without evidence, no verdict before the gates and reads are done, measured read coverage, and the posted note read back. |
Works on Windows, macOS and Linux.
gh CLI, logged in (gh auth login).GITLAB_TOKEN environment variable (a token with api scope). reviewproof calls the GitLab
API itself; glab is not needed.
$ npm i -g reviewproof
Adds the Read and shell hooks and the review-round skill, which drives one round and stops at the draft.
/plugin marketplace add vannt-dev/reviewproof /plugin install reviewproof@reviewproof
cat in a shell or Grep do not count.reviewproof diff and reviewproof read: these are declarations, not measurements.
post only, not an agent that calls the GitHub or GitLab API itself (gh api,
curl, ...).
.cmd tool (such as npm) is retried through cmd.exe, which expands
%VAR% in the arguments.