Merge master 4066512f4 into pool-registry under the master-landing lock

This commit is contained in:
igneum-labs 2026-10-08 20:48:39 +00:00
commit 462dfd97fa
42 changed files with 1144 additions and 184 deletions

View file

@ -27,11 +27,15 @@ population, Apple reported and not headlined; every defence is scored after the
2. The rows (ASAP7, placed and routed, SPEF, gate-level VCD; the SRAM term modelled, bands shown; node factors
claimed): the full core 9.36 pJ per lane-op at ASAP7 on the class v4 draw (8.6 to 11.1), 6.55 at N5, 4.72 at N3;
k 0.64 node-for-node and 0.46 a node ahead at the 5090's lock; the reserve families k 0.33 to 0.86 placed; the
genesis-only core 7.78 (k 0.53 / 0.38); the 32-lane genesis core 10 percent under (synthesis).
genesis-only core 7.78 (k 0.53 / 0.38); the 32-lane cores 10 to 13 percent under their 8-lane forms (synthesis:
the full core 5.73, k 0.39 / 0.28), so the adversary's cheapest row is the 32-lane placed core at about 5.7 pJ
per lane-op at N5 (k 0.55 same-node), a sixth under the headline row.
3. The complete machine (memory, controller, host share, power train, cooling) on the card's own GDDR7: 1.5x the
5090 at its lock per joule node-for-node (1.3x to 1.7x), 1.8x a node ahead (1.5x to 2.0x); 3.3x per dollar; HBM3
buys it nothing; the N2 SRAM die 2.3x and 3.1x; the stored-half hybrid (section 13) 1.9x and 2.4x at USD 2.80 per
MH/s. Capex per MH/s is the larger half of the chip's edge; the project cost is its hold.
5090 at its lock per joule node-for-node on the placed 8-lane full core (1.3x to 1.7x), 2.1x on the placed
32-lane core's floor (1.7x to 2.4x); 1.8x and 2.4x a node ahead; 3.3x per dollar; HBM3 buys it nothing; the N2
SRAM die 2.3x to 4.2x same-node; the stored-half hybrid (section 13) 1.9x to 2.6x at USD 2.80 per MH/s. The
same-node honest bracket across the adversary's choices is 1.5x to 2.1x on the DRAM board. Capex per MH/s is the
larger half of the chip's edge; the project cost is its hold.
4. Data-local execution cannot pay (the live state is 26x the read, section 11); memory sharing is the baseline;
recomputation loses; selective participation gains 2 to 5 percent for 50 to 90 percent of revenue (section 13).
5. Class v7 should take the epoch-defined bounded dataset with a published support horizon and keep the floor
@ -348,10 +352,28 @@ under the class v4 draw (shfla and mm8 live -1.2 percent, all eight live -9.2 pe
hash and pays +29 percent of shadow energy, and the card's premium rises by the same +29 percent (its tile at 70 pJ
per lane against the draw's 10.3): the ratio does not move, the lane count does (section 14, row 1).
The 32-lane genesis core (synthesis only; four window macros, one imem pair shared by 32 lanes): 261,440 cells,
5.29 pJ per lane-op at ASAP7 (4.65 to 6.77) on the class v4 draw, 3.70 at N5, k 0.36 at the lock: 10 percent
under the 8-lane core, the imem and the sequencer amortised over four times the lanes. The 32-lane full core
(synthesis) and its placed form are in the flow (adv-a and adv-f at 16:4x BST) and land as a delta.
The 32-lane cores: the genesis comparator PLACED AND ROUTED (adv-g, 20:1x BST; SPEF, gate-level VCD at the
30 ns constraint, four window macros and one imem macro, 717,268 cells with fill): 4.80 pJ per lane-op at ASAP7 on
the class v4 draw (4.17 to 6.28), 3.36 at N5, 2.42 at N3, k 0.33 node-for-node and 0.24 a node ahead at the
5090's lock. That is 9 percent UNDER its own synthesis row (5.29), where the 8-lane cores read 32 to 42 percent
over theirs: the 32-lane core is routed under a 30 ns constraint (its unpipelined crossbar path is 27 ns) and the
flow's resizer downsizes every cell to it, so the placed figure carries smaller cells and lower capacitance than a
chip clocked at 1.5 ns with its pipeline registers would. The honest 32-lane row is therefore a band, not a point:
3.36 pJ at N5 (the relaxed-clock placement, the floor) to 5.7 (the synthesised 32-lane full core 5.73 at ASAP7
times the 8-lane cores' measured placement factor 1.42, the ceiling), k 0.33 to 0.55 same-node and 0.24 to 0.40 a
node ahead. The synthesis rows beside it: the genesis core 261,440 cells, 5.29 (4.65 to 6.77), 3.70 at N5; the
full core 393,036 cells, 5.73 (5.09 to 7.20), 4.01 at N5, 2.89 at N3, k 0.39 / 0.28; the bank's cost at 32 lanes
8 percent of the energy on the draw and 50 percent of the cells. The placed 32-lane FULL core runs on adv-g (from
synthesis at 19:58 BST, the same 30 ns constraint) and lands as a delta; its placed figure will sit inside the
same band for the same reason.
The complete machine at the 32-lane band (the genesis comparator's placed 3.36 pJ at N5 as the floor; the ceiling
is section 6's placed 8-lane full core less a sixth): the GDDR7 board 2.1x the 5090 at its lock per joule
node-for-node at the floor (1.7x to 2.4x) and 2.4x a node ahead (2.0x to 2.7x), against 1.5x and 1.8x on the
placed 8-lane full core; the N2 SRAM die 4.2x and 5.7x at the floor. So the same-node honest bracket across the
adversary's lane count, core and sizing choices is 1.5x to 2.1x per joule on the DRAM board (1.3x to 2.4x on the
bands), 1.9x to 2.6x with the stored-half hybrid, USD per MH/s unchanged (the core is a tenth of the board's capex
at 32 lanes).
The board rows of section 6 restated at the placed energy (the full core at 6.55 pJ per lane-op at N5, band 6.01
to 7.77; 4.72 at N3): the complete GDDR7 machine 1.53 microjoules per hash, **1.5x the 5090 at its lock per joule
@ -726,7 +748,14 @@ percent (5th to 95th percentile 1.45x to 1.58x on the placed rows); a specialist
gains 2, 3 or 5 percent of ratio and loses 50, 75 or 90 percent of revenue, because difficulty follows the fleet it
joins and it earns in proportion to the time it mines; downtime and re-entry cost it the DAA window's lag each
way and buy it nothing. The GPU-cost budget of 10 percent at the lock (set before these results) is untouched:
no honest energy is spent in this section. Served sentence for the bracket: against a chip on the same node the
no honest energy is spent in this section. (5) "Layer 8 off" (the hash lane's D2 experiment of 18:12 BST: the era layout's window-layer draw removed, every
window the whole dataset): the hottest half then serves exactly 50 percent of the reads at every program, so the
uniform-store row becomes the hot-set row: the hybrid reads 1.85x (1.58 to 2.03) same-node and 2.27x (1.95 to
2.50) a node ahead at USD 3.34 per MH/s and 273 MH/s per board, against 1.93x / 2.40x at USD 2.80 on today's mean
program (hit 0.581) and 2.09x / 2.65x at USD 1.88 on Devnet 3's p98 program (0.72): the window layer's removal
takes 4 percent off the hybrid's per-joule edge at the mean program and 11 percent at the tail, and its capex edge
from 5.7x to 4.8x of the card's, for one and-or per load on the honest side. The rows are in
`tools/chip-model/mf/results/d2b-n5.md` and `d2b-n3.md`. Served sentence for the bracket: against a chip on the same node the
honest floor is the stored-half hybrid at 1.9x to 2.1x per joule and 6x to 9x per dollar (1.65x to 2.3x on the
band), not the DRAM board's 1.5x and 3.3x; the lever on it is the dataset floor as a capex ticket.
@ -751,7 +780,131 @@ Reading: no row loses competitiveness; the cheapest adaptation is firmware for e
sequence for an entry outside it (row 2, 1.3x to 1.45x same-node while live), and a respin only if the chain adds a
family the sequence cannot carry, which it has 360 days' notice of. The stress life of three years holds in full.
PENDING with clocks: the 32-lane full core's synthesis row (adv-a, in ABC at 17:0x BST; by 19:30) and its placed
row (adv-f, at floorplan; by 21:00); the k lane's crossbar, scratch and tile rows (its pod); a real memory
PENDING with clocks: the 32-lane full core's placed row (adv-g from 19:58 BST on a 64-core host, adv-f since 18:12
on a slower one, whichever lands first, by 22:00; the 32-lane genesis comparator's placed row landed at 20:1x,
section 5, and brackets it); the k lane's crossbar, scratch and tile rows (its pod); a real memory
compiler's figure for the two macros (owed, no clock: FakeRAM gives area and pins only); the per-family rows on
the 32-lane placed core (by 21:30 if adv-f lands, else the next pass).
## 15. The SRAM die's ticket reconciled (the research lane's and the coordinator's ask, 17:2x BST; floor lane 3's USD 0.6 against this file's USD 2.94 per MH/s)
The two figures price different machines. Lane B's USD 0.25 to 0.4 of silicon per MH/s (chip-model-v3 5.12,
hardware-future) is the die at ZERO SHADOW: 2,100 MH/s per 2 GiB reticle at 300 W, no shadow core at all; with a
board it reads about USD 0.6. This file's USD 2.94 is the same die carrying the class v4 shadow on the placed mf core
(6.55 pJ per lane-op at N5), with the machine held at lane B's 270 to 300 W: the shadow is 13x the die's own energy
per hash, so at that budget the machine makes 383 MH/s and the fixed tickets (die, package, board, host) divide by
383 instead of 2,100. Neither is the adversary's choice. The designer sets the power budget to minimise dollars per
MH/s; the die's read ceiling (floor lane 3: about 1,060 G reads per second, 8.3 GH/s) is never reached because the
core's silicon and the power train bind first. Line by line, every term with its source and label:
| Component | This file at 270 W (section 6) | The optimised machine (this section) | Source and label |
|---|---|---|---|
| The 2 GiB SRAM die: 452 mm^2 of macro on a 550 to 650 mm^2 N2 die, a USD 30,000 wafer, lane B's yield model | USD 500 (400 to 600) | the same | lane B 4.9 (claimed density and wafer price; the yield approximate) |
| The shadow core's silicon: this core's placed floorplan 0.0036 mm^2 per lane at ASAP7, x0.55 to N5 (0.002 mm^2), one lane-op per 7.5 ns (the 5-phase slot), 770 lanes per MH/s; USD 0.36 per mm^2 of N5 (sram-mirror's yield model) | USD 0.55 per MH/s (590 mm^2 at 383 MH/s) | USD 0.11 to 0.55 per MH/s: a core pipelined to one op per cycle per lane is five times denser (0.0004 mm^2 per lane; about +0.1 to 0.2 pJ per op for the pipeline registers, inside the band); the record's USD 25 to 40 per 166 MH/s (0.15 to 0.24) sits inside | this file's placed floorplan (measured), the pipelining factor approximate |
| The package: two reticle-class dies (the SRAM die and the core die) with a wide link between them | USD 200 (an interposer, approximate) | USD 60 to 200: an organic flip-chip substrate carries a UCIe-class link at the hash's 80 bits per read (floor lane 3's hop, 0.5 pJ per bit); the interposer only if the link must be wider | approximate; the interposer price chip-model-v3 5.1 (claimed) |
| The board, assembly, PSU and cooling | USD 200 flat (board 150, assembly 50; PSU and cooling inside) | USD 150 plus USD 0.15 per watt of PSU and cooling (approximate): USD 240 at 600 W, 375 at 1.5 kW | approximate |
| The host (one full node per 100 machines) | USD 15 | USD 15 | section 6 |
| The sustained rate | 383 MH/s at 270 W (power-bound on the core) | 852 MH/s at 600 W, 1,420 at 1 kW, 2,130 at 1.5 kW, 2,840 at 2 kW (the die's own ceiling 8.3 GH/s, never reached) | board.py on the placed core (modelled) |
| **USD per MH/s** | **2.94** | **1.63 / 1.20 / 0.98 / 0.88 at 600 W to 2 kW on this core; 1.07 / 0.73 / 0.56 / 0.47 with the pipelined core and the organic package** | modelled |
The reconciled figure: **about USD 1.0 per MH/s for the SRAM-die machine carrying the class v4 shadow (0.5 to 1.6),
at 1 to 1.5 kW per machine**, set by the power train and the core's silicon and not by the die; lane B's USD 0.6
holds only at zero shadow, this file's USD 2.94 only at a 300 W budget, and both stand in the record with those
labels. Per joule the optimised machine is unchanged (the energy per hash does not depend on the budget: 2.3x
same-node, 3.1x a node ahead at the placed core).
What a maker's first batch of 1,000 dies would actually pay: not the unit ticket. A thousand 2 GiB dies at 1 to 2
GH/s each are 1 to 2 TH/s, several times the chain's whole hashrate at the rental equilibrium (floor lane 3's
section 4: a third of the network is under two dies at every price in its table), so the batch's cost is the
project (USD 100 M to 500 M at N2, claimed) spread over a hashrate the chain cannot absorb: USD 50 to 250 per MH/s
of NRE against USD 1 of unit cost, and the first dies' yield (a 600 mm^2 die with 452 mm^2 of macro, redundancy
untested) adds USD 100 to 400 per die, approximate. The die's economics are project economics: the coexistence
verdict should take USD 1.0 per MH/s (0.5 to 1.6) as the unit ticket of a fleet that exists and the project cost
as the gate on whether it ever does.
## 16. The formal memory model: the class v6 evaluation in capacity, bandwidth, energy and amortisation terms (the 2.0 register's row, drafted 18:1x BST for the 12:00 delta)
One evaluation (a hash) under class v6: 128 dependent loads of a 4-byte word (W = 1; 16 bytes at W = 4) from a
dataset of D bytes (2 GiB at genesis, the floor schedule 5.5 / 8.5 / 11.5 GiB), each address the fold of the lane's
live state (64 registers, 61 necessary), each load returning into that state; between loads the shadow block (6,912
instructions per iteration, 102,100 per hash) and the base program (512); the dataset rebuilt once per window from
the chain's state (class v5 and v6) or from the epoch's seed (the class v7 default), 157 G ops per GiB. The terms,
each with its bound and whether the bound is closed-form or rests on physical design:
| Term | Per evaluation | Across N evaluations on one machine | The bound | Closed-form or physical |
|---|---|---|---|---|
| Capacity, the dataset | D bytes must be addressable at the hash's latency: every item is reachable from every lane with uniform probability (the fold is keyed by the destination register; no item is colder than 1/D by construction, the hot set is per program and per window) | shared by every lane and every engine on the board: D once per machine, never per engine | a machine holds D or recomputes (section 13: recomputation loses at every point; a partial store of fraction f serves f of the reads uniformly, or up to 0.58 to 0.72 at f = 0.5 on the window layer, 0.50 with the layer off) | closed-form (the item distribution is the census's; the SRAM price per GiB is claimed) |
| Capacity, the live state | 2,112 bits per hash in flight; the chain forbids reducing it (61 of 64 registers necessary; the connected-state lane: free for a chip, only the width counts) | lanes in flight x 2,112 bits: 1,172 lanes on the GDDR7 board (310 KB), 21,000 on the SRAM die (5.5 MB) | an SRAM macro per 8 lanes, 3.5 pJ per access (2.0 to 7.0): the one term this file's placed rows measure | physical (the macro energy band; the rest of the core measured placed) |
| Bandwidth, random reads | 128 activates per hash: the device's activate rate, not its pin rate, binds (21.3 G per second on 16 GDDR7 devices, 82 percent reached by the 5090; 10.7 G on an HBM3 stack, unmeasured, the JEDEC floor 2.3 G; the SRAM die's 1,060 G never reached before power binds) | N x 128 activates: the sustained rate is activates per second over 128, shared across every engine on the board | the memory's activate ceiling per dollar of devices: a chip cannot buy more activates per device than the card has (section 11) | the GDDR7 ceiling measured on the card (82 percent); the HBM3 ceiling physical (the AWS F2 hour); the SRAM die's a model |
| Bandwidth, bytes | 32-byte sectors at W = 1 (4 KB per hash, 38 percent of the GDDR7 pins at the activate ceiling); 2 sectors at W = 16 (dead on the cards) | linear in N | never the bound at W = 1 to 8 | closed-form |
| Bandwidth, the state to the data | 2,112 bits per read if the computation moves to the item; 80 bits per read if the item moves to the lane | 26x on every medium (section 11) | data-local execution cannot pay | closed-form (the bit counts) with the per-bit energies claimed |
| Energy, the memory | 2.0 nJ per GDDR7 read (1.5 to 2.6), 1.2 on HBM3, 0.25 on the SRAM die at W = 1: 0.256 / 0.154 / 0.032 microjoules per hash | linear in N plus the static and controller terms (35 W on the GDDR7 board) | the device's activate energy (chip-model-v3 5.3, modelled from HBM2's breakdown and the vendors' per-bit figures) | physical (claimed breakdowns; the card's marginal measured at 8.7 nJ per read) |
| Energy, the shadow | 102,612 lane-ops x 6.55 pJ (placed, N5) = 0.67 microjoules; 0.48 at N3; the 32-lane core about 0.58 | linear in N; the clock, the window and the units measured per op; the leakage per lane | the placed rows (sections 3 to 5); the SRAM term's band | physical (measured placed; the SRAM term modelled) |
| Energy, the machine | the power train (PSU 92 percent, VRM 90), cooling (3 percent), the host (0.85 W per machine) | fixed per machine, amortised over its rate | section 6's rows | approximate |
| Amortisation, the set-up | the dataset build 0.7 J per GiB per window per machine; the host USD 15 and 0.85 W per machine; the era's registers | shared by every engine of the machine and every hash of the window: 1.4e-12 J per hash, under 1 percent of capex | nothing to amortise further: the set-up is already a window term | closed-form (the build measured on a card, the host approximate) |
| Amortisation, the silicon | the core die USD 0.11 to 0.55 per MH/s, the memory USD 320 to 1,000 per board, the package, the board | spread over the life (0.5 to 3 years): 0.085 USD per TH at 3 years on the GDDR7 machine, 0.22 to 0.27 on the cards | capex per sustained MH/s is the larger half of the chip's edge (section 8) | the core measured placed, the memory and board claimed or approximate |
| Selective participation | the per-epoch ratio spreads 9 percent (5th to 95th percentile 1.45x to 1.58x same-node) | a specialist mining the best x of epochs earns x of the revenue at +2 to +5 percent of ratio | nothing to gain | closed-form on the band (the draws uniform within it, approximate) |
The reading: capacity is a ticket (D once per machine, in DRAM at USD 10 per GiB or SRAM at USD 250), bandwidth is
the activate ceiling per dollar of devices and is the card's own, energy is the memory's activate energy plus the
shadow at the placed core's pJ per op, and amortisation is already complete at one machine (the set-up is a window
term, the silicon a life term). The bounds that are closed-form: the capacity and state terms, the bit counts of
data-local execution, the bytes, the set-up amortisation, selective participation. The bounds that rest on physical
design: the SRAM macro's access energy (the one modelled term in the placed rows), the HBM3 activate ceiling, the
SRAM die's wire term and the on-package hop, the device activate energies (claimed breakdowns), and the board's
power train and cooling (approximate). Nothing in the model rewards a chip for anything but the memory's own
activate energy and the shadow's pJ per op, which is where sections 6 and 13 put the honest bracket.
## 17. Review B's F05: the reg64 address mixer's incremental form, priced at the placed level (20:0x BST; the clock 23:30)
The finding: the connected-state candidate's address (the fold over all 63 live registers before every load) has an
exact incremental form through a prefix-XOR tree, so a chip never reads and folds 63 registers per load; a design
that assumes the literal fold overstates the chip's cost, and a one-register perturbation test says nothing about a
minimum circuit. The shipped class (v4, v5, v6) folds ONE source register per load (this core's load op), so the
finding touches the connected-state candidate (killed as a class at 17:25 BST on other grounds) and the bound it
sets for any future class that couples the address to the whole window. Three designs for that coupling on this
core, priced with the placed per-op figures (6.55 pJ per lane-op at N5 on the class v4 draw; the SRAM macro 3.5 pJ
per 256-bit access, 2.0 to 7.0, shared by 8 lanes; the 102,612-op hash with 128 loads):
| Design | Extra state per lane | Extra work | Extra lane-ops per hash | Extra energy per hash at N5 | Share of the chip's shadow energy (0.672 microjoules) |
|---|---|---|---|---|---|
| The literal fold: read and fold 63 registers at each load | none | 63 reads of the window (SIMD, one macro access per 8 lanes each) and 63 rotate-xor ops per load | 128 x 63 = 8,064 (plus 8,064 macro accesses per 8 lanes: 3.5 pJ x 8,064 / 8 = 3.5 nJ) | 8,064 x 6.55 pJ + 3.5 nJ = 56 nJ (48 to 72) | +8.4 percent |
| The prefix-XOR tree (the reviewer's form, floor lane 3's Fenwick reading): 65 words of prefix state, seven read-modify-writes per register write, eleven ops per load | 260 bytes in a second gated macro (one per 8 lanes, the same shape as the window) | 7 x 2 macro accesses and 7 xor-rotate ops per instruction that writes the window; 11 ops per load | on the base program's 512 writes and 128 loads: 4,992 ops and 7,168 accesses per 8 lanes; on every instruction of the hash (the shadow block writes the same window): 718,000 ops and 1.44 M accesses | base program only: 33 nJ of ops + 3.1 nJ of accesses = 36 nJ; every instruction: 4.7 microjoules of ops + 0.63 of accesses (7x the whole shadow) | +5.4 percent if the shadow block's writes are exempt; +800 percent if they are not |
| The running total (this lane's form: the fold is linear over GF(2), so a write to register j changes the fold by a fixed rotation of old xor new, and the old value is already read in phase 0 of this core's slot) | one 32-bit register per lane (flops, written every instruction) | two rotates and two xors per instruction, merged into the write phase | 102,612 (one op's worth of datapath per instruction, no extra macro access) | about 1.0 pJ per instruction (an xor-rotate pair on operands already latched; the add row's datapath term is 1.7 pJ, approximate): 0.10 microjoules | +15 percent, paid on every instruction; +0.8 percent if only the base program's writes count |
Reading. (1) Which form the adversary picks depends on how many instructions write the window between loads: at
the shipped shape (one load per 800 instructions once the shadow block is in) the LITERAL fold is the cheapest
(+8.4 percent of the shadow, 56 nJ), because any incremental form pays per write and the shadow writes 800 times
per load; the running total wins only if the shadow block's registers are exempt from the fold (then +0.8
percent), and the Fenwick tree never wins on this core (its seven read-modify-writes per instruction are macro
accesses, the one term this core pays dearly for). Floor lane 3's 30 nJ for the tree counts the base program's
writes only; the row above shows both counts. (2) The bound the review asks for: the cheapest adversary form on
the placed core costs at most 56 nJ per hash (the literal fold; 48 to 72 across the SRAM band) and at least 5 nJ
(the running total with the shadow exempt), so the complete-machine bracket for a class carrying the whole-window
fold moves from 1.5x (1.3 to 1.7) same-node to 1.42x to 1.49x (the chip's machine energy 1.528 to 1.53 + 0.056 x
1.21 = 1.60 microjoules at the literal fold; 1.535 at the running total), and 1.8x a node ahead to 1.7x to 1.8x:
the coupling buys the honest side at most 0.08x on this core, which is inside the SRAM term's band and agrees
with the connected-state lane's KILL (1.10x against its 1.25x gate) and floor lane 3's 2.6 percent on the GDDR7
board. (3) No row here assumes a 63-read cost that the adversary can avoid: the literal fold is priced as 63 SIMD
macro reads shared by 8 lanes (3.5 nJ per hash of accesses, not 63 window reads per lane), and the incremental
forms are priced per write. The shipped class is untouched: its fold reads one register. (4) The GPU side of the same two forms (the fleet
lane, 20:4x BST, the hash lane's hl-v6-all fold form against hl-v6-all-prefix, the same program id and vectors,
stock clocks, 250 batches, fingerprints equal; evidence on build-1 under /srv/artefacts/tas/54900078/ and
/srv/artefacts/tas/si1xc4yhpakk1v/): the 5090 reads 70.6 MH/s at 437.8 W (6.20 nJ per hash) on the literal fold
and 70.2 at 500.0 W (7.13 nJ) on the prefix form, 100 against 248 registers per thread; the 4090 31.3 MH/s at
238.1 W (7.60 nJ) against 31.3 at 231.7 W (7.41 nJ), 93 against 154 registers. The rate is unmoved on both cards
(both are bound at the dataset reads) and the prefix form costs the 5090 14 percent more board power for the same
hashes; so on the card as on this core the cheapest form at the shipped shape is the literal fold, and the
review's incremental form is a design the adversary can take and does not want. (5) The bound restated for the
connected-state class's OWN shape (the hash lane's closed form, 20:5x BST: `address_source(s) = r[s] ^ ror(P_s, 1)
^ (S ^ P_s ^ a[s])`, a[k] = rotl(r[k], (63 - k) mod 32), S the xor of every a[k], P_s the prefix xor below s;
32 loads per 64-instruction iteration, 256 loads and 512 register writes per hash in the base program): there the
literal fold is 256 x 63 = 16,128 lane-ops and 16,128 SIMD macro reads per hash, 113 nJ at N5 (97 to 145), and the
prefix form is one running-total update per write (an xor-rotate pair, about 1 pJ) plus six Fenwick read-modify-
writes per write (twelve macro accesses per 8 lanes, 5.3 pJ) and six prefix reads with three xors per load: 512 x
12.3 pJ + 256 x 5.6 pJ = 7.7 nJ (5 to 15). So on that class the review is right by 14x: the chip pays about 8 nJ
per hash for the whole-window coupling, 1.2 percent of its shadow energy, and the complete-machine bracket moves
from 1.5x to 1.49x same-node (not to 1.42x, which was the literal fold's cost); the card meanwhile keeps the fold
at 6.20 nJ per hash on the 5090 and would pay 7.13 on the prefix form. The two shapes together: the chip's cost of
the coupling is 8 nJ (connected-state shape, prefix form) to 56 nJ (shipped shape, literal form), 0.02x to 0.08x
of the bracket, and no design in the record charges the chip a 63-read cost it can avoid.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,21 @@
# UX-01 evidence, run ux-01-20261008-win-2.0.0 (8 October 2026)
Onboard ordinary owners on native desktop apps, the team-run half: the two Windows PCs take the Igneum Miner 2.0.x Windows
entry (2.0.0 live 18:44 UK, Setup exe 793a631d, manifest aa354ed5; 2.0.1 about 20:55 UK with the coinbase-over-u64 fix)
through the app's own update path, with no click after the install and mining on every card (the founder's rule of
18:0x UK), observed through the apps' own intake uploads and the relay agents. The P10 study (30 unaffiliated
participants) is NOT RUN: not yet recruited; never a staff run.
## Shape
- PC 1 (ae432dc7): Igneum Miner 0.3.26 since 17:26 UK, RTX 5090, RTX 5080, RX 7600; mining off under the Devnet 3 off order; the 2.0.0 installer downloaded and verified 18:58 UK, the install queued in the hash lane's order (update-now-20261008-181124).
- PC 2 (1ccfe586): RTX 5090, RTX 5060 Ti, Arc B580; mining off since the Devnet 3 off jobs (#1519 api/pause 16:38 UK, #1521 17:15 UK).
- The read-back: the engine's "update-return: app <v> up after the update from <from>" line at intake, then the relay run "mining on after the 2.0.1 install" (mining-on-after-200.ps1: wait for 2.0.1 or later, clear a stale install-running.flag, api/resume, start the app if silent) printing `RESULT MINING-ON ok|partial version=... network=... node=... synced=... paused=false cards=<n> rates=...`.
## Read-back lines (time UK, PC, the line or the fault and its class)
- 19:22:01 PC 2: `update-return: app 2.0.0 up after the update from 0.3.26 (node igneumd 2.0.0, machine 1ccfe586)`; node started 19:22:05; `[ok] mining resumed` 19:22:13 (no click: relay run #1742 cleared the pause through api/resume).
- 19:28 PC 2 (#1754): `RESULT MINING-ON partial version=2.0.0 network=devnet node=no peers synced=False paused=False cards=3` (every card waiting). Class: the devnet-4 hubs' outage (every dial target down 19:15 to 19:17, back by 19:29), not the install.
- 19:41 PC 2 (#1757): `RESULT MINING-ON partial ... node=behind peers=1 synced=False tip_age_s=1289`; IBD completed 19:29:16, the node then "behind". Class: the 2.0.0 miner refuses every template whose coinbase exceeds a u64 (the shipper, 19:5x UK), fixed in node 777214af as the 2.0.1 entry.
- PC 1: pending (0.3.26; the install runs when its queue reaches update-now, then 2.0.1 through the same path).
## Status
- 20:36 UK: RUNNING; the 2.0.1 read-backs (relay runs #1762 PC 2, #1763 PC 1) are the next lines.

View file

@ -0,0 +1,48 @@
# The native finality runs of 9 October 2026 (the node lane; Review B F04 and I03; V6-09 beside them)
Status: PLANNED (written 8 October 2026, 21:4x UK, main's order under the night rule). The runs start from 00:30 UK on build-8 and build-9 (build-7 for the two-node cache case), under the lease pool, every process under a pid watcher that restarts it and records the restart; the rows land in `sim/results_v2.md` under "Rule v4" with their result files under `sim/finality-attacks-results/` and the registry batch (FIN-08, FIN-02's native half, ROT-05, VER-08's recovery row) through `tools/ci/test-record.mjs`, by 07:00 UK. An accelerated simulation is evidence of the rule's shape, never operating history: every row below runs on real nodes with the 60x file's windows (W = 120 DAA s at 1 block/s) and says so.
The harness: `tools/finality-attacks/v3.mjs` (three nodes on the 60x file, six voters, one-way delay 300 ms per proxied link, the pass lines of `finality-guarantees.md` 6.7), extended for the rows that need a third island, an equivocating key, a stopped voter, a succession item and a backfilled checkpoint history; the extensions land with the rows. The node: the 2.0.2 line (successor-2.0.1 at or after 45e7b910: rule v4 with the pause fix 6872db13, the lock kind of F04, the finality-backed take of a9ff0a25) in the gate pair under `/srv/artefacts/200-<sha>/node-lane` (gate evidence; never a fleet binary).
## 1. The 40/40/20 case past the window with equivocation (F04, the reviewer's hard FAIL line)
Three islands by weight 40 / 40 / 20 (keys p0,p1 on n0; p2,p3 on n1; q0 on n2, shares 0.2 / 0.2 / 0.2 / 0.2 / 0.2 across five keys, the sixth key e the equivocator at 0.2 placed by the row), WARM 230 s, SPLIT 420 s (longer than the window after the last lock), HEAL 400 s, 1 block/s in all, rule v4 with the recovery on.
| row | the equivocator e | expected under 6.2 and 6.5 | the FAIL line |
|---|---|---|---|
| 1a | absent (honest three-way) | no side locks during the split (no island holds more than half of the anchored table), every node pauses, the heal locks within two intervals, 0 conflicts | any lock during the split; any conflicting certificate |
| 1b | mines on island A only (reaching 60 of the anchored table on A) | A recovers once a full window has passed (the recovery lock at the first index past the window), B and C pause, the heal brings B and C onto A's chain, 0 conflicts | a lock on B or C; two certificates at one index |
| 1c | mines dust-valid on A AND B (the 6.5 bound: both at 60 percent) | BOTH A and B recover after the window: two recovery certificates at one index, the measured conflict the spec names; the heal strips e (3.6) and reports the pair under 3.11.4; the history through the anchored lock untouched | a recovery lock presented as final on any surface (lockKind must read "recovery" on both); the anchored history moving |
| 1d | 1c under the pause-only variant (recovery off) | no lock on any side during the split, the pause until the heal, 0 conflicts (the strictly stronger guarantee of 6.5) | any lock during the split |
Measured per row: new locks per side during the split (index and DAA), the lock kind on `igneum_getFinalityCheckpoints` (final or recovery), conflicting certificates logged, disagreeing locked indices after the heal, the equivocator's strip at the heal (the ban line), every pre-heal lock kept, the first lock after the heal (s).
## 2. The pause-only alternative with backfill, missing history and the old keys returning (I03)
Rule v4, recovery off. A chain is run 230 s with six voters, then split 3/3 for 420 s (no lock on either side, the pause), then healed; during the heal window: (a) a fresh node joins from genesis and must backfill every checkpoint and certificate (the historical-checkpoint backfill; it reads the same latest lock as the three), (b) one node restarts from a datadir with its finality state removed (missing historical data: it rebuilds from the chain's carried certificates and must agree), (c) every old key returns and signs (the pause ends on two thirds, the lock within two intervals). Measured: the backfilled node's locked indices equal the others' (0 disagreement), the restarted node's, the first lock after the return, 0 conflicts.
## 3. Authority succession and strip, restart, certificate arrival order, seed boundaries (I03)
| row | shape | expected |
|---|---|---|
| 3a | a voter leaves (W7, the leave item carried) mid-window, the rest sign | the frozen table reduces by the leaver (frozen_floor), the next lock at two thirds of the remaining; the leaver's weight never counts |
| 3b | a key is stripped (an equivocation evidence item carried) one interval before a lock | the strip applies before the lock's test; a certificate carrying the stripped key's signature counts it as 0 |
| 3c | a voter restarts between determination and lock (kept datadir) | it votes once (no double vote), the lock forms on time, its locks equal the others' after the restart |
| 3d | two certificates for consecutive indices arrive in reverse order at a node (the fleet's 263-then-262 read on hub-1) | both lock under the rule, the LOCKED line prints the certificate's fractions (the 2.0.2 log fix), no "signed 0" artefact |
| 3e | a seed boundary (the epoch's reference block) inside a pause | the seed is drawn from the chain block below the lead whether or not it is locked (section 8); mining continues; the first lock after the pause names a block past the boundary |
## 4. The inter-chain verifier and a recovery lock (I03)
The Sepolia certificate verifier (dex lane's bridge, 0x874D8Be5… on igneum-devnet-4's voter table) given (i) a final certificate, (ii) a recovery certificate from row 1b: it accepts (i) as final; for (ii) it must read lockKind "recovery" and never present it as final (the bridge doc 829b839ec: recovery locks fail closed on the verifier, which reads only weight). The row records what the verifier answers for each and the receipt page's word; a recovery certificate accepted as final is the FAIL line.
## 5. V6-09, cold compressed verification on the minimum validator (with the enforced-proving lane)
One validator node pinned to one core (taskset), no warm relay cache (fresh datadir, the pool empty), fed by a relay peer: (a) ten cold valid shard proofs in one block's carried records (the measured 0.668 to 0.710 s a proof on one loaded core); (b) ten expensive-invalid payloads (proofs whose bytes deserialise to the largest accepted shape and fail at the last check) with the relay's pre-deserialise cap (MAX_PROOF_BYTES in consensus-core, V6-08's constant) and the in-flight bound of 8; (c) a forged record under each pair across the key and fee transitions, before, at and after activation, on an unmodified validator. Measured per row: verify seconds per proof, block-validation time against the deadline, the NotReady retries, memory before and after deserialising, the carrier paid exactly once (igneum_getProofRecords on the validator against the relay's), the forged record refused with its reason. The rows go to the test map cell `harness:v6-09-cold-verify` with the F0 fixture, by 12:00 UK 9 October.
## 6. The two-node cache-history test (F01, with the proving lane's fix 3f672661)
Two nodes, one with a warm verdict cache built on carriers 1..k, one cold, both fed the same blocks in a different order (the cold one sees the later carrier first): identical block-validity verdicts and identical payouts (igneum_getProofRecords and the paid map equal on both), with the known-failed shape first (the pre-fix node's cached context refusal replayed under a later carrier, the 19:49 UK reproduction). On build-7 by 03:00 UK.
## Boxes and clocks
build-8: sections 1 and 2 (the 40/40/20 rows 1a to 1d, then the backfill case), from 00:30, rows by 05:00. build-9: sections 3 and 4 (after the 2.0.2 line's gate ends), from 01:00, rows by 06:00; section 5 with the enforced-proving lane's fixtures, rows by 12:00. build-7: section 6, by 03:00. Every run under `lease pool N --class release` with a pid file and a watcher; a stall is recorded for the 08:00 read-back, never a hand-made lock. The rows land in sim/results_v2.md with their result files and the registry batch by 07:00 UK, the plan's status moved to MEASURED per section as each lands.

View file

@ -342,6 +342,39 @@ Rule: a case maps to a cell only where the cell's tests visibly answer it; cover
- Cases:
- GPU-03 Measure the real 64-register GPU cost: partial: the 64-register window on AMD and Intel, rate per unit of work (RX 7600 0 percent, Arc B580 -0.3 percent, kernel throughput, quiet) with the B580 fingerprints equal on both packs and the offline RDNA allocation (160 VGPRs, no spill); energy owed (the 7600 job queued, the B580 counter unsupported unelevated); team-run, not under the standard's paired protocol or a wall meter
### adversary:mf-placed
- Command: `cd tools/chip-model/mf && make flow-<design> power-<design> (inside openroad/orfs:latest on a rented CPU host; never the Mac); python3 flow/collect.py results; python3 flow/board.py <pJ> <lo> <hi> <leak> <mm2>; python3 flow/hash.py results <design> power`
- Box class: rented CPU host (Vast, 48 to 72 cores) on the ORFS image
- Fixtures: F0, F1
- Cases:
- ADV-01 Build a multi-family programmable opponent: the mf core (18 families, SRAM window and imem macros, operand isolation, 5-phase port) placed and routed on ASAP7 with SPEF and a gate-level VCD; k per family and per draw; outputs checked against the RTL simulation's checksums per tag, not yet against the POW vectors (owed)
- ADV-03 Attack with data-local and hybrid execution: the data-local, hybrid and companion-host rows of multi-family-adversary.md sections 11, 13 and 14 (bit counts closed-form; the hop and wire energies claimed)
- ADV-07 Evaluate lifetime without forced obsolescence: the lifetime table and the six-row transition matrix (sections 7 and 14) on the placed rows; the 32-lane genesis comparator placed on adv-g
- ADV-08 Independently challenge the best-cost envelope: the best-cost envelope on the complete machine (section 6) and the SRAM-die ticket reconciliation with lane B (section 15); the unaffiliated second reviewer is not this lane's
- POW-03 Test whether live state is unavoidable: partial: the live state held in an SRAM macro per 8 lanes with a time-multiplexed single port and operand isolation, the complete-system cost in section 6; the liveness trace itself is the connected-state lane's tool
- POW-04 Evaluate connected-resource restructuring: partial: the 64-register window's cost on the macro core (sections 4 and 5, agreeing with the k lane's gated-flop row within 5 percent); the restructured candidate's GPU cost is the invention lane's
- ADV-05 Validate physical and complete-board costs: partial: the SRAM macros, ports, wiring, clocking and the complete-board terms are modelled in sections 2.3, 5 and 6 with the unmodelled items carried as uncertainty; the calibration against an existing hardware block is the k lane's bare-lane row beside it, owed as a named comparison
### adversary:d2b
- Command: `cd tools/chip-model/mf && python3 flow/d2b.py results N5 1 && python3 flow/d2b.py results N3 1 (on a build box under lease pool or a rented host; reads results/table.csv)`
- Box class: any box (a one-minute Python model on the placed rows)
- Fixtures: F0
- Cases:
- ADV-02 Price shared, reduced and reconstructed memory: memory sharing, partial stores at the measured window-layer hit rates (and hit 0.50 with layer 8 off), recomputation and the set-up amortisation on the complete board (section 13); the formal memory model's terms (section 16)
- ADV-04 Measure profitable selective participation: selective participation over 2,000 era draws under the layer 1 band with two reserve families live per epoch, the specialist's revenue against its ratio gain (section 13); downtime and re-entry priced as the DAA window's lag, not simulated against the difficulty rule itself (owed)
### pc:install-update
- Command: `signed jobs and relay runs on PC 1 (ae432dc7) and PC 2 (1ccfe586): the installer over the running app (rule 14: installed versions, the process set, the first upload), the OTA path (update-now, the update-return read-back line), and the no-click resume after the install (relay run mining-on-after-200.ps1)`
- Box class: PC (the two Windows PCs; nothing on the Mac)
- Fixtures: F2
- Cases:
- UX-01 Onboard ordinary owners on native desktop apps: team-run evidence only (the two PCs taking the Windows entry through the app's own update path with no click and mining on every card); the P10 study is NOT RUN until unaffiliated participants are recruited
- UX-07 Expose actionable failures and safe updates: partial: the install classes (the payload's stop step, the detached installer under a job, the installer refusing a wrong-version name, a stale install flag) and the no-click resume; the recovery-instruction and canary rows are the shipper's
- OPS-03 Separate update distribution from consensus authority: partial: the update path's read-back and the signed manifest's verify on the PC (a tampered or rolled-back payload is refused by the engine's manifest check); authority separation is the shipper's review
## Automated cases with no harness in the matrix (NOT RUN, the reason)
- GOV-02 Approve thresholds before results: the approval is recorded in the registry's approval field; the automated half (thresholds frozen before any run_status) is the gate rule landing by 21:00
@ -351,9 +384,7 @@ Rule: a case maps to a cell only where the cell's tests visibly answer it; cover
- GPU-06 Measure accepted work under ordinary connectivity: accepted work under ordinary connectivity needs the fault network F4
- GPU-07 Survive sustained thermal and power operation: the sustained thermal and power soak has no harness tonight: PC 1 mines nothing under the Devnet 3 off order
- POW-05 Prevent amortised cheap winning attempts: amortised cheap winning attempts are the attack lanes' grind and era harnesses (tools/attack/f7-era, f9-grind), not in the release matrix; their rows come from those lanes
- ADV-04 Measure profitable selective participation: selective participation needs the economic model F7 and a live chain window
- ADV-06 Separate process advantage from specialisation: process-advantage separation is the adversary lanes' chip study
- ADV-07 Evaluate lifetime without forced obsolescence: lifetime rows are the adversary lanes' models
- ROT-03 Test miner-voted bring-forward governance: miner-voted bring-forward needs a vote harness on the fault network F4
- ROT-04 Resist seed selection and faster evaluators: seed-selection resistance is the census harness (the class v6 invention lane), not yet in the matrix
- EVM-01 Match the selected EVM semantics: no EVM conformance-vector harness is mapped tonight; the exec suite does not run the reference test vectors
@ -499,4 +530,4 @@ Rule: a case maps to a cell only where the cell's tests visibly answer it; cover
## Count
171 automated cases: 69 mapped to a cell, 152 NOT RUN with a reason.
171 automated cases: 78 mapped to a cell, 150 NOT RUN with a reason.

View file

@ -1547,30 +1547,30 @@
"manual_page": 24,
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "FAIL",
"evidence_path": "docs/analysis/class-v6/connected-state.md; docs/analysis/class-v6",
"run_id": "kills-20261008",
"updated": "2026-10-08T20:10:24.624Z",
"evidence_path": "docs/analysis/class-v6/connected-state.md; docs/analysis/class-v6; docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"requirement_id": "POW-03",
"decision": "FAIL",
"method": "GPU",
"cell": "experiment:connected-state",
"manifest_sha": "7cfa422a",
"run_id": "kills-20261008",
"evidence": "docs/analysis/class-v6",
"in_progress": false,
"coverage": "the experiment ran and its claim failed: live state does not make the work unavoidable for a chip; the master's register row 18 reads FAIL, published, never PASSED",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the live state held in an SRAM macro per 8 lanes with a time-multiplexed single port and operand isolation, the complete-system cost in section 6; the liveness trace itself is the connected-state lane's tool",
"release_identity": {
"commit": "7cfa422a",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "the claims the two experiments carried are withdrawn: live state as an ASIC barrier (connected state), a cheaper mixed-FP32 lane",
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:10:24.624Z"
"at": "2026-10-08T20:41:20.327Z"
},
"approvals": {
"scope_approved": null,
@ -1622,6 +1622,28 @@
"claim_impact": "the claims the two experiments carried are withdrawn: live state as an ASIC barrier (connected state), a cheaper mixed-FP32 lane",
"reviewer": "",
"at": "2026-10-08T20:10:24.624Z"
},
"adversary:mf-placed": {
"requirement_id": "POW-03",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the live state held in an SRAM macro per 8 lanes with a time-multiplexed single port and operand isolation, the complete-system cost in section 6; the liveness trace itself is the connected-state lane's tool",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -1652,27 +1674,30 @@
"manual_page": 25,
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/connected-state.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08 18:3x UK",
"evidence_path": "docs/analysis/class-v6/connected-state.md; docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"what_was_run": "the same experiment, D2(a) closed",
"run_by": "adversary lane (a1a9876a88f5a72fc)",
"under_the_standard": "no: team-run before the standard's procedure; the status is RUNNING until the case is re-run under its steps with the profile's numbers and an independent run where the profile asks one",
"pass_or_fail_today": "not judged under the standard yet",
"method": "static",
"requirement_id": "POW-04",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the 64-register window's cost on the macro core (sections 4 and 5, agreeing with the k lane's gated-flop row within 5 percent); the restructured candidate's GPU cost is the invention lane's",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -1703,6 +1728,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/connected-state.md",
"in_progress": true
},
"adversary:mf-placed": {
"requirement_id": "POW-04",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the 64-register window's cost on the macro core (sections 4 and 5, agreeing with the k lane's gated-flop row within 5 percent); the restructured candidate's GPU cost is the invention lane's",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2114,26 +2161,29 @@
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08 18:3x UK",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"what_was_run": "the 18-family programmable core placed and routed (9.36 pJ per lane-op, k 0.64 same-node)",
"run_by": "adversary lane (a1a9876a88f5a72fc)",
"under_the_standard": "no: team-run before the standard's procedure; the status is RUNNING until the case is re-run under its steps with the profile's numbers and an independent run where the profile asks one",
"pass_or_fail_today": "not judged under the standard yet",
"method": "static",
"requirement_id": "ADV-01",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the mf core (18 families, SRAM window and imem macros, operand isolation, 5-phase port) placed and routed on ASAP7 with SPEF and a gate-level VCD; k per family and per draw; outputs checked against the RTL simulation's checksums per tag, not yet against the POW vectors (owed)",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2164,6 +2214,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true
},
"adversary:mf-placed": {
"requirement_id": "ADV-01",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the mf core (18 families, SRAM window and imem macros, operand isolation, 5-phase port) placed and routed on ASAP7 with SPEF and a gate-level VCD; k per family and per draw; outputs checked against the RTL simulation's checksums per tag, not yet against the POW vectors (owed)",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2196,26 +2268,29 @@
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08 18:3x UK",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"what_was_run": "D2(b): the stored-half hybrid, memory sharing, recomputation priced (the placed hybrid 1.93x same-node at the mean hit)",
"run_by": "adversary lane (a1a9876a88f5a72fc)",
"under_the_standard": "no: team-run before the standard's procedure; the status is RUNNING until the case is re-run under its steps with the profile's numbers and an independent run where the profile asks one",
"pass_or_fail_today": "not judged under the standard yet",
"method": "static",
"requirement_id": "ADV-02",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:d2b",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "memory sharing, partial stores at the measured window-layer hit rates (and hit 0.50 with layer 8 off), recomputation and the set-up amortisation on the complete board (section 13); the formal memory model's terms (section 16)",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2246,6 +2321,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true
},
"adversary:d2b": {
"requirement_id": "ADV-02",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:d2b",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "memory sharing, partial stores at the measured window-layer hit rates (and hit 0.50 with layer 8 off), recomputation and the set-up amortisation on the complete board (section 13); the formal memory model's terms (section 16)",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2278,26 +2375,29 @@
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08 18:3x UK",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"what_was_run": "data-local execution moves nothing (2,112 bits of live state against an 80-bit read)",
"run_by": "adversary lane (a1a9876a88f5a72fc)",
"under_the_standard": "no: team-run before the standard's procedure; the status is RUNNING until the case is re-run under its steps with the profile's numbers and an independent run where the profile asks one",
"pass_or_fail_today": "not judged under the standard yet",
"method": "static",
"requirement_id": "ADV-03",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the data-local, hybrid and companion-host rows of multi-family-adversary.md sections 11, 13 and 14 (bit counts closed-form; the hop and wire energies claimed)",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2328,6 +2428,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true
},
"adversary:mf-placed": {
"requirement_id": "ADV-03",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the data-local, hybrid and companion-host rows of multi-family-adversary.md sections 11, 13 and 14 (bit counts closed-form; the hop and wire energies claimed)",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2360,24 +2482,29 @@
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08T20:10:24.556Z",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"reason": "selective participation needs the economic model F7 and a live chain window",
"at": "2026-10-08T20:10:24.556Z",
"method": "static",
"requirement_id": "ADV-04",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:d2b",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "selective participation over 2,000 era draws under the layer 1 band with two reserve families live per epoch, the specialist's revenue against its ratio gain (section 13); downtime and re-entry priced as the DAA window's lag, not simulated against the difficulty rule itself (owed)",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2408,6 +2535,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true
},
"adversary:d2b": {
"requirement_id": "ADV-04",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:d2b",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "selective participation over 2,000 era draws under the layer 1 band with two reserve families live per epoch, the specialist's revenue against its ratio gain (section 13); downtime and re-entry priced as the DAA window's lag, not simulated against the difficulty rule itself (owed)",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2439,27 +2588,30 @@
"manual_page": 28,
"owner_lane": "k lane (a3c9601a6d4686fe1)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md; docs/analysis/class-v6/floor/shadow-k.md",
"run_id": "team-2026-10-08",
"updated": "2026-10-08 18:3x UK",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md; docs/analysis/class-v6/floor/shadow-k.md; docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"what_was_run": "the complete GDDR7 machine 1.5x same-node, 1.8x a node ahead at the placed energy; the honest same-node bracket 1.5x to 2.1x: FAIL against P04 at R_E 1.5, served as such",
"run_by": "k lane (a3c9601a6d4686fe1)",
"under_the_standard": "no: team-run before the standard's procedure; the status is RUNNING until the case is re-run under its steps with the profile's numbers and an independent run where the profile asks one",
"pass_or_fail_today": "FAIL against P04 at R_E 1.5",
"method": "static",
"requirement_id": "ADV-05",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the SRAM macros, ports, wiring, clocking and the complete-board terms are modelled in sections 2.3, 5 and 6 with the unmodelled items carried as uncertainty; the calibration against an existing hardware block is the k lane's bare-lane row beside it, owed as a named comparison",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2490,6 +2642,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md; docs/analysis/class-v6/floor/shadow-k.md",
"in_progress": true
},
"adversary:mf-placed": {
"requirement_id": "ADV-05",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "partial: the SRAM macros, ports, wiring, clocking and the complete-board terms are modelled in sections 2.3, 5 and 6 with the unmodelled items carried as uncertainty; the calibration against an existing hardware block is the k lane's bare-lane row beside it, owed as a named comparison",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2601,25 +2775,30 @@
"manual_page": 29,
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md section 14",
"run_id": "team-2026-10-08",
"updated": "2026-10-08T20:10:24.556Z",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md section 14; docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"evidence_record": {
"reason": "lifetime rows are the adversary lanes' models",
"at": "2026-10-08T20:10:24.556Z",
"method": "static",
"requirement_id": "ADV-07",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the lifetime table and the six-row transition matrix (sections 7 and 14) on the placed rows; the 32-lane genesis comparator placed on adv-g",
"release_identity": {
"commit": "",
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08 18:3x UK",
"approvals": {
@ -2650,6 +2829,28 @@
"run_id": "team-2026-10-08",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md section 14",
"in_progress": true
},
"adversary:mf-placed": {
"requirement_id": "ADV-07",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the lifetime table and the six-row transition matrix (sections 7 and 14) on the placed rows; the 32-lane genesis comparator placed on adv-g",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
}
},
@ -2681,15 +2882,62 @@
"manual_page": 29,
"owner_lane": "adversary lane (a1a9876a88f5a72fc)",
"run_status": "NOT RUN",
"evidence_path": "",
"run_id": "",
"updated": "2026-10-08 18:3x UK",
"evidence_path": "docs/analysis/class-v6/multi-family-adversary.md",
"run_id": "adversary-20261008-placed-8lane",
"updated": "2026-10-08T20:41:20.327Z",
"approvals": {
"scope_approved": null,
"implementation_complete": null,
"evidence_reproduced": null,
"claim_authorised": null
}
},
"evidence_records": {
"adversary:mf-placed": {
"requirement_id": "ADV-08",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the best-cost envelope on the complete machine (section 6) and the SRAM-die ticket reconciliation with lane B (section 15); the unaffiliated second reviewer is not this lane's",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
}
},
"evidence_record": {
"requirement_id": "ADV-08",
"decision": "NOT RUN",
"method": "model",
"cell": "adversary:mf-placed",
"manifest_sha": "3a8874fef",
"run_id": "adversary-20261008-placed-8lane",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"in_progress": true,
"coverage": "the best-cost envelope on the complete machine (section 6) and the SRAM-die ticket reconciliation with lane B (section 15); the unaffiliated second reviewer is not this lane's",
"release_identity": {
"commit": "3a8874fef",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:20.327Z"
},
"in_progress_since": "2026-10-08T20:41:20.327Z"
}
]
},
@ -8730,29 +8978,30 @@
"manual_page": 54,
"owner_lane": "shipper (ae892a8b0f78fe31c)",
"run_status": "NOT RUN",
"evidence_path": "site/release-manifest.json at the landing sha",
"run_id": "site-manifest-20261008-01",
"updated": "2026-10-08T20:07:45.894Z",
"evidence_path": "site/release-manifest.json at the landing sha; docs/plans/evidence/UX-01-20261008.md",
"run_id": "ux-01-20261008-win-2.0.0",
"updated": "2026-10-08T20:42:25.701Z",
"evidence_record": {
"cell": "site:manifest",
"manifest_sha": "3f1a3f332",
"coverage": {
"OPS-03": "partial: the manifest's versions and network blocks regenerate from their sources; the separation itself is the node suites' (suite:exec, suite:p2p-flows)"
},
"at": "2026-10-08T20:07:45.894Z",
"method": "static",
"requirement_id": "OPS-03",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "partial: the update path's read-back and the signed manifest's verify on the PC (a tampered or rolled-back payload is refused by the engine's manifest check); authority separation is the shipper's review",
"release_identity": {
"commit": "3f1a3f332",
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
},
"approvals": {
"scope_approved": null,
@ -8784,8 +9033,31 @@
"run_id": "site-manifest-20261008-01",
"evidence": "site/release-manifest.json at the landing sha",
"in_progress": false
},
"pc:install-update": {
"requirement_id": "OPS-03",
"decision": "NOT RUN",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "partial: the update path's read-back and the signed manifest's verify on the PC (a tampered or rolled-back payload is refused by the engine's manifest check); authority separation is the shipper's review",
"release_identity": {
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
}
}
},
"in_progress_since": "2026-10-08T20:42:25.701Z"
},
{
"id": "OPS-04",
@ -9242,15 +9514,62 @@
"manual_page": 57,
"owner_lane": "update-return lane (a22d765a2e0355a9f)",
"run_status": "NOT RUN",
"evidence_path": "",
"run_id": "",
"updated": "2026-10-08 18:3x UK",
"evidence_path": "docs/plans/evidence/UX-01-20261008.md",
"run_id": "ux-01-20261008-win-2.0.0",
"updated": "2026-10-08T20:42:25.701Z",
"approvals": {
"scope_approved": null,
"implementation_complete": null,
"evidence_reproduced": null,
"claim_authorised": null
}
},
"evidence_records": {
"pc:install-update": {
"requirement_id": "UX-01",
"decision": "NOT RUN",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "team-run evidence only (the two PCs taking the Windows entry through the app's own update path with no click and mining on every card); the P10 study is NOT RUN until unaffiliated participants are recruited",
"release_identity": {
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
}
},
"evidence_record": {
"requirement_id": "UX-01",
"decision": "NOT RUN",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "team-run evidence only (the two PCs taking the Windows entry through the app's own update path with no click and mining on every card); the P10 study is NOT RUN until unaffiliated participants are recruited",
"release_identity": {
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
},
"in_progress_since": "2026-10-08T20:42:25.701Z"
},
{
"id": "UX-02",
@ -9463,7 +9782,7 @@
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/pool/pool-pair-2026-10-08.md",
"run_id": "pool-2.0-20261008-03",
"updated": "2026-10-08T20:41:26.619Z",
"updated": "2026-10-08T20:48:39.463Z",
"evidence_record": {
"requirement_id": "UX-04",
"decision": "NOT RUN",
@ -9484,7 +9803,7 @@
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:26.619Z"
"at": "2026-10-08T20:48:39.463Z"
},
"in_progress_since": "2026-10-08T19:58:33.370Z",
"approvals": {
@ -9514,7 +9833,7 @@
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:26.619Z"
"at": "2026-10-08T20:48:39.463Z"
}
}
},
@ -9547,10 +9866,10 @@
"run_status": "NOT RUN",
"evidence_path": "docs/analysis/pool/pool-pair-2026-10-08.md",
"run_id": "pool-2.0-20261008-03",
"updated": "2026-10-08T20:41:26.619Z",
"updated": "2026-10-08T20:48:39.463Z",
"evidence_record": {
"reason": "voting keys through pooling is the pool lane's row",
"at": "2026-10-08T20:41:26.619Z"
"at": "2026-10-08T20:48:39.463Z"
},
"in_progress_since": "2026-10-08T19:58:33.370Z",
"approvals": {
@ -9580,7 +9899,7 @@
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:41:26.619Z"
"at": "2026-10-08T20:48:39.463Z"
}
}
},
@ -9700,32 +10019,30 @@
"manual_page": 59,
"owner_lane": "shipper (ae892a8b0f78fe31c)",
"run_status": "NOT RUN",
"evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log",
"run_id": "201-7cfa422a-aa0e0f45",
"updated": "2026-10-08T19:32:50.856Z",
"evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log; docs/plans/evidence/UX-01-20261008.md",
"run_id": "ux-01-20261008-win-2.0.0",
"updated": "2026-10-08T20:42:25.701Z",
"evidence_record": {
"cell": "suite:app",
"manifest_sha": "7cfa422a",
"coverage": {
"UX-02": "partial: the engine state machine's pause, stop and knob tests; the operator study is UX-01's",
"UX-03": "partial: the card and earnings rendering tests; the net-earnings model against real bills is COM/ECO evidence",
"UX-07": "partial: the refused-update and manifest tests; the update-return lane's install classes are its own rows",
"VER-08": "partial: the app's own state-word tests; the wallet and light client rows are VER-01 to VER-03"
},
"at": "2026-10-08T19:32:50.856Z",
"method": "native",
"requirement_id": "UX-07",
"decision": "NOT RUN",
"reviewer": "",
"claim_impact": "",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "partial: the install classes (the payload's stop step, the detached installer under a job, the installer refusing a wrong-version name, a stale install flag) and the no-click resume; the recovery-instruction and canary rows are the shipper's",
"release_identity": {
"commit": "7cfa422a",
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
}
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
},
"in_progress_since": "2026-10-08T19:32:50.856Z",
"approvals": {
@ -9761,6 +10078,28 @@
"run_id": "201-7cfa422a-aa0e0f45",
"evidence": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/miner-9c844503/box2-app.log",
"in_progress": true
},
"pc:install-update": {
"requirement_id": "UX-07",
"decision": "NOT RUN",
"method": "team-reported",
"cell": "pc:install-update",
"manifest_sha": "aa354ed5",
"run_id": "ux-01-20261008-win-2.0.0",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"in_progress": true,
"coverage": "partial: the install classes (the payload's stop step, the detached installer under a job, the installer refusing a wrong-version name, a stale install flag) and the no-click resume; the recovery-instruction and canary rows are the shipper's",
"release_identity": {
"commit": "aa354ed5",
"lockfile": "",
"binary": "",
"network_object": "",
"activation": "",
"profile_hashes": ""
},
"claim_impact": "",
"reviewer": "",
"at": "2026-10-08T20:42:25.701Z"
}
}
},

View file

@ -0,0 +1,20 @@
{
"run_id": "adversary-20261008-placed-8lane",
"manifest_sha": "3a8874fef",
"evidence_dir": "docs/analysis/class-v6/multi-family-adversary.md",
"cells": [
{
"cell": "adversary:mf-placed",
"status": "RUNNING",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"method": "model"
},
{
"cell": "adversary:d2b",
"status": "RUNNING",
"evidence": "docs/analysis/class-v6/multi-family-adversary.md",
"method": "model",
"note": "evidence cited at the document (section 13, D2(b) restated on the placed rows); the mf flow's results file tools/chip-model/mf/results/d2b-n5.md stays on the branch and is cited after it lands (the recorder cites only files in the tree)"
}
]
}

View file

@ -0,0 +1,14 @@
{
"run_id": "ux-01-20261008-win-2.0.0",
"manifest_sha": "aa354ed5",
"evidence_dir": "docs/plans/evidence/UX-01-20261008.md",
"cells": [
{
"cell": "pc:install-update",
"status": "RUNNING",
"evidence": "docs/plans/evidence/UX-01-20261008.md",
"method": "team-reported"
}
],
"method": "team-reported"
}

View file

@ -588,6 +588,64 @@
"coverage": {
"GPU-03": "partial: the 64-register window on AMD and Intel, rate per unit of work (RX 7600 0 percent, Arc B580 -0.3 percent, kernel throughput, quiet) with the B580 fingerprints equal on both packs and the offline RDNA allocation (160 VGPRs, no spill); energy owed (the 7600 job queued, the B580 counter unsupported unelevated); team-run, not under the standard's paired protocol or a wall meter"
}
},
"adversary:mf-placed": {
"command": "cd tools/chip-model/mf && make flow-<design> power-<design> (inside openroad/orfs:latest on a rented CPU host; never the Mac); python3 flow/collect.py results; python3 flow/board.py <pJ> <lo> <hi> <leak> <mm2>; python3 flow/hash.py results <design> power",
"box_class": "rented CPU host (Vast, 48 to 72 cores) on the ORFS image",
"fixtures": [
"F0",
"F1"
],
"cases": [
"ADV-01",
"ADV-03",
"ADV-07",
"ADV-08",
"POW-03",
"POW-04",
"ADV-05"
],
"coverage": {
"ADV-01": "the mf core (18 families, SRAM window and imem macros, operand isolation, 5-phase port) placed and routed on ASAP7 with SPEF and a gate-level VCD; k per family and per draw; outputs checked against the RTL simulation's checksums per tag, not yet against the POW vectors (owed)",
"ADV-03": "the data-local, hybrid and companion-host rows of multi-family-adversary.md sections 11, 13 and 14 (bit counts closed-form; the hop and wire energies claimed)",
"ADV-07": "the lifetime table and the six-row transition matrix (sections 7 and 14) on the placed rows; the 32-lane genesis comparator placed on adv-g",
"ADV-08": "the best-cost envelope on the complete machine (section 6) and the SRAM-die ticket reconciliation with lane B (section 15); the unaffiliated second reviewer is not this lane's",
"POW-03": "partial: the live state held in an SRAM macro per 8 lanes with a time-multiplexed single port and operand isolation, the complete-system cost in section 6; the liveness trace itself is the connected-state lane's tool",
"POW-04": "partial: the 64-register window's cost on the macro core (sections 4 and 5, agreeing with the k lane's gated-flop row within 5 percent); the restructured candidate's GPU cost is the invention lane's",
"ADV-05": "partial: the SRAM macros, ports, wiring, clocking and the complete-board terms are modelled in sections 2.3, 5 and 6 with the unmodelled items carried as uncertainty; the calibration against an existing hardware block is the k lane's bare-lane row beside it, owed as a named comparison"
}
},
"adversary:d2b": {
"command": "cd tools/chip-model/mf && python3 flow/d2b.py results N5 1 && python3 flow/d2b.py results N3 1 (on a build box under lease pool or a rented host; reads results/table.csv)",
"box_class": "any box (a one-minute Python model on the placed rows)",
"fixtures": [
"F0"
],
"cases": [
"ADV-02",
"ADV-04"
],
"coverage": {
"ADV-02": "memory sharing, partial stores at the measured window-layer hit rates (and hit 0.50 with layer 8 off), recomputation and the set-up amortisation on the complete board (section 13); the formal memory model's terms (section 16)",
"ADV-04": "selective participation over 2,000 era draws under the layer 1 band with two reserve families live per epoch, the specialist's revenue against its ratio gain (section 13); downtime and re-entry priced as the DAA window's lag, not simulated against the difficulty rule itself (owed)"
}
},
"pc:install-update": {
"command": "signed jobs and relay runs on PC 1 (ae432dc7) and PC 2 (1ccfe586): the installer over the running app (rule 14: installed versions, the process set, the first upload), the OTA path (update-now, the update-return read-back line), and the no-click resume after the install (relay run mining-on-after-200.ps1)",
"box_class": "PC (the two Windows PCs; nothing on the Mac)",
"fixtures": [
"F2"
],
"cases": [
"UX-01",
"UX-07",
"OPS-03"
],
"coverage": {
"UX-01": "team-run evidence only (the two PCs taking the Windows entry through the app's own update path with no click and mining on every card); the P10 study is NOT RUN until unaffiliated participants are recruited",
"UX-07": "partial: the install classes (the payload's stop step, the detached installer under a job, the installer refusing a wrong-version name, a stale install flag) and the no-click resume; the recovery-instruction and canary rows are the shipper's",
"OPS-03": "partial: the update path's read-back and the signed manifest's verify on the PC (a tampered or rolled-back payload is refused by the engine's manifest check); authority separation is the shipper's review"
}
}
},
"not_run": {
@ -598,9 +656,7 @@
"GPU-06": "accepted work under ordinary connectivity needs the fault network F4",
"GPU-07": "the sustained thermal and power soak has no harness tonight: PC 1 mines nothing under the Devnet 3 off order",
"POW-05": "amortised cheap winning attempts are the attack lanes' grind and era harnesses (tools/attack/f7-era, f9-grind), not in the release matrix; their rows come from those lanes",
"ADV-04": "selective participation needs the economic model F7 and a live chain window",
"ADV-06": "process-advantage separation is the adversary lanes' chip study",
"ADV-07": "lifetime rows are the adversary lanes' models",
"ROT-03": "miner-voted bring-forward needs a vote harness on the fault network F4",
"ROT-04": "seed-selection resistance is the census harness (the class v6 invention lane), not yet in the matrix",
"EVM-01": "no EVM conformance-vector harness is mapped tonight; the exec suite does not run the reference test vectors",

77
tools/fleet/box-dn3.sh Normal file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env bash
# A Devnet 3 box (7 October 2026, the founder's clock: a fresh chain from genesis on 0.3.22, network igneum-devnet-3, every activation at 0,
# NO override file). Modelled on box-dn2.sh. The node runs with NET_ARGS (default "--devnet --devnet-suffix=3": own handshake magic,
# own data directory $F/$APPDIR; a live-devnet or Devnet 2 peer refuses it at the handshake), peered with SEED (comma list); one miner on
# card 0 with the box's vote key; PROVER=1 adds the segment prover loop (CHAIN_NAME igneum-devnet-3). NODE_BIN names the igneumd.
# FRESH=1 wipes $F/$APPDIR (a new genesis); UNSYNCED=1 adds --enable-unsynced-mining (the genesis boxes: a fresh chain's nodes start
# unsynced and must mine anyway). RPC_PORT, P2P_PORT, EVM_PORT: other ports on a box whose live node holds 26610/26611/26790
# (a standing box running a second node for Devnet 3: 36610/36611/36790). Nothing here touches the live devnet's node or miner.
set -uo pipefail
mkdir -p /root/fleet/pids; echo $$ > /root/fleet/pids/loop.pid # 15:3xZ 8 Oct 2026: kills by pid file only (main): loop.pid, node.pid, miner.pid under /root/fleet/pids
F=/root/fleet; OUT=$F/out; mkdir -p $F/in $OUT $F/$APPDIR $F/mine/packs; exec >> $OUT/dn3.log 2>&1
stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; }
LABEL="${LABEL:-dn3}"; WALLET="${WALLET:-0x1919191919191919191919191919191919191919}"; SEED="${SEED:-}"; NODE_BIN="${NODE_BIN:-$F/in/igneumd-0322}"
APPDIR="${APPDIR:-dn3}"; PACK="${PACK:-dn3}"; CHAIN_NAME="${CHAIN_NAME:-igneum-devnet-3}" # 15:4xZ 8 Oct 2026: devnet-4 takes APPDIR=dn4 PACK=dn4 CHAIN_NAME=igneum-devnet-4 NET_ARGS="--devnet --devnet-suffix=4"
PROVER="${PROVER:-0}"; UNSYNCED="${UNSYNCED:-}"; RPC_PORT="${RPC_PORT:-26610}"; P2P_PORT="${P2P_PORT:-26611}"; EVM_PORT="${EVM_PORT:-26790}"; JSON_PORT="${JSON_PORT:-$((RPC_PORT+2080))}"; MINE="${MINE:-1}"
NET_ARGS="${NET_ARGS:---devnet --devnet-suffix=3}"; P2P_LISTEN="${P2P_LISTEN:-0.0.0.0:$P2P_PORT}"; MINER_ONLY="${MINER_ONLY:-0}"; ANNOUNCE="${ANNOUNCE:-}"; export -n MINER_ONLY # 21:3xZ 7 Oct 2026: never in the loop's environment (the puller restarts from it; MINER_ONLY=1 there would leave the node down at the next move) # MINER_ONLY=1: the node stays, only the miner loop restarts (with --announce ip:port when ANNOUNCE is set: the peer directory)
JSONF="--rpclisten-json=127.0.0.1:$JSON_PORT"; case " $NET_ARGS ${EXTRA_ARGS:-} " in *rpclisten-json*) JSONF="";; esac # 13:3xZ 8 Oct: the pool boxes already carry it in NET_ARGS (dn3-pool-b: "cannot be used multiple times")
MINER_BIN="${MINER_BIN:-$F/in/igneum-miner-0322}" # the 0.3.22 miner (sub-version 3 draw); the hive package's 0.3.20 miner is the live devnet's and never mines Devnet 3 (16:5xZ: every block BlockInvalid)
[ -x "$NODE_BIN" ] || { echo "RESULT dn3_failed $(stamp) no node binary at $NODE_BIN"; exit 2; }
[ "${MINE:-1}" = 1 ] && { [ -x "$MINER_BIN" ] || { echo "RESULT dn3_failed $(stamp) no 0.3.22 miner at $MINER_BIN"; exit 2; }; }
# the pack-id gate (main through the shipper, 7 Oct 2026 17:0xZ): BEFORE the miner starts, the worker's pack and the node's engine must come
# from the same igneum-pow pin. Tonight's shape (the shipper, 17:05Z): BY CONSTRUCTION, the pack the worker hashes is EXPORTED on this box by the
# paired 0.3.22 miner (MINER_BIN's sha equals PAIR_MINER_SHA16, default 07246920fd9fe895 = igneum-pow 017e7037, the node's pin), never a copied kit;
# a different miner sha or a pre-shipped pack directory is UNREADABLE and holds the miner. The id-equality read over RPC (a785001687d8688a against
# the kit's id) replaces it from the next cut when the node lane names the method (NODE_ID_CMD / PACK_ID_CMD).
pack_gate() {
local msha want; msha=$(sha256sum "$MINER_BIN" | cut -c1-16); want="${PAIR_MINER_SHA16:-07246920fd9fe895 c29f33bbbd284a12 dfdc6883aa79a76f fb147dd1754cbfc0 cfa9f5ca382e0efc} $(cat $F/in/pair-miners.txt 2>/dev/null | tr '\n' ' ')" # 8 Oct 2026 09:4xZ: the list is also a FILE the puller appends every move's miner sha to (the 10:05 move: 18 miners refused for a sha only in a hand-edited default) # the two paired 0.3.22 miners (hands / node-lane builds, both igneum-pow 017e7037)
if [ -n "${NODE_ID_CMD:-}" ] && [ -n "${PACK_ID_CMD:-}" ]; then
local pid nid; pid=$(eval "$PACK_ID_CMD" 2>/dev/null); nid=$(eval "$NODE_ID_CMD" 2>/dev/null)
[ -n "$pid" ] && [ -n "$nid" ] || { echo "RESULT dn3_pack_gate $(stamp) UNREADABLE pack_id=${pid:-none} node_id=${nid:-none}"; return 1; }
[ "$pid" = "$nid" ] || { echo "RESULT dn3_pack_gate $(stamp) REFUSED pack_id=$pid node_id=$nid"; return 1; }
echo "RESULT dn3_pack_gate $(stamp) PASS by id pack_id=$pid node_id=$nid"; return 0
fi
case " $want " in *" $msha "*) ;; *) echo "RESULT dn3_pack_gate $(stamp) UNREADABLE miner=$msha is not a paired miner ($want); a pre-shipped kit or another miner"; return 1;; esac
[ -e $F/mine/packs/$PACK ] && { echo "RESULT dn3_pack_gate $(stamp) UNREADABLE packs/$PACK already present before this export (a copied kit?)"; return 1; }
echo "RESULT dn3_pack_gate $(stamp) PASS by construction (miner $msha = pair, pack exported here by it, generator v4 sub-version 3)"; return 0
}
echo "RESULT dn3_start $(stamp) label=$LABEL node=$(sha256sum $NODE_BIN | cut -c1-16) miner=$(sha256sum $MINER_BIN 2>/dev/null | cut -c1-16) seed=${SEED:-none} prover=$PROVER mine=$MINE net=\"$NET_ARGS\" ports=$RPC_PORT/$P2P_PORT/$EVM_PORT"
command -v curl >/dev/null || { apt-get update -qq >/dev/null 2>&1; apt-get install -y -qq curl ca-certificates python3 >/dev/null 2>&1; }
if [ ! -x /opt/igneum/pkg/bin/igneum-miner ]; then
read -r PKG_PATH PKG_SHA PKG_VER <<< "$(curl -fsSL -m 30 https://dl.igneum.network/dl/public/igneum-downloads.json | python3 -c 'import sys,json; d=json.load(sys.stdin)["files"]["miner-hive"]; print(d["path"], d["sha256"], d["version"])')"
curl -fsSL -o $F/pkg.tgz "https://dl.igneum.network$PKG_PATH" && echo "$PKG_SHA $F/pkg.tgz" | sha256sum -c - >/dev/null && mkdir -p /opt/igneum/pkg && tar -C /opt/igneum/pkg --strip-components=1 -xzf $F/pkg.tgz || { echo "RESULT dn3_failed package"; exit 2; }
fi
B=/opt/igneum/pkg/bin
# the Devnet 3 node and its miner only (anchored on the dn3 appdir and this RPC port), never the live node beside it
# kills by pid file only (founder 8 Oct 2026, by construction: pkill and killall are shimmed to exit 97 on every box)
pidkill() { local P; P=$(cat "$F/pids/$1.pid" 2>/dev/null); [ -n "$P" ] && kill -0 "$P" 2>/dev/null && { kill -TERM "$P" 2>/dev/null; sleep 2; kill -0 "$P" 2>/dev/null && kill -9 "$P" 2>/dev/null; }; return 0; }
[ "$MINER_ONLY" = 1 ] || pidkill node; pidkill miner; sleep 2
[ "${FRESH:-0}" = 1 ] && { rm -rf $F/$APPDIR; mkdir -p $F/$APPDIR; [ -s $F/$APPDIR-node.log ] && mv $F/$APPDIR-node.log $F/$APPDIR-node.prev.log; echo "RESULT dn3_fresh $(stamp) appdir wiped for the genesis"; }
PEER=""; for sd in ${SEED//,/ }; do PEER="$PEER --addpeer=$sd"; done
UNS=""; [ "$UNSYNCED" = 1 ] && UNS="--enable-unsynced-mining"
if [ "$MINER_ONLY" != 1 ]; then
echo "=== dn3 node start $(stamp) $(sha256sum $NODE_BIN | cut -c1-16)" >> $F/$APPDIR-node.log
IGNEUM_PROOF_PROGRAM_IDS="${PROGRAM_IDS:-}" IGNEUM_PROOF_VERIFIER="${HOST_VERIFIER:-}" setsid nohup $NODE_BIN $NET_ARGS --appdir=$F/$APPDIR --rpclisten=0.0.0.0:$RPC_PORT --evm-rpclisten=127.0.0.1:$EVM_PORT $JSONF --listen=$P2P_LISTEN $PEER $UNS --unsaferpc --nodnsseed --disable-upnp --nologfiles --yes </dev/null >> $F/$APPDIR-node.log 2>&1 &
echo $! > $F/pids/node.pid
sleep 10
echo "RESULT dn3_node $(stamp) pid=$(pgrep -f '[/]root/fleet/in/igneumd-[0-9a-f]+ .* --appdir=/root/fleet/$APPDIR ' | head -1) version=$(grep -oE 'igneumd/[0-9]+\.[0-9]+\.[0-9]+-[0-9a-f]+' $F/$APPDIR-node.log | tail -1) digest=$(grep -o 'digest: [0-9a-f]*' $F/$APPDIR-node.log | tail -1 | awk '{print substr($2,1,16)}') network=$(grep -oiE 'igneum-devnet-[0-9][^ ,]*' $F/$APPDIR-node.log | head -1) genesis=$(grep -oiE 'genesis[^\n]{0,120}' $F/$APPDIR-node.log | grep -oE '[0-9a-f]{64}' | head -1 | cut -c1-16)"
for i in $(seq 1 30); do w="$($B/igneum-miner watch 1 grpc://127.0.0.1:$RPC_PORT 2>/dev/null | grep -o 'blocks=[0-9]*.*synced=[a-z]*' | tail -1)"; [ -n "$w" ] && break; sleep 5; done
echo "RESULT dn3_watch $(stamp) $(printf '%s' "$w" | sed -E 's/difficulty=[0-9.]* sink=[0-9a-f]* //')"
fi
rm -rf $F/mine/packs/$PACK.prev; [ -e $F/mine/packs/$PACK ] && mv $F/mine/packs/$PACK $F/mine/packs/$PACK.prev # the previous run's export, moved aside so the gate sees a clean slot
if [ "$MINE" = 1 ] && ! pack_gate; then echo "RESULT dn3_miner_refused $(stamp) the pack-id gate refused the place; node runs, miner off"; MINE=0; fi
if [ "$MINE" = 1 ]; then
cd $F/mine && rm -rf packs/$PACK && $MINER_BIN export-pack grpc://127.0.0.1:$RPC_PORT packs/$PACK > $OUT/dn3-export-pack.log 2>&1
( echo $BASHPID > $F/pids/miner-loop.pid; while :; do $MINER_BIN mine grpc://127.0.0.1:$RPC_PORT 1 100000000 "$LABEL" --exec-rpc http://127.0.0.1:$EVM_PORT --worker $WORKER_BIN --worker-args "--device 0 --pack packs/$PACK" --prepare-packs packs/$PACK-prepare --exit-on-seed-change ${ANNOUNCE:+--announce $ANNOUNCE} --evm-address "$WALLET" --payout-label "$LABEL" --status-secs 30 >> $OUT/dn3-miner.log 2>&1 & echo $! > $F/pids/miner.pid; wait $(cat $F/pids/miner.pid); sleep 5; done ) </dev/null >/dev/null 2>&1 &
echo "RESULT dn3_miner_started $(stamp) miner=$(sha256sum $MINER_BIN | cut -c1-16) announce=${ANNOUNCE:-none}"
# the engine's program id as the paired miner prints it ("class v4 program id <16 hex>", the node lane 17:0xZ): a785001687d8688a on sub-version 3,
# 1a4230699a6b9c60 is the 0.3.20 kit (known-failed); logged as the gate's id line, refused on the known-failed value
# the worker form prints no id (the node lane, main.rs 1471): a second one-thread CPU miner beside the worker for 20 s prints "class v4 program id <16 hex>"
timeout 60 $MINER_BIN mine grpc://127.0.0.1:$RPC_PORT 1 20 idread --engine igneum-pow --no-vote --stall-secs 0 > $OUT/dn3-idread.log 2>&1 </dev/null
pidl=$(grep -oE 'program id [0-9a-f]{16}' $OUT/dn3-idread.log | tail -n 1 | awk '{print $3}')
if [ "$pidl" = "1a4230699a6b9c60" ] || [ "$pidl" = "a785001687d8688a" ]; then pidkill miner; echo "RESULT dn3_program_id $(stamp) REFUSED $pidl is the shared devnet's id (edc4fa84 seeds), not Devnet 3's; miner stopped"; else echo "RESULT dn3_program_id $(stamp) ${pidl:-unread} (want ${WANT_PROGRAM_ID:-fce15bf61030be57}, the epoch-0 id of genesis 4020cb43; the id changes with the epoch seed every 3,600 DAA)"; fi
fi
if [ "$PROVER" = 1 ] && [ -x /opt/igneum-floor/bin/igneum-prove-host ]; then
cd $F && LABEL="$LABEL" WALLET="$WALLET" EXPORT_FROM=0 CHAIN_NAME=$CHAIN_NAME MINER=none RUN_HOURS=48 EVM="http://127.0.0.1:$EVM_PORT" GRPC="grpc://127.0.0.1:$RPC_PORT" setsid nohup python3 -u $F/in/box-prover.py </dev/null >> $OUT/dn3-prover-launch.log 2>&1 &
echo "RESULT dn3_prover_started $(stamp)"
fi

View file

@ -1,4 +1,5 @@
#!/usr/bin/env bash
. /root/fleet/in/pidkill.sh # kills by pid only (founder 8 Oct 2026)
# Ember Tune's two-knob ladder on a rented NVIDIA card (docs/plans/ember-tune.md, branch ember-tune): the miner runs
# throughout; the power ladder 100, 90, 80, 70, 60, 50% of the default limit at the unlocked clock (clamped at the
# card's reported minimum), then the clock ladder 90, 80, 70, 60% of the maximum graphics clock at the power the
@ -15,7 +16,7 @@ stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; }
say() { echo "$(stamp) $*"; }
q() { nvidia-smi --query-gpu="$1" --format=csv,noheader,nounits -i 0 2>/dev/null | head -1 | tr -d ' '; }
NAME="$(q name)"; DRV="$(q driver_version)"; PDEF="$(q power.default_limit)"; PMIN="$(q power.min_limit)"; PMAX="$(q power.max_limit)"; CMAX="$(q clocks.max.graphics)"
pkill -x sp1-gpu-server 2>/dev/null; rm -f /tmp/sp1-cuda-*.sock
. /root/fleet/in/pidkill.sh; kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
echo "RESULT start $(stamp) card=$NAME driver=$DRV power_default_w=$PDEF min_w=$PMIN max_w=$PMAX clock_max_mhz=$CMAX"
# can we set anything?
nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1 && PL_OK=1 || PL_OK=0
@ -27,7 +28,7 @@ rm -rf packs/devnet; $B/igneum-miner export-pack grpc://127.0.0.1:26610 packs/de
nohup $B/igneum-miner mine grpc://127.0.0.1:26610 1 100000000 "$LABEL" --worker $B/igneum-worker-cuda --worker-args "--device 0 --pack packs/devnet" \
--prepare-packs packs/prepare --exit-on-seed-change --evm-address "$WALLET" --payout-label "$LABEL" --status-secs 10 > $OUT/ember-miner.log 2>&1 &
MPID=$!; cd $F
cleanup() { nvidia-smi -i 0 -rgc >/dev/null 2>&1; [ "$PL_OK" = 1 ] && nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1; kill $MPID 2>/dev/null; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda' 2>/dev/null; }
cleanup() { nvidia-smi -i 0 -rgc >/dev/null 2>&1; [ "$PL_OK" = 1 ] && nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1; kill_children $MPID; kill $MPID 2>/dev/null; }
trap cleanup EXIT
say "miner warming 90 s"; sleep 90
STEPS=$OUT/ember-steps.jsonl; : > $STEPS
@ -38,7 +39,7 @@ step() { # <label> <power_pct> <limit_w> <clock_cap_mhz or 0>
sleep "$SETTLE"
local n0; n0="$(grep -c 'STATUS' $OUT/ember-miner.log)"
( while :; do nvidia-smi --query-gpu=power.draw,clocks.sm,clocks.mem,temperature.gpu --format=csv,noheader,nounits -i 0 2>/dev/null; sleep 1; done ) > $OUT/ember-samp-$lab.csv & local sp=$!
sleep "$HOLD"; pkill -P $sp 2>/dev/null; kill $sp 2>/dev/null; sleep 1; kill -9 $sp 2>/dev/null
sleep "$HOLD"; kill_children $sp; kill $sp 2>/dev/null; sleep 1; kill -9 $sp 2>/dev/null
local n1; n1="$(grep -c 'STATUS' $OUT/ember-miner.log)"
local mhs; mhs="$(grep STATUS $OUT/ember-miner.log | grep -o ' now=[0-9.]*' | tail -n $((n1 - n0 > 0 ? n1 - n0 : 1)) | cut -d= -f2 | awk '{s+=$1; n++} END {if (n) printf "%.2f", s/n; else print 0}')"
local w gclk mclk tmax; read -r w gclk mclk tmax <<< "$(awk -F', *' '{w+=$1; g+=$2; m+=$3; if ($4+0 > t) t=$4+0; n++} END {if (n) printf "%.1f %.0f %.0f %d", w/n, g/n, m/n, t; else print "0 0 0 0"}' $OUT/ember-samp-$lab.csv)"

View file

@ -1,4 +1,5 @@
#!/usr/bin/env bash
. /root/fleet/in/pidkill.sh # kills by pid only (founder 8 Oct 2026)
# The prover-floor agent's known-failed case (6 October 2026, 13:05Z): rebuild sp1-gpu-server from patch v5 (the panic
# hook that turns a failed device allocation into "FLOOR abort ..." and exit 70) and re-run the 2^27 compressed point
# alone on a card it cannot fit; report the host's failing line, the server's FLOOR abort line and the seconds.
@ -19,10 +20,10 @@ echo "RESULT v5_build_exit $rc time_s=$(( $(date +%s) - t0 ))"
[ $rc -eq 0 ] || { grep -n -A6 '^error' $FLOOR/logs/build-server-v5.log | head -30; echo "RESULT v5_failed build"; exit 2; }
mkdir -p $FLOOR/home-v5/.sp1/bin && cp $FLOOR/target/release/sp1-gpu-server $FLOOR/home-v5/.sp1/bin/ && chmod +x $FLOOR/home-v5/.sp1/bin/sp1-gpu-server
echo "RESULT v5_server sha256=$(sha256sum $FLOOR/home-v5/.sp1/bin/sp1-gpu-server | cut -c1-16) bytes=$(stat -c %s $FLOOR/home-v5/.sp1/bin/sp1-gpu-server)"
pkill -9 -x sp1-gpu-server; rm -f /tmp/sp1-cuda-*.sock; sleep 2
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'; sleep 2
t1=$(date +%s)
env HOME=$FLOOR/home-v5 SP1_PROVER=cuda RUST_LOG=off SP1_GPU_FLOOR_LOG=1 SP1_GPU_ELEMENT_THRESHOLD=134217728 timeout 900 $HOST $FLOOR/prove/proving/fixtures/fees-v1-shards2.json --mode compressed --shard 0 --out $OUT/v5-point.json > $OUT/v5-point.log 2>&1; rc=$?
echo "RESULT v5_point rc=$rc wall_s=$(( $(date +%s) - t1 ))"
grep -n -E 'FLOOR abort|panicked|Error|error|RESULT' $OUT/v5-point.log | head -12 | cut -c1-300
pkill -9 -x sp1-gpu-server; rm -f /tmp/sp1-cuda-*.sock
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
echo "RESULT v5_done $(stamp)"

View file

@ -1,15 +1,11 @@
#!/usr/bin/env bash
# Stops every stage process on a box (the matrix, Ember, the prover loop, their miners, workers, samplers and SP1
# servers); never the node. Run as a FILE (bash in/box-kill.sh) so that no pattern below can match the shell that runs
# it (an inline `pkill -f '[i]gneum-prove-host'` killed its own ssh shell on 6 October 2026, 12:38Z).
for i in 1 2; do
pkill -9 -f '[b]ash in/box-matrix.sh' ; pkill -9 -f '[b]ash in/box-ember.sh'; pkill -9 -f '[b]ash in/box-prover.sh'; pkill -9 -f '[p]ython3 -u /root/fleet/in/box-prover.py'
pkill -9 -x igneum-miner; pkill -9 -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda'; pkill -9 -x sp1-gpu-server; pkill -9 -f '[/]opt/igneum-floor/(bin|target|prove)/.*igneum-prove-(host|export)' # pkill -x cannot match a name over 15 characters (igneum-worker-cuda, igneum-prove-host)
pkill -9 -f '[n]vidia-smi --query'
sleep 2
done
rm -f /tmp/sp1-cuda-*.sock
# Stops every stage process on a box through pid files only (the founder, 8 Oct 2026: pkill and killall exit 97 on every box);
# never the node. The stage scripts write their pids under /root/fleet/pids (matrix, ember, prover, prover-loop, miner-loop, miner,
# sampler, sp1-server); a child the scripts spawned is reached through its parent's pid (kill_children walks by parent pid).
. /root/fleet/in/pidkill.sh
for n in matrix ember prover-loop prover miner-loop miner sampler; do p=$(cat /root/fleet/pids/$n.pid 2>/dev/null); [ -n "$p" ] && kill_children "$p" -9; kill_pidfile $n -9 0; done
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
nvidia-smi -i 0 -rgc >/dev/null 2>&1
d="$(nvidia-smi --query-gpu=power.default_limit --format=csv,noheader,nounits -i 0 | tr -d ' ' | cut -d. -f1)"; [ -n "$d" ] && nvidia-smi -i 0 -pl "$d" >/dev/null 2>&1
cd /root/fleet/out 2>/dev/null && for f in matrix.log ember.log prover.log prover-launch.log rows.jsonl; do [ -f "$f" ] && mv "$f" "$f.$(date +%s).old"; done
echo "count=$(pgrep -c -f '[b]ash in/box-|^python3 -u /root/fleet/in/box-prover')+$(pgrep -c -x igneum-miner)+$(pgrep -c -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda')+$(pgrep -c -x sp1-gpu-server)+$(pgrep -c -f '[/]opt/igneum-floor/(bin|target|prove)/.*igneum-prove-host') mem=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits -i 0 | tr -d ' ')"
echo "stopped by pid files: $(ls /root/fleet/pids 2>/dev/null | tr '\n' ' ') mem=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits -i 0 2>/dev/null)"

View file

@ -1,4 +1,5 @@
#!/usr/bin/env bash
. /root/fleet/in/pidkill.sh # kills by pid only (founder 8 Oct 2026)
# Phase 1 on one rented card: the memory matrix of docs/analysis/prover-floor.md on the real card. Every point is one
# igneum-prove-host run against a fresh sp1-gpu-server (killed and its socket unlinked around every point), with an
# nvidia-smi sampler at 1 s (memory.used, power.draw, utilization); peak = max memory.used, base = the reading just
@ -29,10 +30,10 @@ SAMP=""
# one nvidia-smi call a second in a loop: `nvidia-smi -l 1` buffers its file output in 4 KB chunks and ignored SIGTERM
# on the 3080 box (12:19Z), which hung the first matrix in sampler_stop
sampler_start() { ( while :; do nvidia-smi --query-gpu=timestamp,memory.used,power.draw,utilization.gpu --format=csv,noheader,nounits -i 0 2>/dev/null; sleep 1; done ) > "$1" & SAMP=$!; }
sampler_stop() { [ -n "$SAMP" ] && { pkill -P $SAMP 2>/dev/null; kill $SAMP 2>/dev/null; sleep 1; kill -9 $SAMP 2>/dev/null; }; SAMP=""; }
sampler_stop() { [ -n "$SAMP" ] && { kill_children $SAMP; kill $SAMP 2>/dev/null; sleep 1; kill -9 $SAMP 2>/dev/null; }; SAMP=""; }
peak_of() { awk -F', *' 'NR>0 {if ($2+0 > m) m=$2+0} END {print m+0}' "$1"; }
mean_col() { awk -F', *' -v c="$2" '{s+=$c; n++} END {if (n) printf "%.1f", s/n; else print 0}' "$1"; }
kill_server() { pkill -x sp1-gpu-server 2>/dev/null; sleep 2; pkill -9 -x sp1-gpu-server 2>/dev/null; rm -f /tmp/sp1-cuda-*.sock; }
kill_server() { kill_sock_owner 'sp1-cuda-[0-9]*\.sock'; }
idle_mib() { sleep 3; q memory.used; }
# 1. idle
@ -55,7 +56,7 @@ miner_start() {
--prepare-packs packs/prepare --exit-on-seed-change --evm-address "$WALLET" --payout-label "$LABEL" --status-secs 10 > $OUT/miner.log 2>&1 &
MPID=$!; cd $F
}
miner_stop() { [ -n "$MPID" ] && { kill $MPID 2>/dev/null; sleep 2; kill -9 $MPID 2>/dev/null; }; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda' 2>/dev/null; pkill -x igneum-miner 2>/dev/null; MPID=""; sleep 3; }
miner_stop() { [ -n "$MPID" ] && { kill_children $MPID; kill $MPID 2>/dev/null; sleep 2; kill -9 $MPID 2>/dev/null; }; MPID=""; sleep 3; }
miner_rate() { # mean of the STATUS now= values in the last N lines
grep STATUS $OUT/miner.log | grep -o ' now=[0-9.]*' | tail -n "${1:-10}" | cut -d= -f2 | awk '{s+=$1; n++} END {if (n) printf "%.2f", s/n; else print 0}'
}

View file

@ -190,7 +190,18 @@ def fnv1a(s):
return h
def kill_server():
if CARD: subprocess.run(f"rm -f /tmp/sp1-cuda-{DEV}.sock", shell=True) # a rig: never another card's server
else: subprocess.run("pkill -x sp1-gpu-server; sleep 1; rm -f /tmp/sp1-cuda-*.sock", shell=True)
else:
# kills by pid only (founder 8 Oct 2026, by construction): the server is found through the pid that owns its unix socket
# (ss -xlp on /tmp/sp1-cuda-*.sock), written to /root/fleet/pids/sp1-server.pid, then signalled by that pid; never by name
o=subprocess.run("ss -xlp 2>/dev/null | grep -E '/tmp/sp1-cuda-[0-9]*\\.sock' | grep -oE 'pid=[0-9]+' | cut -d= -f2 | sort -u", shell=True, capture_output=True, text=True).stdout.split()
os.makedirs("/root/fleet/pids", exist_ok=True)
for s in o:
try:
pid=int(s); open("/root/fleet/pids/sp1-server.pid","w").write(f"{pid}\n"); os.kill(pid, 15); time.sleep(1)
try: os.kill(pid, 9)
except ProcessLookupError: pass
except Exception: pass
subprocess.run("rm -f /tmp/sp1-cuda-*.sock", shell=True)
MPROC = None
def miner_start():
global MPROC
@ -204,7 +215,7 @@ def miner_start():
def miner_stop():
global MPROC
if MPROC: MPROC.terminate(); time.sleep(2); MPROC.kill(); MPROC = None
subprocess.run(f"pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda --device {DEV} '", shell=True)
pass # the worker is the miner's child; MPROC.terminate() above ends it (no kill by name: founder 8 Oct 2026)
def miner_rate(n=6):
try:
vals = [float(l.split(" now=")[1].split()[0]) for l in open(f"{OUT}/prover-miner.log").read().split("\n") if "STATUS" in l and " now=" in l][-n:]

View file

@ -1,4 +1,5 @@
#!/usr/bin/env bash
. /root/fleet/in/pidkill.sh # kills by pid only (founder 8 Oct 2026)
# Phase 3 on an 8-card rig (RunPod pod, a container: no systemd, so the rig installer's unit steps are exercised with
# --preflight-only and --dry-run and the units' own scripts are run by hand). After box-setup.sh (node, workers, the
# patched server for the rig's arch, the cuda host):
@ -35,7 +36,7 @@ for d in $(seq 0 $((N-1))); do
done
cd $F; sleep 60
( while :; do nvidia-smi --query-gpu=index,power.draw,memory.used,utilization.gpu --format=csv,noheader,nounits; sleep 1; done ) > $OUT/rig-samp-mine.csv & SP=$!
sleep "$MINE_SECS"; pkill -P $SP; kill $SP 2>/dev/null
sleep "$MINE_SECS"; kill_children $SP; kill $SP 2>/dev/null
sum=0
for d in $(seq 0 $((N-1))); do
r=$(grep STATUS $OUT/rig-miner-$d.log | grep -o ' now=[0-9.]*' | tail -n 10 | cut -d= -f2 | awk '{s+=$1; n++} END {if (n) printf "%.2f", s/n; else print 0}')
@ -43,10 +44,10 @@ for d in $(seq 0 $((N-1))); do
echo "RESULT miner card=$d mhs=$r watts=$w"; sum=$(awk -v a=$sum -v b=$r 'BEGIN {print a+b}')
done
echo "RESULT rig_miners $(stamp) cards=$N sum_mhs=$sum watts=$(awk -F', *' '{s+=$2; n++} END {printf "%.0f", s/n*'$N'}' $OUT/rig-samp-mine.csv)"
for p in "${pids[@]}"; do kill $p 2>/dev/null; done; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda'; sleep 3
for p in "${pids[@]}"; do kill_children $p; kill $p 2>/dev/null; done; sleep 3
fi
# C + D. seven core-only provers and one compressing card, in parallel
pkill -9 -x sp1-gpu-server; rm -f /tmp/sp1-cuda-*.sock
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
prove_loop() { # <device> <mode> <threshold> <seconds>
local d=$1 mode=$2 thr=$3 secs=$4 t0=$(date +%s) n=0 tot=0
while [ $(( $(date +%s) - t0 )) -lt $secs ]; do
@ -63,9 +64,9 @@ lp=()
for d in $(seq 0 $((N-2))); do prove_loop $d core 33554432 "$PROVE_SECS" & lp+=($!); done
prove_loop $((N-1)) compressed 67108864 "$PROVE_SECS" & lp+=($!)
for p in "${lp[@]}"; do wait $p; done
pkill -P $SP; kill $SP 2>/dev/null
kill_children $SP; kill $SP 2>/dev/null
echo "RESULT rig_prove $(stamp) host_ram_used_mb_max=$(awk '{if ($2>m) m=$2} END {print m}' $OUT/rig-samp-prove.csv) core_cards=$((N-1)) core_per_min=$(grep 'RESULT prove_loop' $OUT/rig.log | grep 'mode=core' | grep -o 'per_min=[0-9.]*' | cut -d= -f2 | awk '{s+=$1} END {printf "%.2f", s}') compressed_per_min=$(grep 'RESULT prove_loop' $OUT/rig.log | grep 'mode=compressed' | grep -o 'per_min=[0-9.]*' | cut -d= -f2)"
pkill -9 -x sp1-gpu-server; rm -f /tmp/sp1-cuda-*.sock
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
# E. the hand-off cost by file
cf=$(ls -S $F/mine/*.bin $OUT/*.bin 2>/dev/null | head -1); [ -z "$cf" ] && cf=$(find / -name 'block-*-core.bin' -size +1M 2>/dev/null | head -1)
if [ -n "$cf" ]; then
@ -80,5 +81,5 @@ t0=$(date +%s)
env HOME=$FLOOR/home IGNEUM_CUDA_DEVICE=$((N-1)) SP1_PROVER=cuda RUST_LOG=off timeout 1800 $HOST --mode chain --chain "$list" --prover "$WALLET" --save-shards --out $OUT/rig-chain.json > $OUT/rig-chain.log 2>&1; rc=$?
echo "RESULT chain rc=$rc wall_s=$(( $(date +%s) - t0 )) blocks=$(echo "$list" | tr ',' '\n' | wc -l) $(grep -E '^RESULT chain' $OUT/rig-chain.log | tail -1 | cut -c1-200)"
else echo "RESULT chain skipped: no consecutive live fixtures yet (needs the exec layer)"; fi
pkill -9 -x sp1-gpu-server; rm -f /tmp/sp1-cuda-*.sock
kill_sock_owner 'sp1-cuda-[0-9]*\.sock'
echo "RESULT rig_done $(stamp)"

3
tools/fleet/dn3-kill.sh Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
# kills by pid file only (founder 8 Oct 2026): the old name-pattern kills are gone; fleet-stop.sh all stops node, miner and loop through /root/fleet/pids.
bash /root/fleet/in/fleet-stop.sh all

111
tools/fleet/fleet-puller.sh Normal file
View file

@ -0,0 +1,111 @@
#!/usr/bin/env bash
# Igneum fleet puller (main's order 21:5x BST 7 Oct 2026): the box fetches a SIGNED move file from the fleet file host on a
# one-minute timer, verifies the signature against the fleet key this box already trusts (its authorized_keys), downloads the
# named binary pair, checks every sha, and at the named minute (UTC epoch) restarts its Devnet 3 node and miner together from
# the running box-dn3.sh's own environment, then reads the version string and digest back and posts the line to the intake.
# A proxy outage never blocks a digest-moving release again: nothing here needs ssh. Env: BASE (file host prefix), LABEL,
# INTAKE_URL + INTAKE_KEY (the report-only intake key that every miner package carries). State under /root/fleet/move.
set -u
F=/root/fleet; M=$F/move; mkdir -p $M; cd $M
LABEL="${LABEL:?}"; BASE="${BASE:?}"; INTAKE_URL="${INTAKE_URL:-}"; INTAKE_KEY="${INTAKE_KEY:-}"
stamp(){ date -u +%Y-%m-%dT%H:%M:%SZ; }
log(){ echo "$(stamp) $*" >> $M/puller.log; }
post(){ # post "<title>" "<body>"
echo "$(stamp) $1 | $2" >> $M/readback.log
[ -n "$INTAKE_URL" ] && [ -n "$INTAKE_KEY" ] && python3 - "$1" "$2" "$LABEL" "$INTAKE_URL" "$INTAKE_KEY" <<'PY' >/dev/null 2>&1
import sys, json, urllib.request
t,b,l,u,k=sys.argv[1:]
req=urllib.request.Request(u, data=json.dumps({"from":"fleet:"+l,"kind":"note","title":t[:300],"body":b[:4000]}).encode(), headers={"Content-Type":"application/json","x-igneum-key":k}, method="POST")
try: urllib.request.urlopen(req, timeout=20).read()
except Exception as e: print(e)
PY
true; }
awk '{print "igneum-fleet-move " $1, $2}' /root/.ssh/authorized_keys > $M/allowed_signers
jq_(){ python3 -c 'import sys,json; d=json.load(open(sys.argv[1])); v=d
for k in sys.argv[2].split("."): v=v[k] if isinstance(v,dict) else v[int(k)]
print(v if not isinstance(v,(list,dict)) else json.dumps(v))' "$@" 2>/dev/null; }
log "puller start label=$LABEL base=$BASE"
while :; do
if curl -fsS -m 25 -o $M/move.json.tmp "$BASE/move.json" && curl -fsS -m 25 -o $M/move.json.sig.tmp "$BASE/move.json.sig"; then
if ssh-keygen -Y verify -f $M/allowed_signers -I igneum-fleet-move -n igneum-fleet-move -s $M/move.json.sig.tmp < $M/move.json.tmp >/dev/null 2>&1; then
mv -f $M/move.json.tmp $M/move.json; mv -f $M/move.json.sig.tmp $M/move.json.sig
else log "BAD SIGNATURE on move.json, ignored"; rm -f $M/move.json.tmp $M/move.json.sig.tmp; sleep 60; continue; fi
else [ -f $M/move.json ] || { sleep 60; continue; }; fi
id=$(jq_ $M/move.json id); at=$(jq_ $M/move.json at_epoch); [ -n "$id" ] || { log "move.json without id"; sleep 60; continue; }
# a staggered move (8 Oct 2026, the 0.3.25 re-execution from genesis): "delays": {"<label>": <seconds>} adds to at_epoch for that box; absent = 0
dly=$(jq_ $M/move.json delays.$LABEL 2>/dev/null); case "$dly" in ''|*[!0-9]*) dly=0;; esac
if [ "${at:-0}" -gt 0 ] 2>/dev/null; then at=$((at+dly)); fi
if [ -e $M/applied-$id ]; then sleep 60; continue; fi
pair=hands; for l in $(jq_ $M/move.json node_lane_labels | tr -d '[]",'); do [ "$l" = "$LABEL" ] && pair=node_lane; done
url=$(jq_ $M/move.json pairs.$pair.url); tsha=$(jq_ $M/move.json pairs.$pair.sha); dsha=$(jq_ $M/move.json pairs.$pair.igneumd_sha); msha=$(jq_ $M/move.json pairs.$pair.miner_sha)
if [ ! -e $M/fetched-$id ]; then
mkdir -p $M/$id && curl -fsS -m 600 -o $M/$id/pair.tgz "$url" || { log "fetch failed $url"; sleep 60; continue; }
echo "$tsha $M/$id/pair.tgz" | sha256sum -c - >/dev/null 2>&1 || { log "TARBALL SHA MISMATCH $id"; rm -f $M/$id/pair.tgz; sleep 60; continue; }
tar -xzf $M/$id/pair.tgz -C $M/$id && [ "$(sha256sum $M/$id/igneumd | cut -c1-64)" = "$dsha" ] && [ "$(sha256sum $M/$id/igneum-miner | cut -c1-64)" = "$msha" ] || { log "BINARY SHA MISMATCH $id"; rm -rf $M/$id; sleep 60; continue; }
chmod +x $M/$id/igneumd $M/$id/igneum-miner; touch $M/fetched-$id
# the pack gate's pair list by file: this move's miner sha (16 hex) appended once, so box-dn3.sh accepts the pair at the minute without a hand edit
grep -qx "${msha:0:16}" $F/in/pair-miners.txt 2>/dev/null || echo "${msha:0:16}" >> $F/in/pair-miners.txt
post "FLEET MOVE $id FETCHED $LABEL" "pair=$pair igneumd=${dsha:0:16} miner=${msha:0:16} at_epoch=$at"
log "fetched $id pair=$pair"
fi
p0=$(pgrep -of '[b]ash in/box-dn3.sh'); [ -n "$p0" ] && tr '\0' '\n' < /proc/$p0/environ | grep -E '^[A-Z_][A-Z0-9_]*=' | grep -vE '^(PWD|OLDPWD|SHLVL|_|TERM|SHELL|LS_COLORS|HOSTNAME|SSH_[A-Z_]+|LANG|LC_[A-Z_]+|LOGNAME|USER|MAIL|MINER_ONLY)=' > $M/env-last.tmp && [ -s $M/env-last.tmp ] && mv -f $M/env-last.tmp $M/env-last
now=$(date +%s)
if [ "${at:-0}" -le 0 ] 2>/dev/null; then sleep 60; continue; fi
if [ "$now" -lt "$at" ]; then d=$((at-now)); [ $d -gt 60 ] && d=60; sleep $d; continue; fi
# 12:1xZ 8 Oct 2026 (shipper): a box still re-walking at the minute waits for its own restart until its state reads right. move.json may carry
# "require_root": {"height":"0x6687","root":"0x3f53a7b9"}: the box's own EVM (EVM_PORT from env-last, default 26790) must answer that root
# at that height before this box applies; otherwise HELD (posted once every 10 minutes) and re-checked each minute. No EVM answer = held too.
# 15:0xZ 8 Oct 2026 (node lane, the acaf08b0 move): "require_replay_done": true holds a box whose executor has not reached its sink since
# the node's last start (the log's last of "replaying from genesis"/"no snapshot to resume" vs "records up to the tip N are continuous")
if [ "$(jq_ $M/move.json require_replay_done)" = "True" ] || [ "$(jq_ $M/move.json require_replay_done)" = "true" ]; then
last=$(grep -anE 'replaying from genesis|no snapshot to resume from|records up to the tip [0-9]+ are continuous' $F/dn3-node.log 2>/dev/null | tail -n 1)
case "$last" in *"are continuous"*) ;; *) hl=$M/held-replay-$id-stamp; if [ ! -f $hl ] || [ $(( $(date +%s) - $(stat -c %Y $hl) )) -ge 900 ]; then post "FLEET MOVE $id HELD $LABEL" "replay not done: $(echo "$last" | cut -c1-120)"; touch $hl; fi; sleep 60; continue;; esac
fi
rh=$(jq_ $M/move.json require_root.height); rr=$(jq_ $M/move.json require_root.root)
if [ -n "$rh" ] && [ -n "$rr" ]; then
ep=$(grep -oE '^EVM_PORT=.*' $M/env-last 2>/dev/null | head -n 1 | cut -d= -f2 | tr -d "'\""); ep=${ep:-26790}
blk=$(curl -s -m 8 -X POST -H 'content-type: application/json' --data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getBlockByNumber\",\"params\":[\"$rh\",false]}" http://127.0.0.1:$ep 2>/dev/null)
got=$(echo "$blk" | grep -oE '"stateRoot":"0x[0-9a-f]+"' | cut -d'"' -f4); gh=$(echo "$blk" | grep -oE '"hash":"0x[0-9a-f]+"' | head -n 1 | cut -d'"' -f4); rhash=$(jq_ $M/move.json require_root.hash)
if [ "${got:0:${#rr}}" != "$rr" ] || { [ -n "$rhash" ] && [ "${gh:2:${#rhash}}" != "$rhash" ]; }; then
hl=$M/held-$id-stamp; if [ ! -f $hl ] || [ $(( $(date +%s) - $(stat -c %Y $hl) )) -ge 600 ]; then post "FLEET MOVE $id HELD $LABEL" "block $rh reads hash ${gh:2:8} root ${got:-none}, wanted ${rhash:-any}/$rr (re-walk not done); re-checked each minute"; touch $hl; fi
sleep 60; continue
fi
fi
# THE MINUTE: node and miner together, from the running box-dn3.sh's own environment
pid=$(cat /root/fleet/pids/loop.pid 2>/dev/null); [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null || pid=$(pgrep -of '[b]ash in/box-dn3.sh')
# the restart environment: the running box-dn3.sh's (never MINER_ONLY: a loop restarted alone carries it, and it would leave the node down), else env-last (written by every hand start since 21:4xZ 7 Oct 2026)
if [ -n "$pid" ]; then tr '\0' '\n' < /proc/$pid/environ | grep -E '^[A-Z_][A-Z0-9_]*=' | grep -vE '^(PWD|OLDPWD|SHLVL|_|TERM|SHELL|LS_COLORS|HOSTNAME|SSH_[A-Z_]+|LANG|LC_[A-Z_]+|LOGNAME|USER|MAIL|MINER_ONLY)=' > $M/env-$id; else log "no running box-dn3.sh; using last env"; [ -f $M/env-last ] && grep -vE '^MINER_ONLY=' $M/env-last > $M/env-$id; fi
[ -s $M/env-$id ] || { post "FLEET MOVE $id FAILED $LABEL" "no box-dn3.sh environment to restart from"; touch $M/applied-$id; sleep 60; continue; }
cp $M/env-$id $M/env-last
RPC=$(grep -E '^RPC_PORT=' $M/env-$id | cut -d= -f2); RPC=${RPC:-26610}
bash $F/in/fleet-stop.sh all >/dev/null 2>&1; sleep 2
true
cd $F/in && NB=$(grep -oE '^NODE_BIN=.*' $M/env-last | cut -d= -f2 | tr -d "'\"" | xargs -n1 basename 2>/dev/null); NB=${NB:-igneumd-0322}; MB=$(grep -oE '^MINER_BIN=.*' $M/env-last | cut -d= -f2 | tr -d "'\"" | xargs -n1 basename 2>/dev/null); MB=${MB:-igneum-miner-0322}; mv -f $NB $NB.pre-$id 2>/dev/null; mv -f $MB $MB.pre-$id 2>/dev/null
cp $M/$id/igneumd $NB && cp $M/$id/igneum-miner $MB && chmod +x $NB $MB; cd $M
APPDIR_LOG=$(grep -oE '^APPDIR=.*' $M/env-last 2>/dev/null | head -n 1 | cut -d= -f2 | tr -d "'\""); APPDIR_LOG=${APPDIR_LOG:-dn3} # 17:1xZ 8 Oct: the marker and the read-back follow the env's APPDIR (devnet-4 logs to dn4-node.log; the 16:50Z APPLIED lines read version= digest= empty for this)
mk="=== fleet move $id $(date -u +%T)"; echo "$mk" >> $F/$APPDIR_LOG-node.log
# every value quoted before sourcing (09:05Z 8 Oct 2026: a bare NET_ARGS=--devnet --devnet-suffix=3 line ran "--devnet-suffix=3" as a command and nine boxes came up with no node)
python3 - "$M/env-$id" <<'PY' > $M/env-$id.quoted
import sys, shlex
for line in open(sys.argv[1]):
line=line.rstrip("\n")
if "=" not in line or not line.split("=",1)[0].replace("_","").isalnum(): continue
k,v=line.split("=",1); v=v.strip()
if len(v)>=2 and v[0]==v[-1] and v[0] in "'\"": v=v[1:-1]
print(f"{k}={shlex.quote(v)}")
PY
(cd $F && set -a && . $M/env-$id.quoted && set +a && setsid nohup bash in/box-dn3.sh </dev/null >/dev/null 2>&1 &)
want_v=$(jq_ $M/move.json want_version); want_d=$(jq_ $M/move.json want_digest); rb=""; APPDIR_LOG=$(grep -oE '^APPDIR=.*' $M/env-last 2>/dev/null | head -n 1 | cut -d= -f2 | tr -d "'\""); APPDIR_LOG=${APPDIR_LOG:-dn3} # 16:0xZ 8 Oct: devnet-4 logs to dn4-node.log
for i in $(seq 1 18); do sleep 10
v=$(awk -v m="$mk" '$0==m{f=1} f' $F/${APPDIR_LOG:-dn3}-node.log | grep -oE 'igneumd/[0-9]+\.[0-9]+\.[0-9]+-[0-9a-f]+' | tail -n 1); d=$(awk -v m="$mk" '$0==m{f=1} f' $F/${APPDIR_LOG:-dn3}-node.log | grep -o 'digest: [0-9a-f]*' | tail -n 1 | cut -c9-24)
w=$(/opt/igneum/pkg/bin/igneum-miner watch 1 grpc://127.0.0.1:$RPC 2>/dev/null | grep -oE 'blocks=[0-9]+|peers=[0-9]+|synced=[a-z]+' | tr '\n' ' ')
[ -n "$v" ] && [ -n "$d" ] && case "$w" in *synced=true*) [[ "$w" != *peers=0* ]] && break;; esac
done
m=$(pgrep -fc "igneum-miner(-0322)? mine grpc://127.0.0.1:$RPC "); ok=MISMATCH; [ "$v" = "$want_v" ] && [ "$d" = "$want_d" ] && ok=MATCH
fp=$(grep -oE 'igneum-pow fingerprint [0-9a-f]{16}[^ ]*' $F/dn3-node.log 2>/dev/null | tail -n 1); fpb=$(grep -aoE 'IGNEUM_POW_FINGERPRINT=[0-9a-f]{16}' $M/$id/igneumd 2>/dev/null | head -n 1); fp="${fp:-igneum-pow fingerprint none} binary ${fpb:-IGNEUM_POW_FINGERPRINT=none}" # 12:5xZ 8 Oct (shipper): the freeze's crate fingerprint from the node's start line; another value is a stop
post "FLEET MOVE $id APPLIED $LABEL $ok" "version=$v digest=$d $w miner_procs=$m want=$want_v/$want_d rpc=$RPC ${fp:-igneum-pow fingerprint none}"
touch $M/applied-$id; log "applied $id $ok $v $d $w"
# 12:2xZ 8 Oct (node lane): bans persist in the node's DB; once this box's state at the reference block reads equal, unban every address it holds
if [ -n "$rh" ] && [ -n "$rr" ]; then ( cd /root/fleet && EVM_PORT=$(grep -oE '^EVM_PORT=.*' $M/env-last | cut -d= -f2 | tr -d "'\"") RPC_PORT=$RPC setsid nohup bash in/unban-all.sh "$rh" "$rr" "$rhash" </dev/null >> $M/unban.out 2>&1 & ); fi
sleep 60
done

13
tools/fleet/fleet-stop.sh Executable file
View file

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# 15:3xZ 8 Oct 2026 (main: kills by pid file only, never by name): stops the box's Devnet 3 pieces by the pids box-dn3.sh wrote under
# /root/fleet/pids: fleet-stop.sh miner | node | loop | all. The miner process itself is the miner-loop's child (read from the loop pid).
P=/root/fleet/pids; what="${1:-all}"
kp(){ f=$P/$1.pid; [ -s $f ] || return 0; pid=$(cat $f); kill -0 $pid 2>/dev/null || { rm -f $f; return 0; }; kill ${2:--TERM} $pid 2>/dev/null; sleep ${3:-1}; kill -0 $pid 2>/dev/null && kill -9 $pid 2>/dev/null; rm -f $f; echo "stopped $1 pid $pid"; }
kids(){ [ -s $P/$1.pid ] && pgrep -P $(cat $P/$1.pid) 2>/dev/null; }
case "$what" in
loop) kp loop -9 0;;
miner) for c in $(kids miner-loop); do kill -9 $c 2>/dev/null; for g in $(pgrep -P $c 2>/dev/null); do kill -9 $g 2>/dev/null; done; done; kp miner-loop -9 0;;
node) kp node -TERM 6;;
all) kp loop -9 0; for c in $(kids miner-loop); do kill -9 $c 2>/dev/null; for g in $(pgrep -P $c 2>/dev/null); do kill -9 $g 2>/dev/null; done; done; kp miner-loop -9 0; kp node -TERM 6;;
esac
echo "left: node=$(pgrep -fc '[a]ppdir=/root/fleet/dn') miners=$(pgrep -fc '[i]gneum-miner(-0322)? mine') loops=$(pgrep -fc '^bash in/box-dn3.sh')"

3
tools/fleet/kill-node.sh Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
# kill-node.sh <sha>: stops the box's node through its pid file only (founder 8 Oct 2026); the sha argument is kept for the callers' form and read back, not matched.
. /root/fleet/in/pidkill.sh; kill_pidfile node -TERM 4; true

View file

@ -78,7 +78,7 @@ class Box:
return f"{F}/in/{name}"
# ---- node ----
def stop_node(self):
self.run(f"pkill -f '[/]root/fleet/in/igneumd|[/]opt/igneum/pkg/bin/igneumd'; sleep 3; pkill -9 -f '[/]root/fleet/in/igneumd|[/]opt/igneum/pkg/bin/igneumd' 2>/dev/null; true", 40)
self.run(f"bash {F}/in/fleet-stop.sh node >/dev/null 2>&1; . {F}/in/pidkill.sh; kill_pidfile node -TERM 3; true", 40) # by pid file only (founder 8 Oct 2026)
def start_node(self, binary, override_local, peers, devnet_suffix=None, verifier=None, extra=(), appdir=None, log=None, unsynced_mining=False):
"""Writes the override file, kills the old node (anchored on its path), starts the new one; returns the digest it prints."""
appdir = appdir or (f"{F}/dn2" if devnet_suffix else f"{F}/node"); log = log or (f"{F}/dn2-node.log" if devnet_suffix else f"{F}/node.log")
@ -132,11 +132,11 @@ class Box:
log = log or f"{F}/out/miner-{device}.log"
self.check(f"cd {F}/mine 2>/dev/null || mkdir -p {F}/mine/packs && cd {F}/mine; [ -d packs/{pack} ] || {B}/igneum-miner export-pack {grpc} packs/{pack} >/dev/null 2>&1; setsid nohup {B}/igneum-miner mine {grpc} 1 100000000 {shlex.quote(label)} --worker {B}/igneum-worker-cuda --worker-args '--device {device} --pack packs/{pack}' --prepare-packs packs/prepare-{device} --exit-on-seed-change --evm-address {wallet} --payout-label {shlex.quote(label)} --status-secs 30 </dev/null >> {log} 2>&1 & echo $!", 90)
return int(self.run("pgrep -x igneum-miner | tail -1", 20)[1].strip() or 0)
def stop_miners(self): self.run("pkill -x igneum-miner; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda'; true", 30)
def stop_miners(self): self.run(f"bash {F}/in/fleet-stop.sh miner >/dev/null 2>&1; . {F}/in/pidkill.sh; kill_pidfile miner; true", 30) # by pid file only
def start_prover(self, label, wallet, hub_peer="", threshold="", miner="keep"):
self.check(f"cd {F} && chmod +x in/box-prover.sh && LABEL={shlex.quote(label)} WALLET={wallet} HUB_PEER={hub_peer} THRESHOLD={threshold} MINER={miner} setsid nohup in/box-prover.sh </dev/null >/dev/null 2>&1 & echo started", 60)
def stop_all(self):
self.run(f"bash {F}/in/box-kill.sh >/dev/null 2>&1; pkill -f '[p]ython3 -u /root/fleet/in/box-prover.py'; pkill -x igneum-miner; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda'; pkill -x sp1-gpu-server; true", 60)
self.run(f"bash {F}/in/box-kill.sh >/dev/null 2>&1; true", 60) # box-kill.sh stops by pid files
# ---- provider ----
def destroy(self):
import sys; sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Kills by pid only (the founder, 8 Oct 2026, by construction: pkill and killall exit 97 on every box and pod).
# kill_pidfile NAME [SIG] [WAIT] the pid in $F/pids/NAME.pid (TERM, then KILL after WAIT s); removes a stale file
# kill_children PID [SIG] every descendant of PID by pid (pgrep -P walks the tree by parent pid, not by name), deepest first
# kill_sock_owner GLOB the pid that owns a listening unix socket matching GLOB (ss -xlp), written to $F/pids/sp1-server.pid, then killed
F=${F:-/root/fleet}; mkdir -p $F/pids
kill_pidfile() { local f=$F/pids/$1.pid p; [ -s "$f" ] || return 0; p=$(cat "$f"); kill -0 "$p" 2>/dev/null || { rm -f "$f"; return 0; }; kill ${2:--TERM} "$p" 2>/dev/null; sleep ${3:-2}; kill -0 "$p" 2>/dev/null && kill -9 "$p" 2>/dev/null; rm -f "$f"; return 0; }
kill_children() { local c; for c in $(pgrep -P "$1" 2>/dev/null); do kill_children "$c" "$2"; kill ${2:--TERM} "$c" 2>/dev/null; done; return 0; }
kill_sock_owner() { local p; for p in $(ss -xlp 2>/dev/null | grep -E -- "$1" | grep -oE 'pid=[0-9]+' | cut -d= -f2 | sort -u); do echo "$p" > $F/pids/sp1-server.pid; kill -TERM "$p" 2>/dev/null; sleep 1; kill -0 "$p" 2>/dev/null && kill -9 "$p" 2>/dev/null; done; rm -f /tmp/sp1-cuda-*.sock; return 0; }

View file

@ -84,7 +84,7 @@ def update(label):
"""The version follow: the manifest's hive package onto the box, the node pointer rewritten, the supervisor restarts it."""
m = manifest(); b = Box.from_registry(label)
if not m: raise SshError("no manifest")
rc, out, err = b.run(f"set -e; cd {F}; curl -fsSL -m 600 -o pkg-{m['version']}.tgz https://dl.igneum.network{m['path']}; echo '{m['sha256']} pkg-{m['version']}.tgz' | sha256sum -c - >/dev/null; rm -rf /opt/igneum/pkg.new; mkdir -p /opt/igneum/pkg.new; tar -C /opt/igneum/pkg.new --strip-components=1 -xzf pkg-{m['version']}.tgz; rm -rf /opt/igneum/pkg.prev; mv /opt/igneum/pkg /opt/igneum/pkg.prev; mv /opt/igneum/pkg.new /opt/igneum/pkg; echo /opt/igneum/pkg/bin/igneumd > {F}/standing.node; pkill -9 -f '[/]opt/igneum/pkg/bin/igneumd' 2>/dev/null; pkill -9 -f '[/]opt/igneum/pkg.prev/bin/igneumd' 2>/dev/null; echo updated-to-{m['version']}", 900)
rc, out, err = b.run(f"set -e; cd {F}; curl -fsSL -m 600 -o pkg-{m['version']}.tgz https://dl.igneum.network{m['path']}; echo '{m['sha256']} pkg-{m['version']}.tgz' | sha256sum -c - >/dev/null; rm -rf /opt/igneum/pkg.new; mkdir -p /opt/igneum/pkg.new; tar -C /opt/igneum/pkg.new --strip-components=1 -xzf pkg-{m['version']}.tgz; rm -rf /opt/igneum/pkg.prev; mv /opt/igneum/pkg /opt/igneum/pkg.prev; mv /opt/igneum/pkg.new /opt/igneum/pkg; echo /opt/igneum/pkg/bin/igneumd > {F}/standing.node; bash /root/fleet/in/fleet-stop.sh node >/dev/null 2>&1; bash /root/fleet/in/fleet-stop.sh node >/dev/null 2>&1; echo updated-to-{m['version']}", 900)
iid, _ = Registry.find(label); Registry.patch(iid, version_wanted=m["version"], updated_at=now()); return out.strip()
def rerent(label):
"""Same shape again on the same provider; the old row is marked destroyed. Returns the new label or None."""

View file

@ -9,7 +9,7 @@ live=[r["label"] for r in standing.roster() if r["role"]=="live"]
def move(l):
try:
b=Box.from_registry(l); b.put([F16], "/root/fleet/override-16.json")
rc,out,err=b.run("cd /root/fleet && cp override.json override-13.json && cp override-16.json override.json && python3 -c \"import json; d=json.load(open('/root/fleet/override.json')); print('fields', len(d))\" && pkill -9 -f '[/](opt/igneum/pkg/bin|root/fleet/in)/igneumd(-0313|-[0-9a-f]{16})? --devnet --appdir=' ; echo killed-for-restart $(date -u +%T)", 60)
rc,out,err=b.run("cd /root/fleet && cp override.json override-13.json && cp override-16.json override.json && python3 -c \"import json; d=json.load(open('/root/fleet/override.json')); print('fields', len(d))\" && bash /root/fleet/in/fleet-stop.sh node >/dev/null 2>&1; ; echo killed-for-restart $(date -u +%T)", 60)
return l, out.replace("\n"," ").strip()+(" ERR "+err[:60] if err.strip() else "")
except Exception as e: return l, "EXC "+str(e)[:60]
print(st(), "moving", len(live), "boxes", flush=True)

View file

@ -0,0 +1,6 @@
# Retired fleet scripts (8 Oct 2026)
Devnet 2 and 0.3.1x-era scripts that stop processes by name (pkill -f / pkill -x). Since the founder's word of 20:21 BST 8 Oct 2026
every box and pod refuses pkill and killall by construction (exit 97), so none of these can run as written; they are kept for the
record only. The live stop forms are tools/fleet/fleet-stop.sh (pid files under /root/fleet/pids), tools/fleet/lib/pidkill.sh
(kill_pidfile, kill_children, kill_sock_owner) and tools/fleet/box-kill.sh.