Project

EvalGate

Evaluation-driven CI for AI features: tiered golden sets, paired bootstrap significance on per-case score deltas, judges validated against programmatic truth, and a PASS / BLOCK / INCONCLUSIVE merge gate that escalates tiers only when it cannot decide. On the 20-scenario matrix it blocks 12/12 true regressions with 0/8 false blocks.

12/12
true regressions blocked, 0 missed
0/8
false blocks on not-worse changes
87%
false-pass rate of the naive judge, vs 0% strict
4/4
live prompt variants, verdict matches oracle

Why this project exists

Teams change a prompt, ship it, and find out a week later that quality fell. The fix mirrors ordinary software — golden datasets and an evaluation gate in CI — and the interesting part is that a naive version of this gate does not work. Three reasons, each exposed by measurement: a 20-case golden set has almost no power if you compare the arms unpaired (case difficulty swamps the effect; pairing cancels it inside each per-case delta); treating sampling repeats as independent observations triples the apparent sample size and makes the gate confidently block changes it has no evidence against; and a weighted score lets a broken output contract buy itself back — an unparseable response can still score ~0.8 on a naive weighted sum.

What it does

  • Scores responses programmatically — JSON validity, an enum-constrained schema, label correctness — so the primary signal never depends on a model’s opinion
  • Tiers the golden set: smoke (8 cases) on every PR, full (20) nightly or on escalation, with smoke a strict subset of full, enforced by test
  • Pairs baseline against candidate on identical cases and bootstraps the per-case deltas, resampling cases as the exchangeable unit; repeats are averaged per case before pairing
  • Decides from the confidence interval alone: BLOCK when confidently worse, PASS on non-inferiority, INCONCLUSIVE otherwise — which is not indecision but the trigger that escalates to the expensive tier
  • Enforces a format floor (JSON-valid rate under 90% blocks regardless of score), so format can never be traded against label accuracy
  • Validates judges against programmatic truth, reporting false-pass rate separately because that is the error that ships regressions
  • Caps cost per run and reports the marginal generations, tokens, and seconds a PR pays
  • CI integration: smoke gate on PRs with a readable comment, full tier nightly, plus a claim checker that re-derives every README number from committed artifacts and fails the build on drift

Measured results

300 responses harvested once from Ollama gemma4:31b-it-qat (5 prompt variants x 20 cases x 3 repeats), committed so everything reproduces offline with no model.

EvidenceResult
20-scenario confusion matrix12/12 truly-worse blocked, 0 missed; 8/8 not-worse passed, 0 false blocks
Live variants vs pre-fixed oracle labels4/4 match: cosmetic PASS, improved PASS, no_rules BLOCK (score CI), chatty BLOCK (format floor)
Two regression mechanismsno_rules keeps 100% JSON validity and is caught purely by the interval; chatty is caught by the floor at 0% validity
Tier costevery live verdict reached on the smoke tier — 8 cases, 24 generations
Judge validation over 300 responseslenient judge: 80% agreement but 87% false-pass; strict parse-checking judge: 0% false-pass, kappa +1.0
Verdict stability, 200 bootstrap seeds3/4 variants 100% stable; improved reported as a knife-edge (CI bound exactly on the margin), not smoothed over
Paired vs unpaired estimatoron the cosmetic no-op, pairing yields a zero-width interval and PASS; unpaired straddles the margin and would escalate a no-op for nothing
Repeat averagingdropping 3 repeats to 1 flips a confident BLOCK to inconclusive on 42/200 draws — the cost of skipping it, measured

Tech stack

ComponentChoice
LanguagePython 3.12; checkers, statistics, gate, and matrix need no third-party code
CLITyper
StatisticsPercentile bootstrap, paired on per-case deltas; unpaired retained for the power comparison
Live modelOllama gemma4:31b-it-qat, touched only by the resumable harvester
ProvidersLive Ollama plus an offline replay provider over committed responses
CIGitHub Actions: smoke on PRs, full nightly, claim-checking evidence gate