HydraIssues

Phase 3: hydracluster head-body matching on driver intersection
closed unclassified Project: hydracluster Parent: #734 Reporter: 15 Sep 2026 18:46

Description

Depends on Phase 2. Part of #734.

hydracluster hardcodes ALVR when matching a head to a body:

handlers_xr.go:153
if body.District != head.District || body.Status != "online" || !sliceContains(bs.XRDrivers, xrDriverALVR)

and handlers_api.go:978 gates eligibility the same way.

Scope:

  • Heads declare which XR drivers they can speak. A Quest running hydraheadquest speaks alvr; a Quest running the WiVRn client speaks wivrn. The same headset may speak both depending on which client is installed.
  • Match on the intersection of head drivers and body drivers instead of a hardcoded constant, and fail with a clear reason when the intersection is empty.
  • Keep this flowing through normal body selection via /api/v1/bodies/eligible. Manual head-body pinning stays an admin override, per the body-selection rule.

Done when: a WiVRn-capable head is matched only to a WiVRn-capable body, an ALVR head only to an ALVR body, and a mixed fleet resolves correctly without hand-pinning.


DONE 2026-09-16, hydracluster v2.0.120 and v2.0.121, verified live.

Two places assumed alvr was the only XR driver, so a wivrn body was invisible however it was configured:

  • /api/v1/bodies/eligible dropped every body not advertising alvr. It now takes an optional xr_driver parameter and matches on it.
  • Creating an XR session hardcoded the driver in both the capability check and the stored session. The head names the driver it speaks and the session records what was chosen.

Both default to alvr, so older heads are unchanged.

v2.0.121 followed immediately because v2.0.120 left discovery and claim disagreeing: eligible accepted ANY XR-capable body when no driver was named, while session creation defaulted to alvr. An older head could have discovered a wivrn body and then been refused with not_xr_capable. Both now default to alvr.

VERIFIED LIVE against msi1060:
/api/v1/bodies/eligible?district=bxl1-test&stream_mode=xr&xr_driver=wivrn
-> [{"name":"spicy-cactus-76", ..., "xr_drivers":["wivrn"]}]

Two traps found on the way, now in docs/runbooks/body-selection.md, both of which look exactly like a broken driver:

  • xr_drivers appears ONLY on stream_mode=xr queries; a flat query omits the XR fields, so a body can look like it advertises nothing.
  • A role change does NOT reach the body by itself. hydrabody caches its body config and only refetches on a reprovision signal. msi1060's cache was two days stale and still listed the old roles, so the role had no effect until POST /api/v1/nodes/{id}/reprovision.