Skip to content

Add an opt-in verification stage that proves or refutes each blocker and should-fix - #72

Merged
polewskm merged 4 commits into
mainfrom
issue-41
Oct 31, 2026
Merged

polewskm merged 4 commits into
mainfrom
issue-41

Conversation

@polewskm

@polewskm polewskm commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Adds an opt-in verification stage after synthesis: with CODE_REVIEW_VERIFICATION=on, each merged blocker and should-fix goes to a Sonnet call with Read/Grep/Glob in the checkout (same path guard as agent.ts), given the finding, its diff hunk and its reviewers' charters, batched by file (up to 8 per call, $0.50 budget each, shared prefix cached).
Confirmed → kept, code path appended to evidence; refuted → dropped and listed under "Refuted by verification" in the check run and in the trace; uncertain → rephrased as a question and lowered one severity step. Nits aren't verified. Calls are costed as role verification; the eval report now counts posted blockers/should-fixes and refuted findings.
The verification agent is injectable, and test/verify.test.ts covers each verdict path, nits skipped, batching, the off switch and cost recording hermetically. npm run typecheck and npm test (88 tests) pass; the paid eval was not run.

Decisions

  • Off by default (CODE_REVIEW_VERIFICATION must be on), per the issue's eval-gated rule; README and CHANGELOG say so.
  • The schema adds a question field next to { verdict, path, reason } so the model writes the "Is X intended? If not, …" rephrasing; without one, the finding's problem is prefixed with "Is this intended?".
  • A refuted verdict without a reason drops nothing and is treated as uncertain; a failed call leaves its findings unchanged (recorded in the trace).
  • After verification, a request-changes verdict with no blocker or should-fix left becomes comment; verification never turns a review into approve. The summary names each refuted finding, and the trace maps each finding's old id to its posted id (postedAs).

Refs #41 — remaining: the acceptance eval (node evals/run.ts, held-out guidance, 2 runs each with verification on and off), recording the result in the issue, and turning it on by default only if it shows a gain.

…and should-fix

After synthesis, CODE_REVIEW_VERIFICATION=on sends each merged blocker and should-fix, a file's findings per call, to a Sonnet call with the checkout behind the reviewers' path guard. Confirmed findings get the code path in their evidence, refuted ones are dropped and listed with the reason in the check run and the trace, and uncertain ones become questions one severity lower. Nits aren't verified. Off by default until the eval shows a gain.

Refs #41
@polewskm
polewskm deployed to code-review October 31, 2026 04:39 — with GitHub Actions Active

@ncode-review ncode-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 NCode Review at 001fb69: 9 new findings on the changed lines.

Comment thread src/verify.ts Resolved
Comment thread src/verify.ts Resolved
Comment thread src/verify.ts Resolved
Comment thread src/review.ts Resolved
Comment thread src/verify.ts Resolved
Comment thread src/verify.ts Resolved
Comment thread src/results.ts Resolved
Comment thread src/verify.ts Resolved
Comment thread src/review.ts Resolved
@ncode-review

ncode-review Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

🤖 Review complete

Verdict: 💬 Comment — This PR adds an opt-in verification stage that runs after synthesis. Sonnet calls with the checkout confirm, refute or question each blocker and should-fix. Refuted findings are dropped and recorded, uncertain ones become questions one severity lower, and the verdict eases from request-changes to comment but never to approve. The code holds together and has good tests for failures, thrown calls, verdicts outside a batch and renumbering. The main risk is a design one: a refutation is accepted on the model's word alone, while the model reads code the PR author controls. The concurrency ordering also has no test.

7 reviewers run — 2 findings (run details)

Reviewer Model Findings Top
synthesis opus-5-5 2 🟠
architecture sonnet-5-5 0 🟢
completeness sonnet-5-5 0 🟢
conventions sonnet-5-5 0 🟢
correctness sonnet-5-5 0 🟢
hygiene haiku-5-5 0 🟢
rule-check sonnet-5-5 1 🟡
security sonnet-5-5 1 🟠

Skipped: api-compat, data-model, infrastructure, intent, performance, tests

Findings
  • 🟠 F1 src/verify.ts:153: A PR author can steer the verifier into dropping a real finding, including a security blocker
  • 🟡 F2 test/verify.test.ts:344: No test for the first-call-then-rest ordering or the verification concurrency limit

Trial: findings are posted as review threads and in the check run. $0.60 on Amazon Bedrock, 64s, at dbf6003. (how to interact)

…l, note what it changed

Verification no longer turns a review into an approval: a request for changes with nothing serious left becomes a comment, and so does a review without synthesis's verdict whose findings were all refuted. The summary, written before verification, now names the refuted findings and counts the ones made questions, and the trace maps each verified finding to the id it was posted with. A verification agent that throws is recorded as a failed call instead of aborting the review. verifyReview carries the stage's wiring out of review() so it is tested. mapWithConcurrency moves to src/concurrency.ts to break the verify/review import cycle, and the verification concurrency is a setting in config.ts.
@polewskm

Copy link
Copy Markdown
Contributor Author

/review

@ncode-review ncode-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 NCode Review at dbf6003: 2 new findings on the changed lines.

Comment thread src/verify.ts Resolved
Comment thread test/verify.test.ts Resolved
@polewskm

Copy link
Copy Markdown
Contributor Author

Autopilot: Round 2 answered. No blocker or should-fix is left open. The one should-fix, F1, repeats round 1's F1 and is declined as a design point of #41. It could be a follow-up once the eval runs. The remaining thread is a nit, answered above. Recommend merging once you've resolved them.

@polewskm
polewskm marked this pull request as ready for review October 31, 2026 06:42
@polewskm
polewskm deployed to code-review October 31, 2026 06:43 — with GitHub Actions Active
@polewskm
polewskm enabled auto-merge October 31, 2026 06:43
# Conflicts:
#	README.md
#	src/results.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant