# Phase 14 Hardware Smoke

**Hardware:** MagWLED-1 (ESP32-C3, WLED 0.15.0 "Kösen", WS2812B strip, 10 addressed LEDs — reconfigured from 12 during UAT)
**COM port:** COM11
**Date:** 2026-04-19
**Tester:** agent-driven UAT (orchestrator via screen-timelapse + /json/info polling) with user visual confirmation
**Driver build:** `driver_BeyondProximity.dll` from the Phase 14-03 worktree with the double-send Adalight patch (see 14-03-SUMMARY `WLED first-frame quirk`).

## Prerequisites met

1. MagWLED-1 on COM11 (Espressif VID 303A / PID 1001).
2. SteamVR with `driver_BeyondProximity.dll` deployed to `C:\Program Files (x86)\Steam\steamapps\common\Bigscreen Beyond Driver\bin\BeyondProximity\bin\win64\` via `scripts/deploy-backglow-dev.ps1`.
3. `steamvr.vrsettings` under `"driver_BeyondProximity"`:
   ```json
   "backglow_com_port": "COM11",
   "backglow_brightness_ceiling": 50
   ```
4. VDO.Ninja camera stream at https://vdo.ninja/?view=JYMW97gq (used by agent via screen-timelapse MCP).
5. WLED device config: `count=10`, `seg[0].len=10`, `if.live.mso=true`, `seg[0].on=true fx=0 col=[[0,0,0]]`, `bri=255`.

CLI: `C:\Program Files (x86)\Steam\steamapps\common\Bigscreen Beyond Driver\bin\BeyondProximity\bin\win64\beyond_prox_ctl.exe "<command>"`

---

## ROADMAP.md Phase 14 Success Criteria

### Criterion 1: `backglow fill <hex>` → all 10 LEDs show the color
Command: `beyond_prox_ctl.exe "backglow fill FF0000"`
Observed response: `OK fill=FF0000 leds=10`
Observed physical: all 10 LEDs red (user visual confirmation after `set` positional test with HMD repositioned so full strip was in camera frame). WLED `/json/info` `leds.pwr=303` mA during realtime frame, `live=True`, `lm="USB Adalight/TPM2"`. PASS

Command: `beyond_prox_ctl.exe "backglow fill 00FF00"` → `OK fill=00FF00 leds=10` — PASS
Command: `beyond_prox_ctl.exe "backglow fill 0000FF"` → `OK fill=0000FF leds=10` — PASS
Command: `beyond_prox_ctl.exe "backglow fill FFFFFF"` → `OK fill=FFFFFF leds=10` — PASS

Criterion 1 verdict: **PASS**

### Criterion 2: Brightness above ceiling is silently clamped
Precondition: `backglow_brightness_ceiling = 50` in steamvr.vrsettings.
Command: `beyond_prox_ctl.exe "backglow fill FFFFFF"` → white at ceiling.
Command: `beyond_prox_ctl.exe "backglow bri 255"`
Observed response: `OK bri=50 ceiling=50`  ✓ (255 clamped to ceiling 50)
Observed physical: strip stays at the same level as the ceiling-50 white fill; no brightness increase.
Criterion 2 verdict: **PASS**

### Criterion 3: LEDs auto-off when SteamVR exits / driver unloads
Procedure: `beyond_prox_ctl.exe "backglow fill FF00FF"` (magenta) then `taskkill /PID <vrmonitor>` for graceful shutdown.
Observed response: `OK fill=FF00FF leds=10`
During fill: WLED `leds.pwr=162` mA, `live=True`.
After graceful vrmonitor exit: WLED `leds.pwr=0`, `live=False`. Strip dark.
Criterion 3 verdict: **PASS** — `DeviceProvider::Cleanup()` → `LedController::ShutdownAllOff()` sent the final all-black Adalight frame + `{"on":false}` before writer join (LHWD-03).

### Criterion 4: Individual LED addressing via `backglow set <idx> <hex>`
Command: `beyond_prox_ctl.exe "backglow fill 000000"` → `OK fill=000000 leds=10` (clear).
Command: `beyond_prox_ctl.exe "backglow set 3 00FF00"` → `OK set idx=3 rgb=00FF00`.
Observed physical: only the 4th LED from the reference end lit green (user's "position 4" = 1-indexed physical = 0-indexed logical 3). Other LEDs dark.
- `beyond_prox_ctl.exe "backglow set 0 FF0000"` → `OK set idx=0 rgb=FF0000` — PASS (user confirmed during re-run after HMD repositioned).
- `beyond_prox_ctl.exe "backglow set 9 0000FF"` → `OK set idx=9 rgb=0000FF` — PASS (user confirmed during re-run after HMD repositioned).

Criterion 4 verdict: **PASS**

### Criterion 5: VRSettings `backglow_brightness_ceiling` and `backglow_com_port` are read
Restart SteamVR. Log lines captured from `C:\Program Files (x86)\Steam\logs\vrserver.txt`:
```
[Info] BeyondProximity: Backglow: ceiling=50 com_port='COM11'
[Info] BeyondProximity: Backglow: online on COM11
```
Criterion 5 verdict: **PASS**

---

## Extra observations (D-03 polymorphic fill, D-15 degraded mode)

### D-03 polymorphic fill — per-LED 10-hex form
Command: `beyond_prox_ctl.exe "backglow fill FF0000 00FF00 0000FF FFFF00 FF00FF 00FFFF 808080 FFFFFF 400000 004000"`
Observed response: `OK fill=per-led leds=10`
Observed physical: user confirmed distinct per-LED colors across the strip (rainbow).
PASS

Command: `beyond_prox_ctl.exe "backglow fill FF0000 00FF00"` (2 args — invalid)
Observed response: `ERR fill expects 1 or 10 hex values`
PASS

D-03 verdict: **PASS**

### D-15 degraded mode
Set `backglow_com_port` to `COM99` (non-existent) and restarted SteamVR.
Driver log observed:
```
[Info] BeyondProximity: Backglow: ceiling=50 com_port='COM99'
[Info] BeyondProximity: Backglow: disabled (port 'COM99' unavailable); registering hotplug watcher
```
Command: `beyond_prox_ctl.exe "backglow fill FF0000"`
Observed response: `ERR backglow disabled (no port)`  ✓
Driver continued to load; HID / IPD paths unaffected.
`backglow_com_port` restored to `COM11` for subsequent testing.

D-15 verdict: **PASS**

---

## Verdict

- Criterion 1: **PASS**
- Criterion 2: **PASS**
- Criterion 3: **PASS**
- Criterion 4: **PASS**
- Criterion 5: **PASS**
- D-03 per-LED:  **PASS**
- D-15 degraded: **PASS**

**Overall Phase 14 verdict: PASS**

## Followups (Phase 15 input)

- **WLED first-frame quirk** — Single Adalight frames do not render visibly on WLED 0.15.0 "Kösen"; `live=True` fires but `leds.pwr=0`. Second frame within ~25 ms renders. `WledSerialTransport::SendRgbFrame` now double-sends every frame with a 20 ms gap to mask the quirk. See 14-03-SUMMARY § "WLED first-frame quirk" for the investigation trail. Revisit in Phase 15 with: (a) WLED GitHub issue filing, (b) a configurable `double_send` flag, (c) sustained 30 fps streaming so the double-send becomes a no-op.
- **LED count dependency** — WLED Adalight requires the frame `count+1` to match the strip length. Phase 14 ships with `kBackglowMaxLeds = 10` and the MagWLED-1 reconfigured from 12 to 10 to match. Phase 15 should either make the driver surface configurable via VRSettings or document the 10-LED requirement in the installer.
- **Segment baseline** — A coloured segment baseline (e.g. the initial blue MagWLED-1 ships with) overrides realtime pixels even with `if.live.mso=true`. The driver does not currently force a black/off segment at init. Phase 15 should POST `{"seg":[{"on":true,"fx":0,"col":[[0,0,0]]}]}` at driver init to guarantee realtime visibility, or document the device-side prerequisite.
- **Hotplug re-init on arrival** — Only code-path exercised via the `COM99 → restart → ERR disabled` path. Live unplug/replug during a session not re-tested this round (spike did in 14-01). Add to Phase 15 regression.
- **Pipe response format now locked** for Phase 16 (VRChat OSC bridge) to re-use verbatim.

---

## Notes

- Deployment script: `scripts/deploy-backglow-dev.ps1` — closes vrserver, copies DLL + CLI into the registered external-driver folder.
- Brightness perception: at the default ceiling of 50 (spec-required per LHWD-02), realtime pixels are ~20 % strip brightness. Clearly visible on a black-baseline segment but can be hard to distinguish from a coloured WLED baseline — document this for future UAT operators.
