Skip to content

feat(bench): both skeptics over the same frozen passes, and the evidence bench replay dropped (#246) - #411

Merged
zaebee merged 3 commits into
mainfrom
skeptic-arms-246
Aug 17, 2026
Merged

feat(bench): both skeptics over the same frozen passes, and the evidence bench replay dropped (#246)#411
zaebee merged 3 commits into
mainfrom
skeptic-arms-246

Conversation

@zaebee

@zaebee zaebee commented Aug 17, 2026

Copy link
Copy Markdown
Owner

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=gemini over 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_bench scores a run — visible_findingsmatch_findingsscore — and carrying killed_ground_truth, because missed cannot 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 hardcoded evidence=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 what guardian_replay_skeptic already does.

Production runs 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, matching judge_all and 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 None because 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_MODEL is dropped per arm. build_skeptic_provider applies 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

mistral (mistral-medium-latest) -> Status 402
{"detail":"Check your subscription on https://admin.mistral.ai/subscription"}

The local MISTRAL_API_KEY has 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

…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>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment thread scripts/skeptic_arms.py Outdated
zaebee and others added 2 commits August 17, 2026 12:35
#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>
@sonarqubecloud

Copy link
Copy Markdown

@zaebee
zaebee merged commit 2c1d50b into main Aug 17, 2026
3 checks passed
@zaebee
zaebee deleted the skeptic-arms-246 branch August 17, 2026 12:45
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