drivertable::install_hold_keys holds every enabled card of the vendor being installed (the other vendors' cards keep mining; a card already off has nothing to stop); the row says so before the click and while it runs, with the enclosure warning kept on an external row; the toast and the engine's event name the vendor. The x1 gen1 link signature is not on the card state and was not added. Test known-failed first (the 5090 inside the case was not held for an NVIDIA install; red on build-2, then green); box gate 259 + 33 + 8; UI 51. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
9.6 KiB
Driver check: the app detects a missing or old driver and installs it on one click (branch driver-check, 7 October 2026)
the project lead: "can we package the drivers with the miner? for all cards? and the system knows which to install if not present". The answer given: not bundled (size, vendor licences, staleness), but detected and installed on one click. Built off the release-0.3.20 app tree (082f70fb) for 0.3.20's app or the next cut; every cargo build and test on the box.
1. What is built
| Piece | Where |
|---|---|
The per-vendor table, validated in the signer and the app alike (Table::parse): min_version (what the worker needs), version, the vendor's own URL, size, sha256, the page the hash was read from, the silent arguments, the exit codes that mean "restart required", the Authenticode subject word, the Linux and HiveOS package |
app/igneum-app/src/drivertable.rs (pure, shared with src/bin/ota-sign.rs), packaging/ota/drivers.json (today's table) |
The table rides the manifest: drivers object, parsed and validated with the rest, written as is to <app data>/drivers.json, re-read on every change; the app never ships a driver |
src/manifest.rs (Manifest.drivers), src/ota.rs (write_drivers, take_drivers_change, drivers_table), `packaging/ota/publish-manifest.sh --drivers |
Each card's driver version: nvidia-smi's driver_version for NVIDIA, Windows' DriverVersion (the adapter row) for AMD and Intel; CardState.driver_os |
src/detect.rs (the query, the Adapter.driver field, assemble) |
The check at first run and every detection, and on every table change: the offer per card (CardState.driver_offer: status missing, old, fine or none; the row's sentence; installable on Windows only) |
src/engine.rs (refresh_driver_offers, called from the Detected arm and tick_update) |
The click: download from the vendor's server (curl with resume into <app data>/drivers/), size and sha256 against the table, the Authenticode signature (status Valid, subject carries the vendor), then the installer through ONE elevated prompt (platform::elevated_command, the PC 1 driver job's shape), the exit code read (0 installed, a table code = restart required, else an error), "Restart now" on the row; the app never restarts by itself; nothing else pauses (the miners keep mining) |
src/drivers.rs (start_install, download, exit_code_of, restart_now), src/engine.rs (driver_install, driver_event), src/server.rs (POST api/drivers/install {vendor}, POST api/drivers/restart) |
| The row: "Install the NVIDIA driver 581.57 (965 MB). Driver 566.36 is older than the 570.00 the worker needs." with the Install button on the dashboard's card row and on the first-run card list; the progress line; "installed, restart Windows to finish" with Restart now; the error with Install again; macOS "no driver step"; Linux and HiveOS the package line, no button | ui/app.js (View.driverWords, the gl-driver strip, setupDriverHtml, the click handlers), ui/app.css |
Dry run: IGNEUM_DRIVER_DRY_RUN=1 or dry_run: true in the table: the download and every check run, the installer does not (the row says so) |
src/drivers.rs, src/engine.rs |
Tests: version compare, the table's parse and refusals, the offers per tier (missing, old, fine, Apple, Linux, HiveOS), exit codes and Authenticode verdicts, the download against a mocked vendor server (a std TcpListener on 127.0.0.1: the right sha256 passes, a wrong one is refused with the part file gone, the file in place is kept), the manifest's drivers validation; the UI's strip per state |
src/drivertable.rs tests, src/drivers.rs download_tests, ui/view.test.mjs |
The mock's scenarios for the captures: drivers, drivers-running, drivers-reboot, drivers-error, drivers-mac |
tools/ui-mock/server.mjs |
The captures (the installed Mac window's --snapshot on the mock, 1280 x 900, light and dark): docs/plans/driver-check-shots/01 to 12: the dashboard's Cards page with the offers (01, 02), the download running (03, 04), installed and Restart now (05, 06), the error (07, 08), macOS (09, 10), the first-run card list (11, 12).
2. The table today (packaging/ota/drivers.json)
| Vendor | min_version | On offer | Source | State |
|---|---|---|---|---|
| Intel | 32.0.101.9034 (the Arc driver the worker's rotate rewrite is proven on) | 32.0.101.9034, 932,631,144 bytes, sha256 72ba7eea... | downloadmirror.intel.com/929959, Intel's page 785597 (SHA512 printed there; the sha256 read on PC 1 on 7 October) | measured, live |
| NVIDIA | 570.00 (CUDA 12.8) | 617.42 (GeForce Game Ready WHQL, 6 October 2026), 990,853,168 bytes, sha256 f115c927... | us.download.nvidia.com/Windows/617.42; Authenticode CN=NVIDIA Corporation (DigiCert G4) | measured on igneum-build-2, live |
| AMD | 32.0.32000.0 (Adrenalin 25.x) | 26.9.2 (WHQL, 29 September 2026, the win11-b build), 1,000,800,840 bytes, sha256 593c1d73... | drivers.amd.com (an amd.com Referer required); Authenticode CN=Advanced Micro Devices (Sectigo) | measured on igneum-build-2, live |
Apple: none. The exit codes: Intel 14 and 1014 (the bootstrapper's wrap, measured on PC 1), NVIDIA 1 (approximate: NVIDIA's installer returns 1 for "restart required" in silent mode), AMD 3010 (the MSI code, approximate). A wrong code reads as an error on the row and the install is marked failed, never as a success; the table fixes it without an app cut.
3. Consequences per tier
| Tier | What the user sees |
|---|---|
| A home miner with a new card and no driver (Windows) | the first-run card list says "Install the driver (). No driver was found, so this card cannot mine yet." with the button; one click, one administrator prompt, the restart line if the installer asks; the other cards mine through it |
| An old driver (Windows) | the same row with "Driver X is older than the Y the worker needs"; mining on that card may already fail (the worker's self-test) and the row says why |
| macOS | "Apple silicon: no driver step, macOS carries it." in the details; no button |
| Linux, HiveOS | "Linux: install the package nvidia-driver-570 (the worker needs 570.00 or newer)." or the HiveOS line; no installer |
| A rig | one install at a time (the engine refuses a second while one runs); each card's row carries its own offer |
| A pool user | nothing changes |
Sizes: the installers are 889 MB to 1.0 GB each; the download lands in <app data>/drivers/ and stays (a second click reuses it when its sha256 still matches). Time: the download at a home line of 50 Mbit/s is 2.5 to 3 minutes; the install 1 to 4 minutes; the prompt is the only wait on the user.
3b. The vendor's cards stop for the install (7 October 2026, after PC 2; every card of the vendor since 0.3.22)
PC 2 at 16:26Z: the Intel installer started with the app's own worker mining on the Arc B580 in the Razer Core X V2. The installer's display reset took the machine down at 16:27:14Z (every log stops together; a power cycle). The rule, on this branch:
- A driver install stops the worker on every enabled card of that vendor before the installer starts (0.3.22, the shipper's word 19:1x BST; the first cut held only the
externalkind, and at 19:14 BST PC 2's Arc in the Razer Core X V2 readdiscreteon 0.3.21, no USB4 or Thunderbolt router in its parent chain on that board, so the kind alone would have missed the card that crashed the box; the x1 gen1 link signature is not on the card state and was not added) (drivertable::install_hold_keys, through the cards path with the restore choice kept, the--cards-offshape). The vendor's cards inside the case and every other vendor's card keep mining. - The row says so before the click ("The worker on every Intel Arc card stops for the install and comes back after it; the other cards keep mining. The display resets during the install, and a card in an external enclosure can take the machine for a minute and may need a restart: save your work first."; the enclosure clause only on an
externalrow) and while it runs ("The Intel Arc workers are stopped until the installer ends; the display may reset."). - When the installer ends the held card goes back as it was (enabled, identities, cap). A card the install took away (Windows re-enumerates an eGPU through the reset) comes back when the card does: the detection that lists it again restores it (
driver_release_held(true)). The app never restarts the machine.
Per tier: a miner loses the installing vendor's rate for the install (PC 2: the Arc's 11 of 173 MH/s for an Intel install; a one-vendor rig loses everything for those minutes, which is what the installer does to the driver anyway) (3 to 8 minutes on a home line, the download dominating) and nothing else; a rig with the card inside the case sees no change; macOS and Linux have no install step. Tests: the known-failed rule test first (an install on an eGPU card with the worker still running held nothing: an_install_on_an_egpu_card_stops_that_cards_worker_first_and_leaves_the_other_cards_mining, red on build-2 at 17:1xZ, then green), the view test for the two sentences. Captures 13 to 16: the eGPU offer (13, 14) and the install running with the card's worker off (15, 16), mock scenarios drivers-egpu and drivers-egpu-running.
4. Not done, and what follows
- The table's publish:
publish-manifest.sh --drivers packaging/ota/drivers.jsonwith the 0.3.21 manifest (the shipper's step); every row is measured. - The Linux install path stays a line (the brief).
- A PC 1 dry run of the Windows path (the installer not run, the download and the checks live) is one
IGNEUM_DRIVER_DRY_RUN=1engine start away; not run today (PC 1 is the project lead's desk and mines).