Skip to content

feat(benchmark): Signal-to-noise analysis layer: SNR, scenario-health audit, contamination defense#21

Merged
tcballard merged 5 commits into
mainfrom
claude/decisiongrounding-signal-to-noise
Jul 9, 2026
Merged

feat(benchmark): Signal-to-noise analysis layer: SNR, scenario-health audit, contamination defense#21
tcballard merged 5 commits into
mainfrom
claude/decisiongrounding-signal-to-noise

Conversation

@tcballard

@tcballard tcballard commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Applies the lessons from OpenAI's "Separating signal from noise in coding evaluations" and the aligned Ai2 "Signal and Noise" framework. Everything here is reporting/analysis-layer and results-neutral — verified byte-identical arms/cells/stats/per_scenario before/after; only a second paired series is added. Full suite green (462 passed, 6 skipped).

What the articles say, and where we stood

Lesson Before → After
Separate genuine failures from harness/grading noise Already done (error taxonomy + exclusion; deterministic scorer avoids LLM-judge noise) — now cited in Limitations
Report signal-to-noise, not bare point estimates Newscoring/snr.py
Per-subtask decomposition; flag low-signal subtasks Newscoring/health.py discrimination audit
Broken/ambiguous tasks distort the ceiling New — health audit classifies broken/tie scenarios
Contamination (real PEPs/RFCs are pretrained) Newno_grounding floor surfaced as the contamination control

Changes

Both-contrasts paired diff (scoring/crossover.py) — _paired now computes the within-seed paired adherence difference for a list of arm pairs, defaulting to DEFAULT_PAIRS = rac-vs-naive_rag (H1) and rac-vs-no_grounding (H2). A contrast whose arms aren't both in the sweep is silently skipped; pair= still accepted for back-compat.

Signal-to-noise (scoring/snr.py) — SNR = |paired diff_mean| / across-seed diff_std per contrast per N. The article's core caveat is baked in: noise cannot be estimated from one seed, so n_seeds < 2 reports "not estimable" rather than a fabricated ratio. Distinguishes noise-dominated (SNR < 1), clean separation (σ=0, nonzero gap), and no-effect. Headline quoted at the largest N.

Scenario-health audit (scoring/health.py) — classifies every scenario as broken (ceiling context_dump never adheres), contaminated (floor no_grounding adheres → parametric memory suffices), tie (no separation), or discriminating, with summary counts — the analogue of OpenAI's "X% of tasks are broken" ceiling analysis.

Surfacing (scripts/report.py, runner/dashboard.py) — a Signal-to-noise section and a Scenario-health section in the report; a new "Signal / noise" dashboard tab (with the template CSS/tab indices kept in lockstep, guarded by a test). All .get-guarded so legacy/single-seed/no-rac datasets render gracefully.

Methodology + wiring (spec/methodology-signal-to-noise.md, Makefile, run_real.sh, Limitations prose) — documents the SNR definition, the health classes, and the contamination defense (synthetic scenarios are contamination-proof; the floor detects it in real ones), mapping each article lesson to a mechanism. An additive methodology note, not a pre-registration amendment — no gold labels, gates, or the frozen H1/H2 tests change. The real-crossover arms already include rac + no_grounding, so both contrasts populate; the docs now flag that SEEDS≥2 is required for the SNR section.

Testing

  • New: test_snr.py, test_scenario_health.py, test_report_snr.py; extensions to test_real_curve.py (both contrasts) and test_dashboard.py (new tab + tab/section lockstep).
  • Results-neutrality checked explicitly (old single-pair vs new default → adherence/cells/stats identical).
  • Offline e2e: a 3-seed sweep renders the SNR + health sections; the deterministic stub shows "clean (σ=0)" (perfect separation every seed), and a single-seed run shows "noise not estimable".

Independent of PR #20 (roster Step 1); branched from main.

tcballard added 5 commits July 9, 2026 07:32
Generalizes _paired to compute the within-seed paired adherence
difference for a list of arm pairs, not just one, keyed by <a>_vs_<b>.
build_dataset_multiseed and merge_seed_datasets now default to
DEFAULT_PAIRS = (rac-vs-naive_rag, rac-vs-no_grounding) -- the
pre-registered falsifier plus the parametric-memory floor -- while still
accepting a single pair= for back-compat. A contrast whose arms aren't
both in the sweep is silently skipped, so the default is safe for any arm
subset. Each entry's across-seed diff_std is the noise term the
forthcoming signal-to-noise report divides into. Results-neutral: no
adherence number changes, only an additional paired series.
New scoring/snr.py computes SNR = |paired diff_mean| / across-seed
diff_std per arm contrast and per N, with the article's core caveat baked
in: noise cannot be estimated from one seed, so n_seeds<2 reports
'noise_not_estimable' rather than a fabricated ratio. Distinguishes
noise-dominated (snr<1), clean separation (zero noise, nonzero signal),
and no-effect (zero noise, zero signal). Headline SNR is taken at the
largest N (where the thesis is adjudicated). Pure and results-neutral --
reads only the existing paired block.
New scoring/health.py classifies every crossover scenario as broken
(ceiling arm context_dump never adheres -> unsolvable/mis-specified),
contaminated (floor arm no_grounding adheres -> parametric memory
suffices, doesn't test grounding), tie (no between-arm separation), or
discriminating -- the analogue of OpenAI's 'X% of tasks are broken'
ceiling analysis. unknown when neither control arm is in the sweep.
Reports per-scenario rows + summary counts. Pure and results-neutral;
reads only per_scenario.
… dashboard

report.py gains a Signal-to-noise section (SNR per contrast per N, with
noise-dominated cells flagged and a clear 'noise not estimable' notice
for single-seed runs) and a Scenario-health section (the discrimination
audit's summary counts + a table of broken/contaminated/tie scenarios),
inserted after the per-scenario attribution. dashboard.py gains a matching
'Signal / noise' tab (s6); Reproduce->s7, Run->s8, with a new #t8/#s8 rule
in the template CSS and _TABS kept in lockstep (guarded by a new test).
All .get-guarded so legacy/single-seed/no-rac datasets render gracefully.
New spec/methodology-signal-to-noise.md defines the SNR metric (signal =
within-seed paired diff, noise = its across-seed std; >=2 seeds required),
the four scenario-health classes, and the contamination defense (synthetic
scenarios are contamination-proof; the no_grounding floor detects it in
real ones), mapping the OpenAI and Ai2 lessons to the benchmark's
mechanisms. Additive methodology note -- changes no gold labels, gates, or
the frozen H1/H2 tests. The real-crossover Makefile target and run_real.sh
now flag that SEEDS>=2 is required for the signal-to-noise section (arms
already include rac + no_grounding, so both contrasts populate), and
report.py's Limitations section points readers to the methodology.
@tcballard tcballard changed the title Signal-to-noise analysis layer: SNR, scenario-health audit, contamination defense feat(benchmark): Signal-to-noise analysis layer: SNR, scenario-health audit, contamination defense Jul 9, 2026
@tcballard
tcballard merged commit 55c7168 into main Jul 9, 2026
7 checks passed
@tcballard
tcballard deleted the claude/decisiongrounding-signal-to-noise branch July 9, 2026 08:05
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