From 4e87d9d1f9df51d76acf761a53c86bc49c0ff9fd Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sun, 2 Aug 2026 10:51:16 -0500 Subject: [PATCH 1/2] =?UTF-8?q?feat(wizard):=20the=20role=20select=20?= =?UTF-8?q?=E2=80=94=20one=20stick,=20three=20machines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The installer page's first disclosure, above the disk, is now what the machine IS: Pithead / Pithead + RigForge / RigForge. One page, three shapes, everything downstream reshaping exactly the way the disk choice already does. - Pithead: today's flow byte for byte — the default and the regression bar; every existing wizard test passes unchanged. - Pithead + RigForge: Pithead's form with the local-miner switch preset to Yes. The role IS local_miner.enabled, so this leg is fully live end to end on the shipped boot contract. - RigForge: the form collapses to a pool address (pre-filled by the host's LAN discovery of a Pithead at pithead.local:3333, published to the spool like the disk inventory, failing open to an empty field), a worker name defaulting to the machine's own, and an optional stratum password. The disk section gains "Run from this USB stick" as a first-class target for this role only; the card shows the worker name and where it points — a rig has no dashboard and no login. Validation-before-erase (the host dials the pool before anything irreversible), keep semantics (keep means KEEP in every role — no role change crosses a survivor), the card-then-ack gate, self-power-off and the headless first boot are identical in every role. The accepted role lands under the machine-role contract the boot path reads: /data/pithead/machine-role plus rig.json for the rig role; a disk install stages pithead-rig.json on the ESP (carried by pithead-install beside the other pre-seeds) and the target's first boot lands and scrubs it. The rig BOOT LEG belongs to the next phase: a rig-marked machine states its role on the console and stops — nothing mines yet, and the message says so. Also: _console now narrates every line to the journal, not just the first — messages that lived only on a physical console cost a bench session an hour once. Covered at the owning tiers: wizard pytest server contracts (73), frontend render probes (35), stack tests for the discovery publisher, rig consumption, the marker and the boot stub (1935 suite total), plus docs in docs/dev/appliance-wizard.md. Part of #797 (phase R3). Co-Authored-By: Claude Fable 5 --- .../mining_dashboard/web/static/wizard.mjs | 202 +++++++++++++++--- build/dashboard/mining_dashboard/wizard.py | 100 +++++++-- .../dashboard/tests/frontend/wizard.test.mjs | 147 +++++++++++++ build/dashboard/tests/web/test_wizard.py | 134 ++++++++++++ docs/dev/appliance-wizard.md | 43 +++- os/installer/pithead-install | 2 +- pithead | 196 ++++++++++++++++- tests/stack/run.sh | 92 ++++++++ 8 files changed, 866 insertions(+), 50 deletions(-) diff --git a/build/dashboard/mining_dashboard/web/static/wizard.mjs b/build/dashboard/mining_dashboard/web/static/wizard.mjs index fc349f9b..c68a0236 100644 --- a/build/dashboard/mining_dashboard/web/static/wizard.mjs +++ b/build/dashboard/mining_dashboard/web/static/wizard.mjs @@ -87,7 +87,16 @@ export const Gate = ({ error, onSubmit }) => html`
// right — bench screenshots cut off exactly the erase/keep words), and is restated in full // below the control, red when destructive. The server re-validates the choice against the // inventory the HOST published; a browser can never name a disk the host did not offer. -export const InstallSection = ({ disks, chosen, confirm, wipe, onPick, onConfirm, onWipe }) => { +export const InstallSection = ({ + disks, + chosen, + confirm, + wipe, + allowStick, + onPick, + onConfirm, + onWipe, +}) => { const picked = disks.find((d) => d.name === chosen); const verdictText = (d) => d.state === "pithead-with-data" @@ -100,6 +109,13 @@ export const InstallSection = ({ disks, chosen, confirm, wipe, onPick, onConfirm <${Field} label="Target disk"> + ${ + chosen === "usb" && + html`<${Note}>The stick stays in the machine and is the system: the rig's settings ride + on it, no disk is touched, and pulling it out just stops the miner.` + } ${ picked && picked.state === "pithead-with-data" && @@ -158,10 +179,19 @@ export const Installing = ({ status }) => html`
}
`; -export const Done = ({ status, handoff, installer, onAck }) => html`
+export const Done = ({ status, handoff, installer, stick, rig, onAck }) => html`
${ - handoff - ? html`

Save this before anything else

+ handoff && handoff.role === "rig" + ? html`

Check this rig

+

This is what the machine will be.

+ <${Field} label="Worker name">${handoff.worker} + <${Field} label="Mines toward">${handoff.stratum} + <${Note}>A rig has no dashboard and no login — nothing to save. It appears by this + name in the Pithead's Workers view. + ` + : handoff + ? html`

Save this before anything else

This is shown once, here.

<${Field} label="Dashboard user">${handoff.username} <${Field} label="Dashboard password">${handoff.password} @@ -177,7 +207,12 @@ export const Done = ({ status, handoff, installer, onAck }) => html`