adv-accept: gap tool reports the share of reads on indices read 8 or more times (defender's question); report skeleton for the widened rows and the class-v5 row

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-07 19:00:31 +00:00
parent 596a2f0d03
commit 63b752ab9d
2 changed files with 51 additions and 5 deletions

View file

@ -255,6 +255,36 @@ it folds in act as fresh randomness on both sides: the closed form and the live
the 50-program widening is running (gap-50.log). Also: the cheap 256-unit proxy did rank real tail programs,
and 100064 sits 0.0032 above the 0.98 floor at 2^20, so the floor is live in the population tail, not idle.
### Widened live confirmation: the 20 lowest and 20 random (RUNNING, 2^24 nonces each)
- box 1, 19:5x BST: `adv-live warps --program k --nonces 16777216 --threads 48 --diag 1` for the 20 lowest
stand-in-ratio seeds of the 16,337 (3664, 103378, 105756, 6610, 106474, 4765, 106700, 4346, 5245,
101905, 1605, 1738, 105371, 6842, 838, 3387, 103265, 170, 106924, 107022; ratios 0.9945 to 0.9980), log
live-low20-16m.log. This row answers the defender's false-positive question: of the lowest 20 (plus the
five already confirmed), how many are NOT beyond 1.2x live.
- box 2, 19:5x BST: the same at 32 threads for 20 random accepted seeds (4107, 101710, 101886, 6132,
105915, 5133, 1932, 2328, 3665, 101643, 1352, 100521, 106359, 4905, 102519, 101697, 106740, 327, 1180,
101805; ratios 0.9994 to 0.9999), log live-random20-16m.log: the control for the correlation.
| Seed | stand-in ratio (256 u) | live top 0.1% over window model | X_0.1% (X/f) | 6-sigma | hot set |
|---|---|---|---|---|---|
| 3664 (lowest) | 0.9945 | 1.31x BEYOND | | FLAGGED | clear |
| 4107 (random) | 0.9999 | 1.0004x within | | clear | clear |
| (rows land as the runs end) | | | | | |
### Class v5 check of the exemplar (PENDING the lock; the defender's question)
Does seed 100767 (id 9d68e6286fc817d4 under class v4) still read hot under class v5's state-derived
dataset? Tool: tools/attack/adv-accept-v5 (the same f8 harness over the vendored igneum-pow of branch
class-v5 at 25c8063f, read-only input; the program draw is the same since the state flag is not read by
the draw, generator 5; the dataset XORs the window's state leaf into every item). State stream: the Devnet
3 v5 pack's state.igsd1 (inputs/v5-dn3-epoch0-state.igsd1, 11 records, root 7e37a9fb...a311), the only
public state stream. Command, under the per-box sweep lock when my running confirmations end:
`adv-live-v5 warps --program 100767 --nonces 16777216 --threads 32 --diag 1 --state inputs/v5-dn3-epoch0-state.igsd1`.
Known-failed shape: `--plant const-item` on the same run must FLAG. Expectation to test: the hot items are
the era-stride images of small source values at site 6; the leaf changes the words every load folds in, so
the frequency of small source values may move; the images themselves do not.
### Rule change 19:55 BST (box-hours honesty)
The bounded class became 88 cores per box in total across all lanes: no new sweep starts except under the

View file

@ -465,6 +465,8 @@ mod gap {
pub name: &'static str,
pub distinct: Vec<u32>,
pub ratio: Vec<f64>,
/// share of the site's reads on word indices read 8 or more times over the units
pub rep8: Vec<f64>,
pub distinct_mean_c: f64,
pub saturated_c: u32,
pub bias_max_c: u32,
@ -508,19 +510,33 @@ mod gap {
let n = (units * LANES * ITERATIONS) as f64;
let mut distinct = Vec::new();
let mut ratio = Vec::new();
let mut rep8 = Vec::new();
let mut k = 0usize;
for i in p.instrs.iter().filter(|i| i.op == Op::Load) {
let mut v = std::mem::take(&mut sites[k]);
v.sort_unstable();
v.dedup();
// the defender's statistic: the share of this site's reads landing on word indices read 8 or more
// times within the 2^20 evaluations (a uniform site on a 2^26 window repeats an index at most 2 or 3 times)
let (mut reads8, mut run, mut d) = (0u64, 0u64, 0u64);
for j in 0..v.len() {
if j == 0 || v[j] != v[j - 1] {
if run >= 8 { reads8 += run; }
run = 1;
d += 1;
} else {
run += 1;
}
}
if run >= 8 { reads8 += run; }
let wsize = ((1u64 << ACCEPT_DATASET_LOG2) >> (i.win as u64).min(2)) as f64;
distinct.push(v.len() as u32);
ratio.push(v.len() as f64 / (n - n * n / (2.0 * wsize)));
distinct.push(d as u32);
ratio.push(d as f64 / (n - n * n / (2.0 * wsize)));
rep8.push(reads8 as f64 / v.len().max(1) as f64);
k += 1;
}
let half = (ACCEPT_UNITS * LANES / 2) as u32;
let bias_max_c = ones_c.iter().map(|&o| o.abs_diff(half)).max().unwrap_or(0);
Side { name, distinct, ratio, distinct_mean_c: ld_c as f64 / (ACCEPT_UNITS * LANES) as f64, saturated_c: sat_c, bias_max_c }
Side { name, distinct, ratio, rep8, distinct_mean_c: ld_c as f64 / (ACCEPT_UNITS * LANES) as f64, saturated_c: sat_c, bias_max_c }
}
pub fn run(p: &Program, day: u64, threads: usize, zero_plant: bool) {
@ -557,7 +573,7 @@ mod gap {
for s in 0..c.ratio.len() {
let d = c.ratio[s] - l.ratio[s];
if d.abs() > worst.0.abs() { worst = (d, s); }
println!("gap: site {s:2} closed ratio {:.4} ({}) live ratio {:.4} ({}) diff {:+.4}", c.ratio[s], c.distinct[s], l.ratio[s], l.distinct[s], d);
println!("gap: site {s:2} closed ratio {:.4} ({}) live ratio {:.4} ({}) diff {:+.4}; reads on indices read >= 8 times: closed {:.4}% live {:.4}%", c.ratio[s], c.distinct[s], l.ratio[s], l.distinct[s], d, c.rep8[s] * 100.0, l.rep8[s] * 100.0);
}
let cmin = c.ratio.iter().cloned().fold(9.0, f64::min);
let lmin = l.ratio.iter().cloned().fold(9.0, f64::min);