โ€บNavigation

Iteration 5 โ€” the tail floor that never ran RULE 0 ยท NO GATE RUN ยท 0 DECIDED

2026-07-31 ยท ← ledger ยท ← iter 4 ยท PR #686 ยท LEDGER row 0u

4sub-defects in one call
3fixed ยท 1 retained as a limit
60tests, from 9 at iter 0
3audit items left, 0 blockers

The remedy was two lines away and never ran

choose_block_length contains exactly the right fix for Y_tail:

if is_tail:
    L_pw = max(L_pw, K.exceedance_run_p95(y > 0))

and the call site passed False, hardcoded. So exceedance_run_p95 was unreachable, and Y_tail — which is the cascade question this whole axis exists to ask — was tested with a block shorter than its own exceedance clusters.

A too-short block destroys the clustering the null must preserve. The null comes out too narrow and the test over-rejects — pushing in the same direction the C2 defect (D12) did, on the target where it matters most.

And one L stood in for nine

L was calibrated on kyle_lambda_proxy × Y_cost and reused for all 3 candidates × 3 targets. But Politis–White derives L from the IC integrand zrank(f) · zrank(y), so L is a property of the pair — and Y_tail's integrand is two-valued, because 95% ties collapse its z-rank to two distinct values. Nothing like Y_cost's continuous one.

Third: the calibration window was slice(0, 3000) — the oldest 3,000 bars. On a 2018–2026 span that is 2018 microstructure calibrating a test applied through 2026.

The fix, and the evidence it was needed

L is now calibrated per target, with the tail floor live for Y_tail only, on the candidate whose Politis–White length is largest — the most conservative null, the same worst-L discipline already used to choose among the sweep — over the most recent rows.

An offline structural smoke of the whole pipeline produced the confirmation:

Y_cost    calibrated on kyle_lambda_proxy
Y_tail    calibrated on aggression_ratio      <- a DIFFERENT candidate
Y_delta   calibrated on kyle_lambda_proxy

The per-pair dependence the single-L design assumed away is visible on the first run that looks for it.

What was NOT fixed, and why that is stated rather than buried

The fourth sub-defect — size calibrated on a subsample and asserted at full N — is retained as an honest limit. Block-permutation size depends on L/n, so a subsample calibration is an approximation whichever window you pick; there is no version of this that is free. It is now recorded per target alongside its window and n, so a reader can see the approximation instead of inheriting it.

Verification

suiteresult
tests/test_axis2_seal_controls.py60 passed, 1 skipped (9 at iter 0)
axis2:self-test12/12
ch_concurrency_smoke_test.py — live9/9

Where this leaves the campaign

27 found ยท 13 closed ยท 1 retired ยท 13 open ยท 0 blockers.

The three remaining substantive items — D25, D26, D27 — share a property worth naming: none of them can change a verdict. They change what can be reproduced and audited about one. D25: a single serial RNG with data-dependent consumption, so no individual cell can be re-run and reproduce its own numbers — which is what a frozen seed is for. D26: RUSAGE_SELF excludes the ClickHouse client subprocesses and the server, so it cannot supply the very measurement the envelope demands. D27: seven inline literals with no SSoT binding, in a file the self-test's T4 does not scan.

SEAL′ still refuses to fire until the 2.5 GiB ceiling sweep artifact is committed.