Repository navigation
Claude review: LGTM-shaped by construction — give it the repo's traps, a blind read, a structured verdict and the callers rule #3710
Description
The bot review is LGTM-shaped, and the shape is structural
Across the last several hundred PRs the Claude review posted LGTM on very nearly all of them and caught a real defect a handful of times. Every defect it missed that later surfaced was found by behavior — a post-install read, a production page, an EXPLAIN on a rig — never by the review: the sweep-id precision loss (#3487), the twelve file-growth cards from a per-collection fire on an hourly collector (#3636, the same shape as #3628 which the review had passed), MAX(max_dop) grouped across plans (#3648), an ORDER BY 3 + 4 DESC folding to a constant (#3613), the Slack fifty-block breach (#3612), integer division in the Full-edition rate columns.
None of those is visible in a diff read by a generalist, and the review has three handicaps that make LGTM its honest output rather than a lazy one:
- No memory of this repository's traps. Every review starts from nothing. Our bugs recur in shapes —
truncated = rows.Count >= limit, ordinal arithmetic inORDER BY, cumulative-versus-delta on an aggregate across plans, per-observation versus per-collection alert firing, restart-spanning windows,BaseSeverity <= 0skipping amplifiers, a non-virtual method called through a base reference, a census test that fires on a new string constant,pg_total_relation_sizeincluding TOAST — and the reviewer never learns them. - It reads the diff alongside the author's essay. Our PR bodies are persuasive by design. A reviewer that checks the diff against the story is checking consistency, not correctness; the two agree whenever the author was wrong in a consistent way.
- It cannot execute anything. Claude review runs finish green having posted nothing: the allowlist forbids every read tool the prompt invites, denial churn ends sessions without a verdict, and the job never checks that it posted #3650 gave it read-only tools; the runtime and SQL-semantics classes remain invisible.
Slice one (this issue)
.github/REVIEW-TRAPS.md— one line per trap with the PR that bit, loaded into the review prompt; the review must name which traps the diff is near and say why each does or does not apply.- Blind read first. Two phases in one job: the diff with the PR body withheld — what does this change do, what could it break — then the body revealed, and a report of where the author's account and the blind read diverge. Divergence is the finding.
- Structured verdict. For each claim the PR body makes: VERIFIED (how) / UNVERIFIED (why) / REFUTED; the three riskiest changed lines and the test that pins each; a reviewer checklist. A bare LGTM is no longer a valid verdict — the guard's "verdict posted" check should require the structured block.
- Callers rule. For every changed public signature or behavior, enumerate its callers with the read tools and state whether each still holds.
- A ledger. The verdict artifact gains a machine-readable line (
verdict, claims counted by state, traps named) so a later pass can compute the miss rate against post-merge defects instead of an impression.
Slice two (follow-up, after slice one has a few weeks of verdicts)
Reuse the PostgreSQL tests job's TimescaleDB container so the review can execute new SQL; tier the review so the full pass runs only on Analysis/, Storage/, Collectors/, install/ changes and a light pass elsewhere. Roughly triples the review's cost and runtime; worth it only if slice one's ledger shows the SQL class is what remains.
Timing
The review is dark on dev until the next release sync (the action refuses on workflow drift against main), so changing claude-review.yml now costs nothing further and lands with the restore.
Activity
erikdarlingdata commentedon Sep 19, 2026
Model (slice one, ruled 2026-09-19): the workflow sets no model today, so the review runs Claude Code's default.
claude_argsgains--model "claude-opus-5[1m]"(the[1m]selector opts into the 1M context window, which the callers rule and the traps file need on a largeStorage/diff) and a--max-turnsceiling. Tiering rides in the same slice: apaths-filterstep routes changes underAnalysis/,Storage/,Collectors/,install/,Darling/*/Compose,Darling/*/Mcpto the full Opus pass and everything else (tests, docs, viewer XAML, wwwroot) to a Sonnet pass with the same structured verdict — the verdict contract is identical either way, so the guard does not care which tier ran. Expected cost: ~5× per full-pass review, offset by the light tier on roughly half the PRs. Verified againstanthropics/claude-code-actiondocs/configuration.md("Custom Model", "Claude Code Settings":claude_argstakes precedence oversettings.model; no effort flag exists —--append-system-promptis the lever for reasoning depth).Review tier: Alerting and Notifications read at the full tier (#3710)
Claude review: traps file, blind read, structured verdict, callers ru…
erikdarlingdata commentedon Sep 19, 2026
Closed by #3718 (merged to dev).
CHANGELOG: second splice - sixty-three entries from sixty-five merged…