The Notices block takes the hot-plug notices as on gpu-hotplug (card added, not usable, removed). The View block
and the Mine rows, the first-run rows and the Settings cards show a removed card (dimmed, no switch, the row goes
after five minutes) and a faulty card (named in ember, the OS problem code, the reboot hint, no switch); the big
button and the counts take only present cards; the name tooltip carries the tool's code, the device, the platform
and the PCI address. view.test.mjs covers the two states. host.cpp keeps both the WM_GETMINMAXINFO and the
WM_DEVICECHANGE cases.
Build tooling: push-build-inputs.sh and build-job.mjs take --no-node (the app engine only, no node source, no node
build, no node tests), for an app-only PC compile.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
From 18:23Z both Windows workers (CUDA on PC 1 and PC 2, OpenCL on PC 1 after the 18:34Z node restart)
refused every pack for epoch 34 with "the epoch seed bytes do not give the pack's IGNEUM_SEEDW_INIT", and
the miner and the app restarted them every 5 to 60 s until 18:44Z and beyond. The packs were correct.
The generator retries a rejected candidate with seed || k_le32 (attempt_words); epoch 34's attempt 0 was
rejected (246 of 16384 final register values saturated, limit 163) and attempt 1 accepted, so the pack
carried attempt 1's words while pf_load (proto-cuda/nvrtc/packfile.h) derived the expected words from
the bare seed. Both workers also matched jobs to pairs by those bare-seed words, so even a loaded pack
of a retried program would have answered "epoch seed mismatch" on every job.
The rule, in one place per language:
- packfile.h: pf_program_words(bytes, attempt); pf_load reads IGNEUM_PROGRAM_ATTEMPT and checks the
attempt's words; the refusal says "program pack and its seeds disagree: IGNEUM_SEEDW_INIT is not
attempt N of the epoch seed ..." in plain words.
- worker.cpp and proto-opencl/host.c: a job belongs to a pair when the seed hex the node sent is the
pair's (pairIs); the compiled-in placeholder pack keeps the word comparison.
- igneum-pow/src/packcheck.rs: verify_pack_texts / verify_pack_dir, the same rule in Rust; the miner
checks every pack it writes with it before a worker sees it (vendor/igneum-node pack-loop branch).
Tests pin the attempt vectors of epoch 34 on both sides (one vector, two implementations), that
epoch 34 is attempt 1 and epoch 33 attempt 0, a known-good pack of a later attempt, a known-mismatched
(out of date) pack, and self-contradicting packs.
- proto-cuda/nvrtc/emu/packfile-test.c (+ .sh, in CI): pf_load on a known-good attempt-1 pack, the
checked-in attempt-0 pack, and the known-mismatched bare-words pack.
The app (app/igneum-app):
- watchdog.rs: PACK_OUT_OF_DATE_CODE 44, PackRebuilds (at most 3 pack exports per epoch, then the card
shows the reason), pack_refusal (the worker's "error 0 pack" line and the miner's "PACK OUT OF DATE"
line), pack_epoch_of; tests on the incident lines, known-good and known-mismatched.
- engine.rs: exit 44 exports the pack again before the restart instead of a blind restart, the strip
says "program pack out of date, rebuilding", the card and the log name the condition; at the cap the
card is marked failed with the reason and tries again in 10 minutes.
The relay (relay/lib/parse.mjs): PACK_MISMATCH; the card reads "pack mismatch, rebuilding (N refusals
in the tail, M restarts)" in `node tools/console.mjs machines` instead of a bare restart count; tests
on the PC 2 tail of 18:27Z and a healthy tail.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The one long page becomes a rail with six sections, a thin top bar and the status strip under it; the setup
screens and the key sheet stay. Mine: one big start/stop, the numbers, one row per GPU with its switch, hash
rate, temperature and power. Prove: the switch with plain words, the counts, the verifier, the pinned ids.
Rewards: the address with one Copy, the key backup card, another address. Node: the plain lines, the consensus
digest, the next switch. Updates: the version, the jobs. Settings: one switch or slider per setting with one line
of help. Every function that existed is placed, none removed.
Engine (three small additions, each with a unit test): node.consensus_digest from the node's own line,
node.consensus_switches from the override file, proving.program_id and aggregator_id from the host's --mode id.
Hosts: the window minimum is 900 x 600 on both. UI tests: view.test.mjs (10) joins notices and update-card in CI.
Proof: docs/plans/miner-ui-2.md and the 19 screenshots under docs/plans/miner-ui-2/, taken from a build of this
tree running on its own port against the devnet.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PC 1 after Adrenalin 26.9.2 (5 October 2026): two AMD ICDs each listed the iGPU and the RX 9070 XT, so the 0.3.9
app showed five rows for three GPUs (gfx1036, gfx1201, gfx1036, gfx1201 plus the 5090), ran two workers on the one
9070 XT at 9 MH/s each, called the iGPU discrete, and re-enabled it when its key moved from amd:1:gfx1036 to
amd:0:gfx1036.
detect.rs: the Windows path is a pure assemble(Inputs) over nvidia-smi, the worker's --list and the adapter list.
dedupe_platforms keeps one entry per card per vendor: the fuller platform wins (most GPUs, then the newest driver,
then the first listed) and another platform's device survives only at a PCI address the winner lacks (without
addresses: the same code and ordinal); the dropped entries go to the log, never to a worker. resolve_name puts the
Windows adapter name on the row: by PCI bus (the adapter list now carries DEVPKEY_Device_BusNumber and Address),
else by the gfx code's PCI device ids, else by the card names in a gfx table (gfx1201, 1200, 1100, 1101, 1102,
1030, 1031, 1032, 1036, 1035, 1103, 1150, 90c, approximate), else the table's words, else the code. The code stays
in `code`, the key and the row's tooltip; the key is vendor:code with "#2" for a twin, no index. hotplug::pref_for
reads a 0.3.9 key (vendor:index:code) when exactly one matches; the diff matches by key and PCI address, then by
vendor and name or code. The iGPU is integrated and off by default; the choice survives a moved index.
proto-opencl/host.c: --list prints ", pci bb:dd.f" on the info line from CL_DEVICE_TOPOLOGY_AMD or the NVIDIA bus
and slot ids (needs a worker rebuild through proto-cuda/nvrtc/build-windows.sh and push-inputs; an old worker
still works, by code and ordinal).
Tests: detect::tests has the five-row PC 1 list as a fixture (two platforms, the three adapters with DEV_13C0,
DEV_2B85 and DEV_7550) and asserts three rows named NVIDIA GeForce RTX 5090, AMD Radeon(TM) Graphics (integrated,
off) and AMD Radeon RX 9070 XT (discrete, on, 8 identities), the keys, the console line, and the diff against the
one-platform list before the eGPU (iGPU moved, 9070 XT added, nothing removed); plus the list parser with and
without pci, dedupe with and without addresses, name resolution, twins' keys. cargo test -p igneum-app: 96 passed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The elevated launcher exited 0 after Windows cancelled an unanswered UAC prompt at 122 s (PC 1 driver job, 5 October 2026), so the job read as done. Start-Process now runs under -ErrorAction Stop in a try/catch, a missing process is exit 251, and the summary says what to do.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fork tx-gossip e242acd0 adds the inventory relay of EVM transactions (protocol version 14) and replaces the
4-second hand-out cooldown with the hold on block-added. Here: the relay paragraph in execution-layer.md 1.4,
the 10.2 table row (hand-out cooldown, now the block-added hold) and 10.3 item 9 updated, the bench-log entry
with the PC 2 suites (igneum-exec 15 of 15, kaspa-p2p-flows 33 of 33), the digest check (unchanged,
9409dedac4bf...) and the 3-node fast-time run (A - B - C, generator on A at 2/s: 240 of 240 included, B 151
and C 105 over two hops, p50 1.5 s, 0 skipped copies, pools equal on all three nodes at every sample), the
result JSON under docs/benchmarks/evm-relay-2026-10-05/, and tools/txgen/relay-net.mjs (the harness: three
nodes in a chain on the fast-time profile, vmine on B and C paid to throwaway keys, txgen on A, inclusion
counted by miner from A's executed chain).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5 October 2026: an RX 9070 XT went into PC 1 through a Sonnet USB4 box while the app ran and nothing noticed; the
app detected cards once at start. Now src/hotplug.rs compares every enumeration with the list (key, else vendor +
name when unique; a card whose tool did not answer is never called removed): a new usable card starts a worker,
enabled by default like a card at start, with "New card: <name>, mining" on the strip and in the log; a card
Windows lists with a problem code (Win32_VideoController Status / ConfigManagerErrorCode) is shown as "<name>: not
usable (Code 43)" with the reboot-or-reinstall hint and no worker; a card that disappears has its worker stopped
(quit, 8 s) and its row says removed for five minutes, then hides; an unchanged list touches nothing. The Windows
host sends "detect" on WM_DEVICECHANGE; the engine polls every 60 s (300 s on macOS, no GPU hot-plug there).
detect.rs: the Ryzen iGPU is "gfx1036" to the OpenCL worker, so the APU gfx codes count as integrated, plus the
adapter row's Intel processor string and a dedicated memory under 1 GB; integrated defaults to off with "integrated
GPU, off by default (2 to 3 MH/s for 30 W)" on the row, and the user's choice is kept across re-detections and
restarts (settings, found by key or by vendor + name when the index moved).
Console: the engine logs "cards: <name> [<kind>, <state>] | ..." at start, on every change and every 10 minutes;
relay/lib/parse.mjs reads it and the hot-plug events, the machines API and tools/console.mjs machines show them.
Tests: hotplug.rs (added, removed, moved, errored, recovered, revived, unchanged, twins, user override kept,
the console line), detect.rs (PC 1's adapter lines, the Mac, kind classification, the unusable row),
notices.test.mjs (card notices), relay parse.test.mjs (cards line). cargo test -p igneum-app: 91 passed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs/security/keys.md: every key the project depends on (the folder, the gh
keyring, the Vercel env of three projects, the GitHub secrets) with where it
lives, what it unlocks, the blast radius lost and leaked, who rotates it and
the rotation status, written from the files and the scripts that read them.
No value, no private fingerprint. Section 4: the second OTA signing key kept
offline, the app change (a key list plus revocation in the manifest), 0.3.9
as the carrier, and the emergency path if the one key leaks today (a manifest
signed with a new key is useless to 0.3.x apps; the mitigation in order).
tools/keys/backup.sh: ~/Desktop/igneum-keys-<date>.dmg, AES-256, hdiutil's
own prompt (never argv, history or a file), the folder minus build-slots,
dlsite-dir and pytools/, plus a README; attached read-only, every file
compared by sha256, listed, detached. --dry-run lists. restore.sh: --check
compares the image against the live folder without printing values, --to
copies back with 0600/0644 and 0700. test-backup.sh: the end-to-end test on a
scratch folder with a throwaway passphrase, 8 steps, passed.
tools/ci/no-secrets-check.sh, in ci.yml: no tracked file named like a key of
~/.config/igneum, no 64-hex value assigned to a token/key/secret name outside
tests and the allowlist (the OTA public key, the published Hardhat and Anvil
accounts); a --self-test fires on a known-bad tree first. 776 files, 0 hits.
Also: ~/.config/igneum, vercel/ and txgen/ are 0700 now (were 0755).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Footer partial: imprint line with the registered address and the mailbox; Report a flaw mails hello@igneum.network with the spec issues as the second route. Litepaper: Who are you names the entity that ships the software, the team is pseudonymous with no team page, the ledger and the benchmark source are public with the repository at the public testnet, the last paragraph gives the mailbox and the address. Miner: the dev fee goes to Igneum Labs LTD. Evidence (md and page): repository private until the public testnet. Trademark FILING.md: applicant Igneum Labs LTD at the DIFC address. Identity check: the ledger and fixes file join the export list; the forbidden list notes that the registered address is allowed. Site rebuilt (bench page and journey picked up the txgen log entry).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The ledger's header and submission lines, G3's status line, and the fixes file's legend, row 9, decision (b) note and section 5 record the four decisions. Two literal pattern mentions reworded so the identity check passes with both files on its export list.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>