# Phase 6: Standby/Wake Integration - Context

**Gathered:** 2026-03-22
**Status:** Ready for planning

<domain>
## Phase Boundary

Wire the proximity algorithm's `person_detected` boolean (Phase 5) to the SteamVR HMD proximity property so SteamVR correctly knows when the Beyond 2 is on/off the user's head. The driver's job is to keep the HMD property in sync with the algorithm output. SteamVR itself decides what to do with that state (standby, wake, activity level).

</domain>

<decisions>
## Implementation Decisions

### Integration mechanism
- Simple RunFrame poll: read `GetPersonDetected()`, compare to `m_bProximity`, call `SetHmdProximity()` on change
- The existing `SetHmdProximity()` using `SetBoolProperty(Prop_ContainsProximitySensor_Bool)` on the HMD container IS the correct and proven mechanism — it works, SteamVR respects it
- No `/proximity` component needed — driver has no registered tracked device (removed in Phase 3.1)
- State-change guard already exists in `SetHmdProximity()` — only writes on transitions

### Debounce / timeout
- No driver-side debounce — propagate state changes immediately in both directions (true and false)
- The algorithm's hysteresis + 8-sample moving average is sufficient debounce
- SteamVR may have its own standby delay; the driver should not second-guess it

### Manual override
- Pipe `proximity on/off` commands set a manual override flag that disables algorithm-driven updates
- Override persists until explicitly cleared via new `proximity auto` command
- This lets developers lock proximity state for extended testing without the algorithm overwriting it
- Status command shows source: `source=algorithm` or `source=manual`

### Startup behavior
- On driver init: start with `proximity=false` (person absent) — match algorithm default
- On USB reconnect: reset to `proximity=false` (person absent) — match algorithm reset behavior
- No special handling for buffer-fill window — let the algorithm naturally transition when data arrives

### Claude's Discretion
- Exact implementation of the manual override flag (bool + enum, etc.)
- Whether `proximity auto` logs to SteamVR driver log
- Status command formatting for the new source field
- Whether to add algorithm-driven state change logging (e.g., "Proximity: algorithm detected person")

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### SteamVR HMD property write (the proven mechanism)
- `src/driver/device_provider.cpp` lines 230-247 — `SetHmdProximity()`: writes `Prop_ContainsProximitySensor_Bool` to HMD property container with state-change guard
- `src/driver/device_provider.cpp` lines 64-69 — `RunFrame()`: currently has placeholder comment for Phase 6 wiring
- `extern/openvr/headers/openvr_driver.h` — `Prop_ContainsProximitySensor_Bool` (prop 1025)

### Proximity algorithm output (Phase 5)
- `src/hid/proximity_algorithm.h` — `ProximityAlgorithm` class with `GetPersonDetected()` (atomic bool) and `GetDiagState()`
- `src/hid/hid_device.h` lines 47-48 — `GetPersonDetected()` and `GetAlgorithmDiag()` public API

### Named pipe protocol (manual override extension)
- `src/driver/device_provider.cpp` lines 139-213 — `HandlePipeCommand()`: existing pipe commands to extend with `proximity auto`
- `src/ctl/main.cpp` — CLI tool that sends pipe commands

### Project requirements
- `.planning/REQUIREMENTS.md` — INTG-02, INTG-03, INTG-04, INTG-05 define Phase 6 requirements

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `DeviceProvider::SetHmdProximity()`: Proven mechanism, state-change guard, writes to HMD container. Phase 6 just needs to call it from RunFrame based on algorithm output.
- `DeviceProvider::m_bProximity`: Already tracks current proximity state for change detection.
- `HidDevice::GetPersonDetected()`: Atomic bool, lock-free, safe to call from RunFrame every frame.
- `HidDevice::GetAlgorithmDiag()`: Mutex-protected diagnostic snapshot for status command.
- `HandlePipeCommand()`: Existing command dispatch with response protocol. Add `proximity auto` alongside existing commands.

### Established Patterns
- Lock-free atomics for frequently-read values (GetPersonDetected follows GetProxDistance pattern)
- State-change guard on property writes (SetHmdProximity only writes on transitions)
- Pipe protocol: text command in, text response out, disconnect after each exchange
- DriverLog for all state transitions and errors

### Integration Points
- `DeviceProvider::RunFrame()` — Add algorithm polling: read GetPersonDetected(), compare, call SetHmdProximity()
- `DeviceProvider::HandlePipeCommand()` — Add `proximity auto` command, add override flag check
- `DeviceProvider` header — Add manual override flag member
- Status command response — Add `source=algorithm|manual` field

</code_context>

<specifics>
## Specific Ideas

- The goal is NOT to "trigger standby" — it's to have proximity state properly registered against the HMD in SteamVR. SteamVR uses that as one criterion for its own standby logic.
- Whatever `proximity on/off` pipe commands do today via SetHmdProximity is exactly the desired SteamVR API effect. Phase 5's concern about Prop_ContainsProximitySensor_Bool semantics is a non-issue — the mechanism works in practice.
- The RunFrame wiring is intentionally minimal: read atomic bool, compare, call existing function on change. No new SteamVR API exploration needed.

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope

</deferred>

---

*Phase: 06-standby-wake-integration*
*Context gathered: 2026-03-22*
