Statistics review of the E2 analysis code (Phase 6)¶
Reviewer: stats-reviewer subagent, 15 Oct 2026, run before any E2 result was read (the grid was still running; the reviewer was told not to read results/). Scope: src/driftwatch/metrics/stats.py, grid_tables.py, scripts/make_tables.py, scripts/make_figures.py, tests/test_stats.py, tests/test_make_tables.py, against the registered plan (prereg-v1).
Verdict of the reviewer: the statistical machinery is faithful to the registration (contrasts, units, pairing, block lengths, margin, family size), but the table code was not ready to produce citable numbers; fixes for findings 1 to 4, the role and verdict columns of finding 10 and the diagnostics of finding 5 were to land and be re-reviewed before the first E2 table is read. No change to the registered bootstrap scheme was proposed without an addendum.
Findings and what was done¶
# |
Severity |
Finding (short) |
Action |
Where |
|---|---|---|---|---|
1 |
blocker (RQ1 secondary row) |
The “E0 window-level” comparator was built from |
Fixed. Secondary gap = |
|
2 |
major |
Label counts of an arm stored as two seed blocks were merged with the last block winning, so a “0-4” row carried 5-9 numbers |
Fixed. Counts are kept per block and aggregated over exactly the blocks inside the row’s seed set, weighted by cells |
|
3 |
major |
The unit label of the delay slope said “negative = loses” while the value was AUT lost (positive) |
Fixed. Unit text is “AUT lost per slot of delay (positive = AUT falls)”; the raw slope is |
|
4 |
major |
A missing arm dropped a contrast silently; planned-but-unstarted cells were absent from the ledger table; Holm used the number of rows present; |
Fixed. One row per registered contrast, model and seed set, |
|
5 |
major |
Moving blocks without wrap weight edge windows less; the BODMAS window stage has only 16 equally likely block choices; the block is clipped silently when n_windows < block length; the last block is truncated |
Scheme kept as registered (a change needs an addendum). Diagnostics added: |
|
6 |
major |
Wilcoxon on per-seed means ignores window dependence and treats seeds as replicates; with 5 seeds the Holm value is identically 1.0; the CSV puts it next to |
Fixed. Columns renamed |
|
7 |
major |
On BODMAS d = 3 equals never, so C-D2 equals C-P numerically and the delay “rate” is one refit |
Flagged, not removed (the contrasts are registered). |
|
8 |
minor |
|
Fixed. |
|
9 |
minor |
Absolute counts missing at both ends of budget steps; none on the heat map or contrast figure |
Partly fixed. |
|
10 |
minor |
|
Fixed. |
|
11 |
minor |
Unit used the allowance |
Fixed. Units use mean queries per slot (equal to the allowance under random selection) |
|
12 |
minor |
Seed stage draws seeds independently per window position, though overlapping windows share C3 draws |
Documented, not changed. The scheme is the registered one; the net effect is conservative. Chapter 3 says so |
|
13 |
minor |
A contrast could mix cells from different code versions |
Fixed. |
|
14 |
minor |
Test gaps |
Fixed. Tests for RQ1 secondary, counts across blocks, unit sign, |
|
Additional change prompted by the second leakage review¶
stable_code_version retries a transient unknown answer from git (a first grid run was stopped once by one unreadable git rev-parse; the cells finished before that, at commit c26aa5f, are unaffected and the run was resumed from the ledger).
Still open for the researcher¶
Whether to propose an addendum for a circular or stationary block bootstrap before E2 numbers are read. Recommendation: no; keep the registered scheme and report its coarseness.
Whether BODMAS C-D2 and C-P should be presented as one row. Recommendation: yes, in prose and in the table note.
Re-review¶
The reviewer’s blocker and major items are fixed with tests (81 tests in test_grid.py, test_stats.py, test_make_tables.py pass at the commit that carries this file). A second pass of the stats-reviewer on the final tables and the E2 CLAIMS rows is part of the closeout once results exist.