Merge spec-accept-23 64e2a91b into master (gate: green on 64e2a91b, recorded by tools/ci/pre-push.sh; landed on the box mirror)

This commit is contained in:
igneum-labs 2026-10-07 23:56:10 +01:00
commit 8b8346347f
9 changed files with 566 additions and 118 deletions

View file

@ -29,7 +29,7 @@ Evidence locations referenced below: `docs/bench-log.md`, `proto-metal/TESTS.md`
### M1. The program space is tiny
"Eleven integer ops, 64 instructions, 8 iterations, a splitmix register init. That is not RandomX. RandomX leans on a superscalar out-of-order CPU with floating point and branches. Yours is a sea of 32-bit ALUs and a memory bus. A chip for that is a weekend."
Status: Decided (6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no standing bounty. A team with a real 2x chip earns more by mining than any bounty pays, so a device bounty attracts nobody; the tiers announced at 17:25 UTC are withdrawn. The claim "under 2x" is backed by the paid independent cryptanalysis (the Monero route: four paid reviews, no bounty) and by the public benchmark with M22's metrics. Optional, the owner's call later: one cryptanalysis prize of USD 50,000 for a published 2x or better shortcut in the mixer, the chained cache or the acceptance rule, escrowed before it is named; nothing public before that. The claim stays a target until the audit and the benchmark have reported. Was: Open, program space counted, the claim stands as a target (5 October 2026, evening sweep). Was: Open, experiment scheduled. Sweep (5 October 2026): nothing runnable; the bounty, the public benchmark and a chip design are M22's decisions and hardware. The nearest number stays M16's arithmetic.
Status: Decided (6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no standing bounty. A team with a real 2x chip earns more by mining than any bounty pays, so a device bounty attracts nobody; the tiers announced at 17:25 UTC are withdrawn. The claim "under 2x" is backed by the in-house adversarial pass and by the public benchmark with M22's metrics. The claim stays a target until the audit and the benchmark have reported. Was: Open, program space counted, the claim stands as a target (5 October 2026, evening sweep). Was: Open, experiment scheduled. Sweep (5 October 2026): nothing runnable; the bounty, the public benchmark and a chip design are M22's decisions and hardware. The nearest number stays M16's arithmetic.
Decision owner: the founder, decided 6 October 2026 (`docs/plans/ledger-decisions.md`, outcomes section).
Sweep (5 October 2026, evening): the program space, swept as arithmetic from the version 2 generator (`igneum-pow/src/generator.rs`: 16 load slots as a uniform 16-subset of instructions 1 to 63, then nine draws per instruction, 592 draws per program; 10 non-load operations with weights 12/10/8/8/8/7/6/6/6/4; 8 registers; a 31-way rotation, a 32-way bit and a 5-way mask per instruction; two 32-bit immediates). Counting choices: the slot subset is 48.4 bits; the operation draw carries 3.26 bits of entropy (of log2 10 = 3.32); operations and registers alone give about 770 bits per program; with the rotation, bit and mask fields about 1,550 bits; with the immediates about 5,650 bits, all capped by the 256-bit seed, so the space a chip has to serve is 2^256 distinct programs drawn from a structure of about 2^1550 shapes, and the critic is right that it is a small instruction set: 12 operations, 8 registers, no floating point, no branches, by design (vendor-identical rounding). What the sweep adds to the ledger's answer is the number that matters for a fixed-function design, the spread a chip must absorb: under generator version 2 every accepted program does 120 to 128 distinct loads per hash (median 128.00, 20,000-program census), so the per-program hash-rate spread on a memory-bound device is the 1.10x residual the census measured, not the 2.7x of version 1; the chip's advantage therefore cannot come from the program (it is one fixed memory-bound shape) and must come from the memory system or from the recompute route, which is M16's cost model (`docs/analysis/m16-recompute-attacker-2026-10-05.md`: 1.5x to 2.4x at equal integer budget before any fixed-function factor, 3x to 6x with one, and the mixer-cost lever that cuts it below 1x). The experiment that closes M1 is unchanged: the bounty and the public benchmark (M22, decision owner the founder).
@ -1587,7 +1587,7 @@ Run (5 October 2026, night): `python3 sim/difficulty/record_report.py devnet-202
### M22. The ASIC challenge has no scoring rules, and 2x is not the economic line
"Your bounty says 'beats a GPU by more than 2x'. Per what? Hashes per second, per joule, per dollar, on the average program or the worst hour? A chip at 1.6x with half the capital cost wins. And nobody has published eligible hardware, funding or a judge."
Status: Decided (6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no bounty, so no bounty terms; M22's metrics (hashes per second and per joule per program over at least 100 epochs as a distribution, capital cost per unit of hash rate at a stated volume, the longevity term, the shortcut classes scored separately) become the public benchmark's scoring rules and the brief of the paid cryptanalysis; the optional USD 50,000 cryptanalysis prize, if ever set, is escrowed before it is named. Was: Open, decision for the founder (terms, judge and funding) and experiment scheduled (extends O-1.17). Sweep (5 October 2026): nothing runnable; the terms, judge and funding are the founder's decision.
Status: Decided (6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no bounty, so no bounty terms; M22's metrics (hashes per second and per joule per program over at least 100 epochs as a distribution, capital cost per unit of hash rate at a stated volume, the longevity term, the shortcut classes scored separately) become the public benchmark's scoring rules and the brief of the in-house adversarial pass. Was: Open, decision for the founder (terms, judge and funding) and experiment scheduled (extends O-1.17). Sweep (5 October 2026): nothing runnable; the terms, judge and funding are the founder's decision.
Decision owner: the founder, decided 6 October 2026 (`docs/plans/ledger-decisions.md`, outcomes section).
Answer: Correct. M1 and O-1.17 name a bounty for "more than 2x" without a metric, a judge or a fund, and 2x is a design target for the hash, not an economic threshold: a chip at 1.5x per joule and 3x per dollar of capital is an economic ASIC whatever the hash-rate ratio says. The scoring rules go out with the January 2027 benchmark: hashes per second and per joule measured per program over a published set of at least 100 epochs, reported as a distribution (worst decile, median), never as one average; capital cost per unit of hash rate at a stated volume; a longevity term against the instruction-family reserve and the dataset growth of spec 1.13; and the shortcut classes (recomputation, partial storage, weak-program selection) scored separately. Eligible hardware assumptions, the judge, the reward and the payer are the founder's decisions (fud-fixes row 50: the payer is the entity). The supportable public claim until a design has been scored: across the tested workloads and the stated economic assumptions, consumer GPUs remain competitive against the best independently proposed specialised design. Extends M1, M16 and C13.
@ -2505,10 +2505,6 @@ Owed (recorded, not run, by the founder's word): G2 (the CPU verifier on 1,024 h
Status: Fixed in part, finding bounded, stated (7 October 2026, night, the Counter ASIC lane's words): class v4 sub-version 3 (igneum-pow 017e7037, the audit-freeze tag) is frozen with the dataflow rule, the shared-operand rule, the 0.98 ratio and the total draw; the in-house pass's F8 re-gate reads 60 of 64 seeds under 1.2x with the four-seed tail accepted by the coordinator as the window model's unattributed residue (no chip consequence); the pass then attributed the class by value (eight live hot sets at 1.54x to 2.24x in the lowest 30 of 29,032 accepted programs, each about 1 MB of items at 0.3 percent of reads, 1.002x to a chip); class v5 (1c420786, frozen 21:53 UK) carries the fix as rule (c'''), the per-site distinct-index floor at 0.995 on the state flag (its census refuses 2.435 percent of accepted programs; seven of seven live hot sets refused at 0.9821 to 0.9919; the eighth's ratio owed tonight), with a named residual (three mild shadow-block-written concentrations at 0.9992 to 0.9997, about 1.0004x, a value-level test in the next class); the record is `docs/plans/counter-asic-3-status.md` section 7c and the class v5 design's section 14. The eighth live hot set (seed 122960, id 4be7393ab6c84802, the deepest found: X_f +0.111 percent, 1.54x the window model, its hottest item at 475,616 reads from an all-ones source) reads minimum site 12 at 0.9824 at the acceptance's own 2^20 sample (live 0.9822), refused by class v5's (c''') floor at 0.995; so the floor refuses eight of eight live hot sets by X_f at or above f found in the tail of 88,051 accepted programs (minimum sites 0.9821 to 0.9919) against 0 hot sets in 20 random programs; what it misses stays the three mild shadow-block-written concentrations at 0.9992 to 0.9997 (Devnet 3's first program among them), about 1.0004x to a chip, the value-level test in the next class (22:41 BST; the logs under `docs/analysis/cryptanalysis/logs/adv-accept/` on branch adv-accept; the v5 design's section 14). The public sentence (the coordinator's wording, 7 October 2026, night): eight of eight hot sets refused; the diffuse era-stride excess, bounded under 0.1 percent of a hash's reads per site, is not caught by the floor and is the next class's test. The reason, read by the in-house pass (adv-cache-2) and the class v5 lane together: the distinct-index count at 2^20 sees concentration on few word indices (the hot sets put about 3 percent of a site's reads on 512 indices, so the ratio falls to 0.98 to 0.992) and not a diffuse excess over the top 0.1 percent of items (16,384 items), which is what the era-stride low-bit law produces (13 of 27 drawn-era programs carry a site over 1.04x, 8 over 1.2x, worst 1.75x; 0 of 29 refused at the 2^20 sample, minimum sites 0.9965 to 1.0000); its chip value is about 1.0024x at the worst site read, under this row's bound by an order; the row for it is AP-F8-6. The RTX 5080 grid's knee is not in tonight; X37 keeps the 5080's stock premium only.
## Genesis forward-compatibility entries (7 October 2026, mission item 8, branch `genesis-forward`)
The three genesis fields of `docs/analysis/mission/mission.md` section 2.8, built on the node fork branch `genesis-forward` (from release-0.3.19-node dc141409) and the repo branch `genesis-forward`; the design and the gates in `docs/design/genesis-forward.md`. Every switch is never on the devnet (its digest c562d70e... does not move); the testnet genesis sets all three (the testnet lane re-pins and re-digests).
### AP-F8-4. The program id's derivation text omitted generator 4's sub-version suffix (interoperability, documentation; no object change)
Found by the in-house pass adv-accept-3 (report-acceptance-rule-3.md at 0c150e3c, finding 2, 7 October 2026, evening): program.json's `program_id_derivation` and spec 01 section 1.4.6 stated `FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words || attempt_le32` while the code (generator.rs `program_id`) appends `'sub/' || sub_version_le16` under generator 4, so an implementation written from the text derives another id (the devnet v4 pack: 8aa9f185d63f269e from the text against the pack's and the chain's a785001687d8688a; Devnet 3's epoch 0: 30956569d8f3d8d7 against fce15bf61030be57); a second client written from the text would disagree with the chain on every program id. The code is the consensus; the text was wrong.
@ -2517,6 +2513,19 @@ Fix (15008aca and 0f45c8be on ca3-v4-amend, landed on master through the gate on
Status: Fixed (7 October 2026, night): the id and its derivation text come from one byte recipe, every pinned pack's id re-derives from its own text in the suite (the igneum-pow suite on box 2 green at 0f45c8be: 64 + 2 + 7 + 4 + 19 + 2 + 7), the spec states the suffix; no object moved.
### AP-F8-5. The public specification did not describe the shipped acceptance rule (documentary; no object change)
"An implementation written from docs/spec/01-lottery-hash.md section 1.4.6 at 017e7037 mines a different program from the node on 264 of 400 epochs." Found by the in-house pass adv-accept-3 (report-acceptance-rule-3.md at 0c150e3c, finding 3, section 6.2, 7 October 2026, night): the text described (a), (b) and (c) with a 32-attempt cap and an id without a suffix, while the code adds (a') with the shared-operand rule, (c'), (c'') at 2^20 evaluations, the 256-attempt cap keyed on the class v4 shape, the total draw with the last resort, generator 4 and the sub-version suffix, and executes the 256-instruction shadow block 27 times per iteration inside the acceptance interpreter. Measured (sweep 97, 400 seeds, 1,317 attempt verdicts): 759 verdicts differ (758 the code rejects and the text accepts: (a') 733, (c'') 15, (c) 10; 1 the other way, the shadow block changing a (c) statistic); 264 of 400 seeds choose another attempt; the parts the text did carry, (a) and (b), agree on every row.
Status: Spec fixed (7 October 2026, night, the site audit lane by main's order, branch spec-accept-23): sections 1.4.3 and 1.4.6 of `docs/spec/01-lottery-hash.md` rewritten to the shipped rule at igneum-pow 017e7037 with every constant named and every order of operations stated (1.4.3: the two per-register states of the draw, the dataflow table, the shared-operand rule, the shadow block's draw and the draw counts per class; 1.4.6.1 to 1.4.6.6: (a) cyclic over two passes, (b), (a') to the fixpoint then a checking pass, (c) with the shadow executed and its limits in a table, (c') and (c'') with the integer form of the ratio compare, the attempts and the two caps with the measured per-part rates, the last resort stated as unreachable and unverified, the program id with the generator-4 suffix, a constants table in the shape the crate's read-back test parses, the pinned ids a reader must reproduce); section 1.7 gains the shadow block's execution; section 1.13.1 names the two consumed era draws. The hash lane's `igneum-pow/tests` read-back test parses the two tables against the crate's `pub const` items and derives every pinned id (its landing is the row's check; AP-F8-4 carries the derivation-text half of the same finding).
Answer: Correct, and the largest divergence source the pass found was documentary. The rule the chain runs was right; the text a second implementer would read was three sub-versions behind it. The fix is the text, written to the code line by line, and a test that fails when the two drift again.
Evidence: `docs/analysis/cryptanalysis/report-acceptance-rule-3.md` sections 6.2 to 6.4 (branch adv-accept-3); `docs/spec/01-lottery-hash.md` 1.4.3, 1.4.6, 1.7, 1.13.1 (branch spec-accept-23); `igneum-pow/src/accept.rs`, `igneum-pow/src/generator.rs` at 017e7037.
## Genesis forward-compatibility entries (7 October 2026, mission item 8, branch `genesis-forward`)
The three genesis fields of `docs/analysis/mission/mission.md` section 2.8, built on the node fork branch `genesis-forward` (from release-0.3.19-node dc141409) and the repo branch `genesis-forward`; the design and the gates in `docs/design/genesis-forward.md`. Every switch is never on the devnet (its digest c562d70e... does not move); the testnet genesis sets all three (the testnet lane re-pins and re-digests).
### GF1. A post-quantum signature scheme would need a hard fork, and every vote key is a public BLS12-381 point
"When a quantum computer comes, every BLS vote key is forged and the chain has no way to change the scheme without a fork of the kind you say you never need."

View file

@ -2,7 +2,7 @@
Generated by `tools/ledger/export-public.mjs` from `docs/fud-ledger.md`; a gate check fails when the two drift. One row per item: the claim or criticism, its status, what was done, and the evidence. Internal identifiers, times of day and team-member names are left out on purpose; the full ledger is published with the repository.
192 items. By status: Conceded, stated 52; Fixed 31; Decided 22; Fixed on a branch, pending merge 14; Answered by design 9; Answered with evidence 6; Fixed, stated 4; Closed by rule 3; Open 3; Answered by design, with a correction to our own text 1; Answered with evidence, stated 1; Answered by design for finality, Conceded for the lottery 1; Conceded, implemented, stated 1; Rule implemented and measured; launch month simulated 1; Answered by design, with the concession stated 1; Conceded, stated in the litepaper and the design doc 1; Answered with evidence at 1 block/s 1; Conceded, stated in the simulation report 1; Answered by design, with the dependency conceded. Update 7… 1; Conceded, stated in the litepaper, with the dial explained 1; Closed by spec 1; Conceded by decision, stated in the design doc 1; Answered by design, with the founder's edge conceded 1; Answered by design, with a metrics caveat 1; Closed by removal, 3 October 2026 1; Conceded, stated in the litepaper 1; Conceded, stated in the design doc 1; Measured on the live node line, and the overlay does NOT… 1; Conceded, stated in the simulation 1; Conceded in part, labelled, stated 1; Fixed in the node 1; Answered with evidence for the largest body the rules allow 1; Spec fixed 1; Fixed in the proving code 1; Fixed in the spec 1; Rule fixed 1; Rule written 1; Fixed, logged 1; Answered with evidence for the test half 1; Fixed in the node and shipped, rule not yet activated on… 1; Simulation half run 1; Answered with evidence for all four 1; Written 1; Designed 1; Fixed and confirmed 1; Rolled out 1; Conceded by decision 1; Conceded, scheduled, stated 1; Conceded, contained by rule, stated 1; Fixed on a branch and verified locally 1; Answered with evidence and stated 1; Answered with evidence for PC 2 1; Answered by design and with evidence 1; Fixed, stated; restated 1; Fixed, stated; restated further 1; Fixed in part, finding bounded, stated 1; Fixed as a genesis lever, measurement owed 1.
193 items. By status: Conceded, stated 52; Fixed 31; Decided 22; Fixed on a branch, pending merge 14; Answered by design 9; Answered with evidence 6; Fixed, stated 4; Closed by rule 3; Open 3; Spec fixed 2; Answered by design, with a correction to our own text 1; Answered with evidence, stated 1; Answered by design for finality, Conceded for the lottery 1; Conceded, implemented, stated 1; Rule implemented and measured; launch month simulated 1; Answered by design, with the concession stated 1; Conceded, stated in the litepaper and the design doc 1; Answered with evidence at 1 block/s 1; Conceded, stated in the simulation report 1; Answered by design, with the dependency conceded. Update 7… 1; Conceded, stated in the litepaper, with the dial explained 1; Closed by spec 1; Conceded by decision, stated in the design doc 1; Answered by design, with the founder's edge conceded 1; Answered by design, with a metrics caveat 1; Closed by removal, 3 October 2026 1; Conceded, stated in the litepaper 1; Conceded, stated in the design doc 1; Measured on the live node line, and the overlay does NOT… 1; Conceded, stated in the simulation 1; Conceded in part, labelled, stated 1; Fixed in the node 1; Answered with evidence for the largest body the rules allow 1; Fixed in the proving code 1; Fixed in the spec 1; Rule fixed 1; Rule written 1; Fixed, logged 1; Answered with evidence for the test half 1; Fixed in the node and shipped, rule not yet activated on… 1; Simulation half run 1; Answered with evidence for all four 1; Written 1; Designed 1; Fixed and confirmed 1; Rolled out 1; Conceded by decision 1; Conceded, scheduled, stated 1; Conceded, contained by rule, stated 1; Fixed on a branch and verified locally 1; Answered with evidence and stated 1; Answered with evidence for PC 2 1; Answered by design and with evidence 1; Fixed, stated; restated 1; Fixed, stated; restated further 1; Fixed in part, finding bounded, stated 1; Fixed as a genesis lever, measurement owed 1.
| Id | Claim or criticism | Status | What was done | Evidence |
|---|---|---|---|---|
@ -194,6 +194,7 @@ Generated by `tools/ledger/export-public.mjs` from `docs/fud-ledger.md`; a gate
| P23 | An unwound transaction leaves the node's view until its sender resends it | Fixed on a branch, pending merge | a fork a commit (the P23 commit, on the merge of `ledger-fixes` and `ledger-fixes-2` onto the 0.3.11 fork tip a commit); `EvmPool::on_chain_removed` (igneum/exec/src/pool.rs) and `ExecService::requeue_unwound`… | [igneum/exec/src/pool.rs](../igneum/exec/src/pool.rs) |
| AP-F8-1 | A load whose source was last written by `or`, `mul` or `mulhi` makes a cross-hash hot set | Fixed in part, finding bounded, stated | Class v4 sub-version 3 (igneum-pow a commit, the audit-freeze tag) is frozen with the dataflow rule, the shared-operand rule, the 0.98 ratio and the total draw; the in-house pass's F8 re-gate reads 60 of 64 seeds under… | [docs/analysis/ca3-v4-uniform.md](../docs/analysis/ca3-v4-uniform.md) |
| AP-F8-4 | The program id's derivation text omitted generator 4's sub-version suffix (interoperability, documentation; no object change) | Fixed | The id and its printed derivation come from one byte recipe (`generator::IdRecipe`, `program_id_recipe`, `program_id_class_recipe`, `Program::program_id_derivation`), so the two cannot drift; the emitter prints that… | [igneum-pow/tests/derivation.rs](../igneum-pow/tests/derivation.rs) |
| AP-F8-5 | The public specification did not describe the shipped acceptance rule (documentary; no object change) | Spec fixed | Sections 1.4.3 and 1.4.6 of `docs/spec/01-lottery-hash.md` rewritten to the shipped rule at igneum-pow a commit with every constant named and every order of operations stated (1.4.3: the two per-register states of the… | [docs/analysis/cryptanalysis/report-acceptance-rule-3.md](../docs/analysis/cryptanalysis/report-acceptance-rule-3.md) |
| GF1 | A post-quantum signature scheme would need a hard fork, and every vote key is a public BLS12-381 point | Fixed | The byte costs nothing now and a fork later. | none named |
| GF2 | A vote key cannot move: a miner who changes keys re-earns 30 days of weight, and so does the post-quantum migration | Fixed | The successor inherits the window, not a fresh one, so a key rotation costs no weight and the migration of GF1 is one item per key. | none named |
| GF3 | A 256 MB on-chip cache makes the lottery hash 2 to 3x cheaper for the card that has it, and the cache size is a constant | Fixed as a genesis lever, measurement owed | Consumer LLC is 96 to 128 MB today and datacentre 256 MB (`chip-model-v3`, approximate), so the shortcut is a datacentre card's today and a consumer card's in a generation or two. | none named |

View file

@ -118,30 +118,52 @@ The version 1 lever measurement (`load_weight = 17`, `proto-metal/MEMHARD.md` se
### 1.4.3 Draw order
From the program stream of 1.3.3, in this order, whether or not an op uses a value.
Implemented (`igneum-pow/src/generator.rs`, `candidate_from_words_class`; every path the chain and the packs take). From the program stream of 1.3.3, in this order, whether or not an op uses a value. The same procedure draws every class; a class changes what a draw is used for, never whether it is taken, so the stream stays aligned across classes.
(1) Load slots. Let `p[0..62] = 1..63` (instruction 0 is never a load: nothing is fresh before it). For `i` in 0..15 draw `j = i + below(63 - i)` and swap `p[i]` and `p[j]`. The load slots are `p[0..15]`, a uniform 16-subset of 1..63.
(2) For each instruction `k` in 0..63, nine draws:
(2) For each instruction `k` in 0..63, in this order:
```
roll = below(75); op = first entry of the table of 1.4.2 whose cumulative weight exceeds roll
(on a load slot the roll is drawn and ignored and op = load)
dst = below(8)
src: on an ALU slot a = below(7); src = a + (a >= dst)
on a load slot E = the registers other than dst, in register order, that an earlier instruction of this
program has written and that no later load has used as its source (E is empty before
instruction 0); if E is not empty, a = below(|E|) and src = E[a];
if E is empty, a = below(7) and src = a + (a >= dst), and 1.4.6 (a) rejects the program
on a load slot E = the eligible registers (below), in register order;
if E is not empty, a = below(|E|) and src = E[a];
if E is empty, a = below(7) and src = a + (a >= dst) (the fallback; 1.4.6 (a) or (a') rejects the program)
b = below(8) (src2)
imm = low32(next())
imm2 = low32(next())
rot = 1 + below(31)
bit = below(32)
mask = 1 << below(5)
under an era (every chain program of class v3 and v4; section 1.13.1):
k_off = below(3)
o = low32(next()) AND (2^k_off - 1) (k_off and o are kept on a load slot and are (0, 0) on an ALU slot)
```
16 slot draws plus 64 x 9: 592 draws per program. A program is fully determined by its eight seed words. A load's source holds a value written in the same iteration that no earlier load has read, so no load repeats the address of an earlier load of the same hash, across the iteration boundary included (the first form of the rule, with every register eligible at instruction 0, left the wrap open and failed 1.4.6 (a) on 36 percent of programs; census section 7.1).
Eligible registers. Two per-register states are carried through the draw, updated after every instruction is drawn:
| State | Start | After an instruction with `dst = d`, `src = a` | Used by |
|---|---|---|---|
| `fresh[r]` | all false | `fresh[a] = false` if the op is a load; then `fresh[d] = true` | every class |
| `fresh_value[r]` | all true | the table below, then the shared-operand rule | class v4 only |
Under class v2 and class v3, `E` is every register `r != dst` with `fresh[r]`: written by an earlier instruction of this program and not read by a later load. Under the class v4 shape (`is_class_v4_shape`: the 256-instruction shadow block over the class v3 base, the pass count and the era set aside), `E` is every register `r != dst` with `fresh[r]` and `fresh_value[r]`: fresh by dataflow as well. The dataflow table (AP-F8-1, sub-version 2; `docs/analysis/ca3-v4-uniform.md`), evaluated with the values before the instruction:
| Op drawn | `fresh_value[d]` after it |
|---|---|
| `load` | `fresh_value[a]` (a saturated source reads one fixed word and leaves a constant) |
| `add`, `sub`, `xor`, `mad`, `shfl` | `fresh_value[d] OR fresh_value[a]` |
| `rotl`, `rotr` | `fresh_value[d]` (a rotate maps all-ones and zero to themselves) |
| `or`, `mul`, `mulhi` | false |
The shared-operand rule (sub-version 3): after `or d |= s`, a later `xor d ^= s` or `sub d -= s` with neither `d` nor `s` written in between computes `d AND NOT s`; after `xor d ^= s`, a later `or d |= s` computes `d OR s`. Either pair is lossy though its second op would count as injecting on its own (F8's p23: `or r6 |= r4; xor r6 ^= r4`). So the draw keeps `pair[d] = (op, s)` for the last `or` or `xor` written to `d`, and when the instruction drawn is the second half of such a pair on the same `s`, `fresh_value[d]` is set false whatever the table says. Then: `pair[d]` becomes `(op, a)` if the op is `or` or `xor` and the pair rule did not fire, else none; and every `pair[r]` whose `s` equals `d` is cleared (a write to a register clears every pair that names it as the operand). The `src2` register `b` takes no part in either state.
(3) The latency-shadow block (class v4; Counter ASIC 3.0 item 8). After the 64 base instructions, `V4_SHADOW_INSTRS = 256` further instructions are drawn from the same stream, so the base program of a class v4 seed is the class v3 program of that seed draw for draw. Every shadow slot is an ALU slot: `roll = below(75)` and the op from the table of 1.4.2, `dst = below(8)`, `a = below(7); src = a + (a >= dst)`, `b = below(8)`, `imm`, `imm2`, `rot`, `bit`, `mask` as above; under an era `below(3)` and `next()` are drawn and ignored. No shadow instruction is a load, and the shadow block takes no part in the two states above during the draw (the acceptance rule's (a') reads it, section 1.4.6.3). The block runs `V4_SHADOW_REPS = 27` times at the end of every iteration (section 1.7); the latency ladder (`docs/design/latency-ladder.md`) moves the pass count alone and never the draw.
Draw counts: 16 slot draws plus 64 x 9 = 592 under class v2; 64 x 11 + 16 = 720 under class v3 with an era; 720 + 256 x 11 = 3,536 under class v4 with an era. A program is fully determined by its eight seed words and its class. A load's source holds a value written in the same iteration that no earlier load has read, so no load repeats the address of an earlier load of the same hash, across the iteration boundary included (the first form of the rule, with every register eligible at instruction 0, left the wrap open and failed 1.4.6 (a) on 36 percent of programs; census section 7.1).
Test vector: for seed `igneum-genesis` (attempt 0, program id `bcc1248b10cc90f2`, section 1.4.6) the first eight instructions are (`proto-cuda/packs/igneum-genesis-mh/program.json`):
@ -168,21 +190,118 @@ A program is transmitted as the seed bytes, never as instructions. A node hands
### 1.4.6 Program acceptance
Implemented (`igneum-pow/src/accept.rs`, `proto-metal/main.swift`; ledger M6 Fixed). A candidate program is accepted only if all of the following hold, and every conforming implementation MUST evaluate them identically.
Implemented (`igneum-pow/src/accept.rs`; `proto-metal/main.swift` for the class v2 parts; ledger M6 Fixed, AP-F8-1 to AP-F8-3, AP-F8-5). A candidate program is accepted only if every part below that applies to its class holds, and every conforming implementation MUST evaluate them identically. The verdict is accept or reject; the reason is the first failing part in the order of this section and is reported, never relied on.
(a) For every `load`, some instruction between the previous `load` from the same source register and this one, in cyclic order over the 64 instructions, writes that register.
| Part | Name | Class v2 and v3 | Class v4 |
|---|---|---|---|
| (a) | stale load source, cyclic | yes | yes |
| (b) | an injecting write per register | yes | yes |
| (a') | dataflow freshness to a fixpoint, with the shared-operand rule | no | yes |
| (c) | the dynamic test over 2,048 hashes | yes, the 64 base instructions | yes, with the shadow block executed |
| (c') | saturated load sources | no | yes |
| (c'') | the distinct-index ratio at 2^20 evaluations | no | yes |
(b) Every register `r0..r7` is the destination of at least one `add`, `sub`, `xor`, `mad`, `shfl` or `load`.
The class v4 parts and the class v4 cap are keyed on the class v4 shape (`accept::is_class_v4_shape`): the 256-instruction shadow block over the class v3 base, the pass count and the era set aside, so a rung of the ladder keeps every rule and class v2 and v3 verdicts never move.
(c) The program is interpreted (section 1.7) for 64 units at base nonces `low32(next()) AND NOT 31` from a SplitMix64 stream seeded with `FNV-1a-64("igneum-accept/" || seed words as little-endian bytes)`, with init words `I` equal to the seed words and dataset words `dataset_elem(idx, S[0], S[1])` of `verify.rs` (the six-operation closed form of the version 0.1 packs) at 2^28 words (`idx = src AND 0x0fffffff`, a constant of this rule whatever the live dataset size) in place of the memory-hard dataset. Over those 2,048 evaluations: no register has a bit equal in every final value; no `load` site (iteration, instruction) reads one address in all 32 lanes of any unit; the number of final register values equal to 0 or 2^32 - 1 is below 164 (1 percent of 16,384); every output bit's ones count is within 136 of 1,024 (6 sigma); and the number of distinct masked dataset addresses read by one lane in one evaluation, summed over the 2,048 evaluations, exceeds 245,760 (a mean above 120 of the 128 loads).
#### 1.4.6.1 Part (a): no stale load source
Attempts. Attempt 0 of a program seed `b` (the 32-byte epoch seed, or the UTF-8 of a seed string) is the candidate drawn from `seed_words_from_bytes(b)`. If it fails, attempt `k = 1, 2, ...` is drawn from `seed_words_from_bytes(b || k_le32)`; the first accepted candidate is the program of the epoch. Measured rejection rate under this generator: 5.14 percent over 100,000 seeds (census section 7) and the 20,000-seed confirmation of `docs/bench-log.md` (4 October 2026), so the probability that 32 consecutive candidates fail is below 2^-136, and an implementation MAY treat 32 consecutive failures as a consensus fault (`MAX_ATTEMPTS`).
Over the 64 base instructions, twice in a row (so the second pass sees the state carried over the iteration boundary): keep `pending[r]`, set when a load reads `r` and cleared when any instruction writes `r` (its `dst`). A load that reads `r` while `pending[r]` is set rejects the program. The shadow block is not read here.
Program id. `FNV-1a-64("igneum-program/" || generator_le32 || seed words as little-endian bytes || attempt_le32 || suffix)` with `generator = 2` under class v2 and `generator = 3` under class v3 (no suffix), and `generator = 4` under class v4 with the suffix `"sub/" || sub_version_le16` (the class v4 stream's sub-version, 3 since 7 October 2026: `PROGRAM_SUBVERSION_V4` in `generator.rs`, `IGNEUM_PROGRAM_SUBVERSION` in program.h, `"sub_version"` in program.json; without the suffix Devnet 3's epoch-0 id reads 30956569d8f3d8d7 where the chain and the packs say fce15bf61030be57); class v5 is `generator = 5` with no suffix. A program of a non-default class (a read-width, scratch, mixer, derivation, era, shadow or hot rung other than class v4's rung 0) uses the tag `"igneum-program-rw/"` and appends the class's fields after `attempt_le32` (`generator::program_id_class_recipe`). Every pack prints its own derivation as `program_id_derivation` in program.json, built from the same byte recipe the id is hashed from (`generator::IdRecipe`), and `igneum-pow/tests/derivation.rs` re-derives every pinned pack's id from that text. Two implementations that agree on the id agree on the generator version, the seed words, the attempt and, under class v4, the sub-version.
#### 1.4.6.2 Part (b): an injecting write per register
Why the closed form: the test is then a pure function of the program (no cache, no day), costs 1.3 to 3.4 ms on one core, and the census checked on 100,000 programs that its verdict agrees with the memory-hard dataset's on all but 39 threshold-edge cases (section 7.3). What the three parts catch: (a) the empty-list fallback of 1.4.3; (b) registers that saturate to all ones (2.4 percent of candidates); (c) zero-absorbing register sets, lane-constant load sites, output bias and value-level address repeats (2.1 percent). Not in the rule, and why: a contraction as the last write (80 percent of programs) and the `or` count are too common and (c) already catches the cases that matter; the load critical path is a hash-rate question, not a weakness.
Every register `r0..r7` is the `dst` of at least one `add`, `sub`, `xor`, `mad`, `shfl` or `load` among the 64 base instructions. The shadow block is not read here.
Test vectors for the rule (`igneum-pow accept --seed ...`):
#### 1.4.6.3 Part (a'): dataflow freshness in the steady state (class v4)
The draw of 1.4.3 keeps in-pass sources fresh; this part closes the iteration boundary (a source last written late in the previous iteration or in the shadow block, which the draw's empty-list fallback can pick: F8's p11, an `or` at 63 feeding a load at 1). One pass walks the 64 base instructions then the 256 shadow instructions, in that order (the order of one iteration), applying the `fresh_value` table and the shared-operand rule of 1.4.3 to the states `fresh_value[0..7]` and `pair[0..7]`. Start with every register fresh and no pair (the init words are a per-lane hash of the nonce). Run passes until a pass changes neither state (the state only ever falls, so at most 8 passes change it; the implementation runs at most 9 and stops at the first unchanged one). Then run one checking pass in the same order: a load whose source is not fresh at that point rejects the program (`UnfreshLoadSource`, the instruction index counted over base then shadow).
#### 1.4.6.4 Part (c): the dynamic test
The program is interpreted for `ACCEPT_UNITS = 64` units of 32 lanes, `ACCEPT_HASHES = 2,048` hashes, with these inputs and nothing of the live chain:
| Input | Value |
|---|---|
| Base nonces | the first 64 values of SplitMix64 seeded with `FNV-1a-64("igneum-accept/" || seed words as little-endian bytes)`, each `low32(next()) AND NOT 31`; unit `u` runs lanes `base_u + 0 .. base_u + 31` |
| Init words `I` | the program's eight seed words (section 1.6) |
| Dataset | `dataset_elem(idx, S[0], S[1])` of `verify.rs` (the closed form of the version 0.1 packs; `S[0]`, `S[1]` are seed words 0 and 1) at `ACCEPT_DATASET_LOG2 = 28`, 2^28 words, `MASK = 0x0fffffff`, whatever the live dataset size |
| Address of a load with source value `x` | without an era `idx = x AND MASK`; under an era the form of 1.13.1 at `D = 28`: `k = min(k_off, 2)`, `y = rotl(x * M, R)`, `idx = ((y AND (MASK >> k)) OR ((o AND (2^k - 1)) << (28 - k))) AND MASK` |
| Execution | section 1.7 exactly, the shadow block included under class v4: after instruction 63 of every iteration the 256 shadow instructions run 27 times with that iteration's `sel` (sub-version 3, AP-F8-3; until it, the test ran the base instructions alone and judged a program the chain never hashes) |
During the run: a `load` whose 32 lanes compute one address in any unit rejects the program (`LaneConstantSite`, checked at every load of every iteration and unit, the shadow block has none). After the run, over the 2,048 final register states and 2,048 outputs, in this order:
| Check | Limit | Reject |
|---|---|---|
| Nonce-independent bits | no register has a bit equal in all 2,048 final values | `ConstantBit` |
| Saturated finals | the number of final register values equal to 0 or 2^32 - 1 is below `MAX_SATURATED = 164` (1 percent of 16,384) | `Saturated` |
| (c'), (c'') | class v4 only, section 1.4.6.5 | |
| Output bias | every output bit's ones count is within `BIAS_TOLERANCE = 136` of 1,024 (6 sigma) | `OutputBias` |
| Distinct addresses | the number of distinct `idx` values one lane read in one hash, summed over the 2,048 hashes, exceeds `MIN_DISTINCT_SUM = 245,760` (a mean above 120 of the 128 loads; `loads x 2,048 x 120 / 128` for a class with another load count) | `DistinctAddresses` |
#### 1.4.6.5 Parts (c') and (c''): the load sources (class v4)
A load site is a load's ordinal within the iteration, 0 to 15, in instruction order. Both parts read the same interpreter and the same nonce stream as (c).
(c') Saturated sources. Over the 64 units of (c), every site is evaluated 64 x 32 x 8 = 16,384 times. A site whose source value `x` was 0 or 2^32 - 1 in `MAX_SATURATED = 164` or more of them rejects the program (`SaturatedSource`, the first such site in order). A saturated source reads one fixed word whatever delivered the saturation; the draw's rule removes the writers it can see and this count catches every delivery.
(c'') The distinct-index ratio. The one test that runs past the 64 units: `ACCEPT_UNITS_DISTINCT_V4 = 4,096` units, the first 4,096 base nonces of the same stream (the 64 of (c) are its first 64), so every site is evaluated `N = 2^20` times. For each site `s`, `d_s` is the number of distinct `idx` values it computed over those evaluations, `W_s = 2^28 >> min(k_off_s, 2)` is its window in words, and the expectation of a uniform source on that window is `E_s = N - N^2 / (2 W_s)` (an integer at these constants: 2^20 - 2^11, 2^20 - 2^12, 2^20 - 2^13). The site's ratio `d_s / E_s` must reach `MIN_DISTINCT_RATIO_V4 = 0.98`; the first site under it, in order, rejects the program (`LowEntropySite`). The implementation compares in f64; the integer comparison `50 d_s >= 49 E_s` gives the same verdict for every value of `d_s` at these constants (the margin is at least 0.32 of a count; adv-accept-3 section 6.1), and an implementation MAY use it. The floor sits in a measured gap: the accepted population's minimum is 0.983 to 0.989 and the rejected population's maximum 0.966 over 20,275 draws of two lanes, so a floor anywhere in 0.967 to 0.988 gives the same verdicts on every program seen (adv-accept-3 section 6.4). `MAX_SOURCE_REPEAT_V4 = 8` exists in the file and is not part of the rule.
What the parts catch: (a) the empty-list fallback of 1.4.3; (b) registers that saturate to all ones (2.4 percent of class v2 candidates); (c) zero-absorbing register sets, lane-constant load sites, output bias and value-level address repeats (2.1 percent); (a') the cross-hash hot set of a load fed by `or`, `mul` or `mulhi` through the iteration boundary (AP-F8-1); (c') the same set delivered any other way; (c'') a low-entropy index band the lineage rules cannot see (F8's p23, p18, p19, p15, p56). Why (c) uses the closed form: the test is a pure function of the program (no cache, no day), costs about 3 ms on one core for the 64 units and 2.8 s with (c'') on the chosen candidate, and the census checked on 100,000 class v2 programs that its verdict agrees with the memory-hard dataset's on all but 39 threshold-edge cases (section 7.3). Not in the rule, and why: a contraction as the last write (80 percent of programs) and the `or` count are too common and (c) already catches the cases that matter; the load critical path is a hash-rate question, not a weakness; a 2^24 stage of (c'') does not separate the open F8 tail (p4, p8, p10, p34 read the clean seeds' values there; ledger AP-F8-1).
#### 1.4.6.6 Attempts, the cap, the last resort and the program id
Attempts. Attempt 0 of a program seed `b` (the 32-byte epoch seed, or the UTF-8 of a seed string) is the candidate drawn from `seed_words_from_bytes(b)`. If it is rejected, attempt `k = 1, 2, ...` is drawn from `seed_words_from_bytes(b || k_le32)`; the first accepted candidate is the program of the epoch. The cap is `MAX_ATTEMPTS = 32` under class v2 and v3 and `MAX_ATTEMPTS_V4 = 256` under the class v4 shape (`max_attempts_for`).
| Rate, per candidate | Class v2 (census, 100,000 seeds, 4 October 2026) | Class v4 sub-version 3 (adv-accept-3, 3,009,928 candidates of 10^6 seeds and 62,240 of 19,975 full-rule seeds, 7 October 2026) |
|---|---|---|
| Accepted | 0.9486 | 0.323 |
| (a') | not a part | 0.568 |
| (a) | | 0.079 |
| (b) | | 0.022 |
| (c), (c'), (c'') together | | about 0.009 |
| Seeds reaching the cap | 0 of 100,000 | 0 of 1,019,975 |
| Probability a seed reaches the cap | below 2^-136 | 0.677^256, about 4.6 x 10^-44 |
Under class v2 and v3 an implementation MAY treat the cap as a consensus fault. Under class v4 the draw is total (AP-F8-2): a seed whose 256 candidates are all rejected takes the last-resort program, the candidate at attempt 256 with every `or`, `mul` and `mulhi` of its base program and its shadow block rewritten to `xor` (`dst`, `src` and every other field kept), handed to the chain as drawn with no further check. With no lossy op left, (a') holds by construction. The rest of the rule is not checked on it, and does not hold on every seed: on 3,000 seeds the real rule rejects the last-resort program of 271 (251 by (a), the fallback-drawn load source the rewrite does not touch; 14 by (b); 6 by (c)'s distinct sum), so sub-version 3's last resort is stated here as unreachable and unverified (adv-accept-3 finding 1, ledger AP-F8-3); class v5 carries the verified construction (section 1.4.7).
Program id. `FNV-1a-64("igneum-program/" || generator_le32 || seed words as little-endian bytes || attempt_le32 || suffix)` with `generator = 2` under class v2 and `generator = 3` under class v3 (no suffix), and `generator = 4` under class v4 with the suffix `"sub/" || sub_version_le16` (the class v4 stream's sub-version, `PROGRAM_SUBVERSION_V4 = 3` since 7 October 2026: `IGNEUM_PROGRAM_SUBVERSION` in program.h, `"sub_version"` in program.json; without the suffix Devnet 3's epoch-0 id reads 30956569d8f3d8d7 where the chain and the packs say fce15bf61030be57); class v5 is `generator = 5` with no suffix (section 1.4.7). A class v4 program at rung 0 of the ladder uses that form; a program of any other class or rung (a read-width, scratch, mixer, derivation, era, shadow or hot rung other than class v4's rung 0) uses the tag `"igneum-program-rw/"` and appends the class's fields after `attempt_le32` (`generator::program_id_class`). Every pack prints its own derivation as `program_id_derivation` in program.json, built from the byte recipe the id is hashed from, and a worker MUST refuse a pack whose generator version, class, era seed or sub-version is not its own (`packcheck.rs`). Two implementations that agree on the id agree on the generator version, the seed words, the attempt and, under class v4, the sub-version.
Constants of the shipped rule. One row per constant the rule depends on, the value as the crate has it; a reader implementing from this text uses these and nothing else. `tools/ci/spec-constants-check.mjs` (the pre-push gate) reads every table of this shape in this file back against the crate's `pub const` items and fails on a difference; `igneum-pow/tests/spec_readback.rs` derives every pinned id below through the crate.
| Constant | Value | Where |
|---|---|---|
| generator::INSTR_COUNT | 64 | instructions per base program |
| generator::LOAD_SLOTS | 16 | load slots per program |
| generator::ITERATIONS | 8 | iterations per hash |
| generator::LANES | 32 | lanes per unit |
| generator::GENERATOR_VERSION_V4 | 4 | the class v4 generator |
| generator::PROGRAM_SUBVERSION_V4 | 3 | the id suffix "sub/" || le16 |
| generator::MAX_ATTEMPTS | 32 | the cap under class v2 and v3 |
| generator::MAX_ATTEMPTS_V4 | 256 | the cap under the class v4 shape |
| generator::V4_SHADOW_INSTRS | 256 | shadow instructions per program |
| generator::V4_SHADOW_REPS | 27 | shadow passes per iteration at rung 0 |
| accept::ACCEPT_TAG | "igneum-accept/" | the domain tag of the base-nonce stream |
| accept::ACCEPT_UNITS | 64 | (c) units |
| accept::ACCEPT_HASHES | 2048 | (c) hashes |
| accept::ACCEPT_DATASET_LOG2 | 28 | log2 of the closed-form dataset |
| accept::MAX_SATURATED | 164 | (c) saturated finals and (c') saturated sources: the first refused count (the reject message prints 163, the last allowed) |
| accept::BIAS_TOLERANCE | 136 | (c) output bias, inclusive |
| accept::MIN_DISTINCT_SUM | 245760 | (c) distinct-address sum, exclusive |
| accept::ACCEPT_UNITS_DISTINCT_V4 | 4096 | (c'') units, 2^20 evaluations per site |
| accept::MIN_DISTINCT_RATIO_V4 | 0.98 | (c'') ratio floor, inclusive |
| accept::distinct_ratio_pass | 2 | the window cap of (c''): `W_s = 2^28 >> min(k_off_s, 2)`, a literal inside the function |
Pinned program ids. A reader who follows 1.4.3 and this section reproduces these from the seed, the attempt and the sub-version above. The era seed of each chain row is the same 32 bytes as its program seed (the devnet stand-in of 1.13.1). `igneum-pow/tests/spec_readback.rs` derives each id through the crate and draws each class v4 row with the era to its stated attempt; a "must differ" row asserts the current derivation gives another id.
| Seed | Attempt | Id | Note |
|---|---|---|---|
| edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 | 1 | a785001687d8688a | the shared devnet's epoch-0 seed under class v4 sub-version 3 (generator 4, the suffix); attempt 0 is rejected under class v4 |
| edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 | 0 | 73bcbfe8ccf988f1 | the same seed under class v3 (generator 3, no suffix): the class v3 control |
| edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 | 1 | c120d7963abdcd96 | must differ: generator 4 without the suffix, the stream of 6 October 2026 (sub-version 0, never stamped) |
| edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 | 1 | 1a4230699a6b9c60 | must differ: sub-version 1, the stream 0.3.20 and 0.3.21 shipped as object byte 5 |
| edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 | 1 | a788661687db4bb3 | must differ: sub-version 2, never shipped |
| 4020cb4382e3fe4b281c817c02582e147d8f851f566ae9172b28912b8e68b925 | 0 | fce15bf61030be57 | Devnet 3's epoch-0 seed (its genesis hash) under class v4 sub-version 3, accepted at attempt 0; 30956569d8f3d8d7 without the suffix |
Test vectors for the class v2 rule (`igneum-pow accept --seed ...`):
| Seed | Attempt 0 | Attempt 1 |
|---|---|---|
@ -192,7 +311,7 @@ Test vectors for the rule (`igneum-pow accept --seed ...`):
| `igneum-census-2026-10-03/37` | rejected, (c) 245,230 distinct addresses (mean 119.74) | accepted, `947705cc4eb1df0a` |
| `igneum-census-2026-10-03/51` | rejected, (b) r4 has no injecting write | accepted, `9869afcc028bf9f1` |
The Rust crate and the Swift prototype derive identical instruction lists and identical 96-vector sets on all five seeds (`docs/bench-log.md`, 4 October 2026).
The Rust crate and the Swift prototype derive identical instruction lists and identical 96-vector sets on all five seeds (`docs/bench-log.md`, 4 October 2026). For the class v4 rule, a second implementation written from the module table of `accept.rs` and this section agreed with the crate on 5,748 of 5,748 attempt verdicts over 1,792 seeds, part for part, with its known-failed control fired (adv-accept-3 section 6.4); an implementation written from the text of this section as it stood before 7 October 2026 mined a different program on 264 of 400 epochs (adv-accept-3 section 6.2, ledger AP-F8-5), which is why every constant and every order of operations is now stated here.
## 1.5 Fixed memory footprint
@ -244,6 +363,8 @@ The output folding rotations (7, 14, 21; 9, 18, 27) are Implemented, prototype v
`shfl` makes the 32 lanes of a unit interdependent: the hash of one nonce is defined only as a member of its aligned group of 32 (section 1.9).
Class v4 (Counter ASIC 3.0, the latency shadow): after instruction 63 of every iteration, and before the next iteration samples `sel`, the program's 256-instruction shadow block (section 1.4.3 (3)) is applied `V4_SHADOW_REPS` times with the iteration's `sel`, 27 at rung 0 of the latency ladder, so one hash runs 64 x 8 base instructions and 256 x 27 x 8 = 55,296 shadow instructions. The shadow holds no load. The acceptance interpreter of 1.4.6.4 runs the same block the same way (sub-version 3). The ladder (`docs/design/latency-ladder.md`) moves the pass count by miner signal and nothing else in this section.
## 1.8 The memory-hard dataset
Implemented (`memhard.rs`), construction and measurements in `proto-metal/MEMHARD.md`. Every constant below is a prototype value, to be fixed at gate 1, unless marked Definition. What fixes them is the shortcut-ratio and time-memory trade-off measurement on NVIDIA and AMD discrete cards (section 1.16 items 2 and 3) and an external review of the primitives (ledger M7).
@ -321,6 +442,8 @@ item(t) = s
Eight dependent cache reads (`ITEM_ROUNDS = 8`, prototype value): the address of read `r` depends on every earlier read. Nine mixer applications under program class v2.
Under class v5 the item's init words carry the leaf of section 1.8.6.
Program class v3 (Counter ASIC 2.0, decided 5 October 2026, delegated; the founder confirms for the public testnet genesis) applies the mixer `m = 8` times per round with distinct round keys (`LoadClass::mixer_mult`; `docs/plans/mixer-x4.md` section 2), the eight dependent reads unchanged:
```
@ -441,7 +564,7 @@ The era seed `E_n` is the 32-byte output of the 1-hour VDF of section 4.4 (in th
`epoch_len` is the one era-table parameter set by miners rather than by the draw: 90% of blue blocks over a 7-day window carrying the same ladder index (3 bits of the header version, encoding Open in section 5.8) sets that length from the first day boundary at least 2 days after the window closes (section 5.7). It is not a code upgrade: the rule, the ladder and the window are genesis constants, and the chain carries no release. The era stream consumes its draw so that a future draw of this parameter changes no other parameter's value. The threat it answers is a per-program hard datapath (an FPGA fleet: 42 to 160 minutes per compile on a mid-size part, PRflow, FPT 2019, hours on large parts; at 600 s nothing it compiles ever runs); it does not answer a programmable chip, which the other layers answer. The floor 600 is set by the slowest compile-ahead measured (the Metal variant race, 38 s on the M5 Max, 6.3% of a 600-s epoch and inside the 600-s seed window; `docs/plans/epoch-length.md` section 6).
The table layout and the working-set window (Counter ASIC 2.0 layers 4 and 8, decided IN on 5 October 2026, delegated: the six-era hash-rate spread is 1.3% on the RTX 5090, 3.2% on the RX 9070 XT and 0.8% on the M5 Max, under the 5% rule; `docs/plans/era-layout.md`) are drawn under program class v3 by a second stream `S` seeded with words 0 and 1 of `seed_words_from_bytes("igneum-era/" || E_n)` (the index is not in the preimage: `E_n` commits to `n` through the VDF input), seven draws in this order whether or not a value is used:
The table layout and the working-set window (Counter ASIC 2.0 layers 4 and 8, decided IN on 5 October 2026, delegated: the six-era hash-rate spread is 1.3% on the RTX 5090, 3.2% on the RX 9070 XT and 0.8% on the M5 Max, under the 5% rule; `docs/plans/era-layout.md`) are drawn under program class v3 by a second stream `S` seeded with words 0 and 1 of `seed_words_from_bytes("igneum-era/" || E_n)` (the index is not in the preimage: `E_n` commits to `n` through the VDF input), nine draws in this order whether or not a value is used (the eighth and ninth, `epoch_len` and the latency ladder, are consumed and not read: both are set by miner signal, and consuming their slots means a later use of either changes no other draw; `generator::era_draw`):
1. `W = allowed[below(|allowed|)]`: the width in words of every dataset load of the era, from the genesis-fixed set `allowed`; the set is `{1}` (4 bytes, the read-width decision of 5 October 2026), so the draw is consumed and the width pinned.
2. `M = low32(next()) OR 1`: the stride multiplier, odd, so `x -> x * M` is a bijection.

View file

@ -0,0 +1,115 @@
//! Spec read-back, the ids half (adv-accept-3 finding 3, ledger AP-F8-5, 7 October 2026): every table of
//! `docs/spec/01-lottery-hash.md` headed `| Seed | Attempt | Id | Note |` names program ids a reader of sections 1.4.3
//! and 1.4.6 must reproduce. This test derives each one through the crate (never by re-hashing the hex in a script):
//! a row whose Note says "must differ" asserts the current derivation gives another id (an earlier stream or
//! sub-version of the same seed); every other row asserts `program_id` over `attempt_words(seed, attempt)` under the
//! row's generator (3 for "class v3", 5 for "generator 5", else 4) equals the id, and, for a class v4 row, that the
//! chain's own draw with the era seed (the same bytes unless the Note names another) accepts at that attempt.
//! The constants half is `tools/ci/spec-constants-check.mjs` (the pre-push gate; no build).
use igneum_pow::generator::{attempt_words, generate_from_seed_bytes_program_class, program_id, ProgramClass, GENERATOR_VERSION_V3, GENERATOR_VERSION_V4};
use std::path::PathBuf;
const SPEC: &str = "../docs/spec/01-lottery-hash.md";
struct Row {
line: usize,
seed: String,
attempt: u32,
id: u64,
note: String,
}
fn rows() -> Vec<Row> {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(SPEC);
let text = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("{}: {e}", path.display()));
let lines: Vec<&str> = text.lines().collect();
let header = |l: &str| {
let cells: Vec<String> = l.trim().trim_matches('|').split('|').map(|c| c.trim().to_string()).collect();
cells == ["Seed", "Attempt", "Id", "Note"]
};
let mut out = Vec::new();
let mut i = 0;
while i < lines.len() {
if !header(lines[i]) {
i += 1;
continue;
}
let mut j = i + 1;
if j < lines.len() && lines[j].trim_start().starts_with("|---") {
j += 1;
}
while j < lines.len() && lines[j].trim_start().starts_with('|') {
let cells: Vec<String> = lines[j].trim().trim_matches('|').split('|').map(|c| c.trim().trim_matches('`').to_string()).collect();
assert!(cells.len() >= 4, "{}:{}: a Seed | Attempt | Id | Note row needs four cells", SPEC, j + 1);
let attempt: u32 = cells[1].parse().unwrap_or_else(|_| panic!("{}:{}: attempt {:?} is not an integer", SPEC, j + 1, cells[1]));
let id = u64::from_str_radix(cells[2].trim_start_matches("0x"), 16).unwrap_or_else(|_| panic!("{}:{}: id {:?} is not 16 hex", SPEC, j + 1, cells[2]));
out.push(Row { line: j + 1, seed: cells[0].clone(), attempt, id, note: cells[3..].join("|") });
j += 1;
}
i = j;
}
assert!(!out.is_empty(), "{SPEC}: no table headed | Seed | Attempt | Id | Note |");
out
}
fn seed_bytes(seed: &str) -> Vec<u8> {
let hex = seed.len() == 64 && seed.chars().all(|c| c.is_ascii_hexdigit());
if hex {
(0..32).map(|k| u8::from_str_radix(&seed[2 * k..2 * k + 2], 16).unwrap()).collect()
} else {
seed.as_bytes().to_vec()
}
}
fn generator_of(note: &str) -> u32 {
if note.contains("class v3") {
GENERATOR_VERSION_V3
} else if note.contains("generator 5") {
5
} else {
GENERATOR_VERSION_V4
}
}
#[test]
fn every_pinned_id_of_the_spec_derives_from_the_crate() {
let rows = rows();
let mut checked = 0;
for r in &rows {
let bytes = seed_bytes(&r.seed);
let words = attempt_words(&bytes, r.attempt);
let g = generator_of(&r.note);
let derived = program_id(g, &words, r.attempt);
if r.note.contains("must differ") {
assert_ne!(derived, r.id, "{}:{}: the must-differ id {:016x} equals the current derivation for seed {} attempt {}", SPEC, r.line, r.id, r.seed, r.attempt);
} else {
assert_eq!(derived, r.id, "{}:{}: the crate derives {:016x} for seed {} attempt {} under generator {g}, the spec says {:016x}", SPEC, r.line, derived, r.seed, r.attempt, r.id);
}
checked += 1;
}
assert!(checked >= 4, "the spec carries only {checked} pinned ids; the table has shrunk");
}
/// The chain's own draw (the era layout over the class v3 base, the shadow block, the full rule) accepts the class v4
/// rows at the attempt the spec states; the era seed is the program seed unless the Note names another 64-hex value
/// after "era".
#[test]
fn the_chain_draw_accepts_each_class_v4_row_at_its_attempt() {
let rows = rows();
let mut drawn = 0;
for r in rows.iter().filter(|r| !r.note.contains("must differ") && generator_of(&r.note) == GENERATOR_VERSION_V4) {
let bytes = seed_bytes(&r.seed);
let era: Vec<u8> = match r.note.find("era ") {
Some(k) => {
let hex: String = r.note[k + 4..].chars().take_while(|c| c.is_ascii_hexdigit()).collect();
if hex.len() == 64 { seed_bytes(&hex) } else { bytes.clone() }
}
None => bytes.clone(),
};
let p = generate_from_seed_bytes_program_class(&format!("spec:{}", &r.seed[..16.min(r.seed.len())]), &bytes, ProgramClass::V4, Some(&era));
assert_eq!(p.attempt, r.attempt, "{}:{}: the draw accepted seed {} at attempt {}, the spec says {}", SPEC, r.line, r.seed, p.attempt, r.attempt);
assert_eq!(p.program_id(), r.id, "{}:{}: the drawn program's id is {:016x}, the spec says {:016x}", SPEC, r.line, p.program_id(), r.id);
drawn += 1;
}
assert!(drawn >= 1, "no class v4 row to draw");
}

View file

@ -4,13 +4,13 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Igneum ledger: every criticism, answered</title>
<meta name="description" content="Every criticism Igneum expects, in the critic's words, with what was done, the status and the date. 183 entries. Nothing deleted, nothing softened.">
<meta name="description" content="Every criticism Igneum expects, in the critic's words, with what was done, the status and the date. 189 entries. Nothing deleted, nothing softened.">
<link rel="canonical" href="https://igneum.network/ledger">
<meta name="theme-color" content="#0C0C0E">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Igneum">
<meta property="og:title" content="Igneum ledger: every criticism, answered">
<meta property="og:description" content="183 criticisms in the critic's words, with what was done, the status and the date.">
<meta property="og:description" content="189 criticisms in the critic's words, with what was done, the status and the date.">
<meta property="og:url" content="https://igneum.network/ledger">
<meta property="og:image" content="https://igneum.network/og-small.png?v=3">
<meta property="og:image:width" content="256">
@ -18,7 +18,7 @@
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Igneum ledger: every criticism, answered">
<meta name="twitter:description" content="183 criticisms in the critic's words, with what was done, the status and the date.">
<meta name="twitter:description" content="189 criticisms in the critic's words, with what was done, the status and the date.">
<meta name="twitter:image" content="https://igneum.network/og-small.png?v=3">
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<link rel="icon" href="/favicon.ico" sizes="48x48">
@ -53,7 +53,7 @@
<!-- head:end -->
<style>
/* ledger page block (7 Oct 2026, the redesign: the page hero, the count table, the entries as records); tokens, type and components are in /site.css */
.entry p,.entry li,.entry .status{overflow-wrap:anywhere}.status .badge{white-space:normal;max-width:100%}.entry code{white-space:normal;overflow-wrap:anywhere}
.entry p,.entry li,.entry .status{overflow-wrap:anywhere}.entry code{white-space:normal;overflow-wrap:anywhere}
main h2{font-size:27px;margin:64px 0 22px;padding-top:0;border-top:0;scroll-margin-top:120px}@media(max-width:560px){main h2{font-size:22px}}
h3{font-family:var(--f-sans);font-weight:600;font-size:17px;margin:0;flex:1 1 auto;min-width:0}
.intro{font-size:17px;color:var(--ink-2);max-width:76ch;margin:0 0 24px}
@ -89,7 +89,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="nav-groups" id="nav-groups" role="list">
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-mine" data-group="mine" aria-expanded="false" aria-controls="nav-panel-mine" aria-haspopup="true">Mine<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-network" data-group="network" aria-expanded="false" aria-controls="nav-panel-network" aria-haspopup="true">Network<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-learn" data-group="learn" data-active aria-expanded="false" aria-controls="nav-panel-learn" aria-haspopup="true">Learn<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-learn" data-group="learn" aria-expanded="false" aria-controls="nav-panel-learn" aria-haspopup="true">Learn<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
</div>
<div class="nav-controls">
<button class="btn icon-btn" type="button" data-theme-toggle aria-label="Switch to light theme"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1 1m12 12 1 1M5 19l1-1M18 6l1-1"/></svg></button>
@ -154,7 +154,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="sheet-group"><div class="sheet-head">Learn</div>
<a href="/litepaper" data-nav="litepaper"><b>Litepaper</b><span>The design, as published.</span></a>
<a href="/income" data-nav="income"><b>Income per tier</b><span>IGN a day per card at three network sizes, and the electricity.</span></a>
<a href="/ledger" data-nav="ledger" aria-current="page"><b>Ledger</b><span>Every criticism, answered or conceded.</span></a>
<a href="/ledger" data-nav="ledger"><b>Ledger</b><span>Every criticism, answered or conceded.</span></a>
<a href="/claims" data-nav="claims"><b>What Igneum does not claim</b><span>The limits, stated first.</span></a>
<a href="/randomx" data-nav="randomx"><b>Igneum vs RandomX</b><span>What was kept and what was rebuilt for GPUs.</span></a>
<a href="/provenance" data-nav="provenance"><b>Built on the shoulders</b><span>Every borrowed part, credited.</span></a>
@ -216,23 +216,22 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<section class="page-hero">
<div class="container">
<div class="breadcrumb"><a href="/">Igneum</a><span>/</span><span>The ledger</span></div>
<div class="page-heading"><div><div class="eyebrow"><span class="line"></span>Ledger · 183 entries · regenerated from the repository</div>
<div class="page-heading"><div><div class="eyebrow"><span class="line"></span>Ledger · 189 entries · regenerated from the repository</div>
<h1>Every criticism, answered<br><span class="accent">or conceded.</span></h1>
<p class="lead">This is every criticism the project expects, in the critic's words, with what was done about it and the date. 183 entries since 3 October 2026. Entries are never deleted; a status that changes keeps its history on the line. Where the critic was right the entry says Conceded. Where nothing has been done it says Open and names what settles it. The founder mined through the GPU years. Ethereum's move to proof of stake in September 2022 ended that income and the miners' place in that chain. This is one person building, with AI systems doing the engineering, the coin he wanted to exist for miners: GPU-mined, the miners are the provers, no founder allocation, every cost stated. Help is welcome and a team is wanted: cryptographers, node engineers, miners who will test. This ledger is the application form: pick an open row and write to <a href="mailto:hello@igneum.network">hello@igneum.network</a> with its id.</p></div></div>
<p class="lead">This is every criticism the project expects, in the critic's words, with what was done about it and the date. 189 entries since 3 October 2026. Entries are never deleted; a status that changes keeps its history on the line. Where the critic was right the entry says Conceded. Where nothing has been done it says Open and names what settles it. The founder mined through the GPU years. Ethereum's move to proof of stake in September 2022 ended that income and the miners' place in that chain. This is one person building, with AI systems doing the engineering, the coin he wanted to exist for miners: GPU-mined, the miners are the provers, no founder allocation, every cost stated. Help is welcome and a team is wanted: cryptographers, node engineers, miners who will test. This ledger is the application form: pick an open row and write to <a href="mailto:hello@igneum.network">hello@igneum.network</a> with its id.</p></div></div>
</div>
</section>
<section class="section compact"><div class="container">
<div class="table-wrap counts"><table>
<thead><tr><th>Count</th><th>Status</th><th>Meaning</th></tr></thead>
<tbody>
<tr><td class="num">7</td><td><button type="button" class="chip" data-filter="Open">Open</button></td><td>Nothing has settled it yet. The entry names what will</td></tr>
<tr><td class="num">61</td><td><button type="button" class="chip" data-filter="Conceded">Conceded</button></td><td>The critic is right. &quot;Stated&quot; means the public text says so; &quot;not yet stated&quot; means it does not yet</td></tr>
<tr><td class="num">58</td><td><button type="button" class="chip" data-filter="Fixed or built">Fixed or built</button></td><td>A code, spec or text change answers it, with the commit or the page named</td></tr>
<tr><td class="num">3</td><td><button type="button" class="chip" data-filter="Open">Open</button></td><td>Nothing has settled it yet. The entry names what will</td></tr>
<tr><td class="num">64</td><td><button type="button" class="chip" data-filter="Conceded">Conceded</button></td><td>The critic is right. &quot;Stated&quot; means the public text says so; &quot;not yet stated&quot; means it does not yet</td></tr>
<tr><td class="num">64</td><td><button type="button" class="chip" data-filter="Fixed or built">Fixed or built</button></td><td>A code, spec or text change answers it, with the commit or the page named</td></tr>
<tr><td class="num">27</td><td><button type="button" class="chip" data-filter="Closed by rule or decided">Closed by rule or decided</button></td><td>A consensus rule or a decision by the owner answers it, dated</td></tr>
<tr><td class="num">13</td><td><button type="button" class="chip" data-filter="Answered with evidence">Answered with evidence</button></td><td>A measurement or a simulation exists and is named</td></tr>
<tr><td class="num">13</td><td><button type="button" class="chip" data-filter="Answered by design">Answered by design</button></td><td>A design rule answers it; no measurement is possible yet</td></tr>
<tr><td class="num">4</td><td><button type="button" class="chip" data-filter="Other">Other</button></td><td>A status outside the six above, read the line</td></tr>
<tr><td class="num">183</td><td><button type="button" class="chip" data-filter="">All</button></td><td>Every entry. The sections: <a href="#m">Mining and chips</a>, <a href="#f">Finality and attacks</a>, <a href="#p">Proving and the zkEVM</a>, <a href="#e">Economics and the coin</a>, <a href="#g">Governance and the founders</a>, <a href="#c">Comparisons</a>, <a href="#l">Legal and regulatory</a>, <a href="#x">Launch and operations</a>, <a href="#d">Builders</a></td></tr>
<tr><td class="num">15</td><td><button type="button" class="chip" data-filter="Answered with evidence">Answered with evidence</button></td><td>A measurement or a simulation exists and is named</td></tr>
<tr><td class="num">16</td><td><button type="button" class="chip" data-filter="Answered by design">Answered by design</button></td><td>A design rule answers it; no measurement is possible yet</td></tr>
<tr><td class="num">189</td><td><button type="button" class="chip" data-filter="">All</button></td><td>Every entry. The sections: <a href="#ap">The in-house adversarial pass</a>, <a href="#m">Mining and chips</a>, <a href="#f">Finality and attacks</a>, <a href="#p">Proving and the zkEVM</a>, <a href="#e">Economics and the coin</a>, <a href="#g">Governance and the founders</a>, <a href="#c">Comparisons</a>, <a href="#l">Legal and regulatory</a>, <a href="#x">Launch and operations</a>, <a href="#d">Builders</a></td></tr>
</tbody></table></div>
<div class="toolbar"><input type="search" id="q" placeholder="Search the ledger" aria-label="Search the ledger"><span id="shown"></span></div>
<h2 id="m">Mining and chips</h2>
@ -318,7 +317,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="head"><span class="id">M32</span><h3>&quot;Automatic anti-ASIC escalators&quot; overstates what the era draw and the instruction reserve do</h3><span class="date">6 October 2026</span></div>
<blockquote>You sell the era draw and the reserve unlock as anti-ASIC escalators, as if not knowing next era's parameters stops a chip. A chip that stores the dataset reads every drawn parameter as firmware: an address permute, a rotator, an immediate table. The families, the reserve order, the mixer, the dataset schedule and the class v4 shadow are all public at genesis. So what does the draw actually defend against?</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">6 October 2026, evening; the Horizon lane analysis <code>a repository file</code> sections 5.4 and 8, lane 2): the era draw and the instruction reserve are automatic schedule changes against fixed datapaths and against human forks; against the stored-dataset chip every drawn parameter is firmware, and the defence against that chip is the latency-shadow work (class v4) and the price-per-joule model. Stated in <code>a repository file</code>, Mining section (&quot;These are automatic schedule changes ... every drawn parameter is firmware&quot;) and the &quot;A chip is impossible&quot; item (&quot;a chip wired for one program is a bad bet ... not the schedule&quot;), the &quot;Every six months&quot; row of the comparison table, and <code>a repository file</code>, the hourly-program note (&quot;a chip wired for one program is useless&quot;). The phrase &quot;automatic anti-ASIC escalators&quot; is withdrawn from public text; it stays in the internal design summary until that is next edited.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The draw hides (M, R, pos, the op weights within +-2, the fold rotations) until 2 hours before each era, and none of those needs silicon. Biasing the draw is priced at 20 days of 100 percent of the network's hash for one more sample of the same space (lane section 5.4), so the draw is unbiasable at any price that matters and that is its whole job: it is a fairness device and a fork-free schedule, not a chip defence. What a chip wired for one program loses to is the hourly program itself; what the stored-dataset chip loses to is the latency shadow (class v4, 2.1x per joule at k = 1 and 3.9x at k about 0.33, the X9’s core, against the 5090 bench row; 0.9x and 1.7x against the Apple M5 Max; recalibrated under X35) and the price per joule, which is where the public claim now rests.</p></details>
<details><summary>The answer as first written</summary><p>Correct. The draw hides (M, R, pos, the op weights within +-2, the fold rotations) until 2 hours before each era, and none of those needs silicon. Biasing the draw is priced at 20 days of 100 percent of the network's hash for one more sample of the same space (lane section 5.4), so the draw is unbiasable at any price that matters and that is its whole job: it is a fairness device and a fork-free schedule, not a chip defence. What a chip wired for one program loses to is the hourly program itself; what the stored-dataset chip loses to is the latency shadow (class v4, 2.1x per joule at k = 1 against the 5090 bench row, and 3.9x at k about 0.33 as the pessimistic bound: the withdrawn Antminer X9's claimed, unmeasured core, a box of commodity Sophgo SG2044 SoCs withdrawn in mid-May 2026 before any unit shipped, no independent benchmark; 0.9x and 1.7x against the Apple M5 Max; X35, X36 and attack pass AP-F5-1) and the price per joule, which is where the public claim now rests.</p></details>
</article>
<article class="entry" id="M33" data-bucket="Conceded">
<div class="head"><span class="id">M33</span><h3>The FPGA ceiling rests on a tFAW the JEDEC HBM2 table does not give</h3><span class="date">6 October 2026</span></div>
@ -326,10 +325,10 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">6 October 2026, evening; the Horizon lane analysis <code>a repository file</code> section 5.1, the FPGA lane): the public FPGA line carries only the measured row, 2.4 G reads/s per card and 0.30x to 0.39x of the RTX 5090 per watt (Shuhai, FCCM 2020 Fig 7; the tFAW arithmetic from ICCAD 2021 Table I), and the 11.4 G bank-bound row and the 12.2 G ceiling are marked unmeasured until an AWS F2 hour measures them. Stated in <code>a repository file</code> section 5.3 (the activate-bound row marked UNMEASURED with the JEDEC figure beside it, and the FPGA paragraph after the table). The epoch-length analysis's 12.2 row is not on master yet and is corrected when it lands.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The measured 2.4 G/s had been read on 6 October as a mapping artefact (&quot;the paper's point is that this mapping is the wrong one for random access&quot;); the activate window says it is the DRAM's own limit, and a bank-interleaved mapping does not lift it because tFAW is enforced per channel by the die. The measurement that settles it is one AWS F2 hour (f2.6xlarge, Virtex UltraScale+ VU47P, 16 GB HBM2 in 2 stacks, 32 pseudo-channels, USD 1.98 an hour on demand): the chase kernel of <code>a repository file</code> 2.2 ported to a Vitis HLS AXI master over the HBM IP at 1 GiB across all 32 pseudo-channels, 256 to 4,096 lanes in flight, board power at 1 Hz; pass line 15 to 25 M reads/s/W (0.3x to 0.5x of the 5090), alarm 27 (0.5x), over 54 (1.0x) a Counter ASIC 4.0 item. Consequence per tier: none today (no FPGA mines); on the measured row a soft-overlay FPGA mines at an RX 9070 XT's rate per watt for about 7x the price (approximate), so no home or rig tier is displaced.</p></details>
</article>
<article class="entry" id="M34" data-bucket="Other">
<article class="entry" id="M34" data-bucket="Conceded">
<div class="head"><span class="id">M34</span><h3>The shadow size N is a constant of the binary, so the one lever against the dataset-storing chip needs a fork to move</h3><span class="date">7 October 2026</span></div>
<blockquote>Your own Horizon lane says the reserve and the era draw buy nothing against a chip that stores the dataset, and that the only lever is the latency-shadow size N. N is 27 passes of a 256-instruction block, hard-coded in <code>V4_CLASS</code>. So when HBM4 doubles a chip's rate per stack in 2028, your answer is a hard fork, and a fork that retires the M5 Max at the first doubling. And now there is a shipping RandomX ASIC.</blockquote>
<div class="status"><span class="badge b-other">Relabelled</span> <span class="did">7 October 2026, morning, X36): the X9 in this row and in the litepaper paragraph is the chip Bitmain announced and withdrew before launch, its core claimed and never measured; the ladder's arithmetic against that core is unchanged.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, implemented, stated</span> <span class="did">7 October 2026, night, the ledger close): the public text carries the ladder (<code>a repository file</code>, Mining: the six-rung genesis ladder of the latency shadow with a measured admissibility flag per rung, moved by miner signalling, never by a fork; and the X9 relabelled as announced, withdrawn and unbenchmarked), and the rule is implemented behind <code>latency_ladder_activation_daa</code> as the paragraph below records. Was: Conceded, implemented.</span></div>
<details><summary>The answer as first written</summary><p>Correct on both counts, and the second was the sharper one. The X9 (Bitmain, about 1 MH/s at 2,472 W, approximate, github.com/monero-project/monero/issues/10270) is a shipped 3x per-joule edge over a desktop CPU on the best-known latency-bound random-program design, seven years after launch; it makes the k = 0.3 column of the chip model a product class rather than an attacker's claim, and the public headline is now the range 2.1x (k = 1) to 3.9x (k = 0.33) over the RTX 5090 at class v4, with the ladder taking the X9 bracket to about 2.8x by rung 2 and the Apple tier's to about 1.1x by rung 3. The ladder does not close the gap; it is the chain's only automatic answer, it moves at the pace of the cards that pay for it, and the honest card's watts remain the lever that moves every row (algorithm lane proposal 7). What the ladder gives up by design: a chip holding over 10 percent of weight can stall it, and the status quo it stalls is a rung the cards already run.</p></details>
</article>
<h2 id="f">Finality and attacks</h2>
@ -394,9 +393,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>True. The vote key is named in the block header by whoever builds the block, which in a pool is the pool. The design doc states &quot;Pools hold their hashers' votes. Vote concentration equals pool concentration, as on Bitcoin, and is public.&quot; Stratum v2 lets a hasher choose transactions when its pool supports it, and does nothing for the vote key. Solo mining is viable at one block a second (86,400 blocks a day), which widens the key set in a way Bitcoin's block rate does not, and the dust threshold of 100 blocks per 30 days is about 0.004% of hashrate. The litepaper's &quot;governed by the people who power it, and by nobody else&quot; must carry the pool sentence.</p></details>
</article>
<article class="entry" id="F11" data-bucket="Answered by design">
<div class="head"><span class="id">F11</span><h3>VDFs are exotic</h3><span class="date">3 October 2026</span></div>
<div class="head"><span class="id">F11</span><h3>VDFs are exotic</h3><span class="date">7 October 2026</span></div>
<blockquote>A class-group VDF with Wesolowski proofs in a consensus-critical path, in a project with no cryptographer. Chia needed years and still got timelord ASICs.</blockquote>
<div class="status"><span class="badge b-answered-by-design">Answered by design, with the dependency conceded</span></div>
<div class="status"><span class="badge b-answered-by-design">Answered by design, with the dependency conceded</span> <span class="did">Update 7 October 2026 (era VDF lane): the era VDF is in the node (spec 4.4 Implemented, behind <code>era_vdf_activation_daa</code>, never until the founder sets it per network), on a fixed-width integer with no C library, with the hash-chain fallback behind the genesis scheme byte for the day a class group's order is computable; the attack pass's F7 harness fires against the stand-in (1 of 6 cuts re-rolled at no delay) and is silent against the VDF (0 of 6); the measured rates, prove and verify times and the margin against the fastest known prover (chiavdf's AVX-512 path on the same box) are in <code>a repository file</code>. The timelord-ASIC point is answered by the margin table of spec 4.6: the delay only has to exceed the 2-s publish window, and it does so by orders of magnitude on the fastest evaluator measured. The external review (O-4.1) is still owed. Was: Answered by design, with the dependency conceded.</span></div>
<details><summary>The answer as first written</summary><p>The VDF is used for one thing: making the hourly program unknowable within the roughly two seconds a miner has to decide whether to publish a block, closing a withhold-or-publish grind the review measured at about 130 to 1 for a 30% miner. The VDF input is a certified checkpoint at least one epoch before the epoch starts, so honest nodes have about 50 minutes of slack to evaluate a 10-minute VDF, and an evaluator 300x faster than reference would still be needed to beat the two-second decision window. Chia has run class-group VDFs in production since 2021, with faster hardware evaluators existing and not breaking it (approximate, from memory). The design doc lists the VDF as a new dependency and ships the evaluator in every node. The grinding simulation with and without the VDF is scheduled before gate 3.</p></details>
</article>
<article class="entry" id="F12" data-bucket="Answered by design">
@ -430,10 +429,10 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-conceded">Conceded, stated in the litepaper, with the dial explained</span></div>
<details><summary>The answer as first written</summary><p>True, and the litepaper says a full block needs a cluster of 100 to 200 consumer GPUs, approximate. Igneum's gas budget per block is a consensus constant set from measured prover throughput, so throughput is a function of how many cards are proving. With few provers at launch the chain carries little gas. The design treats that as a dial, not a failure, and the litepaper should publish the launch budget as a formula (cards proving times shards per card per minute) so builders can see it. Proving costs have fallen roughly an order of magnitude a year for three years, approximate, and the interface is swappable.</p></details>
</article>
<article class="entry" id="P3" data-bucket="Open">
<div class="head"><span class="id">P3</span><h3>A phone verifies in milliseconds is a SNARK-wrapper claim</h3><span class="date">5 October 2026</span></div>
<article class="entry" id="P3" data-bucket="Answered by design">
<div class="head"><span class="id">P3</span><h3>A phone verifies in milliseconds is a SNARK-wrapper claim</h3><span class="date">7 October 2026</span></div>
<blockquote>Hash-based STARK proofs are hundreds of kilobytes and take real work to verify. Milliseconds on a phone means a Groth16 or Plonk wrapper, and wrapping SP1 proofs needs a big machine for minutes.</blockquote>
<div class="status"><span class="badge b-open">Open, blocked on phase 2</span> <span class="did">the Groth16 or Plonk wrapper of the SP1 compressed proof is unbuilt; the certificate half is measured): next measurement the phase 2 benchmark, design R4 (Nov 2026 to Jan 2027 per the litepaper roadmap), a wrapped segment proof timed on a 12 GB and a 24 GB card and verified on a phone. Was: Open (the wrapper on consumer hardware, phase two), text stated (5 October 2026, night): <code>a repository file</code>, Proving, &quot;Wrapped for light clients, a phone checks it in milliseconds; the wrapping cost is a phase two measurement&quot;, followed by the certificate-half numbers (139 to 155 ms cold, 58 to 68 ms warm, laptop core, no phone) from <code>a repository file</code> &quot;FUD ledger sweep round 6&quot;, P3. Was: Open, the certificate half measured in a phone-sized tab, the wrapper half unmeasured and unbuilt (5 October 2026, evening sweep). Was: Open, experiment scheduled. Sweep (5 October 2026): hardware item (the wrapper on consumer hardware); not runnable here.</span></div>
<div class="status"><span class="badge b-answered-by-design">Answered by design</span> <span class="did">7 October 2026, night, the ledger close): the design rule covers the claim (design 5.6 <code>wrap</code>, R4: the aggregated block proof wrapped once into a small curve-based proof by the aggregator) and the public text says what is and is not measured (<code>a repository file</code>, Proving: &quot;Wrapped for light clients, a phone checks it in milliseconds; the wrapping cost is a phase two measurement&quot;, with the certificate half's 139 to 155 ms cold and 58 to 68 ms warm on a laptop core). The measurement that closes it: a wrapped segment proof timed on a 12 GB and a 24 GB card and verified on a phone, by the proving lane, in the phase 2 benchmark (November 2026 to January 2027 on the roadmap). Was: Open, blocked on phase 2.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The light-client proof is the aggregated block proof wrapped once into a small curve-based proof, and wrapping is the aggregator's job. The cost and latency of that wrapper on consumer hardware is unmeasured and belongs in the phase 2 benchmark alongside the shard time. Until measured, the litepaper should say &quot;wrapped for light clients&quot;.</p></details>
</article>
<article class="entry" id="P4" data-bucket="Conceded">
@ -577,9 +576,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>The founder's name is on every commit. The litepaper defers the team page to public testnet by decision, with disclosed mining addresses at genesis. There are no coins to sell and no sale planned, so there is nothing to run away with before block one. The five log entries dated 3 October 2026 are day one of the project and should be presented as that.</p></details>
</article>
<article class="entry" id="G4" data-bucket="Conceded">
<div class="head"><span class="id">G4</span><h3>No admin keys, except in everything that matters</h3><span class="date">7 October 2026</span></div>
<div class="head"><span class="id">G4</span><h3>No admin keys, except in everything that matters</h3><span class="date">6 October 2026</span></div>
<blockquote>'There are no admin keys.' The DEX, the lending market, the bridge and the dev fund contract all ship from your team. Bridges are where the admin keys live.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">7 October 2026, morning): the one-screen home page is back on the owner's word, so this row is stated on <code>a repository file</code> only; the sentence there is unchanged and the text check lists it under the litepaper.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">6 October 2026, night): the home page was redrawn as one statement, the live scene, three facts and the downloads, so the tile &quot;admin keys in consensus&quot; is no longer on <code>a repository file</code>; the sentence stands on <code>a repository file</code>, Governance (&quot;There are no admin keys in consensus&quot;). The 5 October line below is the history.</span></div>
<details><summary>The answer as first written</summary><p>Correct. Consensus has no admin keys. The genesis apps are contracts and each will have an upgrade policy; the bridge's is the one that matters, and if it starts as a committee bridge (E7) it has keys by definition. The development fund contract named in the quote no longer exists: the fund was removed on 3 October 2026. The litepaper's sentence must be scoped to consensus and each genesis contract must publish its key policy before launch.</p></details>
</article>
<article class="entry" id="G5" data-bucket="Conceded">
@ -619,10 +618,10 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-answered-by-design">Answered by design</span></div>
<details><summary>The answer as first written</summary><p>Monero chose the CPU for egalitarian reasons and accepted botnets as the price. Igneum chooses the GPU because the thesis is paid proving, which CPUs cannot do, and refuses a CPU lane because of botnets. It is a different trade, and the litepaper should say &quot;Monero's technique, applied to GPUs&quot; rather than &quot;finished&quot;.</p></details>
</article>
<article class="entry" id="C2" data-bucket="Other">
<div class="head"><span class="id">C2</span><h3>vs Monero: &quot;no chip in seven years&quot; is not proof</h3><span class="date">7 October 2026</span></div>
<article class="entry" id="C2" data-bucket="Conceded">
<div class="head"><span class="id">C2</span><h3>vs Monero: &quot;no chip in seven years&quot; is not proof</h3><span class="date">6 October 2026</span></div>
<blockquote>Absence of a public RandomX ASIC is not evidence one cannot exist. Monero is also a small prize.</blockquote>
<div class="status"><span class="badge b-other">Reopened as conceded</span> <span class="did">7 October 2026, morning, X36): the X9 never shipped, so Monero's record is again seven years without a shipped chip, and the concession stands as first written; the litepaper says so in the same sentences.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">6 October 2026, night): the home page no longer carries the RandomX paragraph; &quot;since 2019 (approximate)&quot; and &quot;precedent, not proof&quot; stand on <code>a repository file</code> (vs RandomX, Mining). The 5 October line below is the history.</span></div>
<details><summary>The answer as first written</summary><p>True. &quot;No chip publicly shipped, approximate&quot; is the defensible phrasing. The argument from Monero is precedent, not proof, and the bounty exists because precedent is not proof.</p></details>
</article>
<article class="entry" id="C3" data-bucket="Conceded">
@ -634,7 +633,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="C4" data-bucket="Answered with evidence">
<div class="head"><span class="id">C4</span><h3>vs Kaspa: a finality overlay changes GHOSTDAG's guarantees</h3><span class="date">5 October 2026</span></div>
<blockquote>GHOSTDAG's safety comes from blue work. A certificate that overrides blue work and a pruning point that never passes the latest lock are changes to the security model, not features on top.</blockquote>
<div class="status"><span class="badge b-answered-with-evidence">Measured on the live node line, and the overlay does NOT do what the spec says at a heal</span> <span class="did">a NEW SERIOUS FINDING (5 October 2026, evening sweep; owner: cryptographer and consensus engineer, decision owner the owner). Was: Open, experiment scheduled. Sweep (5 October 2026): the overlay has now run on a real DAG (cloud devnet, 4 October): with the module on, two partitions produced 0 conflicting locks, the 15.8% side locked nothing, the 84.2% side locked every interval, and the minority reorganised 423 to 496 blocks at the heal and adopted the majority's certificates within 15 s; the same day's F21 finding (a long honest partition locks alone from day 10 at 50/50) is the one real change to GHOSTDAG's guarantees found so far, and rule v3 answers it. The module-off comparison and the trace-driven adversary of O-3.8 are still owed.</span></div>
<div class="status"><span class="badge b-answered-with-evidence">Measured on the live node line, and the overlay does NOT do what the spec says at a heal</span> <span class="did">a NEW SERIOUS FINDING (5 October 2026, evening sweep; owner: cryptographer and consensus engineer, decision owner the founder). Was: Open, experiment scheduled. Sweep (5 October 2026): the overlay has now run on a real DAG (cloud devnet, 4 October): with the module on, two partitions produced 0 conflicting locks, the 15.8% side locked nothing, the 84.2% side locked every interval, and the minority reorganised 423 to 496 blocks at the heal and adopted the majority's certificates within 15 s; the same day's F21 finding (a long honest partition locks alone from day 10 at 50/50) is the one real change to GHOSTDAG's guarantees found so far, and rule v3 answers it. The module-off comparison and the trace-driven adversary of O-3.8 are still owed.</span></div>
<details><summary>The answer as first written</summary><p>True. Among candidate tips (those passing through every certified checkpoint) GHOSTDAG selects by blue work under the 3,600-second merge-depth bound; a certified checkpoint removes other tips from candidacy. That is a change, and its interaction with pruning, with red blocks in the attacker's weight and with latency is exactly what the gate 3 devnet measures. The module is separable so GHOSTDAG alone remains the fallback.</p></details>
</article>
<article class="entry" id="C5" data-bucket="Conceded">
@ -687,15 +686,15 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
</article>
<h2 id="l">Legal and regulatory</h2>
<article class="entry" id="L1" data-bucket="Open">
<div class="head"><span class="id">L1</span><h3>It is a security under Howey</h3><span class="date">6 October 2026</span></div>
<div class="head"><span class="id">L1</span><h3>It is a security under Howey</h3><span class="date">7 October 2026</span></div>
<blockquote>A founder's company earns a dev fee, runs a pool and a proving business, seeds the DEX, pays 'launch grants', and the roadmap ends in 'exchange listings after'. Expectation of profit from the efforts of others, in writing.</blockquote>
<div class="status"><span class="badge b-open">Open, counsel engaged</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 6, in progress). Was: Open, counsel not yet engaged. Sweep (5 October 2026): counsel; nothing runnable.</span></div>
<div class="status"><span class="badge b-open">Open</span> <span class="did">7 October 2026, night, the ledger close): only the founder's decision with counsel settles it; counsel engaged since 6 October 2026 (decisions item 6). The question for the founder: has counsel's Howey review of the founder-business paragraph, the launch grants and the pool returned, and on that opinion does the litepaper keep or drop the founder-business paragraph before v0.2? The listing sentence is already gone (overclaims 75 and 76).</span></div>
<details><summary>The answer as first written</summary><p>There is no sale, no premine, no allocation and no promise of return, and nothing in consensus is controlled by the team and no protocol fee reaches it (the development fund was removed on 3 October 2026), which is the structure that regulators have treated most favourably (approximate: compare the SEC's own framework on sufficiently decentralised networks and MiCA's exemption for tokens created automatically as a reward for maintaining a distributed ledger, approximate quotation). The weak points a lawyer will circle are the ones quoted: founder-run pool and proving business, founder-seeded DEX, launch grants, and the phrase &quot;exchange listings after&quot;. None is in consensus; all are promotional. The litepaper must drop the listing sentence and counsel must review the founder-business paragraph before v0.2. The legal entity is &quot;offshore, parked&quot; in the design doc, which is not an answer.</p></details>
</article>
<article class="entry" id="L2" data-bucket="Open">
<div class="head"><span class="id">L2</span><h3>Financial promotion rules</h3><span class="date">6 October 2026</span></div>
<div class="head"><span class="id">L2</span><h3>Financial promotion rules</h3><span class="date">7 October 2026</span></div>
<blockquote>Several jurisdictions now treat a cryptoasset promotion to their consumers as regulated: the UK since October 2023 needs an authorised approver, the EU under MiCA has its own marketing rules, the US has the Howey test. 'The people who show up early get the most' on a domain you own is a promotion wherever the reader sits.</blockquote>
<div class="status"><span class="badge b-open">Open, counsel engaged</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 6, in progress); the text half is stated below. Was: Open, counsel not yet engaged (decision owner the owner, with counsel); text half stated (5 October 2026, night): <code>a repository file</code>, Economics, Supply, &quot;Nearly a quarter of all supply is mined in the first year and half in the first two.&quot; with no &quot;so&quot; clause (overclaims 54 and 76, fud-fixes row 6); &quot;Half of all IGN&quot; absent from <code>a repository file</code>. Was: Open, counsel not yet engaged. Sweep (5 October 2026): counsel; nothing runnable.</span></div>
<div class="status"><span class="badge b-open">Open</span> <span class="did">7 October 2026, night, the ledger close): only the founder's decision with counsel settles it; the text half is stated (the schedule facts above). The question for the founder: does counsel confirm that the litepaper's schedule facts are information and not a financial promotion for UK and EU readers, or does the site need an authorised approver before the public testnet opens?</span></div>
<details><summary>The answer as first written</summary><p>A litepaper describing how to mine a coin that does not exist is arguably not an invitation to engage in investment activity, and the regime has carve-outs for information that is not an inducement (approximate; this needs an opinion from counsel in the jurisdiction the project is established in, which is offshore and not yet named). Sentences that read as inducements to acquire (&quot;show up early get the most&quot;, &quot;half of all supply in the first two years&quot;) should be rewritten as schedule facts before v0.2. Country-code domains such as igneum.co.uk redirect to igneum.network and carry no separate content.</p></details>
</article>
<article class="entry" id="L3" data-bucket="Closed by rule or decided">
@ -705,15 +704,15 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>True. the US registrar and the host are both US companies and have both complied with takedowns. Mitigations: an ENS or equivalent name and an IPFS mirror of the site and litepaper, the site's content hash published in the repository and in the genesis block, at least one non-US registrar for a second TLD, and the chain itself never depending on any domain (seed nodes are addresses in the client, not DNS only). Phase 5.</p></details>
</article>
<article class="entry" id="L4" data-bucket="Open">
<div class="head"><span class="id">L4</span><h3>Paying testnet miners real money is a payment before launch</h3><span class="date">6 October 2026</span></div>
<div class="head"><span class="id">L4</span><h3>Paying testnet miners real money is a payment before launch</h3><span class="date">7 October 2026</span></div>
<blockquote>'Testnet miners are paid real money for real proofs from phase five.' That is a business paying contractors in crypto across borders with no entity.</blockquote>
<div class="status"><span class="badge b-open">Open, counsel engaged</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 6, in progress). Was: Open. Sweep (5 October 2026): counsel and entity; nothing runnable.</span></div>
<div class="status"><span class="badge b-open">Open</span> <span class="did">7 October 2026, night, the ledger close): only the founder's decision with counsel settles it. The question for the founder: which entity signs the testnet payment terms with the customer rollup, and does counsel's payments and tax opinion arrive before phase 5, so that paid testnet proving can be announced or the sentence comes out of the roadmap?</span></div>
<details><summary>The answer as first written</summary><p>Correct that it needs an entity, terms and tax treatment before it happens. The payments come from the customer rollup on its own chain, not from Igneum, but the arrangement is organised by the project. Counsel before phase 5.</p></details>
</article>
<article class="entry" id="L5" data-bucket="Open">
<div class="head"><span class="id">L5</span><h3>Trademark</h3><span class="date">6 October 2026</span></div>
<article class="entry" id="L5" data-bucket="Answered with evidence">
<div class="head"><span class="id">L5</span><h3>Trademark</h3><span class="date">7 October 2026</span></div>
<blockquote>Igneum. Have you checked EUIPO, USPTO and the UK IPO? There is no evidence you did.</blockquote>
<div class="status"><span class="badge b-open">Open, counsel engaged</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 6, in progress): the clearance search is recorded in the repository as a dated one-line result per register when it returns. Was: Open. Sweep (5 October 2026): a person's search, recorded outside the repository; nothing runnable.</span></div>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence</span> <span class="did">7 October 2026, night, the ledger close): the clearance search is recorded in the repository as the entry asked, <code>a repository file</code> (3 October 2026, one verdict per register: EUIPO RISK, IGNIUM EUTM 018212492 live in classes 36 and 42; UK IPO RISK, IGNIUM UK00918212492 live; USPTO MODERATE RISK, IGNIUM pending in 9 and 42; WIPO partial, no IGNEUM; UAE unsearched; an identical IGNEUM registered in Australia in 37 and 42; preliminary, automated, no attorney review). The name stays provisional in the public text until counsel's filing plan for the IGNIUM mark; the one decision left for the founder: file in classes 9, 36 and 42 on counsel's plan before the public testnet, or keep the name provisional through launch. Was: Open, counsel engaged.</span></div>
<details><summary>The answer as first written</summary><p>No clearance search is recorded in the repository. One is required before the name is used commercially, in all three registers and in Nice classes 9, 36 and 42, approximate. Until then the name is provisional and the litepaper should not claim otherwise.</p></details>
</article>
<article class="entry" id="L6" data-bucket="Answered by design">
@ -724,9 +723,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
</article>
<h2 id="x">Launch and operations</h2>
<article class="entry" id="X1" data-bucket="Conceded">
<div class="head"><span class="id">X1</span><h3>&quot;Reproducible from the repository&quot; and the repository is private</h3><span class="date">5 October 2026</span></div>
<div class="head"><span class="id">X1</span><h3>&quot;Reproducible from the repository&quot; and the repository is private</h3><span class="date">7 October 2026</span></div>
<blockquote>Your site links to github.com/igneum-network/igneum. It 404s. 'Every number above is measured, published, and reproducible from the repository' is false today.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">5 October 2026, night): <code>a repository file</code>, vs RandomX &quot;Track record&quot; row, &quot;The specification, reference hash, test vectors and simulators are public now (github.com/igneum-network/spec). The node, the miner and the wallet are in a private repository until the public testnet&quot;. Was: Conceded, fix now. Updated (7 October 2026, night): the repository links point at git.igneum.network/igneum-network/spec, and the sentence reads &quot;The node, the miner and the wallet follow to the same host as the repository is published&quot;.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">7 October 2026, night): <code>a repository file</code>, vs RandomX &quot;Track record&quot; row, &quot;The specification, reference hash, test vectors and simulators are public now (git.igneum.network/igneum-network/spec). The node, the miner and the wallet follow to the same host as the repository is published&quot;; every repository link on the site points at the git host while the GitHub account is suspended (checked by <code>a repository file</code>). Was: Conceded, stated (5 October 2026, night): the same row with the GitHub link and &quot;The node, the miner and the wallet are in a private repository until the public testnet&quot;. Was: Conceded, fix now.</span></div>
<details><summary>The answer as first written</summary><p>Correct. Either the repository goes public with the litepaper or the sentence and the GitHub link come off the site until January 2027. Publishing the bench logs, the simulator and the test report with the litepaper is the cheaper fix and the honest one.</p></details>
</article>
<article class="entry" id="X2" data-bucket="Conceded">
@ -736,9 +735,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>Correct. The button should say what exists: &quot;Benchmark: January 2027&quot;.</p></details>
</article>
<article class="entry" id="X3" data-bucket="Conceded">
<div class="head"><span class="id">X3</span><h3>&quot;Proven by fire&quot; when nothing has run</h3><span class="date">5 October 2026</span></div>
<div class="head"><span class="id">X3</span><h3>&quot;Proven by fire&quot; when nothing has run</h3><span class="date">6 October 2026</span></div>
<blockquote>Tagline: Proven by fire. Status: pre-specification, pre-testnet. 'Watch the chain prove itself' with nothing on the page.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded in part, labelled, stated</span> <span class="did">5 October 2026, night): <code>a repository file</code>, the sentence &quot;All of it will be on this page, live&quot; is no longer on the page; the proofs feed now ends &quot;Live rows arrive with the public testnet, August 2027&quot; (overclaim 61). Was: Conceded in part, labelled.</span></div>
<div class="status"><span class="badge b-conceded">Conceded in part, labelled, stated</span> <span class="did">6 October 2026, night): the proofs feed moved to the litepaper's proving section with the home-page redesign and reads &quot;Live rows arrive with the public testnet. The public testnet is weeks away: three seed nodes and the public RPC are up, and it opens when the go checklist closes.&quot; (X31). The 5 October line below is the history.</span></div>
<details><summary>The answer as first written</summary><p>The tagline plays on &quot;proven&quot; as in ZK proofs and &quot;cupel&quot;. The homepage marks every live panel &quot;PREVIEW&quot;, &quot;prototype&quot; or &quot;at testnet&quot;, which is honest. The sentence &quot;All of it will be on this page, live&quot; is a promise about a future testnet and should say when. The tagline stays; nothing in the ledger depends on it.</p></details>
</article>
<article class="entry" id="X4" data-bucket="Conceded">
@ -750,7 +749,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="X5" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">X5</span><h3>1,000 independent miners is a Sybil number</h3><span class="date">6 October 2026</span></div>
<blockquote>Your testnet gate is 1,000 independent miners for 30 days. One person with a script is 1,000 miners.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 3): the independence definition as written, with the silent-fleet addition (a key with no fingerprint counts as its own class only when its address is in an autonomous system no other key uses); the observer columns on <code>ledger-observer</code> (O-X.1) ship with the next cut; measurement scheduled. Was: Conceded, measurement defined from the vote-key window and today's numbers (5 October 2026, evening sweep); decision owner the owner (O-X.1). Was: Conceded, measurement to define.</span></div>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 3): the independence definition as written, with the silent-fleet addition (a key with no fingerprint counts as its own class only when its address is in an autonomous system no other key uses); the observer columns on <code>ledger-observer</code> (O-X.1) ship with the next cut; measurement scheduled. Was: Conceded, measurement defined from the vote-key window and today's numbers (5 October 2026, evening sweep); decision owner the founder (O-X.1). Was: Conceded, measurement to define.</span></div>
<details><summary>The answer as first written</summary><p>Correct. &quot;Independent&quot; needs a definition that can be measured: distinct ASNs, distinct hardware fingerprints from the benchmark, or signed attestations from pool operators. Defined in phase 4, before the gate is tested.</p></details>
</article>
<article class="entry" id="X6" data-bucket="Closed by rule or decided">
@ -766,9 +765,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>Correct. The site needs a contact route before the litepaper is shared, and the repository needs to be public or a public issue tracker needs to exist. Until then this ledger's submission line points at a route that does not exist.</p></details>
</article>
<article class="entry" id="X8" data-bucket="Conceded">
<div class="head"><span class="id">X8</span><h3>Exchange listings as a roadmap item</h3><span class="date">7 October 2026</span></div>
<div class="head"><span class="id">X8</span><h3>Exchange listings as a roadmap item</h3><span class="date">6 October 2026</span></div>
<blockquote>'Mainnet fair launch: Genesis with no premine, 30-day ramp, exchange listings after.' You put listings in the roadmap.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">7 October 2026, morning): the one-screen home page is back on the owner's word, so this row is stated on <code>a repository file</code> only; the sentence there is unchanged and the text check lists it under the litepaper.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">6 October 2026, night): the home page's journey is no longer shown (the inlined feed remains in the page source); the sentence &quot;No listing is arranged, promised or sought by the project&quot; stands on <code>a repository file</code> Roadmap phase 6 and in <code>a repository file</code>. The 5 October line below is the history.</span></div>
<details><summary>The answer as first written</summary><p>Correct. No listing is arranged, promised or sought by the project. The phrase comes off the roadmap and the homepage journey.</p></details>
</article>
<article class="entry" id="X9" data-bucket="Conceded">
@ -848,7 +847,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="F16" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">F16</span><h3>A lock can become uncertified after a heal</h3><span class="date">6 October 2026</span></div>
<blockquote>Section 3.5: two certificates at one index, strike the equivocators, re-evaluate, and if neither or both still lock the index is uncertified. So the lock my node reported and I credited on is revocable.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 2): option B, a verified certificate is never withdrawn (spec 3.11.4); the 3.5 paragraph is replaced by 3.11.4's text after <code>c4-fix</code> merges, <code>finality_conflict</code> and the <code>finality_active</code> clear go into the node, the forced double-certificate test of 3.11.7 follows; fix scheduled, consensus engineer. Was: Open, the two options priced, one recommended (5 October 2026, evening sweep); decision owner the owner (gate 3, O-3.17). Was: Open, decision at gate 3 (extends O-3.6). Sweep (5 October 2026): a decision item (O-3.17); nothing runnable.</span></div>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 2): option B, a verified certificate is never withdrawn (spec 3.11.4); the 3.5 paragraph is replaced by 3.11.4's text after <code>c4-fix</code> merges, <code>finality_conflict</code> and the <code>finality_active</code> clear go into the node, the forced double-certificate test of 3.11.7 follows; fix scheduled, consensus engineer. Was: Open, the two options priced, one recommended (5 October 2026, evening sweep); decision owner the founder (gate 3, O-3.17). Was: Open, decision at gate 3 (extends O-3.6). Sweep (5 October 2026): a decision item (O-3.17); nothing runnable.</span></div>
<details><summary>The answer as first written</summary><p>Correct as the proposal stands. For an exchange &quot;locked&quot; must be irrevocable or it is a confirmation count. The alternative is Kaspa's: a verified certificate is never re-evaluated; two certificates at one index are a chain split that halts <code>finality_active</code> until an operator intervenes, and the node never reports a lock it may withdraw. Equivocation costing history and not coins (F6) means the attacker who caused the split keeps the deposit either way. Decision at gate 3; the devnet partition-and-heal test of O-3.6 measures whichever rule is chosen.</p></details>
</article>
<article class="entry" id="F17" data-bucket="Closed by rule or decided">
@ -957,8 +956,8 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="M22" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">M22</span><h3>The ASIC challenge has no scoring rules, and 2x is not the economic line</h3><span class="date">6 October 2026</span></div>
<blockquote>Your bounty says 'beats a GPU by more than 2x'. Per what? Hashes per second, per joule, per dollar, on the average program or the worst hour? A chip at 1.6x with half the capital cost wins. And nobody has published eligible hardware, funding or a judge.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no bounty, so no bounty terms; M22's metrics (hashes per second and per joule per program over at least 100 epochs as a distribution, capital cost per unit of hash rate at a stated volume, the longevity term, the shortcut classes scored separately) become the public benchmark's scoring rules and the brief of the in-house adversarial pass. Was: Open, decision for the owner (terms, judge and funding) and experiment scheduled (extends O-1.17). Sweep (5 October 2026): nothing runnable; the terms, judge and funding are the owner's decision.</span></div>
<details><summary>The answer as first written</summary><p>Correct. M1 and O-1.17 name a bounty for &quot;more than 2x&quot; without a metric, a judge or a fund, and 2x is a design target for the hash, not an economic threshold: a chip at 1.5x per joule and 3x per dollar of capital is an economic ASIC whatever the hash-rate ratio says. The scoring rules go out with the January 2027 benchmark: hashes per second and per joule measured per program over a published set of at least 100 epochs, reported as a distribution (worst decile, median), never as one average; capital cost per unit of hash rate at a stated volume; a longevity term against the instruction-family reserve and the dataset growth of spec 1.13; and the shortcut classes (recomputation, partial storage, weak-program selection) scored separately. Eligible hardware assumptions, the judge, the reward and the payer are the owner's decisions (fud-fixes row 50: the payer is the entity). The supportable public claim until a design has been scored: across the tested workloads and the stated economic assumptions, consumer GPUs remain competitive against the best independently proposed specialised design. Extends M1, M16 and C13.</p></details>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:35 UTC, by the owner; decisions item 1, corrected): no bounty, so no bounty terms; M22's metrics (hashes per second and per joule per program over at least 100 epochs as a distribution, capital cost per unit of hash rate at a stated volume, the longevity term, the shortcut classes scored separately) become the public benchmark's scoring rules and the brief of the in-house adversarial pass. Was: Open, decision for the founder (terms, judge and funding) and experiment scheduled (extends O-1.17). Sweep (5 October 2026): nothing runnable; the terms, judge and funding are the founder's decision.</span></div>
<details><summary>The answer as first written</summary><p>Correct. M1 and O-1.17 name a bounty for &quot;more than 2x&quot; without a metric, a judge or a fund, and 2x is a design target for the hash, not an economic threshold: a chip at 1.5x per joule and 3x per dollar of capital is an economic ASIC whatever the hash-rate ratio says. The scoring rules go out with the January 2027 benchmark: hashes per second and per joule measured per program over a published set of at least 100 epochs, reported as a distribution (worst decile, median), never as one average; capital cost per unit of hash rate at a stated volume; a longevity term against the instruction-family reserve and the dataset growth of spec 1.13; and the shortcut classes (recomputation, partial storage, weak-program selection) scored separately. Eligible hardware assumptions, the judge, the reward and the payer are the founder's decisions (fud-fixes row 50: the payer is the entity). The supportable public claim until a design has been scored: across the tested workloads and the stated economic assumptions, consumer GPUs remain competitive against the best independently proposed specialised design. Extends M1, M16 and C13.</p></details>
</article>
<h2 id="f">Finality and attacks</h2>
<article class="entry" id="F19" data-bucket="Answered with evidence">
@ -970,7 +969,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="F20" data-bucket="Answered with evidence">
<div class="head"><span class="id">F20</span><h3>During a finality pause the program must keep advancing, and nothing says which guarantees survive</h3><span class="date">5 October 2026</span></div>
<blockquote>Your epoch seed is a VDF of a certified checkpoint. When finality pauses for four days, your own 50% churn figure, which checkpoint seeds hour 50? And when the pause ends, what exactly was still guaranteed in between?</blockquote>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence for the test half</span> <span class="did">5 October 2026, night, ledger close round 1: the fast-time run through four epoch boundaries under a 47.5% silent set, bench-log &quot;5 October 2026 (night), ledger close round 1: F20 finality pause under a 45% silent set through four epoch boundaries&quot;); the gate-3 wording of the four guarantees (O-3.16, O-4.3) stays a decision for the owner. Was: Open, decision scheduled at gate 3 (O-3.16, with O-4.3). Sweep (5 October 2026): the seed half is decided (spec 4.3, from O-4.3: the seed checkpoint is the selected-chain block at the lead's blue score, certified or not, so mining never waits for a certificate) and spec 06 marks O-3.16's text closed; the devnet test through three epoch boundaries under a 45% silent set is still owed (devnet, person).</span></div>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence for the test half</span> <span class="did">5 October 2026, night, ledger close round 1: the fast-time run through four epoch boundaries under a 47.5% silent set, bench-log &quot;5 October 2026 (night), ledger close round 1: F20 finality pause under a 45% silent set through four epoch boundaries&quot;); the gate-3 wording of the four guarantees (O-3.16, O-4.3) stays a decision for the founder. Was: Open, decision scheduled at gate 3 (O-3.16, with O-4.3). Sweep (5 October 2026): the seed half is decided (spec 4.3, from O-4.3: the seed checkpoint is the selected-chain block at the lead's blue score, certified or not, so mining never waits for a certificate) and spec 06 marks O-3.16's text closed; the devnet test through three epoch boundaries under a 45% silent set is still owed (devnet, person).</span></div>
<details><summary>The answer as first written</summary><p>Correct on the gap. Spec 4.3 proposes that the seed checkpoint may be the uncertified selected-chain block at the checkpoint blue score, so a pause does not stop mining, and O-4.3 leaves the decision to gate 3; the design document still says an epoch cannot start without a valid proof. No text states what holds during a pause: that blocks, execution and proofs continue (3.7 item 2 says proof of work in practice), that every lock before the pause stands (3.5), that <code>finality_active</code> is false and exchanges wait on the 12-hour finality depth (3.9), and that the seed pipeline advances from uncertified checkpoint blocks with the reorg exposure that implies (a 1,200-DAA-s lead plus d). Gate 3 takes the uncertified option or states the stop; this ledger recommends uncertified, as spec 4.3 does, and the four guarantees go into spec 3.7. Test: the devnet with the finality module stalled by a 45% silent set (3.3.1 row C) through at least 3 epoch boundaries, recording that the program advanced on schedule, that no node forked on the seed, and that the pre-pause locks survived the heal.</p></details>
</article>
<article class="entry" id="F22" data-bucket="Fixed or built">
@ -1008,7 +1007,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="E14" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">E14</span><h3>No funding table</h3><span class="date">6 October 2026</span></div>
<blockquote>Who pays for development, the independent review, the infrastructure and an incident response, from what, and what happens if revenue is late? You have no fund by design, which means you have no table either.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 4): the funding table stays internal until counsel has read it; one public sentence in the litepaper names the unfunded lines (the second client, the external reviewers, the bounty before escrow). Was: Open, with a placeholder table: <code>a repository file</code> (3 October 2026, marked PLACEHOLDER on 4 October) lists the sources (the founder's own means today, the 1% client fee, the team's own mining and proving, no protocol fee) and the cost lines; the owner parked funding on 4 October 2026 and the decision stays his. Was: Open, decision for the owner.</span></div>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 4): the funding table stays internal until counsel has read it; one public sentence in the litepaper names the unfunded lines (the second client, the external reviewers, the bounty before escrow). Was: Open, with a placeholder table: <code>a repository file</code> (3 October 2026, marked PLACEHOLDER on 4 October) lists the sources (the founder's own means today, the 1% client fee, the team's own mining and proving, no protocol fee) and the cost lines; the founder parked funding on 4 October 2026 and the decision stays his. Was: Open, decision for the founder.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The fund was removed on purpose (E4) and the team earns from the 1% client fee, its pool, its provers and the app share (E5); none of that is costed, and the second client has no funder (fud-fixes row 47), nor do the external reviewers (G1), the bounty (M22), the seed nodes or the public infrastructure. The table: each cost line (development, independent review, infrastructure, incident response, the bounty, the second client) against its source (the entity's own money, the client fee, the proving business, a grant mechanism added by signalling), labelled funded, dependent on future revenue, or unfunded, with the consequence if revenue is late. It assumes a flat IGN price, which is E15's test. The table is internal until counsel has read it (L1, L2); the litepaper states which lines are unfunded.</p></details>
</article>
<article class="entry" id="E15" data-bucket="Closed by rule or decided">
@ -1021,26 +1020,26 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="G11" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">G11</span><h3>Publish the inspectable components now, labelled experimental</h3><span class="date">4 October 2026</span></div>
<blockquote>The organisation has no public repository. Harnesses, test vectors, simulators and the specification could be public tonight, marked experimental. Waiting for January is a choice, and it reads as hiding.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">4 October 2026, 08:20 UTC): the specification subset is public as <code>igneum-network/spec</code> (<code>a repository file</code>), labelled; the node fork, the proving code and the harnesses stay private until the benchmark. Was: Open, decision for the owner.</span></div>
<details><summary>The answer as first written</summary><p>The fact is conceded in X1 (the repository is private and the site says reproducible) and the pre-publication steps are in <code>a repository file</code> section 5 (ledger out of the tree, the project rules file rewritten, history rewritten, licence). The reviewer asks for an earlier date than January 2027 and a narrower scope: the benchmark harnesses, the test vectors, the simulators and <code>a repository file/</code>, each labelled experimental, with the node fork following when the gate-2 work is in. the owner decides which components, under which licence, and when; section 5 runs first in any case. The reviewer's companion advice, one proof-request workflow and one reference application before any broader app set, is the same decision's scope: the genesis-app list (G4, O-5.4) is not a prerequisite for the benchmark or the testnet.</p></details>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">4 October 2026, 08:20 UTC): the specification subset is public as <code>igneum-network/spec</code> (<code>a repository file</code>), labelled; the node fork, the proving code and the harnesses stay private until the benchmark. Was: Open, decision for the founder.</span></div>
<details><summary>The answer as first written</summary><p>The fact is conceded in X1 (the repository is private and the site says reproducible) and the pre-publication steps are in <code>a repository file</code> section 5 (ledger out of the tree, the project rules file rewritten, history rewritten, licence). The reviewer asks for an earlier date than January 2027 and a narrower scope: the benchmark harnesses, the test vectors, the simulators and <code>a repository file/</code>, each labelled experimental, with the node fork following when the gate-2 work is in. The founder decides which components, under which licence, and when; section 5 runs first in any case. The reviewer's companion advice, one proof-request workflow and one reference application before any broader app set, is the same decision's scope: the genesis-app list (G4, O-5.4) is not a prerequisite for the benchmark or the testnet.</p></details>
</article>
<h2 id="x">Launch and operations</h2>
<article class="entry" id="X13" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">X13</span><h3>One paying customer for a stated reason</h3><span class="date">6 October 2026</span></div>
<blockquote>'One rollup signs for testnet' is a letter of intent with no money. A customer who pays once, pays again without a rebate, and then a second unrelated customer, is evidence. A signature is not.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 5): the paid pilot stays in phase 5, the phase 4 gate stays the signature, nothing moves earlier before counsel answers L4. Was: Open, experiment scheduled (the pilot itself), decision for the owner on timing and terms; extends L4 and the customer brief. Sweep (5 October 2026): a decision and a customer; nothing runnable.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The phase 4 gate is a signature and the brief says so (&quot;a signed letter of intent with no payment&quot;). The progression is adopted and the brief carries it at its next version: agree the workload, proof format, deadline, failure rate and price before the pilot; publish the outcome and the customer's own reason for buying; then repeat purchases without reimbursement; then several unrelated customers. The reviewer places the paid pilot before public testnet; the journey has it in phase 5. Phase 4 keeps the signature as its gate and phase 5's line gains the paid pilot; moving it earlier is the owner's call and needs the entity, terms and tax treatment of L4 first.</p></details>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 5): the paid pilot stays in phase 5, the phase 4 gate stays the signature, nothing moves earlier before counsel answers L4. Was: Open, experiment scheduled (the pilot itself), decision for the founder on timing and terms; extends L4 and the customer brief. Sweep (5 October 2026): a decision and a customer; nothing runnable.</span></div>
<details><summary>The answer as first written</summary><p>Correct. The phase 4 gate is a signature and the brief says so (&quot;a signed letter of intent with no payment&quot;). The progression is adopted and the brief carries it at its next version: agree the workload, proof format, deadline, failure rate and price before the pilot; publish the outcome and the customer's own reason for buying; then repeat purchases without reimbursement; then several unrelated customers. The reviewer places the paid pilot before public testnet; the journey has it in phase 5. Phase 4 keeps the signature as its gate and phase 5's line gains the paid pilot; moving it earlier is the founder's call and needs the entity, terms and tax treatment of L4 first.</p></details>
</article>
<article class="entry" id="X14" data-bucket="Answered with evidence">
<div class="head"><span class="id">X14</span><h3>Concentration is unmeasured in four places</h3><span class="date">5 October 2026</span></div>
<blockquote>Define independent for the 1,000-miner gate, then report concentration in hashing, checkpoint signing, proving and aggregation, because a thousand miners behind two pools is two.</blockquote>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence for all four</span> <span class="did">5 October 2026, night, ledger close round 2: signing concentration read from the certificates and votes the chain blocks carry in their coinbase finality section, top-1 10.0%, top-3 29.1%, top-10 77.3% of signed weight over the heaviest certificate at each of 126 indices in the window; bench-log &quot;5 October 2026 (night), ledger close round 2: X14 signing concentration from block payloads&quot;); the independence definition stays the owner's (X5). Was: Answered with evidence for hashing, aggregation and proving, Open for signing (5 October 2026, night, ledger close round 1: no RPC exposes a certificate's signer set, so the signing concentration needs the observer extract of O-X.1; bench-log &quot;5 October 2026 (night), ledger close round 1: X14 concentration in hashing, signing, proving and aggregation from the Apple M5 Max node's RPCs, and E16 one live block&quot;); the independence definition stays the owner's (X5). Was: Open, measurement scheduled (O-X.1); extends X5. Sweep (5 October 2026): hashing concentration computed from the devnet record (<code>a repository file</code>, 8,090 blocks, 18 vote keys): top-1 12.8%, top-3 34.5%, top-9 98.0%, the nine being devnet v4's nine identities run by three machines (approximate), so by machine the devnet is three parties. Signing, proving and aggregation concentration need certificate and proof-record extracts the observer does not keep yet (O-X.1).</span></div>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence for all four</span> <span class="did">5 October 2026, night, ledger close round 2: signing concentration read from the certificates and votes the chain blocks carry in their coinbase finality section, top-1 10.0%, top-3 29.1%, top-10 77.3% of signed weight over the heaviest certificate at each of 126 indices in the window; bench-log &quot;5 October 2026 (night), ledger close round 2: X14 signing concentration from block payloads&quot;); the independence definition stays the founder's (X5). Was: Answered with evidence for hashing, aggregation and proving, Open for signing (5 October 2026, night, ledger close round 1: no RPC exposes a certificate's signer set, so the signing concentration needs the observer extract of O-X.1; bench-log &quot;5 October 2026 (night), ledger close round 1: X14 concentration in hashing, signing, proving and aggregation from the Apple M5 Max node's RPCs, and E16 one live block&quot;); the independence definition stays the founder's (X5). Was: Open, measurement scheduled (O-X.1); extends X5. Sweep (5 October 2026): hashing concentration computed from the devnet record (<code>a repository file</code>, 8,090 blocks, 18 vote keys): top-1 12.8%, top-3 34.5%, top-9 98.0%, the nine being devnet v4's nine identities run by three machines (approximate), so by machine the devnet is three parties. Signing, proving and aggregation concentration need certificate and proof-record extracts the observer does not keep yet (O-X.1).</span></div>
<details><summary>The answer as first written</summary><p>Correct. X5 conceded that &quot;independent&quot; needs a measurable definition (distinct ASNs, benchmark hardware fingerprints, pool attestations) and left it to phase 4. The four concentrations can each be computed from chain data: blue blocks per vote key and per pool (hashing), signed weight per key in certificates (checkpoint signing), proof records per prover key (proving, once P12's fix puts the key in the statement), and certificates and proof records per aggregator key (aggregation). The gate reports all four as top-1, top-3 and top-10 shares over 30 days, beside the independence count, on the live page. Transaction choice inside pools is a separate measurement and is already scheduled: whether members of the reference pool use declared templates (spec 9.4.2, mode C) is recorded under O-9.5.</p></details>
</article>
<article class="entry" id="X15" data-bucket="Open">
<div class="head"><span class="id">X15</span><h3>Remove the founders from a test network and show what continues</h3><span class="date">5 October 2026</span></div>
<article class="entry" id="X15" data-bucket="Answered by design">
<div class="head"><span class="id">X15</span><h3>Remove the founders from a test network and show what continues</h3><span class="date">7 October 2026</span></div>
<blockquote>'The chain runs without its founders' is a sentence. Take the team's miners, provers, aggregators, seed nodes, observer and site off a running testnet and show what keeps producing blocks, proofs and locks.</blockquote>
<div class="status"><span class="badge b-open">Open, blocked on the public testnet</span> <span class="did">armed, opens on the go word; see X31): next step O-X.2 run at a published time on that testnet, with the protocol already in the Answer below (every project-run node, miner, prover, aggregator and seed stopped, the observer and live page down, 24 hours of blocks per second, proof lag, certificates per hour and a fresh sync from the shipped seed list). Was: Open, experiment scheduled (O-X.2). Sweep (5 October 2026): a public-testnet experiment; not runnable before it exists.</span></div>
<div class="status"><span class="badge b-answered-by-design">Answered by design</span> <span class="did">7 October 2026, night, the ledger close): the design rules the sentence rests on are in force (every node ships a VDF evaluator, spec 4.5; the seed list ships in the client, spec 10.6; no project-run service sits in consensus, no stake, no fee to any team, spec 5.5 and 5.6), and the public text claims no more than that (<code>a repository file</code>, Governance). The measurement that proves it: O-X.2 as written in the Answer above (every project-run node, miner, prover, aggregator and seed stopped at a published time, the observer and live page down, 24 hours of blocks per second, proof lag, certificates per hour and a fresh sync from the shipped seed list), by the testnet lane, on the public testnet once it opens on the go word (the three seed nodes and the public RPC are up, 7 October 2026), inside that testnet's first month and before mainnet. Was: Open, blocked on the public testnet.</span></div>
<details><summary>The answer as first written</summary><p>Correct, and it is the right test for the litepaper's sentence (Governance). The test: on the public testnet, at a published time, stop every node, miner, prover, aggregator and seed node the project runs, take the observer feed and the live page down, and record for 24 hours: blocks per second, proof lag, certificates per hour, and a fresh node syncing from the seed list in the client (spec 10.6). What continues is what the sentence may claim. Dependencies the test will expose: the seed list, the release key (G7), the reference pool, the VDF evaluators (every node ships one, 4.5) and the founders' own hashrate share (E2).</p></details>
</article>
<article class="entry" id="X16" data-bucket="Fixed or built">
@ -1088,10 +1087,10 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 11): proving v0 (every producer verifies off the consensus path) through the public testnet; the in-consensus verifier is the execution engineer's plan item for after it; the litepaper sentence labelled Open stands. Was: Open, stated in spec 7.7 item 4 (4 October 2026). Branch <code>proving</code> of the fork, <code>a repository file</code>. Sweep (5 October 2026): stated; the in-consensus verifier is a build item (execution engineer).</span></div>
<details><summary>The answer as first written</summary><p>Correct for v0, and by design for now. The consensus check on a carried record is the native-execution veto (spec 7.2 item 5): the statement must equal the node's own 328-byte shard statement for that shard and payout address, so no record can move state or pay for a wrong claim. The SP1 proof is verified off the consensus path by the proof pool's verifier (<code>igneum-prove-host --mode verify</code>), and a producer offers only verified records to its templates; a producer that includes unverified records (trust mode, test networks only) can pay a prover who did not prove. The damage is bounded to that prover's payout. What closes it: the aggregated segment record of design 5.4 verified in consensus, which needs the SP1 verifier inside the node (the SDK dependency the node does not carry today) or a bounded in-consensus verification budget. Until then the devnet runs v0 with every producer verifying.</p></details>
</article>
<article class="entry" id="P22" data-bucket="Open">
<div class="head"><span class="id">P22</span><h3>The rewards and payouts are inputs to the shard proof, not outputs</h3><span class="date">4 October 2026</span></div>
<article class="entry" id="P22" data-bucket="Answered by design">
<div class="head"><span class="id">P22</span><h3>The rewards and payouts are inputs to the shard proof, not outputs</h3><span class="date">7 October 2026</span></div>
<blockquote>The shard guest takes the segment's rewards and the prover payouts as data and commits the post-root after them. A host can feed any list and the proof still verifies.</blockquote>
<div class="status"><span class="badge b-open">Open, blocked on the phase 2 consensus proof</span> <span class="did">design 7: the aggregator derives the rewards and payouts from consensus data it verifies, so they become outputs of the proof): next step that consensus-proof work, in phase 2 (Nov 2026 to Jan 2027 per the litepaper roadmap), no earlier date. Was: Open, stated in spec 7.7 item 6 (4 October 2026). Sweep (5 October 2026): stated; nothing runnable.</span></div>
<div class="status"><span class="badge b-answered-by-design">Answered by design</span> <span class="did">7 October 2026, night, the ledger close): the design rule that contains it is in force, spec 7.7 item 6 and design 5.5: the rewards and payouts a shard statement carries are checked against every node's own consensus derivation, so a proof over any other list matches no node's statement and pays nothing (the native veto); the consensus-proof switch exists dormant (<code>proving_consensus_verify_daa</code>, exec-sync-0313, 0.3.20). The work that makes them outputs: the consensus proof of design 7 (the aggregator derives the rewards and payouts from consensus data it verifies), by the proving lane, in phase 2 (November 2026 to January 2027); the same class holds for job outputs (D6). Was: Open, blocked on the phase 2 consensus proof.</span></div>
<details><summary>The answer as first written</summary><p>Correct, and already true of the rewards since devnet v4 (<code>BlockFixture.rewards</code>, <code>proving_pool_credit</code>): the shard statement is &quot;from this pre-root, these transactions, these rewards and payouts, the post-root is X&quot;. The node checks the statement against its own execution, which used the rewards and payouts consensus derived, so a proof over a different list does not match any node's statement and pays nothing. Closing it in the proof itself means the aggregator deriving the rewards and payouts from consensus data it verifies (the mergeset's blue blocks and the carried records), which is the consensus-proof work of design section 7.</p></details>
</article>
<h2 id="m">Mining and chips</h2>
@ -1115,9 +1114,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>Correct. The app share is a property of the fee flow, not an income at launch: 20% of the priority fee, per call frame, and the priority fee on an uncongested chain is whatever wallets quote by default. At the three price inputs of <code>a repository file</code> and a 1 gwei tip, a million calls a day pays $146, $730 or $7,300 a year (the last at a 10 gwei tip). What is new in it against Canto and Sonic is library attribution at the code address and factory inheritance, and the fact that it comes from the user's tip and never from emission. The 20% should not be raised: Sonic's 90% has distributed about $2M in a year across a whole chain, and a larger share comes out of the miners' and provers' side, which is the security budget. Blast announced its shutdown on 2 October 2026, so the sentence citing it must go now.</p></details>
</article>
<article class="entry" id="D3" data-bucket="Conceded">
<div class="head"><span class="id">D3</span><h3>Proof of work in 2027 is a perception cost you cannot measure</h3><span class="date">3 October 2026</span></div>
<div class="head"><span class="id">D3</span><h3>Proof of work in 2027 is a perception cost you cannot measure</h3><span class="date">7 October 2026</span></div>
<blockquote>My investors and the exchanges I need read 'GPU-mined' as 2021. Whatever your proofs do, the label costs me.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, no experiment possible</span></div>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">7 October 2026, night, the ledger close): <code>a repository file</code>, What Igneum does not claim, &quot;A label that costs nothing. No. Some investors and exchanges read 'GPU-mined' as 2021 whatever the proofs do, and nothing here measures that cost.&quot; Was: Conceded, no experiment possible.</span></div>
<details><summary>The answer as first written</summary><p>Correct that the cost exists and that nothing in the design measures it. The argument the litepaper makes (&quot;Questions builders ask&quot;: the energy buys a proof of every block as well as its ordering; no stake to capture, no builder cartel, no foundation that can change the rules) is an argument and not a measurement. The only evidence that will exist is whether rows 1 and 2 of the adoption sequence (miner apps, verifiable-compute apps) sign despite the label.</p></details>
</article>
<article class="entry" id="D4" data-bucket="Conceded">
@ -1127,22 +1126,22 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>Correct, and the sequence in <code>a repository file</code> section 4 puts consumer apps third for this reason: after mainnet, after a bridge run by a named operator, after a published record of the app share and the job market. The alternative, a multisig bridge the project labels official, was refused on 3 October 2026. The sentence naming Circle is a request about a third party and the round-3 review already asked for it to go.</p></details>
</article>
<article class="entry" id="D5" data-bucket="Conceded">
<div class="head"><span class="id">D5</span><h3>I cannot debug a revert</h3><span class="date">5 October 2026</span></div>
<div class="head"><span class="id">D5</span><h3>I cannot debug a revert</h3><span class="date">7 October 2026</span></div>
<blockquote>No <code>eth_subscribe</code>, no <code>debug_traceTransaction</code>, no <code>eth_getProof</code>, no explorer, no public RPC, no faucet, <code>finalized</code> resolves to the executed tip. You are inviting builders to a chain they cannot inspect.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, scheduled</span> <span class="did">5 October 2026, night): <code>a repository file</code> section 5, owner and gate named (the execution engineer; no outside team is invited before step 2 is done). Was: Conceded, scheduled. Sweep (5 October 2026): unchanged on the <code>proving</code> branch (no <code>debug_*</code>, <code>eth_subscribe</code> or <code>eth_getProof</code> in <code>a repository file</code>); scheduled work, execution engineer.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, scheduled, stated</span> <span class="did">7 October 2026, night, the ledger close): <code>a repository file</code>, What Igneum does not claim, &quot;A chain you can debug today. Not yet.&quot; with the four steps and the gate (no outside team invited before the second step). The schedule stands as above. Was: Conceded, scheduled.</span></div>
<details><summary>The answer as first written</summary><p>Correct on every item on 4 October 2026 (<code>a repository file</code> 10.3 items 1, 6, 7). The order in <code>a repository file</code> section 5: docs and the Hardhat and Foundry templates first; <code>debug_*</code>, <code>eth_subscribe</code> and <code>eth_getProof</code> second, because the Blockscout fork and Foundry's debugger need them; a public devnet RPC, the chain-id listing on ethereum-lists/chains, wallet tests (R11) and a faucet third; the explorer fourth. No outside team is invited before the second step is done.</p></details>
</article>
<article class="entry" id="D6" data-bucket="Conceded">
<div class="head"><span class="id">D6</span><h3>A forged job result reaches my contract and nobody vetoes it</h3><span class="date">5 October 2026</span></div>
<div class="head"><span class="id">D6</span><h3>A forged job result reaches my contract and nobody vetoes it</h3><span class="date">7 October 2026</span></div>
<blockquote>Segments have the native-execution veto. Jobs do not: full nodes cannot re-run an arbitrary program, so for a precompile job the proof is the only check. A soundness bug in SP1 writes whatever the attacker wants into my callback.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, contained by rule, reviewed</span> <span class="did">5 October 2026, night): <code>a repository file</code>. Next step: the three devnet checks of that review's section 6 (containment under a deliberately broken verifier; the version gate and the overlap; the callback boundary), on the phase 4 devnet once the precompile of design 6 exists (design 10.3 item 5). Was: Conceded, contained by rule, review scheduled. Sweep (5 October 2026): a review item (R12 with the cryptographer); nothing runnable.</span></div>
<div class="status"><span class="badge b-conceded">Conceded, contained by rule, stated</span> <span class="did">7 October 2026, night, the ledger close): <code>a repository file</code>, What Igneum does not claim, &quot;A veto on job results. No.&quot; with the containment (a job output mints nothing and touches no system contract; an app that acts irreversibly on a job result keeps its own fallback). The three devnet checks of the review's section 6 stand as the next step. Was: Conceded, contained by rule, reviewed.</span></div>
<details><summary>The answer as first written</summary><p>Correct. Design 6 says it in those words. The containment: a job output cannot mint IGN or touch system contracts (R12), jobs are gated behind the proof-system version with the three-month overlap and the 90% signal (design 5.6), and the emergency path for a live soundness bug is the version bump of spec 5.7. The rule for an app, the same one the customer brief gives rollups: anything that acts irreversibly on a job output keeps its own fallback. R12 is reviewed with the cryptographer before devnet v2.</p></details>
</article>
<h2 id="x">Launch and operations</h2>
<article class="entry" id="X23" data-bucket="Fixed or built">
<div class="head"><span class="id">X23</span><h3>One shipped key is an administrator channel to the founder's PCs</h3><span class="date">5 October 2026</span></div>
<blockquote>Your relay accepts either the URL token or the <code>x-igneum-key</code> header for everything, including queuing PowerShell that the PC agent runs as administrator. The key is the log intake key, a literal in six tracked files and inside every Windows and prover package you have handed out. And the zip with both relay secrets sits on the downloads host behind the dl token, which is in your git history and in every installed app. One token, four hops, no privilege boundary.</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed on a branch, pending merge</span> <span class="did">5 October 2026, night): ledger-relay 28c028b, tests 47 of 47 (relay, 6 suites) + 16 of 16 (a repository file) + 2 CI class checks. Was: Open, fatal as an operational fact (4 October 2026). The agent was live and elevated on the Windows machine at 13:41 UTC (<code>GET machines</code>, read-only). Sweep (5 October 2026): the relay token was rotated on 4 October (<code>a config file</code> sits beside the new one); <code>POST task</code> with <code>kind: run</code> still needs only the token (<code>relay/api/relay.mjs:114-119</code>, no per-machine secret or signature), so the operational half stands. The 401 test needs the deployed relay and the Windows machine (relay owner; rotation is the owner's).</span></div>
<div class="status"><span class="badge b-fixed-or-built">Fixed on a branch, pending merge</span> <span class="did">5 October 2026, night): ledger-relay 28c028b, tests 47 of 47 (relay, 6 suites) + 16 of 16 (a repository file) + 2 CI class checks. Was: Open, fatal as an operational fact (4 October 2026). The agent was live and elevated on the Windows machine at 13:41 UTC (<code>GET machines</code>, read-only). Sweep (5 October 2026): the relay token was rotated on 4 October (<code>a config file</code> sits beside the new one); <code>POST task</code> with <code>kind: run</code> still needs only the token (<code>relay/api/relay.mjs:114-119</code>, no per-machine secret or signature), so the operational half stands. The 401 test needs the deployed relay and the Windows machine (relay owner; rotation is the founder's).</span></div>
<details><summary>The answer as first written</summary><p>Correct. <code>relay/lib/relay.mjs:33-42</code> returns a truthy value for either secret and <code>relay/api/relay.mjs:111-124</code> accepts <code>kind: run</code> with <code>flags.elevated</code> from it; <code>relay/clients/igneum-agent.ps1:165-166</code> runs every item returned, as administrator, within 20 s. <code>README.md:7</code> and <code>make-clients.sh:8</code> make <code>RELAY_KEY</code> the intake key. The hosted <code>igneum-relay-clients.zip</code> carries the relay token and the key in four files; the dl token that guards it is 0644 on the Apple M5 Max, in commit <code>c47ff03</code>, and in <code>igneum-app.json</code> of every install. Fix, in order: the zip off the host; rotate the relay token; a relay key of its own; a second per-machine secret or an Ed25519 signature over <code>{id, to, body}</code> for <code>run</code>; rotate the intake key and repackage. Review ids R4.4.1, R4.4.2, R4.5.1.</p></details>
</article>
<article class="entry" id="X24" data-bucket="Fixed or built">
@ -1191,7 +1190,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="G14" data-bucket="Closed by rule or decided">
<div class="head"><span class="id">G14</span><h3>Secrets and identity in the history of a repository with a public date</h3><span class="date">6 October 2026</span></div>
<blockquote>The intake key is in six files across eight commits, the dl token in one, the review and ledger files are tracked, 51 tracked files carry the founder's first name, and every commit today is stamped with the local-time offset. The 3 October sweep said zero hits.</blockquote>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 8): the history rewrite runs the morning after the last of the close's branches merges, with every worktree removed first and both secrets rotated regardless. Was: Fixed on a branch, pending merge (5 October 2026, night), the tooling part: ledger-relay 28c028b, tests 47 of 47 (relay, 6 suites) + 16 of 16 (a repository file) + 2 CI class checks. Decision owner: the owner for the rewrite date (<code>a repository file</code>). Was: Open (4 October 2026); extends <code>a repository file</code> section 5.</span></div>
<div class="status"><span class="badge b-closed-by-rule-or-decided">Decided</span> <span class="did">6 October 2026, 17:25 UTC, by the owner; decisions item 8): the history rewrite runs the morning after the last of the close's branches merges, with every worktree removed first and both secrets rotated regardless. Was: Fixed on a branch, pending merge (5 October 2026, night), the tooling part: ledger-relay 28c028b, tests 47 of 47 (relay, 6 suites) + 16 of 16 (a repository file) + 2 CI class checks. Decision owner: the founder for the rewrite date (<code>a repository file</code>). Was: Open (4 October 2026); extends <code>a repository file</code> section 5.</span></div>
<details><summary>The answer as first written</summary><p>Correct, count-only. The key: <code>a repository file</code>, <code>a repository file</code>, <code>a repository file</code>, <code>prove-shard.sh</code>, <code>a repository file</code>, <code>a repository file</code>, commits <code>78df757</code> to <code>4c9810f</code>. The token: <code>a repository file</code>, commit <code>c47ff03</code>. <code>git check-ignore</code> returns nothing for the ledger, fixes and review files. The CI identity grep covers the public export list, by design. Fix: both secrets join section 5 step 4's rewrite list (and are rotated regardless); <code>TZ=UTC</code> in the commit path now. Review ids R4.4.8, R4.5.3, R4.5.4.</p></details>
</article>
<h2 id="x">Launch and operations</h2>
@ -1314,7 +1313,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<article class="entry" id="E18" data-bucket="Answered by design">
<div class="head"><span class="id">E18</span><h3>The dev fee is a protocol fee with better PR</h3><span class="date">4 October 2026</span></div>
<blockquote>A 1% dev fee in the official miner is 1% of the chain's hashrate paid to one company for as long as miners run it. Call it what it is: a founder allocation, hidden in the client, and nobody can tell how often it really fires.</blockquote>
<div class="status"><span class="badge b-answered-by-design">Answered by design and with evidence</span> <span class="did">4 October 2026, evening; the owner's decision of that evening, branch <code>dev-fee</code> in both repositories).</span></div>
<div class="status"><span class="badge b-answered-by-design">Answered by design and with evidence</span> <span class="did">4 October 2026, evening; the founder's decision of that evening, branch <code>dev-fee</code> in both repositories).</span></div>
<details><summary>The answer as first written</summary><p>The fee exists and is disclosed; the rest is wrong in three places. (1) It is software-level, not protocol-level: no consensus rule, coinbase rule or emission rule knows of it. The chain pays whatever payout address a block template names, and the miner software names the dev address for one template in 100. A different client, or the same client with <code>--dev-fee 0</code> (a switch in the app's Settings, <code>DEV_FEE=0</code> on HiveOS), pays nothing and the chain treats its blocks exactly the same. That is the norm for GPU miners (lolMiner, T-Rex, approximate as to their percentages) and the litepaper says so beside the words &quot;the protocol carries no fee&quot;. (2) It is auditable, not hidden: the choice is a template counter, not a random draw. Template n (from 0) is a fee template when floor((n + 1) p / 100) &gt; floor(n p / 100), which at p = 1 is exactly the templates 99, 199, 299, ...; the source is one function (<code>fee_slot</code>, <code>a repository file</code>, section &quot;Software dev fee&quot;), the miner prints <code>dev fee 1% (1 block in 100) to 0x&lt;address&gt;; --dev-fee 0 turns it off</code> at start, logs <code>dev-fee block &lt;hash&gt;</code> for each one and counts <code>fee=N</code> in its status line, and <code>igneum-miner payouts &lt;node&gt;</code> reads the chain back and lists blocks per payout address with the dev address tagged. (3) It takes nothing from anyone else's security: a fee block keeps the user's vote key, so the user's finality weight is unchanged; only the execution-layer payout of that block moves.</p></details>
</article>
<h2 id="x">Launch and operations</h2>
@ -1331,9 +1330,9 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<details><summary>The answer as first written</summary><p>Correct at discovery; fixed before this document was written. The evidence page was brought up to the day's measurements in <code>86e5857</code> and <code>bf4d7ec</code> (rows 29 and 30, rows 10, 12 and 15 restated).</p></details>
</article>
<article class="entry" id="X31" data-bucket="Fixed or built">
<div class="head"><span class="id">X31</span><h3>The public testnet dated &quot;August 2027&quot; on the site</h3><span class="date">6 October 2026</span></div>
<div class="head"><span class="id">X31</span><h3>The public testnet dated &quot;August 2027&quot; on the site</h3><span class="date">7 October 2026</span></div>
<blockquote>The litepaper's For miners section said 'Pools and the public testnet are August 2027', the proving section said 'Live rows arrive with the public testnet, August 2027', the roadmap's phase 5 read 'Aug to Oct 2027' and the home page's journey carried the same row. igneum-testnet-1's genesis is final, three seed nodes and the public RPC are up, and the testnet opens when the go checklist (a repository file) closes, which is weeks away.</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated</span> <span class="did">6 October 2026, night, the owner's decision): every mention of the month is gone from the site. The sentence everywhere is &quot;The public testnet is weeks away: three seed nodes and the public RPC are up, and it opens when the go checklist closes.&quot; (<code>a repository file</code> For miners and the proving section, the roadmap row 5 reads &quot;Weeks away: when the go checklist closes&quot;, <code>a repository file</code> phase 5 and the home page's inlined journey carry the same row). No calendar month is given for the testnet; the owner gives one if he wants one. Updated (7 October 2026, night): the sentence everywhere is now &quot;The public testnet is armed: three seed nodes and the public RPC are up, and it opens on the go word.&quot;; the roadmap row 5 and the journey's phase 5 read &quot;Armed: opens on the go word&quot;.</span></div>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated</span> <span class="did">7 October 2026, night): every mention of the month is gone from the site and no date is given. The sentence everywhere is &quot;The public testnet is armed: three seed nodes and the public RPC are up, and it opens on the go word.&quot; (<code>a repository file</code> For miners and the proving section, the roadmap row 5 and <code>a repository file</code> phase 5 read &quot;Armed: opens on the go word&quot;, the home, download and miner pages carry the sentence). Was: Fixed, stated (6 October 2026, night, the owner's decision): every mention of the month is gone from the site. The sentence everywhere is &quot;The public testnet is weeks away: three seed nodes and the public RPC are up, and it opens when the go checklist closes.&quot; (<code>a repository file</code> For miners and the proving section, the roadmap row 5 reads &quot;Weeks away: when the go checklist closes&quot;, <code>a repository file</code> phase 5 and the home page's inlined journey carry the same row). No calendar month is given for the testnet; the owner gives one if he wants one.</span></div>
<details><summary>The answer as first written</summary><p>The date was the plan of 3 October 2026 and the chain overtook it: the testnet genesis was fixed on 5 October, the three seeds and rpc.testnet.igneum.network are up, and the remaining work is the go checklist. Rows that quoted the month (X3, O-X.2's blocker note, overclaim item 75's replacement text) read the new sentence by reference to this row.</p></details>
</article>
<article class="entry" id="X32" data-bucket="Fixed or built">
@ -1348,24 +1347,43 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated</span> <span class="did">6 October 2026, night, the owner's ruling): both sentences read &quot;The public benchmark with a leaderboard ships with the public testnet.&quot; (<code>a repository file</code>, For miners and Questions miners ask). The gate is one the reader already knows from the roadmap's phase 5. The 5 October answers in M1, X1 and the overclaims list that name January 2027 are the history of the plan and stay as written.</span></div>
<details><summary>The answer as first written</summary><p>The month was the plan of 3 October 2026. The benchmark tool is part of the testnet's go checklist, so it ships with the testnet; no month is given for either.</p></details>
</article>
<article class="entry" id="X34" data-bucket="Other">
<div class="head"><span class="id">X34</span><h3>RandomX described as chip-free</h3><span class="date">7 October 2026</span></div>
<article class="entry" id="X34" data-bucket="Fixed or built">
<div class="head"><span class="id">X34</span><h3>RandomX described as chip-free</h3><span class="date">6 October 2026</span></div>
<blockquote>The home page said the random program 'has kept chips off Monero since 2019', the litepaper said Monero ran on RandomX 'with no chip publicly shipped' and spoke of 'Monero's seven years without a public chip'. Bitmain's Antminer X9, a RandomX chip, ships from July 2026 (1 MH/s at 2,472 W, about USD 5,600; monero-project/monero issue 10270), and RandomX 2.0 shipped on 25 March 2026. Every sentence that said or implied RandomX is chip-free, or that Monero's approach has held, was wrong.</blockquote>
<div class="status"><span class="badge b-other">Corrected</span> <span class="did">7 October 2026, morning, X36): the X9 never shipped. Bitmain opened pre-orders on 26 December 2025 and withdrew the product in mid-May 2026 before any unit was delivered; every sentence below that had it shipping now states that, and RandomX stands as a technique no chip has yet shipped against. The sentences in this row are the history.</span></div>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated</span> <span class="did">6 October 2026, night, from the cryptanalysis research): four sentences corrected, each with the X9 as the stated fact and its date; every sentence that only names the technique stands.</span></div>
<details><summary>The answer as first written</summary><p>The precedent Igneum cites is now a complete one: a fixed random program held CPU mining for about seven years and then a chip shipped. Igneum's program changes every hour from a genesis-fixed schedule, its dataset grows, and the chip model on the numbers page prices the chip that stores the dataset rather than assuming none can be built. The X9's rate and power are Bitmain's published figures, not our measurement.</p></details>
</article>
<article class="entry" id="X35" data-bucket="Other">
<article class="entry" id="X35" data-bucket="Fixed or built">
<div class="head"><span class="id">X35</span><h3>The class v4 chip headline stated as one number, 2.1x</h3><span class="date">7 October 2026</span></div>
<blockquote>The home page said the strongest chip reaches 'about 2x once the lever now in its gates ships' and the litepaper said the latency-shadow work 'brings the chip to about 2x' and that its edge 'falls from 5.6x to 2.1x ... at a chip core equal to the GPU's'. That 2.1x assumes the chip's core costs what the GPU's does per operation (k = 1). Bitmain's Antminer X9 reached about a third of its honest device's energy on a latency-bound random program, so k about 0.33 is a shipped product class, and at that k the same model gives 3.9x.</blockquote>
<div class="status"><span class="badge b-other">Kept, relabelled</span> <span class="did">7 October 2026, morning, X36): the range stands, with k about 0.33 labelled as the X9's claimed, unmeasured core, since no unit shipped or was benchmarked.</span></div>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated; restated</span> <span class="did">7 October 2026, evening, by order of the coordinator; the chip-text rewrite e57da45a, on master at 25f38035): the served texts give the floor and the premium at the 5090's measured knee: 2.1x per joule with a core as good as a GPU lane (k = 1), 3.4x with one three times better (k about 0.33), no core below about 1.8 pJ per op in the model's range, the premium 81.8 W at the best points, Ember Tune named as how a user gets there; the ledger pin for X35 moved to the new sentence; <code>a repository file#chip-model</code> and the home line.</span></div>
<details><summary>The answer as first written</summary><p>One number was the model's k = 1 column; the X9 made the k = 0.33 column a product rather than a claim, so the public figure is the range. Rung 2 of the ladder (the top admissible rung on 6 October 2026) takes the X9 bracket from about 3.9x to about 2.8x and does not close it; the ladder moves at the pace of the cards that pay for it (M34).</p></details>
</article>
<article class="entry" id="X36" data-bucket="Fixed or built">
<div class="head"><span class="id">X36</span><h3>The X9 described as a shipping chip</h3><span class="date">7 October 2026</span></div>
<blockquote>X34 and X35 said Bitmain's Antminer X9 'ships from July 2026' and called it 'the shipping RandomX chip'. It never shipped: Bitmain opened pre-orders on 26 December 2025 for July 2026 delivery, resellers told buyers in mid-May 2026 that Bitmain had discontinued it and refunded them, no unit was delivered and none was independently benchmarked.</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated</span> <span class="did">7 October 2026, morning, from the research agent's primary sources): every public sentence that had the X9 shipping now states the pre-order, the withdrawal and the unbenchmarked core.</span></div>
<div class="status"><span class="badge b-fixed-or-built">Fixed, stated; restated further</span> <span class="did">7 October 2026, evening, from the counter-asic-4 research file d7721ebe; on master at 25f38035): the X9's claimed ratio is against a CPU core, not a GPU lane, so the texts no longer use it as a pessimistic chip core; every served sentence says so; the pin for X36 moved.</span></div>
<details><summary>The answer as first written</summary><p>The k about 0.33 column stays in the public range as the X9's claimed, unmeasured core: Bitmain's figures (1,000 KH/s at 2,472 W, 2.47 J/KH) were a pre-order sheet, never a benchmark, and the RandomX team's own reading (sech1, 25 January 2026) was &quot;no, X9 is not an ASIC... Only 2x efficiency gap (hash/Joule) is not 'cracked'&quot;: a box of commodity Sophgo SG2044 server SoCs with an AES block and over sixty DRAM sticks, no tapeout, about 2x per joule over a tuned Zen 4 part and about 3x over a stock desktop CPU. It was withdrawn rather than face a RandomX re-tune of 1.5x or more. The lesson the public text now carries is that one: a maintained algorithm with a credible upgrade path held, which is what the latency ladder is for Igneum. Monero's hashrate shows no X9 fleet (about 6.1 GH/s before and after, approximate).</p></details>
</article>
<article class="entry" id="X37" data-bucket="Answered with evidence">
<div class="head"><span class="id">X37</span><h3>The class v4 energy premium is a cost the user pays, not a line in a model</h3><span class="date">7 October 2026</span></div>
<blockquote>Your chip model counts joules per hash for the attacker. What does class v4 cost the miner at the wall, and can any hash-side change bring that premium to zero?</blockquote>
<div class="status"><span class="badge b-answered-with-evidence">Answered with evidence</span> <span class="did">7 October 2026, the Counter ASIC lane's measurement; levers in flight): measured on the RTX 5090, 145 W of premium unlocked and 82 W at the knee; the RTX 5080 at stock 84 W, its grid running; the research lane's identity says the premium needed for 2x at k = 1 is 103 W at the lock and a premium of zero is impossible by any hash-side lever; the chip model's section 5.10 (<code>a repository file</code>, aa829826) shows class v5 with the shadow at zero leaves the stored-dataset chip at 5.1x to 9.1x, so the shadow stays the only lever. The levers: the core-clock knob into Ember Tune for 0.3.24, the SM-sparse kernel and the L2 hot-table reads on the Windows machine's queue.</span></div>
<details><summary>The answer as first written</summary><p>Correct that it is a cost at the wall, and it is measured, not modelled: 82 W at the knee on a 5090 is the price of the latency shadow, and Ember Tune is how a user reaches the knee. What no hash-side change can do is remove it: without the shadow the stored-dataset chip's edge returns (5.1x to 9.1x in the model), so the premium is the chip defence, priced per card.</p></details>
</article>
<h2 id="n">N</h2>
<article class="entry" id="N1" data-bucket="Fixed or built">
<div class="head"><span class="id">N1</span><h3>A 0.3.15 node on the live file wrote blocks every 0.3.14 node rejected</h3><span class="date">6 October 2026</span></div>
<blockquote>p2-3090-1 on 713ef876 with the live thirteen-field file, at every reconnect since its 19:42Z restart: P2P, got reject message: wrong block version: got 1026 but expected 2 from peer 188.245.5.161:26611; blocks 122,630, synced false, peers 0.</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed</span> <span class="did">6 October 2026, 20:0xZ, fork commit 17c60367 on ca3-v4-order-fix, the stamp; and 20:4xZ, f1ea7a38, the receive side, after the clean canary of 21:3x UK showed a 0.3.15 node ACCEPTING and relaying a version-1026 block it would never write, off a poisoned peer, and being disconnected by every 0.3.14 peer in turn; in 0.3.15). Conceded: the node lane's fault, twice.</span></div>
<details><summary>The answer as first written</summary><p>the class v4 signal (PROPOSED, <code>a repository file</code> section 6) is the producer's object version in the high byte of the header version; the first 0.3.15 build stamped it from the binary alone, so on the live file (no window, no floor) a new node wrote version 1026 and every 0.3.14 node, whose rule is version 2 or reject, refused its blocks and its relays, although the digest compat rule (the same evening) made the handshake peer. A new miner lost every block; a lagging new node could not re-sync. The fix gates the stamp, the signal read AND the header version rule on publish 2's object (both <code>program_class_v4_signal_window_daa</code> and <code>program_class_v4_activation_daa</code> set): on the thirteen-field file the header is byte for byte what 0.3.14 writes, and a header carrying the signal bit is refused with 0.3.14's own <code>WrongBlockVersion(1026, 2)</code> before the engine and never relayed, so a poisoned peer cannot poison a new node. What no new-node change can do: a 0.3.14 node whose datadir holds version-1026 blocks is disconnected by its 0.3.14 peers by THEIR rule when it relays them, until those blocks leave the relay window; the fleet wipes the poisoned datadirs. Why the gates missed it: the digest compat harness peered the two binaries but neither mined; the new gate mines on both sides, joins a clean node through each, restarts the new node and re-syncs it.</p></details>
</article>
<article class="entry" id="N2" data-bucket="Fixed or built">
<div class="head"><span class="id">N2</span><h3>Any peer could crash any pruned node with a sync request below its retention</h3><span class="date">6 October 2026</span></div>
<blockquote>thread 'tokio-rt-worker' panicked at consensus/src/processes/sync/mod.rs:87:62: called Result::unwrap() on an Err value: KeyNotFound(GhostdagCompact/0/edc4fa84...) then Exiting...&quot; (the hub, a pruned 0.3.14 node, 19:57Z, when p2-3090-1, cut off since 19:42Z, began a sync from the genesis against it).</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed</span> <span class="did">6 October 2026, 20:2xZ, fork commit 7961c5f1 on ca3-v4-order-fix; in 0.3.15). Conceded: a remote crash vector in every release from the first pruned devnet node to 0.3.14; security.</span></div>
<details><summary>The answer as first written</summary><p><code>SyncManager::antipast_hashes_between</code> (the IBD headers path, <code>RequestHeaders</code>) unwrapped the GHOSTDAG reads of the requested low block and of every chain block of the walk; a pruned node holds no GHOSTDAG data below its retention, so a request from the genesis killed the serving node, not the requester. The fix makes the walk fallible: a read below the retention is <code>SyncManagerError::BlockBelowRetention(hash)</code> (also in <code>find_highest_common_chain_block</code> and the pruning-point locator), the consensus API returns it, and the serving flow answers the peer with the error and disconnects it, the node alive; the peer syncs from a node that holds the history. The hub was restarted by hand at 20:00Z (synced in 25 s).</p></details>
</article>
<h2 id="p">Proving and the zkEVM</h2>
<article class="entry" id="P23" data-bucket="Fixed or built">
<div class="head"><span class="id">P23</span><h3>An unwound transaction leaves the node's view until its sender resends it</h3><span class="date">6 October 2026</span></div>
@ -1373,8 +1391,27 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<div class="status"><span class="badge b-fixed-or-built">Fixed on a branch, pending merge</span> <span class="did">6 October 2026, night, ledger close round 3): fork <code>ledger-fixes-0311</code> fbb0082a (the P23 commit, on the merge of <code>ledger-fixes</code> and <code>ledger-fixes-2</code> onto the 0.3.11 fork tip 89dfcb95); <code>EvmPool::on_chain_removed</code> (a repository file) and <code>ExecService::requeue_unwound</code> (service.rs) with <code>ExecState::unwound</code> collected by <code>truncate_to</code>; unit tests <code>pool::tests::a_reorg_hands_the_unwound_transactions_back_to_the_pool_in_nonce_order</code> and <code>rpc::p17_tests::a_reorg_collects_the_unwound_transactions_in_chain_order_for_the_pool</code>, igneum-exec 23 of 23 on the Apple M5 Max (labelled a Mac run); the O-7.2 conformance run on the rebased binaries PASSED (409.9 s) with the <code>reorged out</code> case ending in <code>executed</code> 2.4 s later without a resend (n2's log: <code>reorg: 1 unwound transactions handed back to the pool as pending, 0 refused</code>; bench-log &quot;ledger close round 3&quot;); the Windows machine job <code>build-20261006-012543</code> built fbb0082a for Linux and Windows and ran the seven suites, exit 0 in 46 s, without the igneum-pow feature, so the Apple M5 Max run is the suite evidence. Was: Open, found in round 2 (6 October 2026, night, the P17 conformance run on <code>ledger-fixes-2</code>); fix named, owner the execution engineer; round 3 (<code>ledger-rebase</code>) carries it with the fork rebase. Found by: the ledger-pc2 agent's O-7.2 conformance driver (<code>a repository file</code>, the &quot;reorged out&quot; path), recorded as finding (1) in the P17 round-2 paragraph.</span></div>
<details><summary>The answer as first written</summary><p>Correct. <code>a repository file</code> has <code>on_chain_block</code> and no reorg hook, so a transaction unwound by a selected-chain reorg is neither re-queued nor re-executed; the new <code>state</code> word reports <code>reorged out</code> with <code>reorgedFrom</code>, which tells a wallet to resend and tells nobody else. Fix: on every <code>virtualChainChanged</code> removal the executor hands the unwound transactions back to the pool as pending (nonce order kept, the same validity checks as a fresh submission, the 10,000-hash memory of P17 cleared on re-inclusion); a unit test that unwinds a block and sees its transactions re-queued; the conformance driver's <code>reorged out</code> case then ends in <code>executed</code> again without a resend.</p></details>
</article>
<h2 id="ap">The in-house adversarial pass</h2>
<article class="entry" id="AP-F8-1" data-bucket="Fixed or built">
<div class="head"><span class="id">AP-F8-1</span><h3>A load whose source was last written by <code>or</code>, <code>mul</code> or <code>mulhi</code> makes a cross-hash hot set</h3><span class="date">7 October 2026</span></div>
<blockquote>The item histogram of class v4 over 2^26 nonces is not uniform: the top 0.1 percent of items take 0.520 percent of reads against 0.115 for a uniform control (4.05x), one item takes 78,479 reads (153x the mean), and site 15 feeds 6.37 percent of its reads into that top 0.1 percent in every iteration.&quot; (attack-pass row F8, <code>a repository file</code>, 7 October 2026)</blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed in part, finding bounded, stated</span> <span class="did">7 October 2026, night, the Counter ASIC lane's words): class v4 sub-version 3 (igneum-pow 017e7037, the audit-freeze tag) is frozen with the dataflow rule, the shared-operand rule, the 0.98 ratio and the total draw; the in-house pass's F8 re-gate reads 60 of 64 seeds under 1.2x with the four-seed tail accepted by the coordinator as the window model's unattributed residue (no chip consequence); the pass then attributed the class by value (eight live hot sets at 1.54x to 2.24x in the lowest 30 of 29,032 accepted programs, each about 1 MB of items at 0.3 percent of reads, 1.002x to a chip); class v5 (1c420786, frozen 21:53 UK) carries the fix as rule (c'''), the per-site distinct-index floor at 0.995 on the state flag (its census refuses 2.435 percent of accepted programs; seven of seven live hot sets refused at 0.9821 to 0.9919; the eighth's ratio owed tonight), with a named residual (three mild shadow-block-written concentrations at 0.9992 to 0.9997, about 1.0004x, a value-level test in the next class); the record is <code>a repository file</code> section 7c and the class v5 design's section 14. The eighth live hot set (seed 122960, id 4be7393ab6c84802, the deepest found: X_f +0.111 percent, 1.54x the window model, its hottest item at 475,616 reads from an all-ones source) reads minimum site 12 at 0.9824 at the acceptance's own 2^20 sample (live 0.9822), refused by class v5's (c''') floor at 0.995; so the floor refuses eight of eight live hot sets by X_f at or above f found in the tail of 88,051 accepted programs (minimum sites 0.9821 to 0.9919) against 0 hot sets in 20 random programs; what it misses stays the three mild shadow-block-written concentrations at 0.9992 to 0.9997 (Devnet 3's first program among them), about 1.0004x to a chip, the value-level test in the next class (22:41 local time; the logs under <code>a repository file/</code> on branch adv-accept; the v5 design's section 14). The RTX 5080 grid's knee is not in tonight; X37 keeps the 5080's stock premium only.</span></div>
<details><summary>The answer as first written</summary><p>Correct as a fault, wrong as a null. The window layer (spec 01 1.13.1 as proposed, <code>a repository file</code> 1.4) moves the uniform null from 0.115 to 0.160 percent at the top 0.1 percent (1.39x, not 4.05x) and explains every per-site row of F8's attribution except site 15. Site 15's source r6 was last written by <code>or r6, r4</code> (instruction 61, the load at 63), a non-injective op whose output bits are 1 with probability 3/4, so the all-ones source recurs with probability (3/4)^32 per read; the era map sends it to item 0xca5b92, F8's hottest item exactly, and F8's next seven items are exactly the seven one-zero-bit sources whose zero survives the window mask. The popcount model at the measured bias (p = 0.7585) predicts 77,348 all-ones reads against 78,479, and the program's top-0.1-percent share at 0.58 against 0.52. The acceptance rule's part (a) takes any write as a fresh source and part (c) counts saturation on final register values only, so the class of fault passes it: of 1,024 chain-shaped class v4 programs 96.6 percent carry a load whose source's last writer is <code>or</code>, <code>mul</code> or <code>mulhi</code>, 48.5 percent an <code>or</code>-sourced one (0.30 percent of all reads per site), 4.9 percent an <code>or</code>-of-<code>or</code> chain (p3's class: 72 percent of that site's reads, 4.6 percent of all reads, on 0.1 percent of items). The ceiling under rule (c)'s 120-of-128 floor is one site repeating its item in all 8 iterations, 6.25 percent of reads, a chip edge of at most 1.067x in 64 bytes of SRAM; the public claim's 2x margin stands, and the public line says &quot;bounded&quot;, not &quot;uniform&quot; (<code>a repository file</code> sections 1 to 4).</p></details>
</article>
<article class="entry" id="AP-F8-4" data-bucket="Fixed or built">
<div class="head"><span class="id">AP-F8-4</span><h3>The program id's derivation text omitted generator 4's sub-version suffix (interoperability, documentation; no object change)</h3><span class="date">7 October 2026</span></div>
<blockquote></blockquote>
<div class="status"><span class="badge b-fixed-or-built">Fixed</span> <span class="did">7 October 2026, night): the id and its derivation text come from one byte recipe, every pinned pack's id re-derives from its own text in the suite (the igneum-pow suite on box 2 green at 0f45c8be: 64 + 2 + 7 + 4 + 19 + 2 + 7), the spec states the suffix; no object moved.</span></div>
<p class="intro" style="margin-top:var(--sec)">Source: the project's criticism ledger, a file in the repository, rendered to this page at build time; the repository is published at the public testnet. A criticism that is not here, or that shows an entry is wrong, is added with credit if wanted: <a href="mailto:hello@igneum.network">hello@igneum.network</a> or <a href="https://git.igneum.network/igneum-network/spec/issues" rel="noopener">an issue on the specification repository</a>.</p>
</article>
<article class="entry" id="AP-F8-5" data-bucket="Conceded">
<div class="head"><span class="id">AP-F8-5</span><h3>The public specification did not describe the shipped acceptance rule (documentary; no object change)</h3><span class="date">7 October 2026</span></div>
<blockquote>An implementation written from a repository file section 1.4.6 at 017e7037 mines a different program from the node on 264 of 400 epochs.&quot; Found by the in-house pass adv-accept-3 (report-acceptance-rule-3.md at 0c150e3c, finding 3, section 6.2, 7 October 2026, night): the text described (a), (b) and (c) with a 32-attempt cap and an id without a suffix, while the code adds (a') with the shared-operand rule, (c'), (c'') at 2^20 evaluations, the 256-attempt cap keyed on the class v4 shape, the total draw with the last resort, generator 4 and the sub-version suffix, and executes the 256-instruction shadow block 27 times per iteration inside the acceptance interpreter. Measured (sweep 97, 400 seeds, 1,317 attempt verdicts): 759 verdicts differ (758 the code rejects and the text accepts: (a') 733, (c'') 15, (c) 10; 1 the other way, the shadow block changing a (c) statistic); 264 of 400 seeds choose another attempt; the parts the text did carry, (a) and (b), agree on every row.</blockquote>
<div class="status"><span class="badge b-conceded">Conceded, stated</span> <span class="did">7 October 2026, night, the ledger close): <code>a repository file</code>, What Igneum does not claim, &quot;A delay function that outlives a quantum computer. No.&quot; with the fallback (a hash-chain delay behind the version byte that moves the signature scheme, one class change) and the reading (a liveness nuisance, not a break of finality). Still not sized. Was: Conceded, flagged in spec 04 section 4.8.</span></div>
<details><summary>The answer as first written</summary><p>Correct, and the largest divergence source the pass found was documentary. The rule the chain runs was right; the text a second implementer would read was three sub-versions behind it. The fix is the text, written to the code line by line, and a test that fails when the two drift again.</p></details>
</article>
<p class="intro" style="margin-top:var(--sec)">Source: the project's criticism ledger, a file in the repository, rendered to this page at build time; the repository is published at the public testnet. A criticism that is not here, or that shows an entry is wrong, is added with credit if wanted: <a href="mailto:hello@igneum.network">hello@igneum.network</a> or <a href="https://github.com/igneum-network/spec/issues" rel="noopener">an issue on the specification repository</a>.</p>
</div></section>
</main>
<!-- footer:start -->
@ -1389,7 +1426,7 @@ blockquote{margin:10px 0;padding:10px 14px;border-left:3px solid var(--line-2);c
<a href="https://discord.gg/igneum" target="_blank" rel="noopener" aria-label="The Igneum Discord"><svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M19.6 5.3A17 17 0 0 0 15.4 4l-.2.4a15.6 15.6 0 0 1 3.9 1.9 13.6 13.6 0 0 0-14.2 0A15.6 15.6 0 0 1 8.8 4.4L8.6 4a17 17 0 0 0-4.2 1.3C1.8 9.2 1.1 13 1.4 16.7a17.1 17.1 0 0 0 5.2 2.6l1.1-1.8a10.8 10.8 0 0 1-1.7-.8l.4-.3a12.2 12.2 0 0 0 11.2 0l.4.3-1.7.8 1.1 1.8a17 17 0 0 0 5.2-2.6c.4-4.3-.7-8-3-11.4zM8.7 14.4c-1 0-1.8-.9-1.8-2.1s.8-2.1 1.8-2.1 1.9 1 1.8 2.1c0 1.2-.8 2.1-1.8 2.1zm6.6 0c-1 0-1.8-.9-1.8-2.1s.8-2.1 1.8-2.1 1.9 1 1.8 2.1c0 1.2-.8 2.1-1.8 2.1z"></path></svg></a>
<a data-social="reddit" href="https://www.reddit.com/user/Igneum_network/" target="_blank" rel="noopener" aria-label="Igneum on Reddit"><svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M22 12.1a2.2 2.2 0 0 0-3.7-1.6 10.8 10.8 0 0 0-5.8-1.8l1-4.6 3.2.7a1.5 1.5 0 1 0 .2-.9l-3.6-.8a.5.5 0 0 0-.5.4l-1.1 5.2a10.8 10.8 0 0 0-5.9 1.8A2.2 2.2 0 1 0 3.4 14a4.3 4.3 0 0 0 0 .7c0 3.4 3.9 6.1 8.6 6.1s8.6-2.7 8.6-6.1a4.3 4.3 0 0 0 0-.7 2.2 2.2 0 0 0 1.4-1.9zM7 13.6a1.5 1.5 0 1 1 1.5 1.5A1.5 1.5 0 0 1 7 13.6zm8.6 4.1a5.7 5.7 0 0 1-3.6 1.1 5.7 5.7 0 0 1-3.6-1.1.4.4 0 0 1 .6-.6 4.9 4.9 0 0 0 3 .9 4.9 4.9 0 0 0 3-.9.4.4 0 0 1 .6.6zm-.3-2.6a1.5 1.5 0 1 1 1.5-1.5 1.5 1.5 0 0 1-1.5 1.5z"></path></svg></a>
</div>
<div class="footer-dl" aria-label="Download Ember"><a href="/download#windows"><span class="osmark mini" data-os="windows" title="Windows"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M3 5.6l7.3-1v7.1H3zM11.4 4.4L21 3v8.7h-9.6zM3 12.3h7.3v7.1L3 18.4zM11.4 12.3H21V21l-9.6-1.4z"/></svg></span>Windows</a><a href="/download#mac"><span class="osmark mini" data-os="mac" title="macOS"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M16.4 12.6c0-2.5 2-3.6 2.1-3.7-1.2-1.7-3-1.9-3.6-2-1.5-.2-3 .9-3.8.9-.8 0-2-.9-3.3-.8-1.7 0-3.2 1-4.1 2.5-1.8 3-.5 7.6 1.3 10.1.9 1.2 1.9 2.6 3.2 2.5 1.3 0 1.8-.8 3.3-.8 1.6 0 2 .8 3.3.8 1.4 0 2.3-1.2 3.1-2.5 1-1.4 1.4-2.8 1.4-2.9 0 0-2.7-1-2.9-4.1zM13.9 5.3c.7-.8 1.2-2 1-3.2-1 0-2.2.7-2.9 1.5-.6.7-1.2 1.9-1 3 1.1.1 2.2-.5 2.9-1.3z"/></svg></span>macOS</a><a href="/download#linux"><span class="osmark mini" data-os="linux" title="Linux"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M12 2c-2.4 0-4 1.9-4 4.6 0 1.2.2 2 0 2.8-.6 1.4-2.1 2.9-2.6 4.9-.3 1.1-.1 2 .3 2.6-.6.4-1.3 1-1.1 1.7.3 1 2.1 1.2 3.2 1.8.7.4 1.5.6 2.1.1.6.2 1.3.3 2.1.3s1.5-.1 2.1-.3c.6.5 1.4.3 2.1-.1 1.1-.6 2.9-.8 3.2-1.8.2-.7-.5-1.3-1.1-1.7.4-.6.6-1.5.3-2.6-.5-2-2-3.5-2.6-4.9-.2-.8 0-1.6 0-2.8C16 3.9 14.4 2 12 2zm-1.4 4.2c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zm2.8 0c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zM12 9.3c.9 0 1.9.5 1.9 1s-1 1.2-1.9 1.2-1.9-.7-1.9-1.2 1-1 1.9-1zm0 3.4c2.2 0 3.6 2.6 3.6 4.4 0 1.5-1.6 2.3-3.6 2.3s-3.6-.8-3.6-2.3c0-1.8 1.4-4.4 3.6-4.4z"/></svg></span>Linux</a><a href="/download#hive"><span class="osmark mini" data-os="hive" title="HiveOS"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round" stroke-linecap="round"><path d="M12 2.6 20.2 7.3v9.4L12 21.4 3.8 16.7V7.3z"/><path d="M12 7.4 16 9.7v4.6L12 16.6 8 14.3V9.7z"/><path d="M12 7.4V2.6M16 9.7l4.2-2.4M16 14.3l4.2 2.4M12 16.6v4.8M8 14.3l-4.2 2.4M8 9.7 3.8 7.3"/></svg></span>HiveOS</a></div>
<div class="footer-dl" aria-label="Download Ember"><a href="/download#windows"><span data-os="windows" class="mini"></span>Windows</a><a href="/download#mac"><span data-os="mac" class="mini"></span>macOS</a><a href="/download#linux"><span data-os="linux" class="mini"></span>Linux</a><a href="/download#hive"><span data-os="hive" class="mini"></span>HiveOS</a></div>
<a href="https://git.igneum.network/igneum-network/spec" target="_blank" rel="noopener" class="text-link">Specification and test vectors<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 18 18 6M6 6h12v12"/></svg></a>
</div>
<div class="footer-column"><h4>Run</h4><div>

View file

@ -59,11 +59,13 @@ ship tool self-test
relay unit tests
miner app notice strip and update card tests
launch gates: every row with its check, the handoff text clean (self-test, then the tree)
spec read-back: every constant the lottery-hash spec names agrees with the crate's pub const (known-failed fixture first; the ids half is igneum-pow/tests/spec_readback.rs)
income per tier: the public table equals its inputs, the schedule arithmetic
hash-origin report: a known-finished day and a known-failed day
harness summaries never carry a raw 64-hex key (the writer's own redaction and check)
docs-only pushes skip the compile-or-compute CI jobs (the changes job's classifier)
the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)
the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)
every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)
a box or network check gets one retry before it is red (retry-once self-test)
gh's active account on the pushing Mac is the stored Igneum entry (self-test: another login refused and named; the hook and the merge tool run the check live)

View file

@ -144,11 +144,13 @@ tree_checks() {
run "relay unit tests" node --test relay/test/parse.test.mjs relay/test/auth.test.mjs relay/test/wake.test.mjs relay/test/ember.test.mjs
run "miner app notice strip and update card tests" node --test app/igneum-app/ui/notices.test.mjs app/igneum-app/ui/update-card.test.mjs app/igneum-app/ui/view.test.mjs app/igneum-app/ui/tune-line.test.mjs
run "launch gates: every row with its check, the handoff text clean (self-test, then the tree)" bash -c 'node tools/ci/launch-gates-check.mjs --self-test && node tools/ci/launch-gates-check.mjs'
run "spec read-back: every constant the lottery-hash spec names agrees with the crate's pub const (known-failed fixture first; the ids half is igneum-pow/tests/spec_readback.rs)" bash -c 'node tools/ci/spec-constants-check.mjs --self-test && node tools/ci/spec-constants-check.mjs'
run "income per tier: the public table equals its inputs, the schedule arithmetic" bash -c 'node tools/launch/income-tiers.mjs --check && node --test tools/launch/income-tiers.test.mjs && node tools/launch/income-page.mjs --check'
run "hash-origin report: a known-finished day and a known-failed day" node --test tools/observer/hash-origin.test.mjs
run "harness summaries never carry a raw 64-hex key (the writer's own redaction and check)" node infra/fast-time/lib/redact-keys.mjs --self-test
run "docs-only pushes skip the compile-or-compute CI jobs (the changes job's classifier)" bash tools/ci/docs-only-check.sh --self-test
run "the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)" bash -c 'node tools/ledger/export-public.mjs --self-test && node tools/ledger/export-public.mjs --check'
run "the ledger page reads both entry heading forms (M1 and AP-F8-1) so no in-house pass row is dropped from /ledger (known-failed first)" node tools/ledger-page.mjs --self-test
run "every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)" bash tools/ci/workflow-timeouts-check.sh --self-test
run "a box or network check gets one retry before it is red (retry-once self-test)" bash tools/ci/retry-once.sh --self-test
run "gh's active account on the pushing Mac is the stored Igneum entry (self-test: another login refused and named; the hook and the merge tool run the check live)" bash tools/ci/gh-account-check.sh --self-test

View file

@ -0,0 +1,138 @@
#!/usr/bin/env node
// Spec read-back, the constants half (adv-accept-3 finding 3, ledger AP-F8-5, 7 October 2026): every table in
// docs/spec/01-lottery-hash.md whose header row is `| Constant | Value | Where |` names Rust constants of the igneum-pow
// crate with the value the text relies on, and this check fails when any value differs from the crate's `pub const`.
// So the public text and the shipped rule cannot drift apart unseen again (the spec at 017e7037 described a rule that
// mined a different program on 264 of 400 epochs). The ids half is igneum-pow/tests/spec_readback.rs (a cargo test).
//
// node tools/ci/spec-constants-check.mjs exit 1 listing every row that disagrees, is absent or does not parse
// node tools/ci/spec-constants-check.mjs --self-test a fixture with one wrong value, one absent constant and one pending
// row must fail on the first two and pass the third; the clean fixture passes
//
// Row forms. Constant: `module::NAME` (one file under igneum-pow/src) or `NAME` in backticks (every file searched). Value:
// the Rust literal as it reads (integers with or without underscores, a decimal with a dot, a byte string in double quotes).
// Where: free text; a row whose Where contains "pending" is skipped while the constant is absent from the crate (a class on
// a branch that lands code and text together) and compared once it is present. A constant defined as an expression of other
// constants (`ACCEPT_UNITS * LANES`) is evaluated. One literal that is not a const is read by name: `accept::distinct_ratio_pass`
// with the window cap `.min(N)` inside that function.
import { readFileSync, readdirSync, mkdtempSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { tmpdir } from 'node:os';
import { fileURLToPath } from 'node:url';
const root = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
const SPEC = 'docs/spec/01-lottery-hash.md';
const SRC = 'igneum-pow/src';
// the literals inside functions the spec names as constants: name -> [file, function, regex with one capture]
const LITERALS = {
'accept::distinct_ratio_pass': ['accept.rs', 'distinct_ratio_pass', /\.min\((\d+)\)/],
};
function tables(md) {
// every table whose header is exactly Constant | Value | Where; rows until the first non-table line
const out = []; const lines = md.split('\n');
for (let i = 0; i < lines.length; i++) {
if (!/^\|\s*Constant\s*\|\s*Value\s*\|\s*Where\s*\|\s*$/.test(lines[i])) continue;
const rows = []; let j = i + 1;
if (j < lines.length && /^\|\s*-+\s*\|/.test(lines[j])) j++;
for (; j < lines.length && /^\|/.test(lines[j]); j++) {
const cells = lines[j].replace(/^\||\|$/g, '').split('|').map(c => c.trim());
if (cells.length < 3) continue;
rows.push({ line: j + 1, constant: cells[0].replace(/`/g, '').trim(), value: cells[1].replace(/`/g, '').trim(), where: cells.slice(2).join('|') });
}
out.push(rows); i = j;
}
return out;
}
function constMap(srcDir) {
// name -> { file, raw } for every `pub const NAME: T = <expr>;` under igneum-pow/src (one line each)
const map = new Map(); const files = readdirSync(srcDir).filter(f => f.endsWith('.rs'));
for (const f of files) {
const text = readFileSync(join(srcDir, f), 'utf8');
for (const m of text.matchAll(/^pub const ([A-Z][A-Z0-9_]*)\s*:\s*[^=]+=\s*([^;]+);/gm)) {
const name = m[1]; const raw = m[2].trim();
const key = f.replace(/\.rs$/, '') + '::' + name;
map.set(key, { file: f, raw }); if (!map.has(name)) map.set(name, { file: f, raw, bare: true });
}
}
return { map, files, srcDir };
}
function evalRust(raw, consts, depth = 0) {
// a number, a byte string, or an expression over numbers and other constants
if (depth > 8) throw new Error('constant expression too deep: ' + raw);
const s = raw.replace(/\s+as\s+(u8|u16|u32|u64|usize|i32|i64|f64)/g, '').trim();
const bs = /^b?"((?:[^"\\]|\\.)*)"$/.exec(s); if (bs) return bs[1];
const expr = s.replace(/[A-Z][A-Z0-9_]*/g, name => {
const c = consts.get(name); if (!c) throw new Error('unknown identifier ' + name + ' in ' + raw);
const v = evalRust(c.raw, consts, depth + 1); if (typeof v !== 'number') throw new Error(name + ' is not a number');
return '(' + v + ')';
}).replace(/_/g, '').replace(/(\d)(u8|u16|u32|u64|usize|i32|i64|f64)\b/g, '$1');
if (!/^[\d\s().+\-*/<>]+$/.test(expr)) throw new Error('cannot evaluate ' + raw);
// eslint-disable-next-line no-new-func
return Number(Function('"use strict"; return (' + expr + ');')());
}
function parseSpecValue(v) {
const bs = /^"((?:[^"\\]|\\.)*)"$/.exec(v); if (bs) return bs[1];
const n = Number(v.replace(/_/g, '')); if (v.trim() === '' || Number.isNaN(n)) throw new Error('not a number or a quoted string: ' + v);
return n;
}
function check(rootDir, specRel = SPEC, srcRel = SRC) {
const md = readFileSync(join(rootDir, specRel), 'utf8');
const { map } = constMap(join(rootDir, srcRel));
const fails = []; let rows = 0, pending = 0;
for (const table of tables(md)) for (const r of table) {
rows++;
try {
const want = parseSpecValue(r.value);
if (LITERALS[r.constant]) {
const [file, fn, re] = LITERALS[r.constant];
const text = readFileSync(join(rootDir, srcRel, file), 'utf8');
const start = text.indexOf('fn ' + fn + '('); if (start < 0) throw new Error('no fn ' + fn + ' in ' + file);
const body = text.slice(start, text.indexOf('\n}', start)); const m = re.exec(body);
if (!m) throw new Error('no literal matching ' + re + ' inside ' + fn);
if (Number(m[1]) !== want) fails.push(`${specRel}:${r.line}: ${r.constant} reads ${r.value} in the spec, ${m[1]} in ${file} fn ${fn}`);
continue;
}
const c = map.get(r.constant);
if (!c) {
if (/pending/i.test(r.where)) { pending++; continue; }
fails.push(`${specRel}:${r.line}: ${r.constant} is not a pub const of ${srcRel} (and the row is not marked pending)`); continue;
}
const got = evalRust(c.raw, map);
const same = typeof want === 'string' ? want === got : Math.abs(want - got) < 1e-12;
if (!same) fails.push(`${specRel}:${r.line}: ${r.constant} reads ${r.value} in the spec, ${JSON.stringify(got)} in ${c.file} (${c.raw})`);
} catch (e) { fails.push(`${specRel}:${r.line}: ${r.constant}: ${e.message}`); }
}
if (rows === 0) fails.push(`${specRel}: no table headed | Constant | Value | Where | found`);
return { fails, rows, pending };
}
function selfTest() {
const d = mkdtempSync(join(tmpdir(), 'spec-constants-')); const fails = [];
try {
mkdirSync(join(d, 'docs', 'spec'), { recursive: true }); mkdirSync(join(d, SRC), { recursive: true });
writeFileSync(join(d, SRC, 'accept.rs'), 'pub const ACCEPT_UNITS: usize = 64;\npub const ACCEPT_HASHES: usize = ACCEPT_UNITS * LANES;\npub const MAX_SATURATED: u32 = 164;\npub const MIN_DISTINCT_RATIO_V4: f64 = 0.98;\npub const ACCEPT_TAG: &[u8] = b"igneum-accept/";\npub fn distinct_ratio_pass(x: u64) -> u64 {\n let w = (x as u64).min(2);\n w\n}\n');
writeFileSync(join(d, SRC, 'generator.rs'), 'pub const LANES: usize = 32;\npub const MIN_DISTINCT_SUM: u64 = 245_760;\n');
const clean = '# spec\n\n| Constant | Value | Where |\n|---|---|---|\n| accept::ACCEPT_UNITS | 64 | (c) |\n| accept::ACCEPT_HASHES | 2048 | |\n| `MIN_DISTINCT_SUM` | 245760 | |\n| accept::MIN_DISTINCT_RATIO_V4 | 0.98 | |\n| accept::ACCEPT_TAG | "igneum-accept/" | |\n| accept::distinct_ratio_pass | 2 | the window cap |\n| accept::MIN_DISTINCT_RATIO_V5 | 0.995 | class v5, pending |\n\ntext\n';
writeFileSync(join(d, SPEC), clean);
const ok = check(d); if (ok.fails.length || ok.rows !== 7 || ok.pending !== 1) fails.push('the clean fixture failed: ' + JSON.stringify(ok));
writeFileSync(join(d, SPEC), clean.replace('| 64 |', '| 63 |').replace('| `MIN_DISTINCT_SUM` |', '| `MIN_DISTINCT_SUMM` |'));
const bad = check(d);
if (!bad.fails.some(f => /ACCEPT_UNITS reads 63/.test(f))) fails.push('a wrong value was not caught: ' + JSON.stringify(bad.fails));
if (!bad.fails.some(f => /MIN_DISTINCT_SUMM is not a pub const/.test(f))) fails.push('an absent constant was not caught: ' + JSON.stringify(bad.fails));
if (bad.fails.length !== 2) fails.push('the known-failed fixture had ' + bad.fails.length + ' failures, wanted 2: ' + JSON.stringify(bad.fails));
} finally { rmSync(d, { recursive: true, force: true }); }
if (fails.length) { for (const f of fails) console.error('self-test failed: ' + f); return 1; }
console.log('self-test passed: a wrong value and an absent constant are caught and named; a pending row and the clean fixture pass; an expression over constants evaluates');
return 0;
}
if (process.argv.includes('--self-test')) process.exit(selfTest());
const r = check(root);
if (r.fails.length) { for (const f of r.fails) console.error('spec-constants: ' + f); process.exit(1); }
console.log(`spec-constants: ${r.rows} rows of ${SPEC} agree with the crate's pub const items (${r.pending} pending)`);

View file

@ -45,20 +45,41 @@ function inline(s) {
return t;
}
const lines = readFileSync(src, 'utf8').split('\n');
const entries = [];
let cur = null;
for (const l of lines) {
const m = /^### ([A-Z]\d+)\. (.*)$/.exec(l);
if (m) { cur = { id: m[1], title: m[2].trim(), quote: '', status: '', answer: '' }; entries.push(cur); continue; }
if (!cur) continue;
const s = l.trim();
if (!cur.quote && s.startsWith('"')) cur.quote = s.replace(/^"|"$/g, '');
else if (s.startsWith('Status:')) cur.status = s.slice(7).trim(); // the LAST status line wins, as tools/ledger/export-public.mjs reads it (7 October 2026: the page read the first and counted four entries as Other that the export did not)
else if (!cur.answer && s.startsWith('Answer:')) cur.answer = s.slice(7).trim();
// An entry heading: `### M1. title` or, since 7 October 2026 night, the in-house adversarial pass's `### AP-F8-1. title`
// (the first form alone dropped every AP entry from the page while the export carried them).
const ENTRY_RE = /^### ([A-Z]\d+|AP-[A-Z]\d+-\d+)\. (.*)$/;
const secKey = id => (id.startsWith('AP-') ? 'AP' : id[0]);
export function parseLedger(text) {
const entries = [];
let cur = null;
for (const l of text.split('\n')) {
const m = ENTRY_RE.exec(l);
if (m) { cur = { id: m[1], title: m[2].trim(), quote: '', status: '', answer: '' }; entries.push(cur); continue; }
if (!cur) continue;
const s = l.trim();
if (!cur.quote && s.startsWith('"')) cur.quote = s.replace(/^"|"$/g, '');
else if (s.startsWith('Status:')) cur.status = s.slice(7).trim(); // the LAST status line wins, as tools/ledger/export-public.mjs reads it (7 October 2026: the page read the first and counted four entries as Other that the export did not)
else if (!cur.answer && s.startsWith('Answer:')) cur.answer = s.slice(7).trim();
}
return entries;
}
if (process.argv.includes('--self-test')) {
// known-failed first: the single-letter form alone misses the AP entry; then the parser sees both forms
const fx = '# l\n\n### M1. The space is small\n"Eleven ops."\n\nStatus: Open.\n\n### AP-F8-1. A hot set\n"Top items."\n\nStatus: Fixed (7 October 2026).\n\nAnswer: Yes.\n';
const old = fx.split('\n').filter(l => /^### ([A-Z]\d+)\. /.test(l)).length;
const got = parseLedger(fx);
const fails = [];
if (old !== 1) fails.push('the known-failed form did not drop the AP entry');
if (got.length !== 2 || got[1].id !== 'AP-F8-1' || got[1].status !== 'Fixed (7 October 2026).' || got[1].answer !== 'Yes.') fails.push('the parser did not read both entry forms: ' + JSON.stringify(got));
if (secKey('AP-F8-1') !== 'AP' || secKey('M1') !== 'M') fails.push('the section key is wrong');
if (fails.length) { fails.forEach(f => console.error('self-test failed: ' + f)); process.exit(1); }
console.log('self-test passed: the single-letter heading form drops an AP entry (known-failed), the parser reads M1 and AP-F8-1 with their status and answer, the section key routes AP ids to the pass section');
process.exit(0);
}
const SECTION = { M: 'Mining and chips', F: 'Finality and attacks', P: 'Proving and the zkEVM', E: 'Economics and the coin', G: 'Governance and the founders', C: 'Comparisons', L: 'Legal and regulatory', X: 'Launch and\u00a0operations', D: 'Builders' };
const entries = parseLedger(readFileSync(src, 'utf8'));
const SECTION = { AP: 'The in-house adversarial pass', M: 'Mining and chips', F: 'Finality and attacks', P: 'Proving and the zkEVM', E: 'Economics and the coin', G: 'Governance and the founders', C: 'Comparisons', L: 'Legal and regulatory', X: 'Launch and\u00a0operations', D: 'Builders' };
function bucket(status) {
const s = status.toLowerCase();
@ -104,8 +125,8 @@ const countRows = ORDER.filter(b => counts[b]).map(b => `<tr><td class="num">${c
let body = '';
let lastSec = '';
for (const e of entries) {
const sec = SECTION[e.id[0]] || e.id[0];
if (sec !== lastSec) { body += `<h2 id="${e.id[0].toLowerCase()}">${esc(sec)}</h2>\n`; lastSec = sec; }
const sec = SECTION[secKey(e.id)] || secKey(e.id);
if (sec !== lastSec) { body += `<h2 id="${secKey(e.id).toLowerCase()}">${esc(sec)}</h2>\n`; lastSec = sec; }
const b = bucket(e.status);
const word = statusWord(scrub(e.status));
const rest = scrub(e.status).slice(word.length).replace(/^[\s(:.]+/, '').trim();