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>
The fleet's segment exports (50 to 500 MB each with the old [0, last] export, never pruned) filled 42 GB on the hub
(586 segment dirs, 60 GB disk, 100 percent) and 3 to 46 GB on every standing box between about 13:00Z and 20:44Z on
6 October 2026, 4 to 6 GB an hour a box; the hub's node died on the full disk at 20:42:31Z (its two earlier deaths
at 19:58:08Z and 20:01:55Z were the sync KeyNotFound). The app's prover now:
- enforces a cap on <app dir>/proving before every export: entries older than IGNEUM_PROVING_DIR_MAX_DAYS (7) go,
then the oldest until the total is under IGNEUM_PROVING_DIR_MAX_GB (20); the plan is a pure function with a
unit test (provingdir::prune_plan); the defaults leave 80 GB of a 100 GB box to the node and the system
- skips the export with a logged line when the disk is under 10 percent free (statvfs on unix, GetDiskFreeSpaceExW
on Windows), and the Prove page says so
- deletes a segment's directory (fixtures, proofs, logs) the moment its record is submitted, on the first try or on
a retry; seq.json was already removed after the cut
The fleet's kit (box-prover.py, gpu-fleet 86c9854) carries the same rule on the boxes since 20:5xZ.
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>
PC 1 on 0.3.14 (6 October 2026, 18:16Z, block 140,662): "segment 140661: port state root 0xe45c... differs from the
node's 0xddd7...". The export was [140661, 140662] with the dump; the 0.3.14 exporter seeds from segment 140,661 and
never replays it, so the only exporter that replays 140,661 (from the restart state, hence the mismatch) is the one
from before 0.3.14: the installed binary was not replaced, the same class as the stale verifier host. The prover's
failure line now names the stale exporter by path when the export carries preState and the output has no "account
dump" line (exporter_failure, unit-tested with the PC 1 text); the real line stays when the exporter did read the dump.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Variant C and the Earnings reshaping reverted: Mine and Earnings are exactly as shipped in 0.3.14. Kept from the
polish round: every strip, ask and clock card on the brand tokens (the row surface, a 1 px ember hairline on top,
ash text, ember only on the dot and the chevron; no filled brown or mustard field anywhere; the update strip and the
job strip share .notice), the plain-language strip and event sentences with the technical line behind the chevron,
the header baseline and the pill wording. 36 UI tests pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>