Branch strategy (freeze workaround, live since 2026-07-11): develop is the frozen v1.4 release candidate — v1.5 code must not touch it. So v1.5 work integrates on develop-v1.5 (branched from the develop tip, same 15-check + 1-review protection). Feature branches (claude/v15-*) PR into develop-v1.5 with full CI + review + hand-unioned CHANGELOG, exactly like develop. When v1.4 cuts and back-merges to develop, develop-v1.5 merges to develop in ONE PR (reconcile CHANGELOG: the v1.4 entries are already in [1.4.0] on develop, so keep only the v1.5 entries under [Unreleased]), then delete develop-v1.5 and resume normal develop flow. Net: zero idle dev time, zero v1.5 leakage into the v1.4 cut.
The theme: v1.4 gives the operator hands on the stack; v1.5 extends them across the fleet. The spine is the RigForge integration: the enriched worker feed (rigforge#99) consumed by the dashboard (#235), per-worker configuration (#172 → #185), and remote control from Telegram (#338). Around it: net-profit economics (#260), on-chain payout confirmation (#381), alert transports beyond Telegram (#380), and the fleet e2e suite (#209).
Wave 0 — DECISIONS & RESCOPES (no code until these close)
#172 rescope: per-worker {name,host,port,token} descriptor (body half-mooted)
#249 rewrite: define "backup stack" + what syncs (five-line wish today)
rigforge#99 schema freeze (producer contract for #235)
│
▼
Wave 1 — FLEET SPINE
#172 worker ports & per-worker overrides
└─► #235 consume the enriched feed (badge + health/power chips) [hard dep: rigforge#99]
├─► #185 Worker Inspect page (read/edit config + history) [producer: rigforge#236]
└─► #260 energy & profit calculator [also feeds on #117/#118 from v1.3]
│
Wave 2 — CONTROL & CONFIRMATION
#338 Telegram two-way control [thin client of v1.4's #33 contract]
#381 payout confirmation (view-only wallet)
▼
SHIP 1.5
independent, off the critical path:
#380 alert sinks: generic webhook + ntfy (Tor-routed like Telegram)
#209 integration tests: RigForge worker ↔ xmrig-proxy [needs the 3-mode auth matrix rewrite]
#249 primary/backup stack sync [after its Wave 0 rewrite; may slip]
Gates when it opens: Wave 0 rescopes merged into the issue bodies · rigforge trackers filed · core arc merged to develop · gouda regression pass incl. a real RigForge rig · CHANGELOG · cut per the standard process.
Critical path
Bearer <rig name>auth contract, shippedworkers.api_port, closed Dashboard: config to read workers that use a custom XMRig API token #171). The gap-assessment comments on Configurable worker ports & endpoints: non-standard stratum/API ports + per-worker host/port/token overrides (later) #172/Warm the backup stack's XvB donation state so a failover doesn't cold-start the split #249/Integration tests: RigForge worker ↔ Pithead xmrig-proxy (end-to-end flows) #209 list exactly what to rewrite. Freeze the rigforge#99 JSON schema before [Feature] Dashboard: consume RigForge's enriched feed (rigforge#99) — update badge + per-worker health / power / tune / firmware #235 parses it.Wave 0 — Decisions & rescopes
p2pool.stratum_port+ a from-scratch per-worker{name, host, port, token}descriptor with an explicit merge rule (per-worker > fleet default > inherit).Wave 1 — Fleet spine
pithead's jq, containercontrol_service.pyverbatim;dashboard.workerschanges stay host-CLI-only via the approval gate). Configurablep2pool.stratum_port+ per-worker{name,host,port,token}overrides.dashboard.authis enabled).Wave 2 — Control & confirmation
/restart+/applygated by numericallowed_ids+ one-shot owner-bound confirm button (deny-on-timeout); rides the Stack config editor: change any setting from the dashboard, applied via pithead (incl. P2Pool mode hot-swap) #33 spool with fixed-verb host-side dispatch (no request byte reaches a command). Security-reviewed clean; two non-blocking nits filed as Telegram control (#338) follow-ups: per-operator rate-limit + ControlGate docstring accuracy #470.monero-wallet-rpcon the local node (loopback, non-root, read-only rootfs, password-auth); view key handled likenode_password(tmpfs file never on argv, masked, off the editable allowlist, scoped to the wallet-rpc container only — dashboard never receives it), local-node-only.payouts (chain,txid)table +payout_confirmedalert. Security-reviewed clean; poller hardened against malformed RPC fields.payouts (chain,txid)table +payout_confirmedalert withchain="tari". View-onlyminotari_console_wallet v5.3.1(digest-pinned), created non-interactively via--view-private-key/--spend-key/--non-interactive-mode; loopback-only gRPC127.0.0.1:18143, non-root, read-only rootfs. Secrets delivered via a Dockersecrets:tmpfs mount (NOTenvironment:) so the view key stays out ofdocker inspect; masked, off the Stack config editor: change any setting from the dashboard, applied via pithead (incl. P2Pool mode hot-swap) #33 editable allowlist, local-node-only. Security-reviewed clean (8/8 controls hold). Tier-4 gates for the next gouda run: (1) does the merge-mine coinbase surface viaGetCompletedTransactionsvsGetBalance(documented fallback, one-method swap); (2) the host-rendered 0600 secret file must be readable by the uid-1000 container — confirm the wallet actually starts on the appliance (fails closed if not; fix ownership then, with live observation of the/run/secretsperms); (3)--birthdaybounds the scan (no genesis rescan) + restart replays nothing.Off critical path
v1.4 debt & follow-ups (filed during the v1.4 cycle; off critical path)
config.json(the one accepted residual from the Stack config editor: change any setting from the dashboard, applied via pithead (incl. P2Pool mode hot-swap) #33 security reviews; closes the last secret-exposure of that feature).verify_release_imagesnow cosign-verifies the@sha256digest read from the bundled compose (the exact bytes docker pulls, release: digest-pin bundle images + make cosign opt-in (#376) #461), not the mutable tag; key-present + un-pinned image aborts.stack_upgates the first-install pull with the same fail-closed checkupgradeuses.checkout -f+clean -qfdx -e /results -e /backups -e /data, config.json/.env re-seeded from canonical) +RESTORE_DIRderived from the live compose project'sworking_dirlabel (refuses to adopt E2E_DIR; falls back to CANONICAL_DIR). Tier-4 live-validated on the next gouda run.upgrademaintains thecurrent ->symlink; dashboard data joins the shared data root (docs the canonical layout, replaces the hand-written per-box READMEs).Release status — cycle not open
Gates when it opens: Wave 0 rescopes merged into the issue bodies · rigforge trackers filed · core arc merged to
develop· gouda regression pass incl. a real RigForge rig · CHANGELOG · cut per the standard process.