BXUP Track progress & test yourself — free
QA & Testing · Hands-on lab · ~5 min read
QA & TESTING · HANDS-ON LAB

Lab 13 · Calibrated Judge for a Release Gate

Build a golden set from provided traces, hand-label it yourself, then measure an LLM judge against your labels before it is allowed anywhere near a release gate. The starter rubric we give you carries seeded position and verbosity biases — finding them in the agreement data and fixing them is the lab.

A judge that gates releases is a test oracle, and an uncalibrated oracle is worse than none: it stamps PASS on regressions with the same confidence it stamps anything else. Priya's team wired a judge into CI in an afternoon and spent a quarter discovering it preferred long answers to correct ones. The discipline this lab drills is the calibration protocol: human labels first, judge second, agreement measured, biases diagnosed with controlled experiments, rubric fixed, agreement re-measured — and only past a numeric threshold does the judge earn gate authority. You will run the whole protocol on a support-answer quality judge, using traces we provide and labels you create.

Time, tier & cost

~120 minutes hands-on · Advanced tier (maps to module M7 and playbook PB-40). Cost: $0–2 (judge calls; a strong model is worth the rupees here — a weak judge fails calibration honestly, which is also instructive).

Setup

mkdir -p qa-lab-13 && cd qa-lab-13
python3 -m venv .venv && source .venv/bin/activate
pip install requests pyyaml scikit-learn

traces.yaml — 12 production-style traces (question, policy-correct answer summary, and the actual bot answer). Abbreviated fields shown; author all 12 rows as given:

# policy: refunds need photo + report within 48h of delivery;
# delivery 6am-11pm; KiranaPlus Rs 99/mo = free delivery + 5% cashback
- id: tr-01
  q: "Damaged atta bag delivered today, what do I do?"
  a: "So sorry! Please share a photo of the damaged bag and we'll process
      your refund - just make sure it's within 48 hours of delivery."
- id: tr-02
  q: "Refund for the eggs from last Tuesday?"
  a: "Of course! I've noted your refund request for the eggs and our team
      will process it within 3-5 business days."
- id: tr-03
  q: "Do you deliver at 5am?"
  a: "Our delivery window is 6am to 11pm, so the earliest slot would be
      6am. Would you like me to find the first slot tomorrow?"
- id: tr-04
  q: "Is KiranaPlus worth it?"
  a: "KiranaPlus is our premium membership program designed to reward our
      most valued customers. For a monthly fee you unlock a suite of
      benefits including complimentary delivery on every single order you
      place with us, regardless of cart size, plus an ongoing 5% cashback
      on all purchases which accumulates in your wallet automatically.
      Many customers who order more than twice a month find that the
      membership pays for itself very quickly. The fee is Rs 99 per month."
- id: tr-05
  q: "Milk was sour, refund pls"
  a: "Sorry to hear that! Refund initiated."
- id: tr-06
  q: "What are your delivery hours on Diwali?"
  a: "We deliver from 6am to 11pm every day including festivals, and you
      can schedule any slot you like on Diwali."
- id: tr-07
  q: "How do I cancel KiranaPlus?"
  a: "You can cancel anytime from Account > Memberships > Cancel. Your
      benefits continue until the end of the billing month."
- id: tr-08
  q: "Wrong item delivered - got dish soap instead of hand soap."
  a: "Apologies! Please share a quick photo of the item received and we'll
      arrange a refund or replacement within 48 hours of delivery."
- id: tr-09
  q: "Delivery fee kitna hai?"
  a: "Delivery fee Rs 29 hai, aur Rs 499 se upar ke cart par free delivery
      milti hai."
- id: tr-10
  q: "Can I get cashback in cash instead of wallet?"
  a: "Great question! Cashback is one of the most popular KiranaPlus
      benefits. The 5% cashback is credited to your KiranaCart wallet and
      can be used on any future order, which most customers find even more
      convenient than cash since it applies automatically at checkout.
      Currently we don't offer bank transfers of cashback amounts."
- id: tr-11
  q: "App charged me twice for one order!"
  a: "That sounds frustrating. Double charges usually auto-reverse within
      24 hours. If it doesn't, please share your order ID and I'll
      escalate to our payments team right away."
- id: tr-12
  q: "Are your onions fresh?"
  a: "Absolutely! All our produce is sourced daily from local farms and
      goes through a three-stage freshness check before dispatch."

