Skip to content

Dual-judge runner with Cohen's κ floor + judge-key preflight - #1

Merged
bGOATnote merged 4 commits into
mainfrom
feat/dual-judge-runner
May 25, 2026
Merged

bGOATnote merged 4 commits into
mainfrom
feat/dual-judge-runner

Conversation

@bGOATnote

Copy link
Copy Markdown
Member

Summary

  • Adds DualJudge.evaluate(...) — the substrate's first real capability. Runs two independent judges over a batch, computes Cohen's κ + Wilson 95% CI per judge, and exposes a hard reward_signal_accepted boolean.
  • Adds the judge-key pre-flight check that runs before any multi-hour eval / training run. Never prints the secret value, only the length.
  • Pins behavior with a hermetic test suite (no live API calls) using a scripted in-memory judge.

Why this lands first

This module is the moat. The healthcraft V9 lesson — judge hallucination is the binding ceiling — is what reward_signal_accepted guards against. Without this, the substrate is a slower version of every other open-source medical eval rig. With it, every model trained against this substrate has a quantified inter-judge κ on every batch.

Test plan

🤖 Generated with Claude Code

bGOATnote and others added 4 commits May 25, 2026 01:42
The first real capability of the substrate: every free-text clinical output
the eval rig grades goes through two independent judges. Per-batch Cohen's
kappa is computed against the published kappa_floor (default 0.6, Landis &
Koch substantial-agreement threshold) and the runner exposes a hard
reward_signal_accepted boolean that downstream training callers must check.

This guards the substrate against the binding ceiling we hit on healthcraft
V9: judge hallucination silently propagates into the reward signal unless an
agreement floor is enforced.

Includes:
  - judges/base.py — Judge Protocol + JudgeQuery / JudgeVerdict dataclasses
  - judges/dual_judge.py — DualJudge runner with Wilson 95% CI on per-judge
    pass rates and aggregate kappa
  - judges/preflight.py — pre-multi-hour-run key check that NEVER prints the
    secret value, only the length (per feedback_no_secret_value_dumps lesson)
  - tests using a scripted in-memory judge (no live API calls); pinned to
    pass on perfect agreement, fail on κ<floor, fail-closed on prompt_id
    mismatch and empty batch

Live judge implementations (Anthropic + OpenAI) land in PR #2 along with
canary requests against each provider.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ed pytest

Three independent fixes bundled because CI failed on all three:

1. secrets-scan: gitleaks/gitleaks-action@v2 now requires a paid license
   on org-owned repos. Replace with a direct install of the free gitleaks
   binary and invoke `gitleaks detect --no-banner --redact` from a step.

2. test_smoke.py: the prior Fleiss-style example accidentally produced
   κ=0.20, not 0.00, because observed agreement was 0.6 and expected was
   0.5. Replaced with the canonical independence-table construction
   (n=20, each cell = 5) which provably yields κ = 0.

3. test_judges_preflight.py: drop the unused `import pytest` (ruff F401).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two trivial format normalisations: a wrapped print line in preflight that fits
on one line, and a redundant paren-group in the _ndtri Beasley-Springer-Moro
denominator. No behavior change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bandit B101 (assert_used) flags the two paranoid asserts in manifest_check.
ruff S101 was configured-out via pyproject but bandit runs separately. Convert
to an explicit if/return with exit code 4 so the gate stays meaningful when
running under `python -O` too (which strips asserts).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@bGOATnote
bGOATnote merged commit fe93ed6 into main May 25, 2026
4 checks passed
@bGOATnote
bGOATnote deleted the feat/dual-judge-runner branch May 25, 2026 09:02
bGOATnote added a commit that referenced this pull request May 26, 2026
PRs #1 (dual-judge core) and #2 (live Anthropic + OpenAI judges + canary)
are merged. Update the continuation contract so a future agent picks up at
the shift-gauntlet / CSGG work, not at the (already-done) scaffold.

Notes branch protection is NOT yet enabled on this repo — follow-up once
the shift gauntlet ships.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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