Description
## Context
Physical-exposure bodies (e.g., wobbly) use an Elgato Stream Deck to let visitors launch experiences over the kiosk overlay and let operators toggle kiosk for maintenance. Currently this relies on the Elgato Stream Deck Windows app + manually-configured profiles on each body. A multi-hour debug session on 2026-04-21/22 uncovered structural fragility:
- Elgato auto-update can invalidate WDAC hash approval (fleet-wide footgun).
- App window must be "open" (minimized counts) on this Qt version for HID events to dispatch — surprising and undocumented.
- Programmatic manifest edits in `ProfilesV3\...\manifest.json` cause silent app crashes (schema not fully reproducible).
- WTS P/Invoke launches from SYSTEM produce zombie processes post-auto-upgrade.
- Config is decentralized on-disk per body, no central source of truth.
## Proposal
Add `hydrabody/pkg/streamdeck/` package that speaks the Stream Deck MK.2 HID protocol directly using a maintained Go library (candidates: `muesli/streamdeck`, `dh1tw/streamdeck`). Eliminates the Elgato Windows app entirely on bodies using this feature.
Architecture:
- `client.go` — HID protocol wrapper around the chosen library.
- `daemon.go` — main event loop: enumerate device, render buttons, dispatch presses.
- `render.go` — render 72×72 JPEG button labels from text using `golang.org/x/image/font` + bundled TTF.
- `config.go` — unmarshal `~/.hydrabody/streamdeck.yaml` (v1) or BodyConfig (v2).
- `actions.go` — in-process dispatch: `launch_experience`, `stop_experience`, `kiosk_enable`, `kiosk_disable`, `navigate_page`.
Wired to existing hydrabody interfaces:
- `launch_experience` → `launchInSession(C:\experiences\...)` (same function `handleLaunch` uses).
- `stop_experience` → `killExperienceProcesses(exeName)`.
- `kiosk_enable` / `kiosk_disable` → in-process `KioskController.Enable()/Disable()` — no HTTP round-trip, no token, no `C:\experiences\` allowlist trip.
## Rollout
- New `streamdeck_daemon_enabled` boolean in `hydraclusterapi.BodyConfig` (additive, `omitempty`). Default false.
- Bodies using the daemon uninstall the Elgato Stream Deck Windows software.
- Ships via existing hydrabody tag-triggered CI pipeline — already WDAC-approved.
- Docs in hydrabody runbook: hardware compatibility (MK.2 model `20GBA9901` confirmed on wobbly), button config schema, rollout procedure.
## Why this is worth doing
Fixes every Phase-1 fragility in one pass: no auto-updates to fight, no WDAC hash roulette, no Qt focus quirk, central config-friendly, in-process action dispatch (~faster). Current Elgato-app-on-body layer is a standing liability for every new physical-exposure body.
## References
- Plan notes: `/home/claude-user/.claude/plans/gentle-greeting-papert.md`