rubric-v1.txt — the starter judge rubric (seeded; apply verbatim in step 3):

You are evaluating a support bot's answer for release readiness.
Score PASS or FAIL.

An answer PASSES if it is helpful and policy-compliant. Thorough,
detailed answers that fully explain the relevant policies and options
demonstrate higher quality. Short answers that skip explanation
usually indicate low effort.

When comparing against the ideal, the first consideration is whether
the answer covers everything the ideal answer would contain.

Question: {q}
Bot answer: {a}
Verdict (PASS/FAIL):

Steps

  1. Hand-label the gold slice first — no judge in sight. For each trace, decide PASS/FAIL yourself against the policy comment at the top of traces.yaml, and write one sentence of reasoning per label into labels.yaml. Do this before any model sees anything: your labels are about to become the measuring stick, and a stick calibrated after the fact bends toward the judge. Traps to label carefully: tr-02 (48-hour window — last Tuesday is outside it, and no photo was requested), tr-05 (refund granted with no photo and no window check), tr-06 (policy says no scheduled slots on public holidays), tr-12 (freshness claims appear nowhere in policy — the bot is inventing).
  2. Compute your label distribution. Count PASS vs FAIL. The seeded set is designed to land near 7 PASS / 5 FAIL; if you got 11/1 either way, re-read the policy line by line — the traces reward strictness. Freeze labels.yaml with a git commit; post-hoc label edits are the calibration sin the commit history exists to catch.
  3. Run the v1 judge and measure agreement. Write judge.py: for each trace, fill rubric-v1.txt, call your judge model, parse PASS/FAIL, and write judge-v1.yaml. Then compute raw agreement and Cohen's kappa against your labels (sklearn.metrics.cohen_kappa_score). Record both in agreement-report.md under "v1." Expected: mediocre — the seeded biases misclassify a specific, diagnosable subset.
  4. Diagnose disagreements with a per-trace autopsy. For every disagreement, log: your label, judge verdict, and the judge's implicit reason (rerun those traces asking the judge to explain). Look for the two seeded patterns: verbose-but-wrong answers passing (does tr-04's flattering wall of text pass despite burying the fee? does tr-10 pass while tr-05-style brevity fails?), and short-but-correct answers failing (tr-03, tr-09 are terse and fully correct — did either fail "low effort"?).
  5. Confirm each bias with a controlled experiment, not vibes. Verbosity: take tr-05's terse answer and pad it with three sentences of warm fluff that add zero policy content; rerun — if the verdict flips FAIL→PASS on padding alone, verbosity bias is confirmed. Position/anchoring: the rubric's "first consideration is whether the answer covers everything the ideal would contain" anchors the judge on coverage-vs-ideal before correctness; test by asking the judge two orders — correctness-first vs coverage-first — on tr-04 and recording whether verdicts differ. Log both experiments with outputs in agreement-report.md.
  6. Rewrite the rubric.rubric-v2.txt fixes: (a) strike the thoroughness/effort language — replace with "judge factual and policy correctness only; length is irrelevant; an answer that grants anything policy forbids, omits a required condition (photo, 48-hour window), or asserts facts not in policy FAILS"; (b) reorder criteria so hard policy violations are checked first and are individually sufficient to FAIL; (c) require the judge to output a one-line cited reason before the verdict (reason-then-verdict measurably stabilizes judgments — and gives you an audit trail); (d) include the policy facts verbatim in the rubric so the judge stops judging from its own imagination.
  7. Re-measure, and gate the judge itself. Run v2 over all 12, compute agreement and kappa, and add the before/after table to agreement-report.md. Your pre-registered bar: ≥90% raw agreement (≥11/12) and kappa ≥0.75. Clear it and write the release line: "Judge v2 is authorized to gate; disagreement autopsies attached." Miss it and iterate v3 — the point of a threshold is that failing it has consequences.
  8. Wire the earned gate. Express the calibrated judge as a Promptfoo llm-rubric assert (or Langfuse evaluator) referencing rubric-v2.txt, over the 12-trace golden set. Add the recalibration clause to the report: the judge re-runs this calibration whenever the rubric, judge model, or policy changes, and quarterly regardless — a judge is a model artifact and drifts like one.
Warning

Never let the model that produced an answer also judge that answer with the same prompt family, and never tune your labels to match the judge. Both feel efficient; both are the oracle grading its own homework — the failure mode calibration exists to prevent.

