Repository navigation
fix: refuse to compare Inspect runs scored at different numeric pass thresholds - #95
Merged
noteflowai merged 1 commit intoOct 28, 2026
Conversation
noteflowai
deleted the
automation/feature-2026-10-28-evalarc-133129807485
branch
October 28, 2026 18:54
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.
EA-02 requires that missing or non-comparable evidence never looks like an improvement. diff() checks that the format and task are comparable, but it ignores the numeric pass threshold each Inspect run was loaded with. An Inspect check that scored 0.7 passes at threshold 0.5 and fails at threshold 0.8. A baseline loaded at 0.8 and a current run loaded at 0.5 can therefore report 'improved' checks and a passing gate when behavior has not changed. The report records only current["threshold"] as numeric_pass_threshold, so a reviewer cannot see the mismatch in the output.
Scope: one comparability rule for the Inspect format in the existing entry point evalarc.results_diff.diff(baseline, current). The loaders, the output schema, render_markdown and the other formats do not change.
Input: two run dicts as returned by load_results(path, threshold=...). Each one carries run["format"], run["threshold"] and per-attempt records built by _attempt(passed, evidence, value). _attempt stores "value" only when it is not None.
Rule: the rule runs after the existing format check and task check, and before any per-check classification. It applies only when baseline["format"] == "inspect", because the Inspect loader is the only inspected loader that binarizes values with the threshold. It reads baseline.get("threshold") and current.get("threshold"). The rule fires when all of these hold:
When the rule fires, diff() raises ValueError with this message: 'inputs are not comparable: numeric pass threshold 0.8 (baseline) != 0.5 (current); numeric Inspect scores were judged against different pass thresholds. Load both runs with the same threshold.' The thresholds are rendered with repr(), the same way the existing task-mismatch message uses !r. diff() returns no partial result, gate verdict or Markdown summary. This is the same fail-closed outcome the module already uses for format and task mismatches.
Unchanged cases (compatibility):
Errors: this change adds only the single ValueError above. The existing errors (format mismatch, task mismatch, loader validation) keep their messages and their order, so callers that match on those messages are unaffected.
Documentation: docs/ci-gate.md will state that the format and the task must match, and that for Inspect logs with numeric scores the numeric pass threshold must also match. It will quote the error text and give the remedy.
Non-goals: no new inconclusive gate state, no CLI flag, no change to the loaders, JUnit duplicate handling, promptfoo parsing, Wilson annotations or schema keys.
Acceptance:
One specialist feature. Behavioral acceptance fails on the base and passes on the implementation; project checks and independent model review passed. GPU results are included only when actually executed. Automatically developed and reviewed; no human review is claimed.