MASTER. Make Linux bodies first-class in the fleet so WiVRn + PyroWave becomes an XR driver alongside ALVR, driven by hydracluster and the experience library instead of hand-run commands.
WHY: PyroWave streams today (#388) but only because a human types systemd-run on msi1060. WiVRn's server is Monado-based and Linux-only, so the codec can never reach a venue through the current Windows-only body path. Linux bodies are also independently valuable: cheaper hardware, and we already run an Omarchy fleet for heads.
Route B, putting PyroWave inside Sunshine/Moonlight to keep Windows bodies, is deliberately NOT this ticket. It means implementing the codec in two more codebases from scratch and gives up WiVRn's native OpenXR path. Revisit only if this route stalls.
== VERIFIED GROUND TRUTH 2026-09-15 ==
Further along than expected:
- hydranode runs on Linux. msi1060 = spicy-cactus-76 = node-d71b197c, Omarchy 4.0.2, node v1.10.41, online.
- hydrabody ALREADY builds for linux-amd64 and linux-arm64 (Makefile + release.yml) and is ALREADY RUNNING on msi1060 at v2.0.70-rc.12.
- msi1060 is ALREADY enrolled as a body: roles [hydrabody, hydraguard-air], district bxl1, venue ad6.
- The XR capability model is ALREADY multi-driver in the DATA model: XRDrivers is a []string in both hydrabody's body-status POST and hydracluster (pkg/api/server.go:127, handlers_body.go:357).
- WiVRn + PyroWave proven end to end on this exact machine to a Quest 2 (#388), both eyes 98.7 Mbit/s.
The actual gaps, measured in the source:
- A Linux body CANNOT LAUNCH ANYTHING. pkg/provider/launch_other.go: launchInSession() returns "launch not supported on this platform". This is the hard prerequisite; nothing else matters until it is fixed.
- experiencesDir is hardcoded
C:\experiences with no platform variant (pkg/provider/experiences.go:16).
- 13 subsystems are no-op _other.go stubs on Linux: alvr, audio, firewall, kiosk, launch, notifications, orphan_scanner, portrait_vdd, screenshot, stop, sunshine_health, sunshine_startup, vdd.
- The XR LOGIC hardcodes alvr even though the data model is a list: hydrabody pkg/provider/alvr.go (xrCapable, xrStatusFields) and hydracluster pkg/api/handlers_xr.go:153.
- The WiVRn server has no packaging or config management: hand-built binary in /var/tmp, transient systemd-run unit, hand-written ~/.config/wivrn/config.json, ad-hoc ufw rules.
- The client is a DEBUG-SIGNED APK from a CI artifact, published as prerelease pyrowave-test-1 and side-loaded by adb.
== ORDERED PLAN ==
- #735 Phase 1: Linux experience lifecycle in hydrabody (HARD PREREQUISITE, everything blocks on it)
- #736 Phase 2: wivrn as a second XR driver in hydrabody (depends on #735)
- #737 Phase 3: hydracluster head-body matching on driver intersection (depends on #736)
- #738 Phase 4: package and manage the WiVRn server (can overlap 2 and 3)
- #739 Phase 5: WiVRn client distribution for headsets
- #740 Phase 6: venue readiness for a Linux body (wired ethernet, 6 GHz AP, test district)
Do #728 and the performance measurement FIRST. They are cheap and they tell you whether the rest is worth funding.
== DEFINITION OF DONE ==
A head is assigned to a Linux body through normal hydracluster body selection (never manual pinning, per the body-selection rule), the body arms WiVRn by itself, the headset connects, and an experience from hydraexperiencelibrary streams with PyroWave. No hand-run commands anywhere in that path.
== DEPENDENCIES AND RISKS ==
- #728 blocks portability: PyroWave shader device features are not enabled; NVIDIA tolerates it, another vendor may not. Fix before any second Linux body.
- #721 blocks auto-install: the library blanks build_url for any experience with an exe_path, so bodies cannot self-install or self-heal.
- No performance numbers exist yet. Measure encode/decode/battery vs H.265 before funding the rest; if the win is small the whole route is questionable.
- msi1060 is currently in PRODUCTION district bxl1, venue ad6. Move it to bxl1-test* before using it for this work, per the test-districts rule.
- Linux bodies need a GPU and a live desktop session. msi1060 has a Hyprland session as user cederik; that assumption needs to be explicit and provisioned, not incidental.
- WiVRn is Linux-only. Windows bodies keep ALVR. Expect a mixed fleet permanently.
== AVOID DUPLICATED WORK: EXISTING OMARCHY EFFORTS ==
Recorded 2026-09-15 after a duplicate implementation was written and thrown away on the same day.
- hydrabody PR #1 (feat/omarchy-body) already landed the Linux install paths, desktop session discovery and launch. Phase 1 (#735) is therefore mostly DONE; read #735 before starting it.
- cederikdotcom/omarchy-hydra-experiencenet (v0.5.8) is an Omarchy bar widget that already does Sunshine host discovery over avahi, PIN pairing, app listing and stream start/stop, plus a setup-body.sh that turns an Omarchy machine into a Sunshine host. It covers the FLAT lane. Reuse it rather than rebuilding head-side discovery and pairing.
- #743: those two disagree on the Sunshine user unit name, and msi1060 is where they meet.
Before starting any phase here, check both of the above and the branch list of the repo you are about to touch.
FIRST RELEASE LANDED 2026-09-16. hydracluster v2.0.119 (role + recipe) is live, hydrabody v2.0.70-rc.13 is on msi1060, the WiVRn package is published, and the wivrn role is assigned to msi1060 in district bxl1-test.
Phase status after this release:
- #735 Linux experience lifecycle: DONE and released (install paths and launch from PR #1, stop and the executable bit after it).
- #736 wivrn as an XR driver: the body can advertise it; arm and disarm exist but are NOT wired into the XR state machine, and rendering the WiVRn config from the assigned experience is still the open design question.
- #738 packaging: done except a real release channel; today's package was published by hand.
- #737 cluster matching on driver intersection: NOT started.
- #739 client distribution: NOT started; the Quest still runs a debug-signed APK side-loaded over adb.
- #740 venue readiness: msi1060 moved to bxl1-test, but it is still on WiFi rather than wired, and there is no dedicated 6 GHz AP.
Also resolved along the way: #743, the plugin and hydrabody now coexist on one machine (plugin v0.5.9).
2026-09-16: msi1060 is now discoverable as a WiVRn body through normal cluster selection.
/api/v1/bodies/eligible?district=bxl1-test&stream_mode=xr&xr_driver=wivrn
-> spicy-cactus-76, xr_drivers: ["wivrn"]
That closes the discovery half of the chain. Phase status:
- #735 Linux experience lifecycle: DONE, released.
- #736 wivrn XR driver: body advertises it; arm and disarm still NOT wired into the XR state machine, and rendering the WiVRn config from the assigned experience remains the open design question.
- #737 driver matching: DONE, v2.0.120 + v2.0.121.
- #738 packaging: done except a real release channel; the package was published by hand.
- #739 client distribution: NOT started.
- #740 venue readiness: in bxl1-test, still on WiFi, no dedicated 6 GHz AP.
What remains before a head can actually stream through this: wire arm/disarm into the XR state machine (#736), then decide how the WiVRn config is rendered from the assigned experience, since WiVRn launches the application itself rather than being told to by hydrabody.