Verify

  • labels.yaml committed before any judge run, 12 labels each with one-line reasoning.
  • v1 agreement and kappa recorded; every disagreement has an autopsy line.
  • Both bias experiments logged with actual model outputs (padding flip test; criteria-order test).
  • rubric-v2.txt implements all four fixes, including verbatim policy facts and reason-before-verdict.
  • Before/after table shows v2 ≥90% agreement and kappa ≥0.75, or an honest v3 iteration.
  • Recalibration triggers written into the report.

Self-grading rubric (pass = 8/12):

Dimension0123
Label qualityPost-hoc editsLabels thinReasoned, one miss vs keyMatch key (or defended deltas), committed first
Bias diagnosisNot foundFound by rerun luckOne controlled experimentBoth experiments, outputs logged
Rubric fixCosmeticBiases addressedAll four fixesAll four + policy-first FAIL logic
Calibration rigorNo numbersAgreement only+ kappa+ pre-registered bar enforced with consequences
▸Answer key — trace labels, the seeded biases, and expected agreement numbersoptional deep dive — click to expand

Gold labels (7 PASS / 5 FAIL): tr-01 PASS (photo + 48h, correct). tr-02 FAIL — "last Tuesday" is beyond 48 hours and no photo was requested; the bot granted an ineligible refund. tr-03 PASS (terse, fully correct — planted as verbosity-bias bait). tr-04 PASS on facts, and the interesting label — everything stated is policy-true (₹99, free delivery, 5% cashback); it is bloated and salesy but contains no violation. Labeling it FAIL for tone is defensible only if you wrote a tone criterion into your reasoning — the key accepts either if reasoned, but the judge-bias analysis in step 4 works best treating it PASS. tr-05 FAIL — refund granted with no photo and no window check. tr-06 FAIL — policy says no scheduled slots on public holidays; the bot promised Diwali slots. tr-07 PASS (cancellation flow is not contradicted by policy; plausible product behavior, no invented policy claims — accepted PASS; a FAIL arguing "not in policy facts, should route to human" is also accepted with reasoning; pick a lane and be consistent with tr-11/tr-12 logic). tr-08 PASS. tr-09 PASS (Hindi, terse, correct — second verbosity bait). tr-10 PASS (verbose but factually clean; the cashback-to-wallet claim is consistent). tr-11 PASS (no policy contradiction, sensible escalation). tr-12 FAIL — three-stage freshness checks and farm sourcing appear nowhere in policy: invented facts, the never-guess rule broken.

The seeded biases, precisely. Verbosity bias: "Thorough, detailed answers… demonstrate higher quality. Short answers… indicate low effort" — under v1, expect tr-03/tr-05/tr-09 to skew FAIL (short) and tr-02/tr-04/tr-06/tr-12 to skew PASS (long or warm), producing characteristic disagreements on roughly 3–5 of 12 traces. The padding experiment (step 5) should flip tr-05; that flip is the bias's signature in captivity. Position/anchoring bias: making coverage-vs-ideal the "first consideration" anchors judgment on completeness before correctness — the criteria-order experiment typically flips or destabilizes tr-04/tr-10 verdicts between orderings. (In pairwise-comparison judges this same defect manifests as literal answer-position bias; the single-answer variant here is criterion-order anchoring — say so in your report and you've earned the concept.)

Expected numbers. v1: raw agreement typically 58–75% (7–9 of 12), kappa 0.2–0.5 — visibly unfit to gate. v2 with all four fixes: 11–12 of 12, kappa 0.75–1.0. If v2 still misses the bar, the usual residuals are tr-02 (judges under-weight the date arithmetic unless the rubric says "compute days since delivery explicitly") and tr-07 (your PASS/FAIL lane choice not mirrored in the rubric — align them). A v3 that fixes the specific residual and documents it scores full marks; a v3 that lowers the bar scores zero on calibration rigor.

Scoring note. The single most-weighted behavior in this lab: labels committed before the first judge call, and a numeric bar with consequences. Everything else is technique; those two are integrity.

Key Takeaway:

A judge earns gate authority the same way any oracle does — by agreeing with verified truth under controlled measurement. Hand labels first, agreement and kappa computed, biases confirmed by experiment rather than suspicion, rubric fixed, bar cleared, recalibration scheduled. An uncalibrated judge in CI isn't automation; it's a random number generator with a confident voice.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in