feat(bench): both skeptics over the same frozen passes, and the evidence bench replay dropped (#246) - #411
Merged
Merged
Conversation
…nce bench replay dropped (#246) #246 asks whether a cross-model skeptic cuts noise where a same-model one cannot. Running it as written would measure the configuration already in production (GUARDIAN_PROVIDER=mistral, GUARDIAN_SKEPTIC=gemini) and could not say why that still produced 19 findings with 1 real. What was never measured is the comparison itself: the same finder output judged by both. The corpus turns out to allow a stronger question than the one asked. Of the 37 frozen passes carrying findings, 30 came from a gemini finder and 7 from a mistral finder, so both orientations are present. Judging every pass with each skeptic separates two hypotheses the issue conflates — cross-vendor refuting more in both orientations, versus gemini refuting more whichever finder wrote the findings. The original single-orientation design cannot tell those apart. Also fixed, and found while building this: guardian_bench's replay path hardcoded evidence=None, justified by "a recording is not a checkout". True, and beside the point — the commit is named by the fixture, so a worktree gets one, which is what guardian_replay_skeptic already does. Production runs with GUARDIAN_EVIDENCE=1, so every --replay-finder measurement to date was of a configuration nobody runs. _judge_recording now takes evidence keyword-only with no default, like judge_all and for the same reason. Two guards earned their place before any measurement: Both arms are built before either runs. A single-arm result costs the same as none and reads like a result. This is what stopped the first attempt after two calls instead of 135, when the local mistral key returned HTTP 402. GUARDIAN_SKEPTIC_MODEL is dropped per arm rather than passed through. build_skeptic_provider applies it to whichever provider it builds, so an environment holding the production value would have handed a gemini model name to the mistral arm — one arm on a model that does not exist, reported as a comparison between vendors. The measurement is NOT run: the local mistral key returns 402 (subscription), and no ollama is running, so no second arm exists today. Production is unaffected — the last review ran mistral successfully on 2026-08-16 22:53, and the 402s I first thought I saw in that log were the PR number. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates guardian_bench.py to collect and pass evidence when replaying finder recordings instead of hardcoding it to None. It also introduces a new script, skeptic_arms.py, along with unit tests, to compare and score Gemini and Mistral skeptics on the same frozen finder passes. The review feedback highlights an issue in the _vendor classification function in skeptic_arms.py, where Mistral's codestral models are incorrectly classified as other instead of mistral, and suggests a fix to handle this case-insensitively.
#246) gemini-code-assist on #411 spotted that codestral-latest is a Mistral model whose name does not contain "mistral", so _vendor called it "other" and the report then labelled it cross when paired with the mistral arm. Sonar separately flagged the nested conditional. Both are the same line, and patching in "codestral" would have fixed one instance of a mechanism. The mechanism: "other" equals no arm name, so every row of an unattributed model read `cross` — in the exact variable this experiment measures. A new vendor would not have raised anything. It would have produced a wrong answer shaped like the expected one. So the markers are an explicit table (mistral also ships ministral and magistral), matching is case-insensitive, and an unrecognised model becomes UNKNOWN_VENDOR, which the report keeps as its own kind rather than folding into cross. same-vs-cross for a model nobody has attributed is not merely unmeasured, it is unknowable, and printing "cross" would be inventing it. The unattributed names are listed under the table with the one-line fix, because nobody can add a marker for a number they never saw. Mutation-verified: restoring the two-branch kind reddens the new test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SonarCloud on #411: the same/cross/unknown choice was a nested conditional inside the report loop. It is the variable the whole experiment turns on, so it becomes a named function with its own tests rather than an expression read three clauses deep. Behaviour is unchanged; the parametrised test pins both orderings of the unknown case, because which arm an unattributed model happened to meet must not decide how it is classified. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Tooling for #246, plus a real defect found while building it. The measurement itself did not run — see the blocker at the bottom.
The issue as written can no longer be run
#246 asks for "the bench with
GUARDIAN_SKEPTIC=geminiover a mistral finder". That is production today (GUARDIAN_PROVIDER=mistral,GUARDIAN_SKEPTIC=gemini), and it is the configuration that produced 19 findings with 1 real on #399. Running it would measure what already runs and could not say why.What was never measured is the comparison: the same finder output judged by both skeptics.
A stronger question, on the same corpus
Of the 37 frozen passes carrying findings, 30 came from a gemini finder and 7 from a mistral finder — 52 and 83 findings respectively. Both orientations are present, so judging every pass with each skeptic separates two hypotheses the issue conflates:
The original single-orientation design cannot tell those apart.
Scored exactly as
guardian_benchscores a run —visible_findings→match_findings→score— and carryingkilled_ground_truth, becausemissedcannot tell "the finder never found it" from "the finder found it and the skeptic hid it" (#270), and only the second is something an arm did.The defect this uncovered
guardian_bench's replay path hardcodedevidence=None, justified by "the replay path holds a recording, not a checkout: there is no project root". True, and beside the point — the commit is named by the fixture, so a worktree gets one, which is whatguardian_replay_skepticalready does.Production runs
GUARDIAN_EVIDENCE=1. So every--replay-findermeasurement to date was of a configuration nobody runs._judge_recordingnow takesevidencekeyword-only with no default, matchingjudge_alland for the same reason: this function passed None for months, and a default lets the next caller do it again silently.Evidence covers 96 of 135 findings: four fixtures touch Python, two touch none and are judged with
Nonebecause production would collect nothing for them either.Two guards that earned their place before any call was spent
Both arms are built before either runs. Half an experiment costs the same as none and reads like a result. This is what stopped the first attempt after 2 calls instead of 135.
GUARDIAN_SKEPTIC_MODELis dropped per arm.build_skeptic_providerapplies it to whichever provider it builds, so an environment holding the production value (gemini-2.5-flash) would have handed that name to the mistral arm — one arm on a model that does not exist, the other on the intended one, and the difference reported as a comparison between vendors.Blocker: the measurement did not run
The local
MISTRAL_API_KEYhas no active subscription, and no ollama is running, so no second arm exists today. gemini works.Production is unaffected. The last review ran mistral successfully on 2026-08-16 22:53. I first read 31 occurrences of "402" in that run's log as HTTP status codes; they are the PR number, and the two "subscription" hits came from a GitHub API JSON blob. Whether the CI secret is still valid is testable only by running
/guardian review.Options, none taken here: restore the mistral subscription and run as designed; start a local ollama for a free cross-vendor arm; or use a second gemini model, which answers the weaker cross-model question rather than the cross-vendor one.
17 tests, 96% coverage on the new script; 2001 tests overall.
🤖 Generated with Claude Code