| 1 | """Per-cell latency verdicts (oakbench.cellstats) and their devloop wiring."""
|
| 2 | from __future__ import annotations
|
| 3 |
|
| 4 | import importlib.util
|
| 5 | import random
|
| 6 | import sys
|
| 7 | import unittest
|
| 8 | from pathlib import Path
|
| 9 |
|
| 10 | sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
| 11 |
|
| 12 | from oakbench import cellstats # noqa: E402
|
| 13 |
|
| 14 |
|
| 15 | def rows_for(subject, cell_values, *, scenario="tiny_text", operation="status.dirty"):
|
| 16 | return [{"subject": subject, "scenario": scenario, "operation": operation, "run": run,
|
| 17 | "returncode": 0, "elapsed_ms": value, "vcs_tool_call_count": 1}
|
| 18 | for run, value in enumerate(cell_values)]
|
| 19 |
|
| 20 |
|
| 21 | def load_devloop():
|
| 22 | path = Path(__file__).resolve().parents[1] / "scripts" / "devloop.py"
|
| 23 | spec = importlib.util.spec_from_file_location("devloop_cellstats", path)
|
| 24 | module = importlib.util.module_from_spec(spec)
|
| 25 | spec.loader.exec_module(module)
|
| 26 | return module
|
| 27 |
|
| 28 |
|
| 29 | class CellStatsTest(unittest.TestCase):
|
| 30 | def test_gate_reproduction_identical_binary_is_not_an_improvement(self):
|
| 31 | # Samples from the 2026-09-19 gate: same binary both arms, the old
|
| 32 | # global 25.5% threshold published "-25.9% faster tiny_text/snapshot.dirty".
|
| 33 | baseline = [13.8, 16.2, 21.1, 22.0, 27.0]
|
| 34 | target = [14.9, 15.4, 15.6, 16.5, 17.0]
|
| 35 | control = [15.0, 21.5, 14.1, 25.0, 17.2]
|
| 36 | rows = (rows_for("oak_installed", baseline) + rows_for("oak_local", target)
|
| 37 | + rows_for("oak_installed_aa", control))
|
| 38 | floors = cellstats.cell_floors(rows, "oak_installed", "oak_installed_aa", lambda row: row["elapsed_ms"])
|
| 39 | verdicts = cellstats.classify_cells(rows, "oak_local", "oak_installed", floors)
|
| 40 | item = verdicts[("tiny_text", "status.dirty")]
|
| 41 | self.assertNotIn(item["verdict"], ("improvement", "regression"), item)
|
| 42 | self.assertLess(item["delta_pct"], -20) # the point estimate alone would have been "published"
|
| 43 |
|
| 44 | def test_large_consistent_change_across_family_is_detected(self):
|
| 45 | rng = random.Random(3)
|
| 46 | rows = []
|
| 47 | for index in range(10):
|
| 48 | op = f"op{index}"
|
| 49 | rows += rows_for("oak_installed", [10 + rng.random() * 0.3 for _ in range(6)], operation=op)
|
| 50 | rows += rows_for("oak_installed_aa", [10 + rng.random() * 0.3 for _ in range(6)], operation=op)
|
| 51 | rows += rows_for("oak_local", [20 + rng.random() * 0.3 for _ in range(6)], operation=op)
|
| 52 | floors = cellstats.cell_floors(rows, "oak_installed", "oak_installed_aa", lambda row: row["elapsed_ms"])
|
| 53 | verdicts = cellstats.classify_cells(rows, "oak_local", "oak_installed", floors, min_delta_ms=5)
|
| 54 | self.assertEqual({item["verdict"] for item in verdicts.values()}, {"regression"})
|
| 55 | self.assertTrue(all(item["fdr_rejected"] for item in verdicts.values()))
|
| 56 |
|
| 57 | def test_single_cell_change_without_fdr_support_is_unconfirmed_not_claimed(self):
|
| 58 | rows = []
|
| 59 | for index in range(20):
|
| 60 | op = f"op{index}"
|
| 61 | slow = index == 0
|
| 62 | rows += rows_for("oak_installed", [10.0, 10.1, 10.2, 10.1, 10.0], operation=op)
|
| 63 | rows += rows_for("oak_installed_aa", [10.1, 10.0, 10.2, 10.0, 10.1], operation=op)
|
| 64 | rows += rows_for("oak_local", [20.0, 20.2, 20.1, 20.3, 20.1] if slow else [10.0, 10.2, 10.1, 10.0, 10.1],
|
| 65 | operation=op)
|
| 66 | floors = cellstats.cell_floors(rows, "oak_installed", "oak_installed_aa", lambda row: row["elapsed_ms"])
|
| 67 | verdicts = cellstats.classify_cells(rows, "oak_local", "oak_installed", floors, min_delta_ms=5)
|
| 68 | slow = verdicts[("tiny_text", "op0")]
|
| 69 | self.assertEqual(slow["verdict"], "unconfirmed_regression")
|
| 70 | self.assertGreater(slow["required_n"], 0)
|
| 71 | self.assertEqual(sum(item["verdict"] == "no_change" for item in verdicts.values()), 19)
|
| 72 |
|
| 73 | def test_missing_aa_floor_or_samples_is_unmeasured(self):
|
| 74 | rows = rows_for("oak_installed", [10, 10, 10]) + rows_for("oak_local", [30, 30, 30])
|
| 75 | verdicts = cellstats.classify_cells(rows, "oak_local", "oak_installed", {})
|
| 76 | self.assertEqual(verdicts[("tiny_text", "status.dirty")]["verdict"], "unmeasured")
|
| 77 | rows = rows_for("oak_installed", [10, 11]) + rows_for("oak_local", [30, 31])
|
| 78 | verdicts = cellstats.classify_cells(rows, "oak_local", "oak_installed", {("tiny_text", "status.dirty"): 3.0})
|
| 79 | self.assertEqual(verdicts[("tiny_text", "status.dirty")]["verdict"], "unmeasured")
|
| 80 |
|
| 81 | def test_aa_floor_describes_the_cell_not_a_global_number(self):
|
| 82 | quiet = rows_for("oak_installed", [10.0, 10.1, 10.0, 10.1, 10.0], operation="quiet") + \
|
| 83 | rows_for("oak_installed_aa", [10.1, 10.0, 10.1, 10.0, 10.1], operation="quiet")
|
| 84 | noisy = rows_for("oak_installed", [10, 25, 12, 30, 11], operation="noisy") + \
|
| 85 | rows_for("oak_installed_aa", [28, 10, 26, 11, 13], operation="noisy")
|
| 86 | floors = cellstats.cell_floors(quiet + noisy, "oak_installed", "oak_installed_aa", lambda row: row["elapsed_ms"])
|
| 87 | self.assertEqual(floors[("tiny_text", "quiet")], cellstats.MIN_FLOOR_PCT)
|
| 88 | self.assertGreater(floors[("tiny_text", "noisy")], 30.0)
|
| 89 |
|
| 90 | def test_permutation_p_value_is_exact_for_small_samples(self):
|
| 91 | self.assertAlmostEqual(cellstats.permutation_p_value([1, 2, 3, 4, 5], [11, 12, 13, 14, 15]), 2 / 252)
|
| 92 | self.assertEqual(cellstats.permutation_p_value([1, 2, 3], [1, 2, 3]), 1.0)
|
| 93 |
|
| 94 | def test_failed_and_skipped_rows_are_not_samples(self):
|
| 95 | rows = rows_for("oak_local", [10, 11, 12])
|
| 96 | rows[0]["returncode"] = 1
|
| 97 | rows[1].update(returncode=77, skipped=True)
|
| 98 | self.assertEqual(cellstats.samples_by_cell(rows, "oak_local", lambda row: row["elapsed_ms"]),
|
| 99 | {("tiny_text", "status.dirty"): {2: 12.0}})
|
| 100 |
|
| 101 |
|
| 102 | class DevloopCellWiringTest(unittest.TestCase):
|
| 103 | def test_compare_subjects_uses_cell_verdicts_not_global_threshold(self):
|
| 104 | devloop = load_devloop()
|
| 105 | rows = rows_for("oak_installed", [10, 10, 10]) + rows_for("oak_local", [30, 30, 30])
|
| 106 | verdicts = {("tiny_text", "status.dirty"): {"verdict": "no_change"}}
|
| 107 | notes: list[str] = []
|
| 108 | regressions, improvements = devloop.compare_subjects(
|
| 109 | rows, "oak_local", "oak_installed", "Oak baseline", 10.0, 5.0,
|
| 110 | efficiency_gates=False, output_bytes_threshold_pct=25.0, diagnostics=notes, cell_verdicts=verdicts)
|
| 111 | self.assertEqual((regressions, improvements), ([], []))
|
| 112 | regressions, _ = devloop.compare_subjects(
|
| 113 | rows, "oak_local", "oak_installed", "Oak baseline", 10.0, 5.0,
|
| 114 | efficiency_gates=False, output_bytes_threshold_pct=25.0)
|
| 115 | self.assertTrue(regressions) # legacy path unchanged when no cell verdicts are supplied
|
| 116 |
|
| 117 | def test_unconfirmed_regression_is_a_note_not_a_regression(self):
|
| 118 | devloop = load_devloop()
|
| 119 | rows = rows_for("oak_installed", [10, 10, 10]) + rows_for("oak_local", [30, 30, 30])
|
| 120 | item = {"verdict": "unconfirmed_regression", "scenario": "tiny_text", "operation": "status.dirty",
|
| 121 | "delta_pct": 200.0, "ci_low_pct": 190.0, "ci_high_pct": 210.0, "floor_pct": 3.0,
|
| 122 | "p_value": 0.1, "baseline_median": 10.0, "target_median": 30.0, "baseline_n": 3,
|
| 123 | "target_n": 3, "required_n": 6}
|
| 124 | notes: list[str] = []
|
| 125 | regressions, _ = devloop.compare_subjects(
|
| 126 | rows, "oak_local", "oak_installed", "Oak baseline", 10.0, 5.0, efficiency_gates=False,
|
| 127 | output_bytes_threshold_pct=25.0, diagnostics=notes, cell_verdicts={("tiny_text", "status.dirty"): item})
|
| 128 | self.assertEqual(regressions, [])
|
| 129 | self.assertTrue(notes[0].startswith("UNCONFIRMED slower"), notes)
|
| 130 |
|
| 131 | def test_devloop_defaults_are_at_least_five_runs(self):
|
| 132 | devloop = load_devloop()
|
| 133 | import sys as _sys
|
| 134 | argv = _sys.argv
|
| 135 | try:
|
| 136 | _sys.argv = ["devloop.py"]
|
| 137 | args = devloop.parse_args()
|
| 138 | finally:
|
| 139 | _sys.argv = argv
|
| 140 | self.assertGreaterEqual(args.runs, 5)
|
| 141 |
|
| 142 |
|
| 143 | if __name__ == "__main__":
|
| 144 | unittest.main()
|