Codex R15 on the previous fix:
- [P2] reclassifyInput derived the raw input level from the already-displayed
(inverted) contact state, so toggling inversion twice didn't restore the
original. The ingest + device page now carry the raw `on` inside the contact
state, so flipping role/inversion is fully reversible. +1 round-trip test.
- Latent: Device::isOnline() could return null (null demo, no last_seen) and
break the type hint / views. Now returns a strict bool.
Suite 58 green, 12/12 tabs clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>