Trustworthy CUJ Scoring
Overview
A broken oracle reads as a capability gap. Before you trust any CUJ/agent score, the
deterministic floor must be validated bidirectionally and the judge must be quarantined — a
grader that silently passes wrong answers (or fails right ones) makes the harness optimize
against a phantom, and any loop built on it hill-climbs in the wrong direction.
Build the score as a cascade: deterministic oracles are the gate; the LLM-judge is a
separate, last-resort layer for what no parser can express (semantic, taste, reward-hacking).
Full method, the LLM-judge statistics, and the 31 grounding sources live in methodology.md —
read it when building a harness, designing a judge protocol, or defending a reported number.
When to Use
- Building or running an agent eval / CUJ score / agentic benchmark / automated-improvement loop.
- A whole lane fails (or passes) uniformly — check the grader first, not the model.
- A score looks too good or too bad to be true.
- You're about to trust a new oracle, grader, or judge.
- On Windows, the harness shells out to
pnpm / npm / tsc / any .cmd wrapper.
Not for: rating a web surface (use rate-fix-loop); multi-benchmark eval-driver fault
isolation (a separate suite-resilience concern); the broader CUJ→cluster→fix loop (a separate
harness-evolution concern).
The gates (checklist — run in order)
- Bidirectional oracle validation BEFORE any scored batch. For every grader, run one
known-correct input (MUST pass) AND one known-wrong / empty input (MUST fail). If
either direction is wrong, the grader is broken — stop. (WebArena passed empty replies;
tau-bench's do-nothing succeeded on 38% of tasks.)
1b. Output-format / answer-equivalence validation. Bidirectional validity proves the oracle
DISCRIMINATES (right vs wrong); it does NOT prove it accepts every VALID answer. Also run a
known-correct answer whose format differs from the reference (same numeric value at
different precision, JSON keys reordered,
int vs str, currency/percent symbols, thousands
separators) — it MUST pass. If it fails, NORMALIZE before exact-match
(strip/case/round/sort-keys/set-compare) OR pin the exact format in the task spec. Right-but-
differently-formatted answers are false GAPs that DEFLATE the category — a 25–52 pp false-
negative gap between strict and normalized scoring is measured in the wild (Ganapaneni 2026;
CFMatch 2024). Receipts: a numeric-precision case + a JSON int-vs-str case (
key-order) both scored GAP while trivially correct.
- Deterministic floor, THEN a quarantined judge. Code graders (exit-code, regex, schema,
AST, unit test, exact-match) are the gate. The judge runs only after the floor passes, only
for what no parser can express, and its score is a separate non-blended track — never
averaged into the deterministic headline. (Reward-hacking detection is the one thing only the
judge can do: a test can't see a deleted assertion.)
- Per-task append-only checkpoint. Write+flush one
status.jsonl record per completed task;
write run_config.json with the full task-ID list at run start; resume re-runs only
errored+never-started. Never write-only-at-end.
- Pre-state the SNR / MDE / noise band before the batch (N, baseline, minimum detectable
effect, confidence). A result outside 2σ triggers a noise investigation, not a capability
conclusion. Don't use the CLT under a few hundred datapoints.
- Sealed holdout + pre-registered gates. Lock the pass/fail thresholds before any model is
scored; test gold answers stay private. Treat a "clean" contamination scan as weak evidence —
RL/GRPO training conceals contamination signals.
- ≥2 distinct failure modes = rework, NOT relaunch. Diagnose the root cause (subprocess,
OS shell behavior, env leak) before re-running. Verify liveness before relaunch; ONE owner per
run.
- Windows
.cmd smoke-test. pnpm.cmd / tsc.cmd via list-argv subprocess returns
exit-127 without shutil.which() or shell=True — it falsely fails the whole lane. Smoke-
test the invocation on the target OS with a known-good pair before the batch.
Quick Reference — run discipline
| Phase |
Do |
| Pre-run |
oracle self-test (good PASS + bad FAIL) · pre-register gates · state MDE/SNR · smoke-test .cmd on target OS · init run_config.json + status.jsonl |
| During |
append+flush per-task checkpoint · asyncio.wait_for(timeout=N) per task · ONE owner |
| Post-run |
judge as separate track (N≥3, AB+BA, Cohen's κ) · check vs pre-stated band · cluster failures · match fix-lever to cluster cardinality · retest before/after |
| Never |
blind-relaunch after ≥2 failure modes · blend judge into the gate · trust a "clean" decon scan · single-trial judge on a high-stakes gate · CLT on small-N |
Common Mistakes
- Reading a uniform lane failure as a capability gap. Check the grader first — the pnpm.cmd
exit-127 trap made an entire UI lane (3/4) falsely fail and read as "the agent can't do UI."
- Treating a deflated category score as a capability gap before ruling out oracle-strictness.
A trivially correct answer (easy mean, easy kv-get) that fails on numeric precision or JSON key
order reads identically to a genuine capability failure. A 52 pp gap between strict and
normalized scoring was measured in the wild (Ganapaneni 2026). Normalize the comparison first
(strip/case/round/sort-keys/set-compare) and audit easy tasks that fail uniformly BEFORE drawing
a capability conclusion. "Tool-use 40%" may be "40% minus N pp format deflation."
- Blending judge and oracle into one headline number. Judge variance pollutes the gate;
quarantine it.
- Single-trial judging on a gate. Pairwise preferences flip 13.6% on average; 11 trials are
needed for 95% fidelity. Use N≥3, randomized AB/BA, Cohen's κ — not raw agreement (which
overstates discrimination 33–41 pp).
- Write-only-at-end. A crash or a killed subprocess loses every completed task. Checkpoint
per task.
- Optimizing before validating the signal. A loop built on an unvalidated oracle gets worse
at the real task while the metric appears to improve.
1---2name: trustworthy-cuj-scoring3description: Use when building or running an agent eval, CUJ score, benchmark, or automated-improvement loop — and especially when a whole lane fails uniformly, a score looks too good or too bad to be true, you're about to trust a new grader/oracle/judge, or a scored harness invokes pnpm / npm / tsc / any .cmd subprocess on Windows. Symptoms: "the agent can't do X" reads as a capability gap, exit-127 / exit 127, a lane scores 0% or 100%, judge and oracle scores blended into one number, write-only-at-end eval crashed and lost work, ≥2 different failure modes on one harness, hill-climbing against a contaminated signal. Keywords: oracle, grader, LLM-as-judge, position bias, Cohen kappa, sealed holdout, decontamination, SNR, MDE, noise floor, checkpoint, status.jsonl, broken oracle, reward hacking, blind relaunch.4---56# Trustworthy CUJ Scoring78## Overview910**A broken oracle reads as a capability gap.** Before you trust any CUJ/agent score, the11deterministic floor must be validated *bidirectionally* and the judge must be quarantined — a12grader that silently passes wrong answers (or fails right ones) makes the harness optimize13against a phantom, and any loop built on it hill-climbs in the wrong direction.1415Build the score as a **cascade**: deterministic oracles are the gate; the LLM-judge is a16separate, last-resort layer for what no parser can express (semantic, taste, reward-hacking).1718Full method, the LLM-judge statistics, and the 31 grounding sources live in **methodology.md** —19read it when building a harness, designing a judge protocol, or defending a reported number.2021## When to Use2223- Building or running an agent eval / CUJ score / agentic benchmark / automated-improvement loop.24- A whole lane fails (or passes) uniformly — check the **grader first**, not the model.25- A score looks too good or too bad to be true.26- You're about to trust a new oracle, grader, or judge.27- On Windows, the harness shells out to `pnpm` / `npm` / `tsc` / any `.cmd` wrapper.2829**Not for:** rating a web surface (use `rate-fix-loop`); multi-benchmark eval-driver fault30isolation (a separate suite-resilience concern); the broader CUJ→cluster→fix loop (a separate31harness-evolution concern).3233## The gates (checklist — run in order)34351. **Bidirectional oracle validation BEFORE any scored batch.** For every grader, run one36 **known-correct** input (MUST pass) AND one **known-wrong / empty** input (MUST fail). If37 either direction is wrong, the grader is broken — stop. (WebArena passed empty replies;38 tau-bench's do-nothing succeeded on 38% of tasks.)391b. **Output-format / answer-equivalence validation.** Bidirectional validity proves the oracle40 DISCRIMINATES (right vs wrong); it does NOT prove it accepts every VALID answer. Also run a41 known-correct answer whose **format differs** from the reference (same numeric value at42 different precision, JSON keys reordered, `int` vs `str`, currency/percent symbols, thousands43 separators) — it MUST pass. If it fails, NORMALIZE before exact-match44 (strip/case/round/sort-keys/set-compare) OR pin the exact format in the task spec. Right-but-45 differently-formatted answers are false GAPs that DEFLATE the category — a 25–52 pp false-46 negative gap between strict and normalized scoring is measured in the wild (Ganapaneni 2026;47 CFMatch 2024). Receipts: a numeric-precision case + a JSON int-vs-str case (48 key-order) both scored GAP while trivially correct.492. **Deterministic floor, THEN a quarantined judge.** Code graders (exit-code, regex, schema,50 AST, unit test, exact-match) are the gate. The judge runs only after the floor passes, only51 for what no parser can express, and its score is a **separate non-blended track** — never52 averaged into the deterministic headline. (Reward-hacking detection is the one thing only the53 judge can do: a test can't see a deleted assertion.)543. **Per-task append-only checkpoint.** Write+flush one `status.jsonl` record per completed task;55 write `run_config.json` with the full task-ID list at run start; resume re-runs only56 errored+never-started. Never write-only-at-end.574. **Pre-state the SNR / MDE / noise band** before the batch (N, baseline, minimum detectable58 effect, confidence). A result outside 2σ triggers a noise investigation, not a capability59 conclusion. Don't use the CLT under a few hundred datapoints.605. **Sealed holdout + pre-registered gates.** Lock the pass/fail thresholds before any model is61 scored; test gold answers stay private. Treat a "clean" contamination scan as weak evidence —62 RL/GRPO training conceals contamination signals.636. **≥2 distinct failure modes = rework, NOT relaunch.** Diagnose the root cause (subprocess,64 OS shell behavior, env leak) before re-running. Verify liveness before relaunch; ONE owner per65 run.667. **Windows `.cmd` smoke-test.** `pnpm.cmd` / `tsc.cmd` via list-argv subprocess returns67 **exit-127** without `shutil.which()` or `shell=True` — it falsely fails the whole lane. Smoke-68 test the invocation on the target OS with a known-good pair before the batch.6970## Quick Reference — run discipline7172| Phase | Do |73|---|---|74| Pre-run | oracle self-test (good PASS + bad FAIL) · pre-register gates · state MDE/SNR · smoke-test `.cmd` on target OS · init `run_config.json` + `status.jsonl` |75| During | append+flush per-task checkpoint · `asyncio.wait_for(timeout=N)` per task · ONE owner |76| Post-run | judge as separate track (N≥3, AB+BA, Cohen's κ) · check vs pre-stated band · cluster failures · match fix-lever to cluster cardinality · retest before/after |77| Never | blind-relaunch after ≥2 failure modes · blend judge into the gate · trust a "clean" decon scan · single-trial judge on a high-stakes gate · CLT on small-N |7879## Common Mistakes8081- **Reading a uniform lane failure as a capability gap.** Check the grader first — the pnpm.cmd82 exit-127 trap made an entire UI lane (3/4) falsely fail and read as "the agent can't do UI."83- **Treating a deflated category score as a capability gap before ruling out oracle-strictness.**84 A trivially correct answer (easy mean, easy kv-get) that fails on numeric precision or JSON key85 order reads identically to a genuine capability failure. A 52 pp gap between strict and86 normalized scoring was measured in the wild (Ganapaneni 2026). Normalize the comparison first87 (strip/case/round/sort-keys/set-compare) and audit easy tasks that fail uniformly BEFORE drawing88 a capability conclusion. "Tool-use 40%" may be "40% minus N pp format deflation."89- **Blending judge and oracle into one headline number.** Judge variance pollutes the gate;90 quarantine it.91- **Single-trial judging on a gate.** Pairwise preferences flip 13.6% on average; 11 trials are92 needed for 95% fidelity. Use N≥3, randomized AB/BA, Cohen's κ — not raw agreement (which93 overstates discrimination 33–41 pp).94- **Write-only-at-end.** A crash or a killed subprocess loses every completed task. Checkpoint95 per task.96- **Optimizing before validating the signal.** A loop built on an unvalidated oracle gets *worse*97 at the real task while the metric appears to improve.