Viewing files at commit ebd567552629Commit detailsView latest

Browse files
tests/test_claim_eligibility.py 188 lines · 9.6 KB · python
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()