Class v6 family gate, the 17:00 cut: the measured coverage (24,000 drawn eras through the ring-B tests on build-1 and build-3, 54 core-hours), per stratum and per axis, with the bound arithmetic on the counts; four measured rows (the lossy corner of B = 4 exhausts the 256 cap in 1.2 percent of eras, the band capped at the lossy families; the (c''') floor's per-width calibration; the shape axis's draw cost; the era-stride bias at bit R in half the eras of every stratum); the census rows, logs, scripts and the harness patch series under logs/

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-08 11:25:26 +00:00
parent 3ee2030f14
commit d4cd6a3ce2
22 changed files with 25186 additions and 25 deletions

View file

@ -1,6 +1,6 @@
# Class v6, the family gate: how a parameter family is cryptanalysed as a family
Research lane D of the class v6 rotating-family design, under the Counter ASIC coordinator. First cut 8 October 2026, 11:0x to 17:00 BST (the deliverable clock); the full report by 09:00 BST on 9 October. Branch `class-v6-family-gate` (this document) and the harness branch `family-gate-v5` (the class v5 crate at 8f481459 plus the census harness, never a chain path). Internal research, not an independent review; nothing here touches a served number, the devnet or the testnet object; no consensus code this week. Every figure carries its source: a lane report on the mirror, a log on a box, or an arithmetic step shown in the text. Figures from memory are labelled approximate.
Research lane D of the class v6 rotating-family design, under the Counter ASIC coordinator. First cut landed on the mirror's master at 11:40 BST, 8 October 2026 (fbe62a8b); this cut, with the measured coverage, is the 17:00 BST deliverable; the full report by 09:00 BST on 9 October. Branch `class-v6-family-gate` (this document) and the harness branch `family-gate-v5` (the class v5 crate at 8f481459 plus the census harness, never a chain path). Internal research, not an independent review; nothing here touches a served number, the devnet or the testnet object; no consensus code this week. Every figure carries its source: a lane report on the mirror, a log on a box, or an arithmetic step shown in the text. Figures from memory are labelled approximate.
The question. Class v6 (the founder's word at 11:1x BST, 8 October 2026) draws per era the parameters a release used to fix (layer 1), lets the dataset track the chain state (layer 2), rotates instruction families by height (layer 3) and generalises the acceptance floor and the uniformity test to each era's draw with a redraw on failure (layer 4). A chip is then built against a FAMILY of hashes, not one hash. The in-house pass of 7 October and the attack board F1 to F10 bounded ONE member of the family (class v4 sub-version 3 at 017e7037 and class v5 at 1c420786). This document says how the family is bounded: what the space is, how many eras must be drawn to say anything about the worst era, which tests the chain runs itself on every era and epoch, what the offline board looks like over the testnet period, what a published proof of testing contains, and what the whole apparatus cannot see.
@ -14,7 +14,7 @@ The question. Class v6 (the founder's word at 11:1x BST, 8 October 2026) draws p
| The per-era tests (section 3) | Three rings. Ring A, the chain runs per era at the cut, microseconds: the structural redraw rules (the band membership of every draw, the day-key cost rule, the product-bias rotation class recorded). Ring B, the chain runs per epoch, seconds: the acceptance rule generalised to the family's shape ((a) (b) (a') (c) (c') (c'') (c''') plus the two next-class tests, the per-site largest-256-item-bucket bound and the index-bit bias read, on the same 2^20 pass). Ring C, the gate runs offline per drawn era, box-hours: the F8-form census at 2^24 on 64 seeds, the attempts census, the exhaustion count. Each row carries its known-failed shape and its clean-seed cost so the redraw is priced |
| The board (section 4) | F1 to F10 and the nine lanes classified per-era, per-family or chain-run, with the harness taking the era draw as an input; the proof of testing is one JSON record per drawn era (the draw, the object, the binary, the seeds, every verdict with its statistic, threshold and log sha256, the core-seconds) and one family summary (eras per stratum, the worst era per test, the refuse rate per band, the bound's arithmetic) |
| The honest line (section 5) | The gate sees what its tests see. It does not see the diffuse era-stride class below the bit-bias read's resolution (a bias under 0.3 percent at 2^20), a mechanism that lives in a joint corner no stratum names, a mixer weakness below adv-mixer-3's bands, or an era whose draw sits in the untested 1 in 64. A GPU-like chip loses nothing on any era; what a corner buys it is a per-era hot set bounded at 1.002x (the floor) or 1.0024x (the diffuse class), or, at `m = 4`, a mixer with 2 applications of measured margin instead of 6 |
| Running now (section 6) | The harness `family_gate_era_census` on build-1 from 11:16 BST: one drawn era per seed, every family parameter from the era's own stream, the chain draw through the real rule keyed on the family's shape, one TSV row per era with the (c'') ratio, the bucket ratio, the bit bias and the attempts; the base control (`v5_attempts_census`, the shipped draw) beside it. The coverage table in section 6 is filled from the logs at 16:xx BST |
| Measured (section 6) | 24,000 drawn eras through the ring-B tests in 54 core-hours (1.7 box-hours) on build-1 and build-3, 11:16 to 12:13 BST, the harness as a patch series in `logs/`. Four measured rows move the design: the lossy corner of B = 4 exhausts the 256 cap in 1.2 percent of eras (61 of 5,000) against 0 of 19,000 elsewhere, so the band is B = 4 on the injecting families with or/mul/mulhi never raised (0 of 3,000 under it); the (c''') floor at 0.995 costs 4.5 to 6.5 percent of candidates at width 4 against 0.6 to 1.0 at width 1 (a per-width calibration); the shape axis moves the draw from 1.8 attempts (64 x 108) to 3.8 (256 x 27); the era-stride bias sits at over 6 sigma on one address bit (bit R in 73 percent of cases) in about half the eras of every stratum and at over 100 sigma in a third, falling to 7.5 percent under R in 28..31, a structural fact for the research lane's layer 4 rather than a per-epoch refusal |
## 1. The parameter space
@ -23,7 +23,7 @@ The question. Class v6 (the founder's word at 11:1x BST, 8 October 2026) draws p
| Axis | Band proposed for the draw | What fixed the band (the measured rows) | The tested margin inside the band | Known-failed corner, named |
|---|---|---|---|---|
| Mixer multiplier `m` (applications per round, `LoadClass::mixer_mult`; 72 per item at `m = 8`, 8 between dependent reads) | {4, 8, 16}; the research lane's outline; this lane's reading: {8} plus {4} as a corner, {16} only after the verifier row | x4 and x8 measured (`docs/plans/mixer-x4.md` section 6.4: 1.92 and 2.79 ms per unit on a loaded M5 Max core; the daily build 42 ms at x8 on the 5090, measured); x16 estimated at about 3.7 ms per unit on the M5 Max core and 9 ms on a 2019-class core (chip-model-v3 section 3 item 1), against the 10 ms verifier gate | adv-mixer-3 (`report-mixer-3.md`, "The round margin, stated"): no statistic survives 2 of the 8 keyed applications between reads at bands 0.0015 (Q2, 2^24 states), 0.00026 (2^27), 0.00018 (Q2b, 2^28); SAT solved at k = 1 in 137 s and timed out at k = 2, 3, 4; two real days and eight random days agree. So at `m = 8` 6 of 8 applications are margin; at `m = 4` the same rows leave 2 of 4; at `m = 16` 14 of 16 | None measured. The corner is `m = 4` by margin and `m = 16` by the verifier; the all-ROT-equal day key is the day-level corner (rejected by the AP-F4-1 rule) |
| Op-mix weights (the ten non-load families, sum 75) | Each weight within B points of table 1.4.2 (add 12, xor 10, mul 8, mad 8, shfl 8, rotl 7, sub 6, mulhi 6, rotr 6, or 4), renormalised by largest remainder; shfl and mulhi never raised; B = 2 (spec 1.13.1, proposed) or B = 4 (the research lane) | The microbench (`counter-asic-4-research.md` 15.1a, the 5090 alone, 8 October): pJ per counted op at the stock clock and the 1,300 MHz lock: arx 11.3 / 6.2, mul 13.9 / 8.3, mulhi 39.6 / 21.0, prmt 22.3 / 11.5, lop3 24.1 / 13.0, shfl 55.8 / 29.4; the shuffle is 4.9x the add, so a draw that raises shfl raises the card's premium per instruction with no better `k` for a chip (15.1b). F7's era census: the op-weight corners (15 to 31 of 75) read 1.0x against the GPU, 0 memory effect | The acceptance's rejection rate moves with the lossy share: at the table 0.68 per candidate ((a') 83.5 percent of rejections; adv-accept row 90, 20,000 seeds); the F7 census at B = 2 read every corner clean for the chip; nothing was measured at B = 4 before today (section 6) | The lossy corner: or, mul and mulhi all at +B. It raises (a') rejections and so the attempts per seed; the exhaustion bound `r^256` is the number to read there (section 3, ring C) |
| Op-mix weights (the ten non-load families, sum 75) | Each weight within B points of table 1.4.2 (add 12, xor 10, mul 8, mad 8, shfl 8, rotl 7, sub 6, mulhi 6, rotr 6, or 4), renormalised by largest remainder; shfl and mulhi never raised; B = 2 (spec 1.13.1, proposed) or B = 4 (the research lane) | The microbench (`counter-asic-4-research.md` 15.1a, the 5090 alone, 8 October): pJ per counted op at the stock clock and the 1,300 MHz lock: arx 11.3 / 6.2, mul 13.9 / 8.3, mulhi 39.6 / 21.0, prmt 22.3 / 11.5, lop3 24.1 / 13.0, shfl 55.8 / 29.4; the shuffle is 4.9x the add, so a draw that raises shfl raises the card's premium per instruction with no better `k` for a chip (15.1b). F7's era census: the op-weight corners (15 to 31 of 75) read 1.0x against the GPU, 0 memory effect | The acceptance's rejection rate moves with the lossy share: at the table 0.68 per candidate ((a') 83.5 percent of rejections; adv-accept row 90, 20,000 seeds); the F7 census at B = 2 read every corner clean for the chip. MEASURED today (section 6): at B = 4 with the lossy families free to rise the random stratum reads r = 0.72 and a maximum attempt of 107 (the shipped stream's maximum is 28); at the lossy corner r = 0.956 and 1.2 percent of eras EXHAUST the 256 cap | The lossy corner: or, mul and mulhi all at +B (30 of 75 against the table's 18). It is OUTSIDE the band: 8 of 663 drawn eras reached the last resort, which fails rule (a) in 9 percent of seeds (adv-accept-3 finding 1). The band this lane carries: B = 4 on the seven injecting families, or/mul/mulhi never raised above their base (the `lossybase` stratum of section 6 is its measurement), with ring A's lossy-share rule as the check |
| Read width `W` (words per load) | {1, 4} | `docs/plans/read-width.md` (5 October): w16 within the rules (5090 139.8 against 136.1 MH/s, 9070 XT 17.90 against 18.15, M5 Max within 1 percent); w64 bandwidth-bound (5090 share 0.58, 71.9 MH/s): out; the per-load mixes out on the 5 percent spread rule | The acceptance runs unchanged on aligned addresses (read-width.md section 2), but (c'') and (c''') read a site's distinct ALIGNED indices against `E_s = N - N^2 / 2W_s`: at `W = 4` the index space is `W_s / 4`, so the expectation must follow or every width-4 program reads 0.976 at a quarter window and is refused by the 0.98 floor. The harness divides the window by the width (`site_window_words`); the spec line is owed | `W = 16` (w64): excluded by measurement, never in the band |
| Shadow block shape (instructions per block, passes per iteration) | {64 x 108, 128 x 54, 256 x 27}: 6,912 shadow instructions per iteration at rung 0 | 64-instruction blocks ran 2.5 to 3.5 percent faster than 256 on the 5090 and the M5 Max (6 October, measured); 1,024 cost the M5 Max 17 percent (out) | F1's shadow redundancy bound (3.0 percent of peephole-removable instructions, the v5 generator's `SHADOW_REMOVABLE_MAX_PERMILLE`) was set from F1's census at 256 instructions; the removable fraction per block is a property of the block's length, so the fraction must be re-read at 64 and 128 (a per-family row). The acceptance's (a') fixpoint and the shadow's execution in (c) take any length | The per-load placement (16 sub-blocks of 16 after each load): dead as a chain class (`counter-asic-4-research.md` 20.2a-close): 22 of 1,621 candidates accepted, 42 of 64 seeds exhaust 32 attempts, candidate 0 carries index bit 0 set in 40 of 1,024 addresses at site 0 (z 29.5). The placement axis therefore has ONE value in the band |
| Program length `N` (counted ops per hash) | Not drawn: the ladder's signal (rungs 0 to 2); the research lane's outline keeps it so | F6: the worst of 10^5 class v4 programs 8.708 ms on the half-core proxy, so N about 300,000 fits under 10 ms (rung 2 admissible, rung 3 not); the M5 Max loses 3.3 to 10 points across the band (measured ladder) | The verifier's worst case was censused at rung 0 only; a draw inside the ladder needs the 10^5-program worst case at the top rung (per-family row) | Rung 3 (inadmissible by F6) |
@ -65,6 +65,8 @@ Let a per-era test have a fixed verdict per era and let `p` be the fraction of t
| 2^-10 | 505 years | 3,067 | 4,713 |
| 2^-20 | the F4 and F7 gate's fraction | 3.1 million | 4.8 million |
Measured today (section 6.3): 10,000 random eras of the family and 3,000 of the proposed band pass the ring-B exhaustion and floor tests, so the failing fraction of eras on those tests is under 3.0e-4 and 1.0e-3 at 95 percent; the lossy corner fails at 1.2 percent and is out of the band.
What this buys and does not. The F4 and F7 gates ask "no class with gain over 1.1x at a fraction over 2^-20" and reach it by censusing 2^24 draws of a CHEAP statistic (microseconds per day key or era seed). A per-era test that costs box-hours (the F8 census at 2^24) can be run on hundreds of eras, so it bounds the failing fraction at the 1/64 to 1/256 class, never 2^-20. That is why layer 4 puts the tests on the chain: a per-era test the chain runs on EVERY era (ring A) or every epoch (ring B) needs no sampling bound at all; the offline census (ring C) is then a check on the chain-run tests' calibration (their clean refuse rate and their known-failed firing per stratum), and a reading of the one statistic the chain cannot afford, the live-dataset census.
### 2.2 The union bound over the per-era tests
@ -103,7 +105,7 @@ The three rings. A test's ring says who runs it and what a failure costs.
| Band membership: `m` in the band, `W` in the allowed set, the shape in the set, every weight within B of the table with shfl and mulhi at or under their base, the sum 75 | the layer-1 draws | a draw outside the band (a unit test) | 0 by construction (the draw is bounded) | spec 1.13.1's form |
| The day-key cost rule (AP-F4-1, class v5) | ROT, MUL | mul1all, mulnaf, day 29,337 | 6.1e-4 per day | f4-weakday.md 6.7 to 8; 8ca66afa |
| The rotation class recorded: whether R leaves a product's low bits inside the index at the era's D | R, D | none (a record, not a refusal: restricting R to {29, 30} would cut the interleave's entropy from 31 to 2 values; the value-level test of ring B is the catch) | 0 | adv-cache-2 2.3 |
| The weights' lossy share bound: or + mul + mulhi at most the table's 18 plus B, so the exhaustion bound `r^256` stays under 1e-18 (r under 0.85) | weights | the lossy corner of section 6 if its `r` reads over 0.85 | 0 by construction | row 90 (r = 0.681 at the table) and section 6 |
| The weights' lossy share bound: or + mul + mulhi at most the table's 18 (never raised), so the exhaustion bound `r^256` stays under 1e-18 (r under 0.85) | weights | the lossy corner of section 6: r = 0.956, 8 of 663 eras at the cap (FIRED) | 0 by construction | row 90 (r = 0.681 at the table) and section 6 |
### 3.2 Ring B: the acceptance rule generalised to the family, per epoch
@ -187,35 +189,73 @@ What the family gate cannot see, and how a chip would use it.
A GPU-like chip (the `f = 1` stored-dataset chip with a programmable core, chip-model-v3 section 5) loses nothing on any era of the family: every drawn parameter is firmware to it, and what the family costs it is the core sized for the band's top (the research lane's USD 30 to 60 per chip, modelled). The family gate's job is therefore not to defeat that chip (the identity of the research file's section 2 says the per-joule edge is the card's own idle, 2.1x at `k = 1`) but to make sure no drawn era hands ANY chip more than the one hash did: a per-era hot set, a per-era mixer shortcut, a per-era verifier miss. Everything in this document is a bound on that increment, and the increments found so far are 1.002x and 1.0024x.
## 6. Running now, and the coverage measured
## 6. The coverage measured (24,000 drawn eras, 11:16 to 12:13 BST, 8 October 2026)
Started 11:1x BST, 8 October 2026, on igneum-build-1 under `lease pool` (class measure, owner class-v6-family-gate), the scripts under `/srv/builds/_adv-family-gate/` (fg-setup.sh, fg-build.sh, fg-census.sh), every binary run from a pinned copy under `bin/<tag>/` with its sha256 (AP-H2's rule), logs and TSV rows under `logs/`, copies of the finished logs land under `docs/analysis/class-v6/logs/` on this branch with the full report.
The harness: branch `family-gate-v5` at e94f4db0 (the class v5 crate 8f481459 plus `accept::tests::family_gate_era_census`; the patch series is `logs/harness-family-gate-v5-e94f4db0.patch` in this directory, since the branch's push to the mirror was refused by the class v5 tree's own pre-push hook and is held). What it does per era `k` of a label space: the era bytes from `igneum-family-gate[/stratum]/era/k` and the epoch bytes from `.../program/k` (the F8 label space's form); from the era's own stream, in a fixed order and consumed whether pinned or not, the shadow block shape in {64 x 108, 128 x 54, 256 x 27}, the mixer multiplier in {4, 8, 16} (recorded: the acceptance never runs the mixer), the ten non-load weights perturbed by `below(2B + 1) - B` with shfl and mulhi never raised and renormalised to 75 by largest remainder (B = 4), the read width through the era draw over {1, 4} words (the mix one-hot on the drawn width); then the chain draw of that era's epoch through the real rule keyed on the family's shape (`is_family_shape`, the acceptance's `is_class_v4_shape` generalised behind `IGNEUM_FAMILY_GATE`; the draw's source rule reads the same predicate), every candidate's first failing part recorded, the cap 256 and the last resort as shipped; on the accepted program, on the rule's own 2^20 sample (4,096 units), per site: the (c'') and (c''') ratio with the window divided by the width, the largest 4,096-word (256-item) bucket in sigma of its expectation, and the largest index-bit one-count excess in sigma over the free bits. One TSV row per era (`logs/<stratum>-family_gate_era_census-<from>-<n>.tsv`, the run's log beside it with the binary's sha256 and the lease line); every binary a pinned copy under `/srv/builds/_adv-family-gate/bin/<tag>/` (fg2 9b7f764a for the first corners, fg5 e7a50f8d for the width-4 and lossy-base strata). Cost: about 10 core-seconds per era; 54.4 core-hours in all (1.7 box-hours of 32-core slots) on build-1 (random, lossy cap, width 4) and build-3 (shape 64, lossy base, width 4 plus lossy cap), every run under `lease pool` at class measure. The control: `v5_attempts_census` on the shipped class v5 draw over 10,000 seeds of the F8 label space (build-1, 24 cores, 1,534 s, binary 4bec799c, `logs/base-v5_attempts_census-1000-10000.log`): r = 0.6854, mean attempt 2.179, 0 exhaustions, (a') 82.5 percent of rejections, (c''') 0.9 percent, the row-90 reading reproduced.
| Run | What | Where | State |
|---|---|---|---|
| base | `v5_attempts_census` (the shipped class v5 draw: shape 256 x 27, `m = 8`, `W = 1`, the table weights) over f8-label seeds 1,000 to 11,000, each seed its own drawn era (M, R, pos, windows) | build-1, 24 cores, binary 4bec799c (8f481459 unmodified) | running from 11:16 BST |
| fg1 random | `family_gate_era_census` with every axis drawn (shape in {64, 128, 256}, `m` in {4, 8, 16} recorded, `W` over {1, 4}, weights at B = 4 with shfl and mulhi never raised) | build-1 | the harness built at 11:2x BST; the smoke run and the chunks follow |
| fg1 corners | the same harness pinned per cell: `IGNEUM_FG_LOSSY_CAP`, `IGNEUM_FG_WIDTH=4`, `IGNEUM_FG_SHAPE=64`, the combinations | build-1, build-3, build-4 as the pool frees | queued |
Voided and stated: the first width-4 stratum (3,000 eras, 11:2x to 11:4x BST) ran at width 1, because `LoadClass::era` with a one-entry allowed set is the pinned path and redraws to the base's widest width; the fix builds the pinned class by hand (the era drawn over the one-entry set, the mix one-hot); the void rows are not in this directory and the stratum was re-run under its own label space. The first corner strata (lossy cap, shape 64) share the random stratum's label space, so where the random draw happened to land on the pinned value the era is the same program in both; the later strata use per-stratum labels.
The coverage table (filled from the TSV rows at 16:xx BST for the 17:00 cut; the full read at 09:00 BST tomorrow):
### 6.1 Per stratum
| Stratum | Eras drawn | `r` per candidate | Mean attempt, max | Exhausted | min (c'') ratio (the worst era) | Under 0.995 (the (c''') refuse rate on the accepted draw) | Largest bucket ratio (worst era, site) | Largest bit bias in sigma (worst era, site, bit) |
| Stratum | Eras | r per candidate | Mean attempt, max | Exhausted at the 256 cap | min (c'') ratio of the accepted draw, worst era | The floors' refuse rates over all candidates | Largest bucket excess, worst era | Largest index-bit bias, worst era; the share of eras over 6 and over 100 sigma |
|---|---|---|---|---|---|---|---|---|
| base (shipped draw) | pending | | | | | | | |
| random (every axis drawn) | pending | | | | | | | |
| lossy cap | pending | | | | | | | |
| W = 4 | pending | | | | | | | |
| shape 64 | pending | | | | | | | |
| random (every axis drawn, B = 4 on every family) | 10,000 | 0.724 | 2.63, 236 | 0 | 0.9950 at site 0 of era 1150 (R 14, shape 64, W 1) | (c''') 988 of 36,285 candidates (2.72 percent), (c'') 368 (1.01) | +512 sigma at site 4 (full window) of era 2794 (R 11) | z = -1,024 at site 13 bit 18 of era 3310 (R 18); over 6 sigma 5,172 (51.7 percent), over 100 sigma 3,390 (33.9) |
| lossy base, THE PROPOSED BAND (B = 4 on the seven injecting families, or/mul/mulhi never raised) | 3,000 | 0.595 | 1.47, 59 | 0 | 0.9951 at site 0 of era 114 (R 25, shape 64, W 4) | (c''') 290 of 7,410 (3.91 percent), (c'') 110 (1.48) | +369 sigma at site 12 of era 2099 (R 10) | z = -1,024 at site 14 bit 26 of era 499 (R 26); over 6 sigma 1,431 (47.7 percent), over 100 sigma 933 (31.1) |
| lossy cap (or, mul, mulhi all at +4: 30 of 75) | 3,000 | 0.957 | 19.21, 254 | 37 (1.23 percent of eras; the first eight 22, 123, 125, 170, 293, 305, 348, 584) | 0.9950 at site 13 of era 2359 | (c''') 282 of 69,363 (0.41 percent), (c'') 131 (0.19) | +184 sigma at site 0 of era 2085 (R 14) | z = -896 at site 3 bit 26 of era 2141 (R 26); over 6 sigma 57.7 percent, over 100 sigma 37.0 |
| width 4 words (the pinned width, every other axis drawn) | 3,000 | 0.738 | 2.82, 114 | 0 | 0.9950 at site 4 of era 865 (R 2) | (c''') 497 of 11,454 (4.34 percent), (c'') 134 (1.17) | +44 sigma at site 5 (half window) of era 270 (R 21) | z = -768 at site 15 bit 25 of era 183 (R 25); over 6 sigma 47.5 percent, over 100 sigma 28.6 |
| width 4 plus lossy cap | 2,000 | 0.959 | 20.15, 253 | 24 (1.20 percent) | 0.9950 at site 1 of era 1869 | (c''') 352 of 47,934 (0.73 percent), (c'') 124 (0.26) | +70 sigma at site 0 (quarter window) of era 1440 (R 10) | z = -736 at site 11 bit 27 of era 1239 (R 27); over 6 sigma 52.3 percent, over 100 sigma 31.2 |
| shape 64 x 108 (the pinned shape) | 3,000 | 0.643 | 1.80, 31 | 0 | 0.9950 at site 0 of era 1150 | (c''') 301 of 8,399 (3.58 percent), (c'') 104 (1.24) | +512 sigma at site 4 of era 2794 (R 11) | z = -1,024 at site 10 bit 1 of era 2431 (R 1); over 6 sigma 52.1 percent, over 100 sigma 34.0 |
| the shipped draw (control) | 10,000 | 0.685 | 2.18, 28 | 0 | not read (the census test reports parts only) | (c''') 0.6 percent of candidates, (c'') 0.8 | | |
Rejections by first failing part, the random stratum (26,285 rejected candidates): (a') 76.4 percent, (a) 13.4, (b) 3.8, (c''') 3.8, (c'') 1.4, (c) constant bit 0.6, (c) saturated 0.5, (c') 0.1, (c) distinct addresses 0.1, (c) output bias 0.0. At the lossy cap (66,400): (a') 74.6, (a) 20.8, (b) 3.7, the dynamic parts under 1 together. The shape of the rule's cost does not change across the family; its level does.
### 6.2 Per axis, inside the random stratum (10,000 eras) and the proposed band (3,000)
| Axis | Value | Eras (random / band) | Mean attempt (random / band) | Max attempt | r (random / band) | (c''') refusals per candidate (random / band) | Eras with a site over 6 sigma | Over 100 sigma | Bucket sigma p99 | min ratio p1 |
|---|---|---|---|---|---|---|---|---|---|---|
| width (words) | 1 | 4,978 / 1,508 | 2.35 / 1.30 | 158 / 59 | 0.701 / 0.565 | 0.61 / 0.98 percent | 55.7 / 52.1 percent | 39.1 / 36.4 | +51.5 | 0.9959 |
| width (words) | 4 | 5,022 / 1,492 | 2.91 / 1.64 | 236 / 23 | 0.744 / 0.621 | 4.52 / 6.50 percent | 47.8 / 43.3 | 28.8 / 25.7 | +28.2 | 0.9956 |
| shape | 64 x 108 | 3,371 / 980 | 1.81 / 1.22 | 40 / 14 | 0.645 / 0.550 | 3.86 / 4.31 | 50.5 / 48.7 | 33.0 / 31.3 | +40.7 | 0.9958 |
| shape | 128 x 54 | 3,302 / 963 | 2.26 / 1.28 | 62 / 12 | 0.694 / 0.562 | 2.76 / 4.32 | 51.8 / 48.7 | 34.1 / 32.9 | +46.0 | 0.9958 |
| shape | 256 x 27 | 3,327 / 1,057 | 3.82 / 1.87 | 236 / 59 | 0.792 / 0.651 | 2.02 / 3.33 | 52.8 / 45.9 | 34.6 / 29.2 | +41.7 | 0.9957 |
| mixer m (recorded) | 4 | 3,305 / 990 | 2.72 / 1.64 | 236 / 59 | 0.731 / 0.621 | 2.74 / 3.94 | 51.5 / 47.8 | 34.0 / 31.5 | +41.5 | 0.9958 |
| mixer m | 8 | 3,382 / 1,011 | 2.67 / 1.38 | 158 / 21 | 0.728 / 0.580 | 2.76 / 3.86 | 51.2 / 47.2 | 33.9 / 31.3 | +42.5 | 0.9957 |
| mixer m | 16 | 3,313 / 999 | 2.49 / 1.39 | 113 / 36 | 0.714 / 0.581 | 2.66 / 3.94 | 52.4 / 48.1 | 33.8 / 30.5 | +42.4 | 0.9959 |
| rotation class | R 1..27 | 8,732 / 2,587 | 2.64 / 1.51 | 236 / 59 | 0.725 / 0.602 | 3.07 / 4.40 | 53.9 / 49.2 | 37.7 / 35.0 | +44.5 | 0.9957 |
| rotation class | R 28..31 (bit 0 cut at D = 28) | 1,268 / 413 | 2.57 / 1.21 | 231 / 12 | 0.720 / 0.548 | 0.29 / 0.44 | 36.5 / 38.5 | 7.5 / 6.8 | +6.5 | 0.9985 |
Readings, each a measured row above:
1. The mixer axis is invisible to every per-era statistic, as section 1.3 said it must be: the three `m` values read the same to the noise (r 0.714 to 0.731, the biased share 51 to 52 percent). `m` is a per-family axis, closed by the mixer rows of section 4, not by drawing eras.
2. The shape axis moves the draw's cost: 256 x 27 costs 3.82 attempts against 1.81 at 64 x 108 (r 0.792 against 0.645), because the freshness fixpoint (a') walks the whole block and a 256-instruction block holds more lossy last writers per iteration than a 64-instruction one. The band's cheapest shape is the fastest card shape too (64, measured 2.5 to 3.5 percent faster on 6 October).
3. The width axis moves the (c''') floor's calibration: at width 4 the floor at 0.995 refuses 4.5 to 6.5 percent of candidates against 0.6 to 1.0 at width 1, with the expectation already divided by the width. The clean spread of the ratio at width 4 is not the width-1 spread the floor was set from (the aligned index space is a quarter the size, so the birthday collisions on the closed form are 4x denser, and the `N - N^2 / 2W` form is 0.0007 low at `N / W = 1/16`). A floor fixed at one number across the family is therefore a per-width liveness cost of 4x the (c''') attempts; the family's floor is set per width from the clean spread (the next measurement, section 7 item 1), or the statistic is re-expressed as a sigma over its own expectation as the bucket statistic now is.
4. The lossy corner breaks the exhaustion bound: r = 0.957 to 0.959 and 1.2 percent of eras at the 256 cap in both lossy strata (61 of 5,000), against 0 of 19,000 in every other stratum and 0 of 10,000 on the shipped draw. The arithmetic agrees: 0.957^256 = 1.3e-5 per seed is the geometric estimate, but the attempts are not independent across one seed's candidates (the lossy weight table is shared by every attempt of the era, so the rejection rate per era is itself drawn from a spread), and the measured per-era rate is 1.2e-2, three orders above the independent-attempt figure. The ring-A rule is the one the data forces: or + mul + mulhi never raised above the table's 18 of 75. Under it (the lossy-base stratum) r = 0.595, the mean attempt 1.47, the maximum 59, 0 exhaustions in 3,000.
5. The index-bit bias is the family's standing fact: 48 to 58 percent of accepted programs in every stratum carry one site with a bias over 6 sigma at 2^20, and 73 percent of those are at bit R exactly, 12 percent at R + 1, 5 percent at R + 2 (the product law's bits 0, 1, 2 at P = 1/4, 3/8, 7/16 through `rotl(x * M, R)`); 74 percent read P(bit) under 1/2 (a product's low bit), 26 percent over 1/2 (an or-shaped source, 5/8 and up). Under R in 28..31 (bit 0 cut by the 28-bit mask) the share over 100 sigma falls from 37.7 to 7.5 percent and the bucket excess's p99 from +44 to +6.5 sigma, which is adv-cache-2's R-class reading at 10,000 eras. The shipped devnet's R = 29 is one of the four clean rotations; the chain's eras are drawn from all 31. The bucket statistic and the bit statistic see the same mechanism (the bucket's p99 on the bit-clean eras is +6.8 sigma, on the biased ones +44), so one next-class test covers both: the value-level read, with the structural fix in `load_index` as the remedy rather than a refusal (a 6-sigma refusal redraws half the epochs; a 100-sigma one a third).
6. The (c''') floor holds everywhere by construction (0 accepted programs under 0.995) and its clean spread at width 1 is the shipped one (p1 of the minimum ratio 0.9958 to 0.9961, median 0.9999 across strata); the floor's refuse rate moves from 2.7 percent (random) to 3.9 (the band) and 0.4 (the lossy corner, where (a') refuses first).
### 6.3 What the counts bound (the arithmetic of section 2 on these rows)
| Claim | n | Bound at 95 percent | Bound at 99 percent |
|---|---|---|---|
| An era of the proposed band whose chain draw exhausts the 256 cap | 3,000 of 3,000 passed (lossy base) | under 1.0e-3 of eras (one in 1,000: one per 490 years at 180-day eras) | under 1.5e-3 |
| The same on the random stratum at B = 4 on every family | 10,000 of 10,000 | under 3.0e-4 | under 4.6e-4 |
| An era of the band whose accepted draw sits under the (c''') floor | 3,000 of 3,000 (and 19,000 of 19,000 outside the lossy corner) | under 1.0e-3 | under 1.5e-3 |
| An era of the lossy corner that exhausts | 61 of 5,000 FAILED | the rate is 1.2 percent, a measurement, not a bound: the corner is out of the band | |
| The (c''') floor's miss rate on the few-item hot-set class | 9 of 9 fired (unchanged: this census reads the acceptance's sample, not the live dataset) | under 0.33 | under 0.40 |
| The bit-bias read's firing on the product class | 5,172 of the random stratum's eras read over 6 sigma; the three named cases (Devnet 3 site 0, era-drawn-28 site 15, the per-load candidate 0) are of that class | a record, not a refusal: no miss rate is claimed | |
The union bound stays loose where section 2.2 said it would: the two floors' miss rates on the live-dataset classes rest on nine and five cases, and this census adds cases to the exhaustion and bias rows only. The live-dataset census at 2^24 on 64 seeds of two eras of the band (one at width 4, one at R in 1..27 with a 1,000-sigma site) is the next ring-C row (section 7 item 6); it is what turns the bit read's z into a per-era hot-set price on the real item map.
## 7. Owed by 09:00 BST on 9 October (the full report)
1. The coverage table of section 6 filled from the logs, with the per-stratum refuse rates and the union-bound arithmetic on the measured numbers, and the TSV rows and logs under `docs/analysis/class-v6/logs/`.
2. The clean spread of the bucket ratio and the bit bias per stratum, so the two new ring-B tests get a bound and a clean refuse rate (not a guess).
3. The lossy-corner `r` against the 0.85 line, and the exhaustion count at 10^4 seeds on that corner.
4. The width-4 reading of (c'') and (c''') with the divided expectation, and the spec line for 1.4.6.5.
5. The mixer rows at `m = 4` and 16 (adv-mixer-3's index and sac at k = 2 on two days; the SAT at k = 2) as the per-family corner rows, if the boxes have the cores after the other lanes' jobs arrive; else the plan with its hours.
6. The F8-form census at 2^24 on 64 seeds of one lossy-cap era and one width-4 era, the first ring-C rows on the family (about 2 box-hours each).
7. The gate-record JSON written for every era of the census from the TSV (the format of 4.3), and the summary.
1. The (c''') floor's clean spread per width (and per shape) from the accepted draws of section 6, with the per-width floor or the sigma form that keeps the clean refuse rate near the shipped 2.4 percent; the spec line for 1.4.6.5's expectation under a drawn width.
2. The bucket bound stated in sigma from the bit-clean spread (p99 +6.8, max +28 over 4,828 eras): a band at +8 sigma refuses under 1 percent of bit-clean programs and every F8 tail seed (+17 to +37); its cost on the biased eras is the bit read's cost, so the two tests are one rule.
3. The lossy-corner reading taken one step further: the exhaustion rate per era against the lossy share in points (18 to 30 of 75), so the band's edge is a measured curve, not one corner; 10^4 seeds at each of three shares.
4. The mixer rows at `m = 4` and 16 (adv-mixer-3's index and sac at k = 2 on two days; the SAT at k = 2) as the per-family corner rows, on build-4 when its pool frees; else the plan with its hours.
5. The last-resort programs of the 61 exhausted eras run through the real rule (adv-accept-3's finding 1 at the corner: how many fail (a)).
6. The F8-form census at 2^24 on 64 seeds of two eras of the band (one at width 4, one with a 1,000-sigma site under R in 1..27), the first ring-C rows on the family (about 2 box-hours each): the live-dataset hot-set price of the bit-level bias.
7. The gate-record JSON per era (the format of 4.3) generated from the TSV rows by `fg-records.py` (in `logs/`), and the family summary.
8. The two build-4 strata (shape 64 plus lossy cap, shape 256) when its pool frees; nothing in the cut depends on them.
## 8. Sources

View file

@ -0,0 +1,23 @@
binary 4bec799c42e4c843 commit 8f4814591a4ad543e8cb91a50fa049da80d82b5d test v5_attempts_census from 1000 seeds 10000 threads 24 start 2026-10-08T10:15:44Z
lease: holding 24 pool cores (48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71, waited 0 s, class measure): family gate: v5_attempts_census base seeds 1000+10000
running 1 test
test accept::tests::v5_attempts_census ... v5_attempts_census: 10000 seeds 1000..11000 in 1534 s on 24 threads
candidates 31788, rejected 21788, per-candidate rejection 0.6854, exhaustions 0, P(256 consecutive) 1.010e-42
first failing part (a') unfresh source: 17980 (82.5 percent of rejections, 56.6 percent of candidates)
first failing part (a) stale load: 2521 (11.6 percent of rejections, 7.9 percent of candidates)
first failing part (b) no injecting write: 670 (3.1 percent of rejections, 2.1 percent of candidates)
first failing part (c''') hot-item site: 201 (0.9 percent of rejections, 0.6 percent of candidates)
first failing part (c'') low-entropy site: 240 (1.1 percent of rejections, 0.8 percent of candidates)
first failing part (c') saturated source: 14 (0.1 percent of rejections, 0.0 percent of candidates)
first failing part (c) constant bit: 88 (0.4 percent of rejections, 0.3 percent of candidates)
first failing part (c) distinct addresses: 7 (0.0 percent of rejections, 0.0 percent of candidates)
first failing part (c) saturated: 67 (0.3 percent of rejections, 0.2 percent of candidates)
accepted attempt mean 2.179
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 79 filtered out; finished in 1533.90s
Terminated
lease: released 24 pool cores after 1534 s, exit 0
end 2026-10-08T10:41:18Z rc 0

View file

@ -0,0 +1,27 @@
#!/usr/bin/env python3
"""family-gate lane: the per-axis and per-rotation-class readings of one stratum's TSV (markdown tables)."""
import sys, csv, collections, statistics
rows = [r for p in sys.argv[1:] for r in csv.DictReader(open(p), delimiter='\t')]
acc = [r for r in rows if r['attempt'] not in ('', '-1')]
print(f"eras {len(rows)}, accepted {len(acc)}, exhausted {len(rows)-len(acc)}")
def z(r): return abs(float(r['bit_z_max']))
print("\n| Axis | Value | Eras | Mean attempt | Max attempt | r per candidate | (c''') refusals per candidate | Biased site over 6 sigma | Over 100 sigma | Bucket sigma p99 | min ratio p1 |")
print("|---|---|---|---|---|---|---|---|---|---|---|")
def rcls(r): R = int(r['R']); return 'R 28..31 (bit 0 cut at D = 28)' if R >= 28 else 'R 1..27'
for axis, keyf in [('width (words)', lambda r: r['width']), ('shape', lambda r: r['shape']), ('mixer m', lambda r: r['mixer']), ('rotation class', rcls)]:
d = collections.defaultdict(list)
for r in rows: d[keyf(r)].append(r)
for k in sorted(d, key=lambda x: (len(x), x)):
g = d[k]; ga = [r for r in g if r['attempt'] not in ('', '-1')]
cands = sum(int(r['candidates']) for r in g); rej = cands - len(ga); c3 = sum(int(r['c3_hot_item']) for r in g)
bz = sorted(float(r['bucket_z_max']) for r in ga); mr = sorted(float(r['min_ratio']) for r in ga)
print(f"| {axis} | {k} | {len(g)} | {statistics.mean(int(r['attempt']) for r in ga):.2f} | {max(int(r['attempt']) for r in ga)} | {rej/cands:.3f} | {100*c3/cands:.2f} percent | {100*sum(z(r)>6 for r in ga)/len(ga):.1f} percent | {100*sum(z(r)>100 for r in ga)/len(ga):.1f} percent | +{bz[int(len(bz)*.99)]:.1f} | {mr[int(len(mr)*.01)]:.4f} |")
rel = collections.Counter((int(r['bit']) - int(r['R'])) % 32 for r in acc if z(r) > 6)
tot = sum(rel.values())
print("\nBiased bit minus R, mod 32, among the biased eras:", ', '.join(f"{k}: {v} ({100*v/tot:.0f} percent)" for k, v in rel.most_common(5)))
neg = sum(1 for r in acc if float(r['bit_z_max']) < -6); pos = sum(1 for r in acc if float(r['bit_z_max']) > 6)
print(f"Sign: {neg} with P(bit) under 1/2 (the product law), {pos} over 1/2 (an or-shaped source)")
clean = sorted(float(r['bucket_z_max']) for r in acc if z(r) <= 6); n = len(clean)
print(f"Bucket excess on the {n} bit-clean eras: median +{clean[n//2]:.1f} sigma, p95 +{clean[int(n*.95)]:.1f}, p99 +{clean[int(n*.99)]:.1f}, max +{clean[-1]:.1f}")
cz = sorted(z(r) for r in acc if z(r) <= 6); print(f"Bit |z| on the eras under 6 sigma: median {cz[len(cz)//2]:.2f}, p99 {cz[int(len(cz)*.99)]:.2f} (the maximum of about 26 free bits over 16 sites of a clean program)")
mr = sorted(float(r['min_ratio']) for r in acc); print(f"Minimum (c'') ratio of the accepted draw: min {mr[0]:.5f}, p1 {mr[int(len(mr)*.01)]:.5f}, p5 {mr[int(len(mr)*.05)]:.5f}, median {mr[len(mr)//2]:.5f}")

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# family-gate lane: build the test binary of a box-side source dir under the lease pool and pin a copy. usage: fg-build.sh <tagdir> [threads]
set -euo pipefail
TAG="$1"; T="${2:-32}"; ROOT=/srv/builds/_adv-family-gate; W="$ROOT/src-$TAG"
cd "$W/igneum-pow"; export PATH="$HOME/.cargo/bin:$PATH"; CARGO=$(command -v cargo)
export RUSTC_WRAPPER=${RUSTC_WRAPPER:-$(command -v sccache || true)}
/srv/builds/_bin/lease pool "$T" --min 8 --class measure --label "family gate: build the harness test binary ($TAG)" --owner class-v6-family-gate -- "$CARGO" test --release --lib --no-run -j "{cores}" > "$ROOT/logs/build-$TAG.log" 2>&1
BIN=$(ls -t target/release/deps/igneum_pow-* | grep -v '\.d$' | head -1)
mkdir -p "$ROOT/bin/$TAG"; cp "$BIN" "$ROOT/bin/$TAG/igneum_pow_test"; sha256sum "$ROOT/bin/$TAG/igneum_pow_test" | tee "$ROOT/bin/$TAG/sha256"

View file

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# family-gate lane: one chunk of the class v5 attempts census (every candidate of each seed's chain draw through the real rule, the
# era of each seed drawn from its own label) from a pinned copy of the test binary, under the lease pool.
# usage: fg-census.sh <commit> <test-name> <from> <seeds> <threads> <tag>
set -euo pipefail
C="$1"; TEST="$2"; FROM="$3"; N="$4"; T="$5"; TAG="$6"
ROOT=/srv/builds/_adv-family-gate; BIN="$ROOT/bin/$C/igneum_pow_test"; LOG="$ROOT/logs/$TAG-$TEST-$FROM-$N.log"
echo "$$" > "$ROOT/pids/$TAG-$TEST-$FROM-$N.pid"
echo "binary $(sha256sum "$BIN" | cut -c1-16) commit $C test $TEST from $FROM seeds $N threads $T start $(date -u +%FT%TZ)" > "$LOG"
IGNEUM_V5_CENSUS_FROM="$FROM" IGNEUM_V5_CENSUS_SEEDS="$N" IGNEUM_V5_CENSUS_THREADS="$T" IGNEUM_FG_FROM="$FROM" IGNEUM_FG_SEEDS="$N" IGNEUM_FG_THREADS="$T" IGNEUM_FG_OUT="$ROOT/logs/$TAG-$TEST-$FROM-$N.tsv" \
/srv/builds/_bin/lease pool "$T" --min 8 --class measure --label "family gate: $TEST $TAG seeds $FROM+$N" --owner class-v6-family-gate -- "$BIN" --ignored "$TEST" --nocapture --test-threads 1 >> "$LOG" 2>&1
echo "end $(date -u +%FT%TZ) rc $?" >> "$LOG"

View file

@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""family-gate lane: one gate-record JSON per drawn era from the census TSV rows (the format of family-gate.md section 4.3).
usage: fg-records.py <outdir> <stratum>=<tsv>[,<tsv>] ... ; the harness binary sha and box from the matching .log header."""
import sys, csv, json, os, pathlib, hashlib
FAMILY = {"id": "class-v6-draft-2026-10-08", "spec": "docs/spec/01-lottery-hash.md 1.4.6, 1.13.1 (the family's bands in docs/analysis/class-v6/family-gate.md section 1)",
"object": "igneum-pow class-v5 8f481459 plus the harness (branch family-gate-v5), the acceptance keyed on the family's shapes behind IGNEUM_FAMILY_GATE"}
def header(logpath):
try:
line = open(logpath).readline().split()
return {"binary": line[1], "box": None, "started": line[-1]}
except Exception:
return {}
out = pathlib.Path(sys.argv[1]); out.mkdir(parents=True, exist_ok=True)
n = 0
for arg in sys.argv[2:]:
stratum, paths = arg.split('=', 1)
for p in paths.split(','):
if not os.path.exists(p): continue
h = header(p[:-4] + '.log')
with open(p) as f:
for r in csv.DictReader(f, delimiter='\t'):
acc = r['attempt'] not in ('', '-1')
rec = {"family": FAMILY, "label": "internal research, not an independent review",
"era": {"label": f"igneum-family-gate/era/{r['k']}", "stratum": stratum,
"draw": {"m": int(r['mixer']), "weights": [int(r[k]) for k in ['w_add','w_xor','w_mul','w_mad','w_shfl','w_rotl','w_sub','w_mulhi','w_rotr','w_or']],
"width_words": int(r['width']), "shape": [int(r['shape']), int(r['reps'])], "R": int(r['R']), "M": "0x" + r['M'], "pos": json.loads(r['pos'])}},
"harness": {**h, "source_tsv": os.path.basename(p), "secs": float(r['secs'])},
"tests": [
{"name": "attempts", "epoch": f"igneum-family-gate/program/{r['k']}", "candidates": int(r['candidates']), "accepted_attempt": int(r['attempt']) if acc else None,
"first_failing_part": {k: int(r[k]) for k in ['a_prime','a','b','c_const','c_lane','c_sat','c_bias','c_distinct','c1_sat_source','c2_low_entropy','c3_hot_item']},
"exhausted": not acc, "verdict": "PASS" if acc else "EXHAUSTED"},
{"name": "c2-c3-ratio", "floor": [0.98, 0.995], "min_ratio": float(r['min_ratio']) if acc else None, "min_site": int(r['min_site']) if acc else None, "verdict": "PASS" if acc else "n/a"},
{"name": "bucket-256-items", "max_ratio": float(r['bucket_ratio_max']) if acc else None, "max_sigma": float(r.get('bucket_z_max') or 'nan') if acc else None, "site": int(r['bucket_site']) if acc else None, "window": int(r.get('bucket_win') or -1) if acc else None, "bound": "not yet set (the clean spread is this census)", "verdict": "RECORD"},
{"name": "index-bit-bias", "max_sigma": float(r['bit_z_max']) if acc else None, "site": int(r['bit_site']) if acc else None, "bit": int(r['bit']) if acc else None, "window": int(r.get('bit_win') or -1) if acc else None, "band_sigma": 6, "over_band": (abs(float(r['bit_z_max'])) > 6) if acc else None, "verdict": "RECORD"}]}
(out / stratum).mkdir(exist_ok=True)
(out / stratum / f"era-{r['k']}.json").write_text(json.dumps(rec, indent=1))
n += 1
print(f"{n} records under {out}")

View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""family-gate lane: per-stratum summary of family_gate_era_census TSV rows (and the gate-record JSON per era)."""
import sys, csv, json, math, os, statistics
def load(path):
with open(path) as f:
r = csv.DictReader(f, delimiter='\t')
return [row for row in r]
def num(x, d=float('nan')):
try: return float(x)
except: return d
def summarise(name, rows):
n = len(rows)
if n == 0: return f"| {name} | 0 | | | | | | | | |"
acc = [r for r in rows if r['attempt'] not in ('', '-1')]
cands = sum(int(r['candidates']) for r in rows); rej = cands - len(acc)
r_per = rej / cands if cands else float('nan')
atts = [int(r['attempt']) for r in acc]
exh = n - len(acc)
ratios = [(num(r['min_ratio']), r) for r in acc]
worst = min(ratios, key=lambda x: x[0])
under995 = sum(1 for x, _ in ratios if x < 0.995)
c3 = sum(int(r['c3_hot_item']) for r in rows); c2 = sum(int(r['c2_low_entropy']) for r in rows)
exh_eras = [r['k'] for r in rows if r['attempt'] in ('', '-1')]
bz = [(num(r.get('bucket_z_max', 'nan')), r) for r in acc]
bzw = max(bz, key=lambda x: x[0]) if bz and not math.isnan(bz[0][0]) else (float('nan'), {})
bitz = [(abs(num(r['bit_z_max'])), r) for r in acc]
bitw = max(bitz, key=lambda x: x[0])
over6 = sum(1 for z, _ in bitz if z > 6); over100 = sum(1 for z, _ in bitz if z > 100)
parts = {k: sum(int(r[k]) for r in rows) for k in ['a_prime','a','b','c_const','c_lane','c_sat','c_bias','c_distinct','c1_sat_source','c2_low_entropy','c3_hot_item']}
pshare = ' '.join(f"{k} {100*v/rej:.1f}" for k, v in parts.items() if rej and v)
def era(r): return f"era {r['k']} (R {r['R']}, shape {r['shape']}, W {r['width']})"
return (f"| {name} | {n} | {r_per:.3f} | {statistics.mean(atts):.2f}, {max(atts)} | {exh}{(' (eras ' + ','.join(exh_eras[:8]) + ')') if exh else ''} | {worst[0]:.4f} at site {worst[1]['min_site']} of {era(worst[1])} | (c''') refused {c3} of {cands} candidates ({100*c3/cands:.2f} percent), (c'') {c2} ({100*c2/cands:.2f}) "
f"| +{bzw[0]:.1f} sigma at site {bzw[1].get('bucket_site','')} (win {bzw[1].get('bucket_win','')}) of {era(bzw[1]) if bzw[1] else ''} | {bitw[1]['bit_z_max']} at site {bitw[1]['bit_site']} bit {bitw[1]['bit']} of {era(bitw[1])}; over 6 sigma {over6} ({100*over6/len(acc):.1f} percent), over 100 sigma {over100} ({100*over100/len(acc):.1f} percent) |\n"
f"| rejections by part (percent of {rej}) | {pshare} | | | | | | | |")
if __name__ == '__main__':
print("| Stratum | Eras | r per candidate | Mean attempt, max | Exhausted at the 256 cap | min (c'') ratio of the accepted draw, worst era | The floors' refuse rates over all candidates | Largest bucket excess (sigma), worst era | Largest index-bit bias (sigma), worst era; the share over 6 and over 100 sigma |")
print("|---|---|---|---|---|---|---|---|---|")
for arg in sys.argv[1:]:
name, path = arg.split('::', 1)
rows = []
for p in path.split(','):
if os.path.exists(p): rows += load(p)
print(summarise(name, rows))

View file

@ -0,0 +1,627 @@
From 4c408ef180a2f9a321756e10de224b7610c37cbc Mon Sep 17 00:00:00 2001
From: igneum-labs <337424239+[removed]>
Date: Thu, 8 Oct 2026 11:15:23 +0100
Subject: [PATCH 1/5] class v6 family-gate harness: the acceptance keyed on the
family's shapes behind IGNEUM_FAMILY_GATE (never a chain path), per-thread
weight tables, family_site_stats (largest 256-item bucket, index-bit bias)
and the family_gate_era_census test (one drawn era per seed, every parameter
from the era's stream, one TSV row per era)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
igneum-pow/src/accept.rs | 295 +++++++++++++++++++++++++++++++++++-
igneum-pow/src/generator.rs | 21 ++-
2 files changed, 311 insertions(+), 5 deletions(-)
diff --git a/igneum-pow/src/accept.rs b/igneum-pow/src/accept.rs
index 808451a4..7035c82e 100644
--- a/igneum-pow/src/accept.rs
+++ b/igneum-pow/src/accept.rs
@@ -241,7 +241,100 @@ pub struct SiteIndexStats {
/// The window of a load site in words at the rule's dataset: `2^28 >> min(win, 2)`.
pub fn site_window_words(ins: &Instr) -> u64 {
- (1u64 << ACCEPT_DATASET_LOG2) >> (ins.win as u64).min(2)
+ // a load of `width` words reads an aligned address, so its index space is the window over `width` (1 on every
+ // shipped class; the class v6 family-gate harness draws 4 and the expectation must follow, 8 October 2026)
+ ((1u64 << ACCEPT_DATASET_LOG2) >> (ins.win as u64).min(2)) / (ins.width.max(1) as u64)
+}
+
+/// Class v6 family-gate harness: what one load site's indices look like beyond [`SiteIndexStats`]: the largest
+/// 256-item bucket (4,096 words, the bucket of the F8 tail attribution of 8 October 2026) as a ratio to the window's
+/// expectation, and the largest index-bit one-count excess in sigma over the window's free bits (adv-cache-2's
+/// value-level read: a product's low bits placed at address bit R and up).
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct FamilySiteStats {
+ pub base: SiteIndexStats,
+ pub bucket_ratio: f64,
+ pub bucket_id: u32,
+ pub bit_z: f64,
+ pub bit: u8,
+}
+
+/// The same run as [`site_index_stats`] with the two extra statistics per site.
+pub fn family_site_stats(p: &Program, units: usize) -> Result<Vec<FamilySiteStats>, Reject> {
+ let loads = p.loads_per_hash();
+ let sites = loads / ITERATIONS;
+ let mut acc = Acc {
+ sources: None,
+ indices: Some(vec![Vec::with_capacity(units * LANES * ITERATIONS); sites]),
+ sat_source: vec![0; sites],
+ and_acc: [u32::MAX; 8],
+ or_acc: [0; 8],
+ saturated: 0,
+ bit_ones: [0; 64],
+ distinct_sum: 0,
+ };
+ let mut lane_addrs = vec![0u32; LANES * loads];
+ for (unit, &base) in accept_base_nonces_n(&p.seed, units).iter().enumerate() {
+ run_unit(p, unit, base, &mut acc, &mut lane_addrs)?;
+ }
+ let load_instrs: Vec<&Instr> = p.instrs.iter().filter(|i| i.op.is_load()).collect();
+ let mut out = Vec::with_capacity(sites);
+ for (site, ix) in acc.indices.take().unwrap().iter_mut().enumerate() {
+ let ins = load_instrs[site];
+ let n = ix.len() as f64;
+ let k = (ins.win as u32).min(2);
+ let free_bits = ACCEPT_DATASET_LOG2 - k;
+ let mut ones = [0u64; 32];
+ let mut buckets = vec![0u32; 1usize << (ACCEPT_DATASET_LOG2 - 12)];
+ for &x in ix.iter() {
+ buckets[(x >> 12) as usize] += 1;
+ let mut v = x;
+ let mut b = 0;
+ while v != 0 {
+ ones[b] += (v & 1) as u64;
+ v >>= 1;
+ b += 1;
+ }
+ }
+ let width = ins.width.max(1) as u32;
+ let align_bits = width.trailing_zeros();
+ let (mut bit_z, mut bit) = (0.0f64, 0u8);
+ for b in align_bits..free_bits {
+ let z = (ones[b as usize] as f64 - n / 2.0) / (n / 4.0).sqrt();
+ if z.abs() > bit_z.abs() {
+ bit_z = z;
+ bit = b as u8;
+ }
+ }
+ let window_buckets = (site_window_words(ins) * width as u64) >> 12;
+ let expect = n / window_buckets as f64;
+ let (mut bmax, mut bid) = (0u32, 0u32);
+ for (i, &c) in buckets.iter().enumerate() {
+ if c > bmax {
+ bmax = c;
+ bid = i as u32;
+ }
+ }
+ ix.sort_unstable();
+ let mut st = SiteIndexStats { distinct: 0, pairs: 0, top_index: 0, top_count: 0 };
+ let mut i = 0;
+ while i < ix.len() {
+ let mut j = i + 1;
+ while j < ix.len() && ix[j] == ix[i] {
+ j += 1;
+ }
+ let run = (j - i) as u32;
+ st.distinct += 1;
+ st.pairs += (run as u64) * (run as u64 - 1) / 2;
+ if run > st.top_count {
+ st.top_count = run;
+ st.top_index = ix[i];
+ }
+ i = j;
+ }
+ out.push(FamilySiteStats { base: st, bucket_ratio: bmax as f64 / expect, bucket_id: bid, bit_z, bit });
+ }
+ Ok(out)
}
/// One interpreter run over `units` units with every load site's word indices kept, then per site the sorted
@@ -353,11 +446,38 @@ pub fn check_indices_v5(p: &Program) -> Result<(), Reject> {
/// Whether `class` is the class v4 shape (the 256-instruction shadow block over the class v3 base, the pass count and
/// the era set aside): the shape the sub-version 2 rules (a') and (c') apply to, on every draw path.
pub fn is_class_v4_shape(class: &LoadClass) -> bool {
+ if family_gate_on() {
+ return is_family_shape(class);
+ }
matches!(class.shadow, Some(ShadowClass { instrs: V4_SHADOW_INSTRS, .. }))
// class v5 (docs/design/class-v5-stored-state.md) is judged under the same rules: its state flag is set aside
&& LoadClass { era: None, shadow: None, state: false, ..*class } == LoadClass { shadow: None, ..V4_CLASS }
}
+/// Class v6 family-gate harness (8 October 2026, `docs/analysis/class-v6/family-gate.md`): the acceptance keyed on the
+/// FAMILY's shapes instead of the one class v4 shape, on when `IGNEUM_FAMILY_GATE` is set in the environment of a
+/// harness run and never on a chain path. The family: the shadow block in {64, 128, 256} instructions at the same
+/// 6,912 instructions per iteration, the mixer multiplier in {4, 8, 16}, the read width the era's draw over {1, 4}
+/// words (the mix one-hot on the drawn width), the rest the class v4 base with the state flag set aside.
+pub fn is_family_shape(class: &LoadClass) -> bool {
+ let sh = match class.shadow {
+ Some(s) => s,
+ None => return false,
+ };
+ if !matches!(sh.instrs, 64 | 128 | 256) || sh.instrs as usize * sh.reps as usize != V4_SHADOW_INSTRS as usize * crate::generator::V4_SHADOW_REPS as usize {
+ return false;
+ }
+ if !matches!(class.mixer_mult, 4 | 8 | 16) {
+ return false;
+ }
+ LoadClass { era: None, shadow: None, state: false, mixer_mult: 8, mix: V4_CLASS.mix, ..*class } == LoadClass { shadow: None, ..V4_CLASS }
+}
+
+fn family_gate_on() -> bool {
+ static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
+ *ON.get_or_init(|| std::env::var_os("IGNEUM_FAMILY_GATE").is_some())
+}
+
/// One pass of the dataflow freshness over the base program then the shadow block (the order of one iteration),
/// from `fresh`; `check` reports the first load that reads a register that is not fresh. The rule (AP-F8-1,
/// `docs/analysis/ca3-v4-uniform.md`): a load leaves its destination fresh only if its source was (a saturated
@@ -1262,4 +1382,177 @@ mod tests {
assert!(check(&generate(s)).is_ok());
}
}
+
+ /// Class v6 family-gate harness (8 October 2026, `docs/analysis/class-v6/family-gate.md`): one drawn era per seed of a
+ /// label space, every parameter of the family drawn from the era's own stream (the shadow block shape in {64, 128,
+ /// 256}, the mixer multiplier in {4, 8, 16}, the read width over {1, 4} words through the era draw, the ten non-load
+ /// weights perturbed within B points with shuffle and mulhi never raised), the chain draw of that era's epoch
+ /// through the real rule with the first failing part of every candidate, then on the accepted program the per-site
+ /// statistics at the rule's own 2^20 sample: the (c'') ratio, the largest 256-item bucket, the index-bit bias.
+ /// One TSV row per era to `IGNEUM_FG_OUT`. Pins for the strata: `IGNEUM_FG_SHAPE`, `IGNEUM_FG_MIXER`,
+ /// `IGNEUM_FG_WIDTH`, `IGNEUM_FG_B` (default 4), `IGNEUM_FG_LOSSY_CAP` (or, mul and mulhi at +B: the lossy corner),
+ /// `IGNEUM_FG_LABEL` (default `igneum-family-gate`). Requires `IGNEUM_FAMILY_GATE=1` in the environment.
+ #[test]
+ #[ignore]
+ fn family_gate_era_census() {
+ use crate::generator::{set_family_weights, LoadClass, ShadowClass, NONLOAD_WEIGHTS, V5_CLASS, MAX_ATTEMPTS_V4};
+ use crate::seed::seed_words_from_bytes;
+ use std::io::Write;
+ use std::sync::atomic::{AtomicU32, Ordering};
+ use std::sync::Mutex;
+ assert!(family_gate_on(), "IGNEUM_FAMILY_GATE=1 is required");
+ let env_u = |k: &str, d: u32| std::env::var(k).ok().and_then(|v| v.parse().ok()).unwrap_or(d);
+ let seeds = env_u("IGNEUM_FG_SEEDS", 1000);
+ let from = env_u("IGNEUM_FG_FROM", 0);
+ let threads = env_u("IGNEUM_FG_THREADS", 32) as usize;
+ let b_pts = env_u("IGNEUM_FG_B", 4) as i64;
+ let label = std::env::var("IGNEUM_FG_LABEL").unwrap_or_else(|_| "igneum-family-gate".to_string());
+ let pin_shape = std::env::var("IGNEUM_FG_SHAPE").ok().and_then(|v| v.parse::<u16>().ok());
+ let pin_mixer = std::env::var("IGNEUM_FG_MIXER").ok().and_then(|v| v.parse::<u8>().ok());
+ let pin_width = std::env::var("IGNEUM_FG_WIDTH").ok().and_then(|v| v.parse::<u8>().ok());
+ let lossy_cap = std::env::var_os("IGNEUM_FG_LOSSY_CAP").is_some();
+ let out_path = std::env::var("IGNEUM_FG_OUT").unwrap_or_else(|_| "family-gate.tsv".to_string());
+ let out = Mutex::new(std::fs::File::create(&out_path).expect("IGNEUM_FG_OUT"));
+ let wnames: Vec<String> = NONLOAD_WEIGHTS.iter().map(|(o, _)| format!("w_{o:?}").to_lowercase()).collect();
+ writeln!(out.lock().unwrap(), "k\tshape\treps\tmixer\twidth\tR\tM\tpos\t{}\tattempt\tcandidates\ta_prime\ta\tb\tc_const\tc_lane\tc_sat\tc_bias\tc_distinct\tc1_sat_source\tc2_low_entropy\tc3_hot_item\tmin_ratio\tmin_site\ttop_count_max\tbucket_ratio_max\tbucket_site\tbit_z_max\tbit_site\tbit\tsecs", wnames.join("\t")).unwrap();
+ let part_ix = |r: &Reject| -> usize {
+ match r {
+ Reject::UnfreshLoadSource { .. } => 0,
+ Reject::StaleLoadSource { .. } => 1,
+ Reject::NoInjectingWrite { .. } => 2,
+ Reject::ConstantBit { .. } => 3,
+ Reject::LaneConstantSite { .. } => 4,
+ Reject::Saturated { .. } => 5,
+ Reject::OutputBias { .. } => 6,
+ Reject::DistinctAddresses { .. } => 7,
+ Reject::SaturatedSource { .. } => 8,
+ Reject::LowEntropySite { .. } | Reject::RepeatedSource { .. } => 9,
+ Reject::HotItemSite { .. } => 10,
+ }
+ };
+ let next = AtomicU32::new(from);
+ let t0 = std::time::Instant::now();
+ let done = AtomicU32::new(0);
+ std::thread::scope(|sc| {
+ for _ in 0..threads {
+ sc.spawn(|| loop {
+ let k = next.fetch_add(1, Ordering::Relaxed);
+ if k >= from + seeds {
+ break;
+ }
+ let ts = std::time::Instant::now();
+ let w = |s: String| -> Vec<u8> { seed_words_from_bytes(s.as_bytes()).iter().flat_map(|x| x.to_le_bytes()).collect() };
+ let epoch = w(format!("{label}/program/{k}"));
+ let era = w(format!("{label}/era/{k}"));
+ // the family's draws from the era's own stream, in a fixed order, each consumed whether pinned or not
+ let dw = seed_words_from_bytes(&[b"igneum-family-gate/draw/".as_slice(), era.as_slice()].concat());
+ let mut rng = SplitMix64::new(dw[0] as u64 | ((dw[1] as u64) << 32));
+ let shapes = [64u16, 128, 256];
+ let shape = pin_shape.unwrap_or(shapes[rng.below(3) as usize]);
+ let mixers = [4u8, 8, 16];
+ let mixer = pin_mixer.unwrap_or(mixers[rng.below(3) as usize]);
+ let mut weights = NONLOAD_WEIGHTS;
+ let mut raw = [0i64; 10];
+ for (i, (op, wgt)) in NONLOAD_WEIGHTS.iter().enumerate() {
+ let mut d = rng.below((2 * b_pts + 1) as u64) as i64 - b_pts;
+ if matches!(op, Op::Shfl | Op::MulHi) && d > 0 {
+ d = 0;
+ }
+ if lossy_cap && matches!(op, Op::Or | Op::Mul | Op::MulHi) {
+ d = b_pts;
+ }
+ raw[i] = (*wgt as i64 + d).max(1);
+ }
+ // renormalise to 75 by largest remainder
+ let total: i64 = raw.iter().sum();
+ let mut floors = [0u64; 10];
+ let mut rems: Vec<(i64, usize)> = Vec::new();
+ let mut sum = 0u64;
+ for i in 0..10 {
+ floors[i] = ((raw[i] * 75) / total) as u64;
+ rems.push((((raw[i] * 75) % total), i));
+ sum += floors[i];
+ }
+ rems.sort_by(|x, y| y.0.cmp(&x.0).then(x.1.cmp(&y.1)));
+ let mut short = 75 - sum;
+ for &(_, i) in &rems {
+ if short == 0 {
+ break;
+ }
+ floors[i] += 1;
+ short -= 1;
+ }
+ for i in 0..10 {
+ weights[i].1 = floors[i];
+ }
+ set_family_weights(Some(weights));
+ let reps = (V4_SHADOW_INSTRS as u32 * crate::generator::V4_SHADOW_REPS as u32 / shape as u32) as u16;
+ let base = LoadClass { shadow: Some(ShadowClass { instrs: shape, reps }), mixer_mult: mixer, ..V5_CLASS };
+ let allowed: &[u8] = match pin_width {
+ Some(1) => &[1],
+ Some(4) => &[4],
+ _ => &[1, 4],
+ };
+ let class = LoadClass::era(base, &era, allowed);
+ let e = class.era.unwrap();
+ let lbl = f8_label(&epoch);
+ let mut parts = [0u32; 11];
+ let mut accepted: Option<(u32, Program)> = None;
+ for attempt in 0..MAX_ATTEMPTS_V4 {
+ let c = candidate_class(&lbl, &epoch, attempt, class);
+ match check(&c) {
+ Ok(_) => {
+ accepted = Some((attempt, c));
+ break;
+ }
+ Err(r) => parts[part_ix(&r)] += 1,
+ }
+ }
+ set_family_weights(None);
+ let candidates: u32 = parts.iter().sum::<u32>() + accepted.is_some() as u32;
+ let (attempt, stats_row) = match &accepted {
+ Some((att, p)) => {
+ let st = family_site_stats(p, ACCEPT_UNITS_DISTINCT_V4).expect("the accepted program runs");
+ let n = (ACCEPT_UNITS_DISTINCT_V4 * LANES * ITERATIONS) as f64;
+ let loads: Vec<&Instr> = p.instrs.iter().filter(|i| i.op.is_load()).collect();
+ let (mut min_r, mut min_s) = (f64::MAX, 0usize);
+ let (mut bmax, mut bsite) = (0.0f64, 0usize);
+ let (mut zmax, mut zsite, mut zbit) = (0.0f64, 0usize, 0u8);
+ let mut top = 0u32;
+ for (s, fs) in st.iter().enumerate() {
+ let r = site_ratio(fs.base.distinct, n, site_window_words(loads[s]));
+ if r < min_r {
+ min_r = r;
+ min_s = s;
+ }
+ if fs.bucket_ratio > bmax {
+ bmax = fs.bucket_ratio;
+ bsite = s;
+ }
+ if fs.bit_z.abs() > zmax.abs() {
+ zmax = fs.bit_z;
+ zsite = s;
+ zbit = fs.bit;
+ }
+ top = top.max(fs.base.top_count);
+ }
+ (*att as i64, format!("{min_r:.5}\t{min_s}\t{top}\t{bmax:.3}\t{bsite}\t{zmax:.2}\t{zsite}\t{zbit}"))
+ }
+ None => (-1, "\t\t\t\t\t\t\t".to_string()),
+ };
+ let wcols: Vec<String> = weights.iter().map(|(_, x)| x.to_string()).collect();
+ let pcols: Vec<String> = parts.iter().map(|x| x.to_string()).collect();
+ let row = format!("{k}\t{shape}\t{reps}\t{mixer}\t{}\t{}\t{:08x}\t{:?}\t{}\t{attempt}\t{candidates}\t{}\t{stats_row}\t{:.1}", e.width_words, e.stride_rot, e.stride_mul, e.pos, wcols.join("\t"), pcols.join("\t"), ts.elapsed().as_secs_f64());
+ writeln!(out.lock().unwrap(), "{row}").unwrap();
+ let d = done.fetch_add(1, Ordering::Relaxed) + 1;
+ if d % 100 == 0 {
+ println!("family_gate_era_census: {d} eras in {:.0} s", t0.elapsed().as_secs_f64());
+ out.lock().unwrap().flush().unwrap();
+ }
+ });
+ }
+ });
+ out.lock().unwrap().flush().unwrap();
+ println!("family_gate_era_census: {} eras {from}..{} in {:.0} s on {threads} threads -> {out_path}", done.load(Ordering::Relaxed), from + seeds, t0.elapsed().as_secs_f64());
+ }
}
diff --git a/igneum-pow/src/generator.rs b/igneum-pow/src/generator.rs
index 3f2d6723..00730eac 100644
--- a/igneum-pow/src/generator.rs
+++ b/igneum-pow/src/generator.rs
@@ -1316,6 +1316,18 @@ pub const NONLOAD_WEIGHTS: [(Op, u64); 10] = [
];
/// Version 1 weights (retired). Sum 100, load at 25 percent.
+thread_local! {
+ static FAMILY_WEIGHTS: std::cell::Cell<Option<[(Op, u64); 10]>> = const { std::cell::Cell::new(None) };
+}
+/// Class v6 family-gate harness (8 October 2026): the ten non-load weights this thread's draws use when set, else
+/// [`NONLOAD_WEIGHTS`]. Set only by the harness census (`accept::tests::family_gate_era_census`), never on a chain path.
+pub fn set_family_weights(w: Option<[(Op, u64); 10]>) {
+ FAMILY_WEIGHTS.with(|c| c.set(w));
+}
+pub fn family_weights() -> [(Op, u64); 10] {
+ FAMILY_WEIGHTS.with(|c| c.get()).unwrap_or(NONLOAD_WEIGHTS)
+}
+
pub const OP_WEIGHTS: [(Op, u64); 11] = [
(Op::Load, 25),
(Op::Add, 12),
@@ -1436,8 +1448,9 @@ pub fn candidate_from_words_class(
// era set aside) on EVERY draw path, era or not, so a census through candidate_class reads the same stream as
// the chain; v2, v3 and every other class take no part. The draw order and the stream are otherwise the same.
// class v5 (docs/design/class-v5-stored-state.md) draws under the same rule: its state flag is set aside here too
- let source_rule_v4 = matches!(class.shadow, Some(ShadowClass { instrs: V4_SHADOW_INSTRS, .. }))
- && LoadClass { era: None, shadow: None, state: false, ..class } == LoadClass { shadow: None, ..V4_CLASS };
+ // class v6 family-gate harness (8 October 2026): the same predicate as the acceptance's, generalised to the
+ // family's shapes only when IGNEUM_FAMILY_GATE is set (never on a chain path; see accept::is_family_shape).
+ let source_rule_v4 = crate::accept::is_class_v4_shape(&class);
let mut fresh = [false; 8];
let mut fresh_value = [true; 8];
// the shared-operand idiom (AP-F8-1, sub-version 3): after `or d |= s`, a later `xor d ^= s` or `sub d -= s` with
@@ -1449,7 +1462,7 @@ pub fn candidate_from_words_class(
for k in 0..INSTR_COUNT {
let mut roll = rng.below(75);
let mut op = Op::Add;
- for &(o, w) in &NONLOAD_WEIGHTS {
+ for &(o, w) in &family_weights() {
if roll < w {
op = o;
break;
@@ -1556,7 +1569,7 @@ pub fn candidate_from_words_class(
for _ in 0..sh.instrs {
let mut roll = rng.below(75);
let mut op = Op::Add;
- for &(o, w) in &NONLOAD_WEIGHTS {
+ for &(o, w) in &family_weights() {
if roll < w {
op = o;
break;
--
2.41.0
From 1d5f551e0bec6840377c5e5bc3b98fe00e2cb5fa Mon Sep 17 00:00:00 2001
From: igneum-labs <337424239+[removed]>
Date: Thu, 8 Oct 2026 11:22:50 +0100
Subject: [PATCH 2/5] family-gate harness: the bucket excess in sigma and each
site's window draw beside the ratio (a clean full-window site reads a ratio
of 2.1 at +4.4 sigma, so the ratio alone cannot carry a bound); the
retired-weights doc comment back on its item
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
igneum-pow/src/accept.rs | 22 +++++++++++++++-------
igneum-pow/src/generator.rs | 2 +-
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/igneum-pow/src/accept.rs b/igneum-pow/src/accept.rs
index 7035c82e..f9febaab 100644
--- a/igneum-pow/src/accept.rs
+++ b/igneum-pow/src/accept.rs
@@ -254,7 +254,12 @@ pub fn site_window_words(ins: &Instr) -> u64 {
pub struct FamilySiteStats {
pub base: SiteIndexStats,
pub bucket_ratio: f64,
+ /// the same excess in sigma of the bucket's own expectation (a clean full-window site's maximum over 65,536
+ /// Poisson(16) buckets is about +4.4 sigma, a ratio of 2.1; the quarter-bit tail of 8 October read 3.1x to 5.6x)
+ pub bucket_z: f64,
pub bucket_id: u32,
+ /// the site's window draw `k_off` (0 the dataset, 1 a half, 2 a quarter)
+ pub win: u8,
pub bit_z: f64,
pub bit: u8,
}
@@ -332,7 +337,7 @@ pub fn family_site_stats(p: &Program, units: usize) -> Result<Vec<FamilySiteStat
}
i = j;
}
- out.push(FamilySiteStats { base: st, bucket_ratio: bmax as f64 / expect, bucket_id: bid, bit_z, bit });
+ out.push(FamilySiteStats { base: st, bucket_ratio: bmax as f64 / expect, bucket_z: (bmax as f64 - expect) / expect.sqrt(), bucket_id: bid, win: k as u8, bit_z, bit });
}
Ok(out)
}
@@ -1414,7 +1419,7 @@ mod tests {
let out_path = std::env::var("IGNEUM_FG_OUT").unwrap_or_else(|_| "family-gate.tsv".to_string());
let out = Mutex::new(std::fs::File::create(&out_path).expect("IGNEUM_FG_OUT"));
let wnames: Vec<String> = NONLOAD_WEIGHTS.iter().map(|(o, _)| format!("w_{o:?}").to_lowercase()).collect();
- writeln!(out.lock().unwrap(), "k\tshape\treps\tmixer\twidth\tR\tM\tpos\t{}\tattempt\tcandidates\ta_prime\ta\tb\tc_const\tc_lane\tc_sat\tc_bias\tc_distinct\tc1_sat_source\tc2_low_entropy\tc3_hot_item\tmin_ratio\tmin_site\ttop_count_max\tbucket_ratio_max\tbucket_site\tbit_z_max\tbit_site\tbit\tsecs", wnames.join("\t")).unwrap();
+ writeln!(out.lock().unwrap(), "k\tshape\treps\tmixer\twidth\tR\tM\tpos\t{}\tattempt\tcandidates\ta_prime\ta\tb\tc_const\tc_lane\tc_sat\tc_bias\tc_distinct\tc1_sat_source\tc2_low_entropy\tc3_hot_item\tmin_ratio\tmin_site\ttop_count_max\tbucket_ratio_max\tbucket_z_max\tbucket_site\tbucket_win\tbit_z_max\tbit_site\tbit_win\tbit\tsecs", wnames.join("\t")).unwrap();
let part_ix = |r: &Reject| -> usize {
match r {
Reject::UnfreshLoadSource { .. } => 0,
@@ -1516,8 +1521,8 @@ mod tests {
let n = (ACCEPT_UNITS_DISTINCT_V4 * LANES * ITERATIONS) as f64;
let loads: Vec<&Instr> = p.instrs.iter().filter(|i| i.op.is_load()).collect();
let (mut min_r, mut min_s) = (f64::MAX, 0usize);
- let (mut bmax, mut bsite) = (0.0f64, 0usize);
- let (mut zmax, mut zsite, mut zbit) = (0.0f64, 0usize, 0u8);
+ let (mut bmax, mut bz, mut bsite, mut bwin) = (0.0f64, 0.0f64, 0usize, 0u8);
+ let (mut zmax, mut zsite, mut zbit, mut zwin) = (0.0f64, 0usize, 0u8, 0u8);
let mut top = 0u32;
for (s, fs) in st.iter().enumerate() {
let r = site_ratio(fs.base.distinct, n, site_window_words(loads[s]));
@@ -1525,20 +1530,23 @@ mod tests {
min_r = r;
min_s = s;
}
- if fs.bucket_ratio > bmax {
+ if fs.bucket_z > bz {
bmax = fs.bucket_ratio;
+ bz = fs.bucket_z;
bsite = s;
+ bwin = fs.win;
}
if fs.bit_z.abs() > zmax.abs() {
zmax = fs.bit_z;
zsite = s;
zbit = fs.bit;
+ zwin = fs.win;
}
top = top.max(fs.base.top_count);
}
- (*att as i64, format!("{min_r:.5}\t{min_s}\t{top}\t{bmax:.3}\t{bsite}\t{zmax:.2}\t{zsite}\t{zbit}"))
+ (*att as i64, format!("{min_r:.5}\t{min_s}\t{top}\t{bmax:.3}\t{bz:.2}\t{bsite}\t{bwin}\t{zmax:.2}\t{zsite}\t{zwin}\t{zbit}"))
}
- None => (-1, "\t\t\t\t\t\t\t".to_string()),
+ None => (-1, "\t\t\t\t\t\t\t\t\t\t".to_string()),
};
let wcols: Vec<String> = weights.iter().map(|(_, x)| x.to_string()).collect();
let pcols: Vec<String> = parts.iter().map(|x| x.to_string()).collect();
diff --git a/igneum-pow/src/generator.rs b/igneum-pow/src/generator.rs
index 00730eac..6e611d45 100644
--- a/igneum-pow/src/generator.rs
+++ b/igneum-pow/src/generator.rs
@@ -1315,7 +1315,6 @@ pub const NONLOAD_WEIGHTS: [(Op, u64); 10] = [
(Op::Or, 4),
];
-/// Version 1 weights (retired). Sum 100, load at 25 percent.
thread_local! {
static FAMILY_WEIGHTS: std::cell::Cell<Option<[(Op, u64); 10]>> = const { std::cell::Cell::new(None) };
}
@@ -1328,6 +1327,7 @@ pub fn family_weights() -> [(Op, u64); 10] {
FAMILY_WEIGHTS.with(|c| c.get()).unwrap_or(NONLOAD_WEIGHTS)
}
+/// Version 1 weights (retired). Sum 100, load at 25 percent.
pub const OP_WEIGHTS: [(Op, u64); 11] = [
(Op::Load, 25),
(Op::Add, 12),
--
2.41.0
From adce49deea93678b0165fbaa76349a0b347794c5 Mon Sep 17 00:00:00 2001
From: igneum-labs <337424239+[removed]>
Date: Thu, 8 Oct 2026 11:33:16 +0100
Subject: [PATCH 3/5] family-gate harness: a pinned width is a two-entry
allowed set (the one-entry set is LoadClass::era's pinned path and redraws to
the base's 1 word: the first width-4 stratum ran at width 1, void)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
igneum-pow/src/accept.rs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/igneum-pow/src/accept.rs b/igneum-pow/src/accept.rs
index f9febaab..c92a54ce 100644
--- a/igneum-pow/src/accept.rs
+++ b/igneum-pow/src/accept.rs
@@ -1493,9 +1493,12 @@ mod tests {
set_family_weights(Some(weights));
let reps = (V4_SHADOW_INSTRS as u32 * crate::generator::V4_SHADOW_REPS as u32 / shape as u32) as u16;
let base = LoadClass { shadow: Some(ShadowClass { instrs: shape, reps }), mixer_mult: mixer, ..V5_CLASS };
+ // a one-entry set is the pinned-width path of LoadClass::era (the mix stays the base's and the draw is
+ // redrawn to the base's widest, 1 word), so a pin is a two-entry set of one value: the era draw then
+ // sets the mix one-hot on that width as it does for the drawn set
let allowed: &[u8] = match pin_width {
- Some(1) => &[1],
- Some(4) => &[4],
+ Some(1) => &[1, 1],
+ Some(4) => &[4, 4],
_ => &[1, 4],
};
let class = LoadClass::era(base, &era, allowed);
--
2.41.0
From a1a7e1318961869b0ef074ec753e1bb45544127b Mon Sep 17 00:00:00 2001
From: igneum-labs <337424239+[removed]>
Date: Thu, 8 Oct 2026 11:41:57 +0100
Subject: [PATCH 4/5] family-gate harness: IGNEUM_FG_LOSSY_BASE, the proposed
band (B on the injecting families only, or/mul/mulhi never raised)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
igneum-pow/src/accept.rs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/igneum-pow/src/accept.rs b/igneum-pow/src/accept.rs
index c92a54ce..d6551ec5 100644
--- a/igneum-pow/src/accept.rs
+++ b/igneum-pow/src/accept.rs
@@ -1416,6 +1416,9 @@ mod tests {
let pin_mixer = std::env::var("IGNEUM_FG_MIXER").ok().and_then(|v| v.parse::<u8>().ok());
let pin_width = std::env::var("IGNEUM_FG_WIDTH").ok().and_then(|v| v.parse::<u8>().ok());
let lossy_cap = std::env::var_os("IGNEUM_FG_LOSSY_CAP").is_some();
+ // the proposed band after the 12:00 BST reading of 8 October: B on the injecting families only, the three lossy
+ // families (or, mul, mulhi) never raised above their base
+ let lossy_base = std::env::var_os("IGNEUM_FG_LOSSY_BASE").is_some();
let out_path = std::env::var("IGNEUM_FG_OUT").unwrap_or_else(|_| "family-gate.tsv".to_string());
let out = Mutex::new(std::fs::File::create(&out_path).expect("IGNEUM_FG_OUT"));
let wnames: Vec<String> = NONLOAD_WEIGHTS.iter().map(|(o, _)| format!("w_{o:?}").to_lowercase()).collect();
@@ -1466,6 +1469,9 @@ mod tests {
if lossy_cap && matches!(op, Op::Or | Op::Mul | Op::MulHi) {
d = b_pts;
}
+ if lossy_base && matches!(op, Op::Or | Op::Mul | Op::MulHi) && d > 0 {
+ d = 0;
+ }
raw[i] = (*wgt as i64 + d).max(1);
}
// renormalise to 75 by largest remainder
--
2.41.0
From e94f4db05dd3fd76e356de8bdb4de70455144e5c Mon Sep 17 00:00:00 2001
From: igneum-labs <337424239+[removed]>
Date: Thu, 8 Oct 2026 11:43:12 +0100
Subject: [PATCH 5/5] family-gate harness: a pinned width builds the class by
hand (era_draw over the one-entry set, the mix one-hot); the two-entry set
tripped era_draw's ascending assert (w4b exit 101)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
igneum-pow/src/accept.rs | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/igneum-pow/src/accept.rs b/igneum-pow/src/accept.rs
index d6551ec5..f38e4399 100644
--- a/igneum-pow/src/accept.rs
+++ b/igneum-pow/src/accept.rs
@@ -1500,14 +1500,20 @@ mod tests {
let reps = (V4_SHADOW_INSTRS as u32 * crate::generator::V4_SHADOW_REPS as u32 / shape as u32) as u16;
let base = LoadClass { shadow: Some(ShadowClass { instrs: shape, reps }), mixer_mult: mixer, ..V5_CLASS };
// a one-entry set is the pinned-width path of LoadClass::era (the mix stays the base's and the draw is
- // redrawn to the base's widest, 1 word), so a pin is a two-entry set of one value: the era draw then
- // sets the mix one-hot on that width as it does for the drawn set
- let allowed: &[u8] = match pin_width {
- Some(1) => &[1, 1],
- Some(4) => &[4, 4],
- _ => &[1, 4],
+ // redrawn to the base's widest, 1 word) and the set must be strictly ascending, so a pinned width is
+ // built by hand: the era drawn over the one-entry set and the mix one-hot on that width, as the
+ // drawn-set path does
+ let class = match pin_width {
+ Some(w) if w == 1 || w == 4 => {
+ let mut c = base;
+ let i = crate::generator::WIDTH_WORDS.iter().position(|&x| x == w).unwrap();
+ c.mix = [0, 0, 0];
+ c.mix[i] = 100;
+ c.era = Some(crate::generator::era_draw(&era, &[w]));
+ c
+ }
+ _ => LoadClass::era(base, &era, &[1, 4]),
};
- let class = LoadClass::era(base, &era, allowed);
let e = class.era.unwrap();
let lbl = f8_label(&epoch);
let mut parts = [0u32; 11];
--
2.41.0

View file

@ -0,0 +1,41 @@
binary 9b7f764acb5bf1bc commit fg2 test family_gate_era_census from 0 seeds 3000 threads 16 start 2026-10-08T10:23:28Z
lease: holding 16 pool cores (80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, waited 1 s, class measure): family gate: family_gate_era_census lossy seeds 0+3000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 95 s
family_gate_era_census: 200 eras in 169 s
family_gate_era_census: 300 eras in 248 s
family_gate_era_census: 400 eras in 324 s
family_gate_era_census: 500 eras in 401 s
family_gate_era_census: 600 eras in 475 s
family_gate_era_census: 700 eras in 551 s
family_gate_era_census: 800 eras in 625 s
family_gate_era_census: 900 eras in 705 s
family_gate_era_census: 1000 eras in 780 s
family_gate_era_census: 1100 eras in 853 s
family_gate_era_census: 1200 eras in 934 s
family_gate_era_census: 1300 eras in 1008 s
family_gate_era_census: 1400 eras in 1080 s
family_gate_era_census: 1500 eras in 1142 s
family_gate_era_census: 1600 eras in 1200 s
family_gate_era_census: 1700 eras in 1261 s
family_gate_era_census: 1800 eras in 1324 s
family_gate_era_census: 1900 eras in 1392 s
family_gate_era_census: 2000 eras in 1457 s
family_gate_era_census: 2100 eras in 1524 s
family_gate_era_census: 2200 eras in 1589 s
family_gate_era_census: 2300 eras in 1649 s
family_gate_era_census: 2400 eras in 1717 s
family_gate_era_census: 2500 eras in 1781 s
family_gate_era_census: 2600 eras in 1846 s
family_gate_era_census: 2700 eras in 1920 s
family_gate_era_census: 2800 eras in 1995 s
family_gate_era_census: 2900 eras in 2066 s
family_gate_era_census: 3000 eras in 2136 s
family_gate_era_census: 3000 eras 0..3000 in 2136 s on 16 threads -> /srv/builds/_adv-family-gate/logs/lossy-family_gate_era_census-0-3000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 2136.31s
lease: released 16 pool cores after 2137 s, exit 0
end 2026-10-08T10:59:05Z rc 0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
binary e7a50f8dcf57a14b commit fg5 test family_gate_era_census from 0 seeds 3000 threads 16 start 2026-10-08T10:45:36Z
lease: holding 16 pool cores (16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, waited 0 s, class measure): family gate: family_gate_era_census lossybase seeds 0+3000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 34 s
family_gate_era_census: 200 eras in 65 s
family_gate_era_census: 300 eras in 95 s
family_gate_era_census: 400 eras in 128 s
family_gate_era_census: 500 eras in 160 s
family_gate_era_census: 600 eras in 190 s
family_gate_era_census: 700 eras in 222 s
family_gate_era_census: 800 eras in 253 s
family_gate_era_census: 900 eras in 283 s
family_gate_era_census: 1000 eras in 316 s
family_gate_era_census: 1100 eras in 347 s
family_gate_era_census: 1200 eras in 379 s
family_gate_era_census: 1300 eras in 410 s
family_gate_era_census: 1400 eras in 441 s
family_gate_era_census: 1500 eras in 474 s
family_gate_era_census: 1600 eras in 505 s
family_gate_era_census: 1700 eras in 536 s
family_gate_era_census: 1800 eras in 569 s
family_gate_era_census: 1900 eras in 600 s
family_gate_era_census: 2000 eras in 632 s
family_gate_era_census: 2100 eras in 663 s
family_gate_era_census: 2200 eras in 695 s
family_gate_era_census: 2300 eras in 725 s
family_gate_era_census: 2400 eras in 757 s
family_gate_era_census: 2500 eras in 788 s
family_gate_era_census: 2600 eras in 820 s
family_gate_era_census: 2700 eras in 853 s
family_gate_era_census: 2800 eras in 883 s
family_gate_era_census: 2900 eras in 914 s
family_gate_era_census: 3000 eras in 948 s
family_gate_era_census: 3000 eras 0..3000 in 948 s on 16 threads -> /srv/builds/_adv-family-gate/logs/lossybase-family_gate_era_census-0-3000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 947.88s
lease: released 16 pool cores after 947 s, exit 0
end 2026-10-08T11:01:23Z rc 0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,111 @@
binary 9b7f764acb5bf1bc commit fg2 test family_gate_era_census from 0 seeds 10000 threads 32 start 2026-10-08T10:23:28Z
lease: holding 32 pool cores (24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,72,73,74,75,76,77,78,79, waited 1 s, class measure): family gate: family_gate_era_census rand seeds 0+10000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 45 s
family_gate_era_census: 200 eras in 86 s
family_gate_era_census: 300 eras in 121 s
family_gate_era_census: 400 eras in 156 s
family_gate_era_census: 500 eras in 197 s
family_gate_era_census: 600 eras in 231 s
family_gate_era_census: 700 eras in 264 s
family_gate_era_census: 800 eras in 300 s
family_gate_era_census: 900 eras in 334 s
family_gate_era_census: 1000 eras in 370 s
family_gate_era_census: 1100 eras in 404 s
family_gate_era_census: 1200 eras in 437 s
family_gate_era_census: 1300 eras in 472 s
family_gate_era_census: 1400 eras in 507 s
family_gate_era_census: 1500 eras in 543 s
family_gate_era_census: 1600 eras in 579 s
family_gate_era_census: 1700 eras in 615 s
family_gate_era_census: 1800 eras in 651 s
family_gate_era_census: 1900 eras in 690 s
family_gate_era_census: 2000 eras in 726 s
family_gate_era_census: 2100 eras in 761 s
family_gate_era_census: 2200 eras in 796 s
family_gate_era_census: 2300 eras in 832 s
family_gate_era_census: 2400 eras in 867 s
family_gate_era_census: 2500 eras in 903 s
family_gate_era_census: 2600 eras in 940 s
family_gate_era_census: 2700 eras in 976 s
family_gate_era_census: 2800 eras in 1011 s
family_gate_era_census: 2900 eras in 1048 s
family_gate_era_census: 3000 eras in 1081 s
family_gate_era_census: 3100 eras in 1112 s
family_gate_era_census: 3200 eras in 1142 s
family_gate_era_census: 3300 eras in 1170 s
family_gate_era_census: 3400 eras in 1197 s
family_gate_era_census: 3500 eras in 1225 s
family_gate_era_census: 3600 eras in 1255 s
family_gate_era_census: 3700 eras in 1288 s
family_gate_era_census: 3800 eras in 1320 s
family_gate_era_census: 3900 eras in 1352 s
family_gate_era_census: 4000 eras in 1385 s
family_gate_era_census: 4100 eras in 1417 s
family_gate_era_census: 4200 eras in 1452 s
family_gate_era_census: 4300 eras in 1485 s
family_gate_era_census: 4400 eras in 1516 s
family_gate_era_census: 4500 eras in 1548 s
family_gate_era_census: 4600 eras in 1580 s
family_gate_era_census: 4700 eras in 1611 s
family_gate_era_census: 4800 eras in 1643 s
family_gate_era_census: 4900 eras in 1673 s
family_gate_era_census: 5000 eras in 1707 s
family_gate_era_census: 5100 eras in 1740 s
family_gate_era_census: 5200 eras in 1769 s
family_gate_era_census: 5300 eras in 1800 s
family_gate_era_census: 5400 eras in 1831 s
family_gate_era_census: 5500 eras in 1863 s
family_gate_era_census: 5600 eras in 1899 s
family_gate_era_census: 5700 eras in 1936 s
family_gate_era_census: 5800 eras in 1974 s
family_gate_era_census: 5900 eras in 2008 s
family_gate_era_census: 6000 eras in 2042 s
family_gate_era_census: 6100 eras in 2077 s
family_gate_era_census: 6200 eras in 2115 s
family_gate_era_census: 6300 eras in 2145 s
family_gate_era_census: 6400 eras in 2172 s
family_gate_era_census: 6500 eras in 2195 s
family_gate_era_census: 6600 eras in 2219 s
family_gate_era_census: 6700 eras in 2244 s
family_gate_era_census: 6800 eras in 2269 s
family_gate_era_census: 6900 eras in 2294 s
family_gate_era_census: 7000 eras in 2318 s
family_gate_era_census: 7100 eras in 2344 s
family_gate_era_census: 7200 eras in 2370 s
family_gate_era_census: 7300 eras in 2395 s
family_gate_era_census: 7400 eras in 2419 s
family_gate_era_census: 7500 eras in 2444 s
family_gate_era_census: 7600 eras in 2468 s
family_gate_era_census: 7700 eras in 2491 s
family_gate_era_census: 7800 eras in 2515 s
family_gate_era_census: 7900 eras in 2539 s
family_gate_era_census: 8000 eras in 2563 s
family_gate_era_census: 8100 eras in 2585 s
family_gate_era_census: 8200 eras in 2607 s
family_gate_era_census: 8300 eras in 2629 s
family_gate_era_census: 8400 eras in 2650 s
family_gate_era_census: 8500 eras in 2673 s
family_gate_era_census: 8600 eras in 2695 s
family_gate_era_census: 8700 eras in 2715 s
family_gate_era_census: 8800 eras in 2734 s
family_gate_era_census: 8900 eras in 2755 s
family_gate_era_census: 9000 eras in 2776 s
family_gate_era_census: 9100 eras in 2797 s
family_gate_era_census: 9200 eras in 2817 s
family_gate_era_census: 9300 eras in 2838 s
family_gate_era_census: 9400 eras in 2859 s
family_gate_era_census: 9500 eras in 2880 s
family_gate_era_census: 9600 eras in 2900 s
family_gate_era_census: 9700 eras in 2919 s
family_gate_era_census: 9800 eras in 2938 s
family_gate_era_census: 9900 eras in 2958 s
family_gate_era_census: 10000 eras in 2977 s
family_gate_era_census: 10000 eras 0..10000 in 2977 s on 32 threads -> /srv/builds/_adv-family-gate/logs/rand-family_gate_era_census-0-10000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 2976.75s
lease: released 32 pool cores after 2977 s, exit 0
end 2026-10-08T11:13:05Z rc 0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
binary 9b7f764acb5bf1bc commit fg2 test family_gate_era_census from 0 seeds 3000 threads 24 start 2026-10-08T10:23:52Z
lease: holding 24 pool cores (8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, waited 0 s, class measure): family gate: family_gate_era_census shape64 seeds 0+3000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 26 s
family_gate_era_census: 200 eras in 48 s
family_gate_era_census: 300 eras in 73 s
family_gate_era_census: 400 eras in 96 s
family_gate_era_census: 500 eras in 120 s
family_gate_era_census: 600 eras in 144 s
family_gate_era_census: 700 eras in 167 s
family_gate_era_census: 800 eras in 188 s
family_gate_era_census: 900 eras in 211 s
family_gate_era_census: 1000 eras in 234 s
family_gate_era_census: 1100 eras in 256 s
family_gate_era_census: 1200 eras in 281 s
family_gate_era_census: 1300 eras in 304 s
family_gate_era_census: 1400 eras in 327 s
family_gate_era_census: 1500 eras in 350 s
family_gate_era_census: 1600 eras in 372 s
family_gate_era_census: 1700 eras in 395 s
family_gate_era_census: 1800 eras in 418 s
family_gate_era_census: 1900 eras in 442 s
family_gate_era_census: 2000 eras in 464 s
family_gate_era_census: 2100 eras in 488 s
family_gate_era_census: 2200 eras in 510 s
family_gate_era_census: 2300 eras in 533 s
family_gate_era_census: 2400 eras in 556 s
family_gate_era_census: 2500 eras in 578 s
family_gate_era_census: 2600 eras in 602 s
family_gate_era_census: 2700 eras in 625 s
family_gate_era_census: 2800 eras in 649 s
family_gate_era_census: 2900 eras in 673 s
family_gate_era_census: 3000 eras in 695 s
family_gate_era_census: 3000 eras 0..3000 in 695 s on 24 threads -> /srv/builds/_adv-family-gate/logs/shape64-family_gate_era_census-0-3000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 694.93s
lease: released 24 pool cores after 695 s, exit 0
end 2026-10-08T10:35:27Z rc 0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
binary 71b25e59d765561c commit fg1 test family_gate_era_census from 0 seeds 16 threads 8 start 2026-10-08T10:20:51Z
lease: holding 8 pool cores (8,9,10,11,12,13,14,15, waited 0 s, class measure): family gate: family_gate_era_census smoke seeds 0+16
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 16 eras 0..16 in 22 s on 8 threads -> /srv/builds/_adv-family-gate/logs/smoke-family_gate_era_census-0-16.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 21.91s
Terminated
lease: released 8 pool cores after 22 s, exit 0
end 2026-10-08T10:21:13Z rc 0

View file

@ -0,0 +1,17 @@
k shape reps mixer width R M pos w_add w_xor w_mul w_mad w_shfl w_rotl w_sub w_mulhi w_rotr w_or attempt candidates a_prime a b c_const c_lane c_sat c_bias c_distinct c1_sat_source c2_low_entropy c3_hot_item min_ratio min_site top_count_max bucket_ratio_max bucket_site bit_z_max bit_site bit secs
6 256 27 8 1 18 f5374043 [4, 7, 11, 14] 17 8 4 10 8 8 6 2 4 8 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99925 7 3 2.344 7 256.38 7 18 8.1
1 256 27 16 4 6 50b5995b [0, 1, 7, 10] 11 12 11 7 5 7 10 3 3 6 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99936 0 5 2.312 2 -223.84 0 6 8.9
3 64 108 8 1 28 0ea25b7d [5, 6, 7, 13] 8 10 13 6 4 3 10 6 9 6 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99989 13 3 2.312 2 -8.62 14 0 8.9
4 256 27 4 1 14 b0d09763 [0, 6, 8, 11] 14 12 5 5 6 10 8 5 7 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99969 7 4 2.375 1 -3.10 0 24 9.1
2 128 54 8 1 10 8833036b [0, 5, 11, 13] 10 9 9 4 6 4 10 5 11 7 6 7 5 1 0 0 0 0 0 0 0 0 0 0.99994 0 4 2.375 7 -3.21 2 20 9.2
5 64 108 16 1 26 7f8a4ac1 [0, 9, 10, 13] 12 15 9 13 9 5 5 3 3 1 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99944 7 3 2.438 13 -440.40 7 26 9.6
0 128 54 4 4 22 78e9ab5b [0, 1, 3, 12] 12 9 8 5 9 12 3 7 9 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99995 4 4 2.375 4 -2.99 0 6 10.3
7 256 27 4 1 17 c8678a37 [0, 6, 13, 15] 14 12 6 5 7 9 7 3 7 5 1 2 0 0 0 0 0 0 0 0 0 1 0 0.99544 4 5 13.938 4 -468.09 3 17 12.7
8 64 108 4 4 25 71a1775d [0, 1, 7, 15] 17 10 10 7 5 4 5 7 9 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99993 10 5 2.312 10 2.97 12 6 7.9
12 256 27 8 1 5 da7c079d [3, 5, 6, 12] 14 9 9 9 7 3 7 6 4 7 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99985 6 4 2.375 15 -129.94 5 6 8.4
10 256 27 4 4 5 5aa8d8e5 [0, 1, 12, 15] 13 12 11 11 7 4 3 5 4 5 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99992 10 4 2.312 1 2.86 2 23 8.9
11 256 27 16 4 30 43f23edb [0, 1, 10, 14] 12 7 11 7 5 3 7 7 10 6 0 1 0 0 0 0 0 0 0 0 0 0 0 1.00001 8 5 2.250 12 -3.27 1 9 9.0
13 128 54 16 4 1 62dcc64d [0, 1, 7, 9] 11 8 10 13 8 5 9 6 2 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99809 2 5 2.438 13 -254.71 2 2 8.7
14 64 108 16 1 29 d740df07 [1, 3, 9, 10] 17 7 8 7 6 7 4 7 11 1 3 4 2 1 0 0 0 0 0 0 0 0 0 0.99989 10 3 2.438 5 -3.73 2 6 8.0
9 64 108 8 4 18 da7e862f [0, 1, 2, 8] 15 9 11 5 4 5 2 7 9 8 23 24 17 4 2 0 0 0 0 0 0 0 0 0.99990 9 4 2.188 1 2.37 7 25 9.6
15 128 54 8 4 25 b6a91d0d [0, 1, 5, 12] 14 7 9 4 8 8 8 6 7 4 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99654 8 5 4.188 8 -510.81 8 25 9.2
1 k shape reps mixer width R M pos w_add w_xor w_mul w_mad w_shfl w_rotl w_sub w_mulhi w_rotr w_or attempt candidates a_prime a b c_const c_lane c_sat c_bias c_distinct c1_sat_source c2_low_entropy c3_hot_item min_ratio min_site top_count_max bucket_ratio_max bucket_site bit_z_max bit_site bit secs
2 6 256 27 8 1 18 f5374043 [4, 7, 11, 14] 17 8 4 10 8 8 6 2 4 8 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99925 7 3 2.344 7 256.38 7 18 8.1
3 1 256 27 16 4 6 50b5995b [0, 1, 7, 10] 11 12 11 7 5 7 10 3 3 6 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99936 0 5 2.312 2 -223.84 0 6 8.9
4 3 64 108 8 1 28 0ea25b7d [5, 6, 7, 13] 8 10 13 6 4 3 10 6 9 6 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99989 13 3 2.312 2 -8.62 14 0 8.9
5 4 256 27 4 1 14 b0d09763 [0, 6, 8, 11] 14 12 5 5 6 10 8 5 7 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99969 7 4 2.375 1 -3.10 0 24 9.1
6 2 128 54 8 1 10 8833036b [0, 5, 11, 13] 10 9 9 4 6 4 10 5 11 7 6 7 5 1 0 0 0 0 0 0 0 0 0 0.99994 0 4 2.375 7 -3.21 2 20 9.2
7 5 64 108 16 1 26 7f8a4ac1 [0, 9, 10, 13] 12 15 9 13 9 5 5 3 3 1 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99944 7 3 2.438 13 -440.40 7 26 9.6
8 0 128 54 4 4 22 78e9ab5b [0, 1, 3, 12] 12 9 8 5 9 12 3 7 9 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99995 4 4 2.375 4 -2.99 0 6 10.3
9 7 256 27 4 1 17 c8678a37 [0, 6, 13, 15] 14 12 6 5 7 9 7 3 7 5 1 2 0 0 0 0 0 0 0 0 0 1 0 0.99544 4 5 13.938 4 -468.09 3 17 12.7
10 8 64 108 4 4 25 71a1775d [0, 1, 7, 15] 17 10 10 7 5 4 5 7 9 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0.99993 10 5 2.312 10 2.97 12 6 7.9
11 12 256 27 8 1 5 da7c079d [3, 5, 6, 12] 14 9 9 9 7 3 7 6 4 7 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99985 6 4 2.375 15 -129.94 5 6 8.4
12 10 256 27 4 4 5 5aa8d8e5 [0, 1, 12, 15] 13 12 11 11 7 4 3 5 4 5 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99992 10 4 2.312 1 2.86 2 23 8.9
13 11 256 27 16 4 30 43f23edb [0, 1, 10, 14] 12 7 11 7 5 3 7 7 10 6 0 1 0 0 0 0 0 0 0 0 0 0 0 1.00001 8 5 2.250 12 -3.27 1 9 9.0
14 13 128 54 16 4 1 62dcc64d [0, 1, 7, 9] 11 8 10 13 8 5 9 6 2 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99809 2 5 2.438 13 -254.71 2 2 8.7
15 14 64 108 16 1 29 d740df07 [1, 3, 9, 10] 17 7 8 7 6 7 4 7 11 1 3 4 2 1 0 0 0 0 0 0 0 0 0 0.99989 10 3 2.438 5 -3.73 2 6 8.0
16 9 64 108 8 4 18 da7e862f [0, 1, 2, 8] 15 9 11 5 4 5 2 7 9 8 23 24 17 4 2 0 0 0 0 0 0 0 0 0.99990 9 4 2.188 1 2.37 7 25 9.6
17 15 128 54 8 4 25 b6a91d0d [0, 1, 5, 12] 14 7 9 4 8 8 8 6 7 4 1 2 1 0 0 0 0 0 0 0 0 0 0 0.99654 8 5 4.188 8 -510.81 8 25 9.2

View file

@ -0,0 +1,42 @@
binary e7a50f8dcf57a14b commit fg5 test family_gate_era_census from 0 seeds 3000 threads 16 start 2026-10-08T10:43:53Z
lease: holding 16 pool cores (8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, waited 0 s, class measure): family gate: family_gate_era_census w4c seeds 0+3000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 55 s
family_gate_era_census: 200 eras in 106 s
family_gate_era_census: 300 eras in 158 s
family_gate_era_census: 400 eras in 211 s
family_gate_era_census: 500 eras in 263 s
family_gate_era_census: 600 eras in 315 s
family_gate_era_census: 700 eras in 369 s
family_gate_era_census: 800 eras in 412 s
family_gate_era_census: 900 eras in 457 s
family_gate_era_census: 1000 eras in 507 s
family_gate_era_census: 1100 eras in 557 s
family_gate_era_census: 1200 eras in 606 s
family_gate_era_census: 1300 eras in 659 s
family_gate_era_census: 1400 eras in 725 s
family_gate_era_census: 1500 eras in 788 s
family_gate_era_census: 1600 eras in 847 s
family_gate_era_census: 1700 eras in 907 s
family_gate_era_census: 1800 eras in 958 s
family_gate_era_census: 1900 eras in 1002 s
family_gate_era_census: 2000 eras in 1046 s
family_gate_era_census: 2100 eras in 1086 s
family_gate_era_census: 2200 eras in 1134 s
family_gate_era_census: 2300 eras in 1182 s
family_gate_era_census: 2400 eras in 1227 s
family_gate_era_census: 2500 eras in 1271 s
family_gate_era_census: 2600 eras in 1316 s
family_gate_era_census: 2700 eras in 1357 s
family_gate_era_census: 2800 eras in 1394 s
family_gate_era_census: 2900 eras in 1433 s
family_gate_era_census: 3000 eras in 1472 s
family_gate_era_census: 3000 eras 0..3000 in 1472 s on 16 threads -> /srv/builds/_adv-family-gate/logs/w4c-family_gate_era_census-0-3000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 1472.04s
Terminated
lease: released 16 pool cores after 1472 s, exit 0
end 2026-10-08T11:08:25Z rc 0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
binary e7a50f8dcf57a14b commit fg5 test family_gate_era_census from 0 seeds 2000 threads 8 start 2026-10-08T10:45:36Z
lease: holding 8 pool cores (8,9,10,11,12,13,14,15, waited 0 s, class measure): family gate: family_gate_era_census w4lossy seeds 0+2000
running 1 test
test accept::tests::family_gate_era_census ... family_gate_era_census: 100 eras in 98 s
family_gate_era_census: 200 eras in 193 s
family_gate_era_census: 300 eras in 289 s
family_gate_era_census: 400 eras in 378 s
family_gate_era_census: 500 eras in 479 s
family_gate_era_census: 600 eras in 576 s
family_gate_era_census: 700 eras in 672 s
family_gate_era_census: 800 eras in 767 s
family_gate_era_census: 900 eras in 867 s
family_gate_era_census: 1000 eras in 952 s
family_gate_era_census: 1100 eras in 1002 s
family_gate_era_census: 1200 eras in 1052 s
family_gate_era_census: 1300 eras in 1101 s
family_gate_era_census: 1400 eras in 1148 s
family_gate_era_census: 1500 eras in 1198 s
family_gate_era_census: 1600 eras in 1247 s
family_gate_era_census: 1700 eras in 1297 s
family_gate_era_census: 1800 eras in 1345 s
family_gate_era_census: 1900 eras in 1393 s
family_gate_era_census: 2000 eras in 1444 s
family_gate_era_census: 2000 eras 0..2000 in 1444 s on 8 threads -> /srv/builds/_adv-family-gate/logs/w4lossy-family_gate_era_census-0-2000.tsv
ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 80 filtered out; finished in 1443.67s
lease: released 8 pool cores after 1443 s, exit 0
end 2026-10-08T11:09:39Z rc 0

File diff suppressed because it is too large Load diff