Skip to content

Let the reviewer pin findings and inline comments to diff lines - #596

Open
JoviDeCroock wants to merge 14 commits into
mainfrom
JoviDeCroock/karachi-v2
Open

Let the reviewer pin findings and inline comments to diff lines#596
JoviDeCroock wants to merge 14 commits into
mainfrom
JoviDeCroock/karachi-v2

Conversation

@JoviDeCroock

Copy link
Copy Markdown
Owner

What

The AI reviewer can now pin its findings — and leave short advisory comments — on specific lines of the diff, instead of every assistant note floating above the hunks in a banner.

The mechanism is deliberately narrow: the model never states a line number. It submits an anchor — one line copied verbatim out of the evidence it was served — and server/lib/ai-review/anchors.ts resolves that string against the same text sample, requiring a unique match. An anchor that misses, matches several lines, or is too generic to identify one (}, });) resolves to no line and falls back to the existing unpinned banner. Matching a string the model must have actually seen is the only claim we can check, so it's the only claim we accept — a mis-pinned finding is worse than an unpinned one, because it points a maintainer at innocent code and quietly exonerates the guilty line.

Two kinds of annotation ride that machinery:

  • Assistant findings gain an optional anchor, resolved to a line that is persisted on the scan_findings row and captioned assistant · line N.
  • Assistant comments are new: severity-free advisory notes pinned next to a line, badged assistant note in the neutral info tone. They live in scans.ai_json only — never scan_findings rows, never in finding_count, never in Risk signals or the file-tree counts.

Why a pinned line can't move the verdict

A resolved line is display-only. annotateFindingsWithDiffStatus now scopes source: "ai" findings by file rather than by line, because the reviewer pins a concern to the clearest line illustrating it — which for a whole-file or manifest-wide argument is often a line the release never touched. Reading that coordinate as line-level evidence would move an AI finding out of the release bucket that releaseRisk and the workflow gate score: a display feature quietly lowering risk. AI findings stay scoped exactly as they were before anchors existed.

Comments cannot move risk at all. A comment naming a file the review could not see is dropped outright; a finding in the same position is kept, because its evidence still stands on its own.

Contract changes

  • anchor (optional, per finding) and comments (optional, capped) added to the submission schema, with matching prompt sections and AI_REVIEW_BOUNDS entries.
  • MAX_REVIEW_OUTPUT_TOKENS 8k → 10k, so a worst-case submission still serializes without truncating mid-JSON.
  • AI_REVIEWER_VERSION 1.2.0 → 1.3.0, with the recorded eval corpus re-stamped in the same change per docs/ai-review-eval.md.
  • Persisted-review schema takes line and comments as optional/defaulted, so every review written before this branch still parses.

Testing

  • pnpm run verify green (lint, format, typecheck, tests).
  • New: test/ai-review-anchors.test.mjs (anchor resolution — exact/partial/marker-stripped/ambiguous/too-generic), anchor + comment coverage in test/ai-review.test.mjs, file-scoping of AI findings in test/review.test.mjs, caption behavior in test/diff-annotations.test.ts, and persistence/export coverage in test/workers/.
  • Docs updated: docs/release-safety.md (anchor contract, comments-are-not-signals) and docs/ui.md (the three annotation kinds).

The final commit is a self-review fix: the branch changed the prompt, the schema, and the output budget while leaving AI_REVIEWER_VERSION at 1.2.0, which is exactly the drift that constant exists to prevent.

🤖 Generated with Claude Code

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 20, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
staged-publish-review c670003 Commit Preview URL

Branch Preview URL
Aug 22 2026, 05:30 AM

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Detection eval report

  • generated: 2026-08-22T05:31:01.309Z
  • deterministic rules version: 1.28.0

Regression (gated)

metric value
malicious recall 100% (39/39)
critical recall 100% (6/6)
benign control false positives 0/6

Frontier (reported — truth-labeled hard cases)

recall 91% (10/11)

  • MISS npm-solana-web3js-keytheft (network-exfil)

Benign hard-negatives (reported — false-positive precision)

false positives 0/10 (0%)

Evasion robustness (reported)

transform samples still blocked code rules retained
splitStringLiterals 20 95% 100%
bracketifyMemberAccess 20 100% 100%
base64Wrap 20 65% 14%
pushPastWindow 20 100% 100%

Updated by CI for this PR.

@JoviDeCroock
JoviDeCroock force-pushed the JoviDeCroock/karachi-v2 branch 2 times, most recently from 96c2ae0 to b1407f2 Compare August 21, 2026 12:32
JoviDeCroock and others added 14 commits August 22, 2026 07:25
The AI reviewer could only report whole-file findings, so every assistant
signal landed in the diff's unpinned banner instead of on the hunk that
triggered it, and every observation below critical/high vanished into the
summary prose.

The reviewer now submits an `anchor` — a line copied verbatim from the
evidence it was served — and `resolveAnchorLine` matches that string against
the same text sample, requiring a unique match. It never states a line
number: the evidence tools serve unnumbered text, so a number would be
counted from memory, and a mis-pinned finding points a maintainer at
innocent code while quietly exonerating the guilty line. An anchor that
misses, matches several lines, or is too generic resolves to no line and
falls back to the banner.

Findings carry the resolved line through both stores into `scan_findings.line`,
so an assistant finding pins to its hunk like a deterministic one. A review
may also return up to six `comments`: severity-free notes pinned to a line,
persisted in `scans.ai_json`, rendered with a neutral badge and the info tone
because a note is not a signal. They are never `scan_findings` rows, never
count into `finding_count`, and cannot move risk.

A resolved line is display only. `annotateFindingsWithDiffStatus` ignores it
for `source: "ai"` findings — otherwise a whole-file concern anchored to an
untouched line would fall out of the release bucket `releaseRisk` and the
workflow gate read, letting a display feature lower the gate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`AI_REVIEWER_VERSION` identifies the prompt, evidence tools, model routing,
and response contract as one unit, and its own comment requires a bump
whenever a change can alter reviewer behavior. This branch rewrites the
system prompt with two new sections, adds `anchor` and `comments` to the
submission schema, and raises MAX_REVIEW_OUTPUT_TOKENS — all behavior-altering
— while leaving the stamp at 1.2.0. Persisting the old version is exactly the
failure the constant exists to prevent: analytics and recorded eval cases
would compare two different reviewer contracts as though they were one.

Re-stamps the recorded eval corpus onto 1.3.0 in the same change, which is the
procedure docs/ai-review-eval.md prescribes — the harness gates on the current
version, so the bump and the records have to move together.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@JoviDeCroock
JoviDeCroock force-pushed the JoviDeCroock/karachi-v2 branch from b1407f2 to c670003 Compare August 22, 2026 05:30
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