A node before the exec RPC bounds fix (every 0.3.17 node) dies when a method that resolves a block number or indexes the record vector is asked while its exec follower holds no record; PC 1 crash-looped on two callers in one night (eth_getBlockByNumber from the clock sample, then igneum_getAssignedShards from the prover loop: 'panicked at igneum/exec/src/rpc.rs:808:35: range start index 1 out of range for slice of length 0'). Every caller (prover.rs's evm_rpc, update.rs's clock sample, extnode's rpc for chainfacts and the external-node probe) now goes through execrpc::call: SAFE_ON_EMPTY methods go out, GATED ones wait for igneum_getExecStatus's executedTipHash, an unclassified method is refused. The test every_caller_goes_through_the_gate scans src/ for JSON-RPC requests built elsewhere and for unclassified exec method names.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The 0.3.18 clock-sample gate stopped one caller; the prover's first igneum_getAssignedShards after the node reads synced killed PC 1's 0.3.17 node the same way (rpc.rs:808, records[1..=0] on an empty vector) because its follower loads after the sync flag. The loop now waits on igneum_getExecStatus's executedTipHash, the same gate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
View: poisson, ignPerDay, ladderRungs (every threshold from the node's params: dust, weightWindow, presenceWindow),
blockCard, earningsLines (IGN first, the typed price never fetched, the share and rank, IGN per kWh), cardIgnDay,
timeline, profileWords; FIELDS names every number's RPC field for the title on hover. Overview: the Poisson
count-up until the first block, the block card in place with Save the card (a canvas PNG, no network call), Copy the
link and the explorer, the ladder strip. Earnings: the six lines, the ladder card, Your first hour. Prove: the shard
card. Cards: IGN a day per card. Settings: Make my page public. The chain scene is the site lane's EMBER 02 pack
(live-dag.js and proof-core.js byte-identical): the compact card fed by the page's own api/live read, Inspect opens
the full scene with the block inspector in the site's words. ui-mock: scenarios firstwait, firstblock, ladder,
api/ladder, api/card. view.test.mjs: a Devnet 2 key walks every rung; 47 UI tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
src/ladder.rs: this machine's record (first block by card, hash joined to the miner's ACCEPTED line by nonce from the
node's PoW accepted line, blocks per UTC day, VOTE and LOCK lines as the signing record and streak, paid shards, the
milestone at 1, 100, 1,000, every 10,000th and the first block of a new card, the first-hour marks); persisted, in
api/state.ladder. src/chainfacts.rs: GET /api/ladder, getFinalityWeights through the node's EVM port when it answers
igneum_getFinalityWeights (owed), else the observer's relay plus /api/stats; this machine's keys ranked; the source
named. src/card.rs and POST /api/card: the page's 1200x630 PNG written under <data root>/cards/ and revealed.
settings.profile_public behind api/settings. Hooks in engine.rs (block, node line, vote, lock, synced, mining) and
prover.rs (paid shard). Box: 190 + 27 + 8 tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A node before 0.3.18's exec RPC fix dies on eth_getBlockByNumber when its exec follower holds no record (rpc.rs indexes records[0] on an empty vector; the panic hook exits the process), and this sample ran every 9 s once blocks arrived, so a fresh install's IBD and PC 1's restart crash-looped. The sample now waits for executedTipHash. No node change; the pin stays at 5899f603. Version 0.3.18 on the 0.3.17 app tree.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PC 1's read-back: the node reported synced while its finality replay blocked the template RPC for three minutes; the miners printed only timeouts and the watchdog faulted every card. The timeout line is the miner's heartbeat: silence clocks start over from it, the card says it waits for templates, one Activity line per episode. Recorded sequence as the test; 173 box tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The card watchdog judges a miner only while the node is synced; a silence fault from the node's sync is released at the synced transition and the card starts again with an Activity line; a worker silent from its start is faulted at 60 s; one Activity line per card at its first start. Known-failed test from PC 1's 04:51Z relaunch; 173 box tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Main's rule 7 October 2026 03:3xZ: the version scheme is three-part everywhere, so the hotfix (f1ea7a38 plus the IBD-guard fix) ships as 0.3.17; the feature tree becomes 0.3.18, decimals 0.3.19.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
src/merge.rs, pure: every network sink more than the merge depth ahead and none of our blocks in the network's view for 120 s. Engine polls the observer's view every 30 s while mining and runs the check after sync_decision_v2; state behind, sync_cause not merging, one error event. Known-failed test first; 172 box tests, 42 UI tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The mode (own | external | none) is re-decided every 5 s while the app reads or refuses another node; gone for 60 s, the app starts its own node and says so in Activity. node.mode and node.mode_reason in api/state and on the Node details. Pure extnode::step with the goes-away test first.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
View.finalityWords with Ember's test (41 UI tests). extnode reads the node lane's reply shape: params compared value by value, network must match, a stub engine is refused and a fault on the app's own node. 168 box tests green.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
engine::sync_decision_v2 gates the old decision on the watch line's tip_age_s (<= 120 s; -1 on an older node gates
nothing) and peers >= 1, with the cause word frozen | no peers | syncing | behind on node.sync_cause; the node state
reads 'behind' or 'no peers', never 'synced' on a tip that stopped moving. engine::is_stall_exit: code 45 or a
"STALLED '" tail line (the node lane, ca3-v4-0316); the first restarts the miner, the second since the node started
restarts the node and re-dials its peers (restart_node). The known-failed case is the first test: the old rule says
synced on a tip frozen 3,180 s with one peer. UI: 'Node behind · 1 peer · 133,000 blocks · last block 53 min ago'
with the cause line, 'Node no peers', the pill 'Node behind' in ember, the big button 'waiting: the node is behind
the chain'. 39 UI tests pass; the app crate's tests run on the box.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Mac and PC 1 took earlier 0.3.15 builds (nodes 713ef876 and 7961c5f1) through deploys of the shared downloads folder before the publish; the updater compares version strings only, so the number moves them to the final build. Node pin unchanged at f1ea7a38.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Main's rule of 6 October 2026 from the 0.3.14 repro (docs/evidence/reproduced/0.3.14.md): prost's protowire.rs embeds OUT_DIR,
libmimalloc-sys embeds __DATE__/__TIME__, sccache hid both. lib.sh bs_repro_env exports SOURCE_DATE_EPOCH=<author time> TZ=UTC in
front of every remote command (build-remote.sh, cross-remote.sh, workers-remote.sh); remote-run.sh exports BR_SDE too and logs it
as source_date_epoch; proto-cuda/windows-node/cross-build.sh exports the same; the PC job carries node.commit_time in the manifest
(push-build-inputs.sh) and exports it before every cargo build of a stage (jobbuild.rs, unit test asserts it; 4 of 4 pass on the
box). Target dirs stay one fixed path per target. tools/build-remote.sh --self-test-repro [--full] from a fork worktree, run on
the box: igneum-miner twice a minute apart without sccache (RUSTC_WRAPPER=/usr/bin/env, an empty value is unset to cargo) MATCH
91e130f5..., a per-run target path differs (OUT_DIR shown); --full: kaspad with libmimalloc-sys recompiled a minute later MATCH
70219bc2..., without the epoch differs (__DATE__ shown).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The site agent committed the module at 3e5a880; the app's copy now matches it exactly (the earlier copy was taken
from the working tree before the commit). Same contract; quieter colours (chain in ember, included in bone, pending
in ash), opts.mine, opts.poll:false with dag.push.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Main's correction: the app uses the same words as the site, the litepaper and the ledger for the chain's own objects,
or users cannot match the app to the docs. Shard (not piece), segment (not run of blocks, 'runs of 8 blocks' as the
explanation), checkpoint and 'locked checkpoint' (not lock point), aggregator (not combiner), verifying (not checking
proofs). Card, app, Default · Balanced, the Ember Tune strip, the state words and the one-sentence rule stay. 37 UI
tests pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every file under app/igneum-app/ui/ is that branch's side; outside ui/: src/live.rs (new), the /api/live route, mod live, ota.rs's live_api_from made pub, the copy table and the reshot screenshots.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
src/live.rs reads the observer's /api/live through curl (the URL ota.rs already polls), caches it 2 s per window,
marks this machine's blocks as the lane 'you' by matching the miner id against every card's vote-key ids, and
answers {ok:false} when the observer is unreachable so the UI draws its own strip; four unit tests shape a fixture
in the observer's reply shape. The local node speaks gRPC and wRPC only, so a local-node source stays owed.
The copy sweep: no fleet, lane, identities, prior, hill climb, sweep, DAA, digest, manifest, shard, segment,
aggregator, verifier, worker or engine on a user surface; every toast and event line one sentence; the full list
in docs/plans/miner-ui-4-copy.md. The per-card goal's inherit option reads 'Default · Balanced' and follows the
shared goal; the cap's unpin is 'Back to Default'; the Cards strip is titled Ember Tune; each goal carries its
meaning as a tooltip. 37 UI tests pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every file under app/igneum-app/ui/ is that branch's side, per the merge rule; outside ui/: the GET /live-dag.js route in server.rs, the ui-mock's synthetic /api/live, the plan and its screenshots. .gitignore: the shipper's local test target dir and the build box's artefact dir.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rail: Overview, Cards, Earnings, Prove, Settings. Overview: the fleet rate at 84 px on the fade with W, £ a day and
blocks, Start/Stop as the bar under it, the site's live-dag.js on the engine's api/live with this machine's lane as
'you' (the app's blocks strip as the fallback until the engine serves api/live), the node line, the activity feed.
Cards: the Tuning strip (goal with its £ a day, the fleet saving in W and £, Tune all, the schedule, Power control
when off), the rows with a flame mark that fills with the tune's progress, before -> after watts, a sparkline of the
ladder, 'Tuned 2 h ago · 2470 MHz at 80% · next check Sunday · saves 84 W, 0.16% of rate', Retune, and under the
chevron the cap, the card's own goal, the curve with the chosen point ringed. Reads Ember's tune_before_watts,
tune_before_mhs, tune_goal, sweep_watts, sweep_mhs, tune_curve. Rust: one route, GET /live-dag.js. The ui-mock gains
/api/live. 37 UI tests pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The 0.3.13 engine on PC 1 ran update-now-0313-switch at 15:43Z, found nothing newer, and install_asked stayed true; when 0.3.14's manifest arrived at 17:47Z the moment was urgent and safe_to_apply returned Ok before the slot, the patience and the busy rule, so the install went under a measurement job. Now Moment carries job_active (jobs.active(), separate from miner_busy) and safe_to_apply holds on it first; the Checked branch that finds this version current clears install_asked. Tests: urgent under an active job is held, the same with the slot closed; urgent with no job still goes. CLAUDE.md job rule row.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
override-60x.json keeps master's side (the rehearsal object with the fresh-rule dedup) plus exec_restart_state_root; docs/bench-log.md is the union of both sides.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>