| 1 | """Adversarial saved-baseline comparisons and claim eligibility controls."""
|
| 2 | from dataclasses import replace
|
| 3 | import contextlib
|
| 4 | import io
|
| 5 | import json
|
| 6 | from pathlib import Path
|
| 7 | import subprocess
|
| 8 | import sys
|
| 9 | import tempfile
|
| 10 | import unittest
|
| 11 | from unittest.mock import patch
|
| 12 |
|
| 13 | sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
| 14 | import benchmark_stats
|
| 15 | from oakbench.baseline_book import Target, book_json, cells_from_rows, load_baseline_book
|
| 16 | from oakbench.populations import comparison_identity
|
| 17 | from oakbench.scorecard import evaluate_targets
|
| 18 |
|
| 19 |
|
| 20 | def rows(subject="git", **overrides):
|
| 21 | result = []
|
| 22 | for index in range(30):
|
| 23 | row = dict(subject=subject, subject_kind="git" if subject == "git" else "oak",
|
| 24 | bench_id="campaign", run=index, lane="core", profile="standard",
|
| 25 | scenario="tiny", operation="status.clean", returncode=0,
|
| 26 | elapsed_ms=10.0 if subject == "git" else 1.0,
|
| 27 | benchmark_track="core-equivalent", command_semantics_version=1,
|
| 28 | fixture_version=1, scenario_version=1, runner_class="mac-arm",
|
| 29 | cache_state="warm", env_isolation_version="1", load_tier="idle",
|
| 30 | binary_sha256="git-sha" if subject == "git" else "oak-sha")
|
| 31 | row.update(overrides)
|
| 32 | result.append(row)
|
| 33 | return result
|
| 34 |
|
| 35 |
|
| 36 | TARGET = Target("t", "core", "standard", "tiny", "status.clean", "oak_local", "git",
|
| 37 | "elapsed_ms", "median", "ratio_at_most", .8, {})
|
| 38 |
|
| 39 |
|
| 40 | def baseline(source=None):
|
| 41 | return cells_from_rows(rows() if source is None else source, lane="core", metrics=("elapsed_ms",),
|
| 42 | statistics_names=("median",), noise_floor_pct=1.0, bootstrap_samples=20)[0]
|
| 43 |
|
| 44 |
|
| 45 | def evaluate(candidate=None, cell=None, mode="claim"):
|
| 46 | cell = baseline() if cell is None else cell
|
| 47 | return evaluate_targets(rows("oak_local") if candidate is None else candidate,
|
| 48 | [TARGET], {cell.key: cell}, mode=mode, bootstrap_samples=20)[0]
|
| 49 |
|
| 50 |
|
| 51 | class ClaimEligibilityTest(unittest.TestCase):
|
| 52 | def test_comparable_independent_trials_allow_different_vcs_binary_hashes(self):
|
| 53 | result = evaluate()
|
| 54 | self.assertEqual(result["verdict"], "GREEN")
|
| 55 | self.assertTrue(result["claim_eligible"])
|
| 56 |
|
| 57 | def test_saved_baseline_mismatch_is_invalid_even_in_diagnostic_mode(self):
|
| 58 | for field, value in [("runner_class", "linux"), ("fixture_version", 2),
|
| 59 | ("benchmark_track", "agent-default"), ("cache_state", "cold"),
|
| 60 | ("remote_transport", "network"), ("load_tier", "cpu50"),
|
| 61 | ("output_oracle_version", "different")]:
|
| 62 | with self.subTest(field=field):
|
| 63 | for mode in ("claim", "diagnostic"):
|
| 64 | result = evaluate(rows("oak_local", **{field: value}), mode=mode)
|
| 65 | self.assertEqual(result["verdict"], "INVALID")
|
| 66 | self.assertFalse(result["claim_eligible"])
|
| 67 |
|
| 68 | def test_missing_and_duplicate_trials_cannot_manufacture_precision(self):
|
| 69 | candidates = [rows("oak_local")[:1], rows("oak_local", run=0),
|
| 70 | rows("oak_local") + [rows("oak_local")[0]] * 1000]
|
| 71 | missing = rows("oak_local")
|
| 72 | del missing[0]["bench_id"]
|
| 73 | candidates.append(missing)
|
| 74 | for candidate in candidates:
|
| 75 | with self.subTest(n=len(candidate)):
|
| 76 | result = evaluate(candidate)
|
| 77 | self.assertEqual(result["verdict"], "AMBER")
|
| 78 | self.assertFalse(result["claim_eligible"])
|
| 79 |
|
| 80 | def test_unknown_baseline_evidence_cannot_be_public_green(self):
|
| 81 | for changes in ({"noise_floor_pct": None}, {"noise_floor_pct": float("nan")},
|
| 82 | {"noise_floor_pct": -1}, {"comparison_identity": None},
|
| 83 | {"comparison_identity": {}}, {"independent_n": 1},
|
| 84 | {"attempted_n": None}, {"failure_n": 1}, {"ci_low": None}):
|
| 85 | with self.subTest(changes=changes):
|
| 86 | result = evaluate(cell=replace(baseline(), **changes))
|
| 87 | self.assertNotEqual(result["verdict"], "GREEN")
|
| 88 | self.assertFalse(result["claim_eligible"])
|
| 89 |
|
| 90 | def test_uniformly_unknown_cache_cannot_be_claim_evidence(self):
|
| 91 | result = evaluate(rows("oak_local", cache_state="unknown"), baseline(rows(cache_state="unknown")))
|
| 92 | self.assertEqual(result["verdict"], "AMBER")
|
| 93 | self.assertIn("cache_state", " ".join(result["messages"]))
|
| 94 |
|
| 95 | def test_legacy_diagnostic_is_explicitly_not_claim_eligible(self):
|
| 96 | cell = replace(baseline(), comparison_identity=None, noise_floor_pct=None)
|
| 97 | result = evaluate(rows("oak_local")[:1], cell, mode="diagnostic")
|
| 98 | self.assertEqual(result["verdict"], "GREEN")
|
| 99 | self.assertFalse(result["claim_eligible"])
|
| 100 | self.assertIn("diagnostic only", " ".join(result["messages"]))
|
| 101 |
|
| 102 | def test_baseline_builder_preserves_failures_and_unmeasured_denominators(self):
|
| 103 | source = rows() + [dict(rows()[0], returncode=1), dict(rows()[0], elapsed_ms=None)]
|
| 104 | cell = baseline(source)
|
| 105 | self.assertEqual(cell.attempted_n, 32)
|
| 106 | self.assertEqual(cell.failure_n, 1)
|
| 107 | self.assertFalse(evaluate(cell=cell)["claim_eligible"])
|
| 108 |
|
| 109 | def test_baseline_builder_rejects_mixed_populations(self):
|
| 110 | with self.assertRaisesRegex(ValueError, "incompatible baseline population"):
|
| 111 | baseline(rows() + rows(runner_class="linux"))
|
| 112 |
|
| 113 | def test_book_v2_roundtrip_and_duplicate_keys_rejected(self):
|
| 114 | book = book_json([baseline()])
|
| 115 | self.assertEqual(book["schema_version"], 2)
|
| 116 | with tempfile.TemporaryDirectory() as tmp:
|
| 117 | path = Path(tmp) / "book.json"
|
| 118 | path.write_text(json.dumps(book))
|
| 119 | cell = next(iter(load_baseline_book(path).values()))
|
| 120 | self.assertTrue(evaluate(cell=cell)["claim_eligible"])
|
| 121 | book["cells"].append(book["cells"][0])
|
| 122 | path.write_text(json.dumps(book))
|
| 123 | with self.assertRaisesRegex(ValueError, "duplicate baseline cell"):
|
| 124 | load_baseline_book(path)
|
| 125 |
|
| 126 | def test_unknown_identity_version_rejected(self):
|
| 127 | book = book_json([baseline()])
|
| 128 | book["cells"][0]["comparison_identity"]["schema_version"] = 99
|
| 129 | with tempfile.TemporaryDirectory() as tmp:
|
| 130 | path = Path(tmp) / "book.json"
|
| 131 | path.write_text(json.dumps(book))
|
| 132 | with self.assertRaisesRegex(ValueError, "unsupported baseline comparison_identity"):
|
| 133 | load_baseline_book(path)
|
| 134 |
|
| 135 | def test_versioned_patch_guard_requires_actual_success(self):
|
| 136 | target = replace(TARGET, guards={"patch_apply_ok": True})
|
| 137 | cell = baseline(rows(patch_oracle_version="apply-tree-v1"))
|
| 138 | for evidence in (None, False, True):
|
| 139 | candidate = rows("oak_local", patch_oracle_version="apply-tree-v1", patch_apply_ok=evidence)
|
| 140 | result = evaluate_targets(candidate, [target], {cell.key: cell}, mode="claim", bootstrap_samples=20)[0]
|
| 141 | self.assertEqual(result["verdict"], "GREEN" if evidence is True else "INVALID")
|
| 142 |
|
| 143 | def test_failure_only_recall_guard_fails_without_crashing(self):
|
| 144 | target = replace(TARGET, guards={"information_recall_at_least": 1.0})
|
| 145 | cell = baseline()
|
| 146 | result = evaluate_targets(rows("oak_local", returncode=1), [target], {cell.key: cell})[0]
|
| 147 | self.assertEqual(result["verdict"], "INVALID")
|
| 148 |
|
| 149 | def test_nested_fixture_version_normalizes_but_subject_prompt_does_not_compare(self):
|
| 150 | row = rows("oak_local")[0]
|
| 151 | del row["fixture_version"]
|
| 152 | row["fixture"] = {"fixture_version": 1}
|
| 153 | row["task_prompt_id"] = "oak-specific-label"
|
| 154 | self.assertEqual(comparison_identity(row), comparison_identity(rows()[0]))
|
| 155 |
|
| 156 | def test_cli_defaults_to_claim_and_refuses_legacy_evidence(self):
|
| 157 | target = {"schema_version": 1, "targets": [dict(id="t", lane="core", profile="standard",
|
| 158 | scenario="tiny", operation="status.clean", subject="oak_local", comparator="git",
|
| 159 | metric="elapsed_ms", goal=dict(type="ratio_at_most", value=.8))]}
|
| 160 | with tempfile.TemporaryDirectory() as tmp:
|
| 161 | root = Path(tmp)
|
| 162 | (root / "rows.jsonl").write_text("\n".join(json.dumps(row) for row in rows("oak_local")))
|
| 163 | (root / "book.json").write_text(json.dumps(book_json([replace(baseline(), comparison_identity=None)])))
|
| 164 | (root / "targets.json").write_text(json.dumps(target))
|
| 165 | command = [sys.executable, "scripts/scorecard.py", str(root / "rows.jsonl"),
|
| 166 | "--baseline-book", str(root / "book.json"), "--targets", str(root / "targets.json"), "--json"]
|
| 167 | proc = subprocess.run(command, capture_output=True, text=True)
|
| 168 | self.assertEqual(proc.returncode, 1)
|
| 169 | self.assertEqual(json.loads(proc.stdout)[0]["mode"], "claim")
|
| 170 |
|
| 171 |
|
| 172 | class OutcomeReportingTest(unittest.TestCase):
|
| 173 | def test_failure_only_cells_and_unknown_outcomes_stay_visible(self):
|
| 174 | source = [dict(rows()[0], returncode=1, elapsed_ms=999),
|
| 175 | dict(rows()[0], returncode=None), dict(rows()[0], returncode=77)]
|
| 176 | with tempfile.TemporaryDirectory() as tmp:
|
| 177 | path = Path(tmp) / "rows.jsonl"
|
| 178 | path.write_text("\n".join(json.dumps(row) for row in source))
|
| 179 | output = io.StringIO()
|
| 180 | with patch.object(sys, "argv", ["benchmark_stats.py", str(path)]), contextlib.redirect_stdout(output):
|
| 181 | self.assertEqual(benchmark_stats.main(), 0)
|
| 182 | self.assertIn("| `git` | `tiny/status.clean` | 2 | 0 | 1 | 1 | 1 | 0 |", output.getvalue())
|
| 183 | self.assertIn("| 0 | unmeasured |", output.getvalue())
|
| 184 | self.assertNotIn("999", output.getvalue())
|
| 185 |
|
| 186 |
|
| 187 | if __name__ == "__main__":
|
| 188 | unittest.main()
|