4d42e298dd
Android: a gated DiagnosticsReporter taps connectivity, server-health, UPnP drops/player-state/route, power (Doze/battery-opt/screen), and app fg/bg, plus a heartbeat snapshotting Sonos-vs-local position — the locked-phone desync signal. Events buffer in a Room ring buffer (deliberately NOT the MutationQueue: high-volume best-effort telemetry that must survive the dead zone being debugged) and DiagnosticsUploader drains them on a tick / health-recovery / sign-in. Gating: the account flag (users.debug_mode_enabled) reaches the device via a new /api/me refresh in AuthController; a per-device local OFF switch lives in Settings. Reporter runs only when enabled && !optOut; disabling drops the unsent buffer. Web admin: /admin/diagnostics — pick account+device+kind+time-window, see a chronological timeline, flip an account's debug mode remotely, and Copy-JSON / Download-NDJSON the slice for analysis. Room schema 6→7 (new diagnostic_events table + auth_session.diagnosticsOptOut; pre-v1 destructive fallback). Refs Scribe M9 (#119), tasks #1174 #1175 #1176 #1177. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K55iTxn95BtshocgdE1shW