- client: ControlError.sent says whether the display had the request;
should_fall_back() allows a mailbox write only when it did not, or when
the display is too old to know the command (upgrade case)
- on-demand start/stop: a display that had the request and failed it is
answered 503 (400 for invalid_args), no mailbox copy
- errors.clear: new socket command, answered on the connection thread by
a handler the display registers; applied and republished before the
answer; plugin_error_clear_request only on fallback
- display: on-demand mailbox looked at once a second while the socket is
up (0.25 s without), read only when its file changed (one stat via
CacheManager.file_signature / MailboxWatch); socket commands no longer
touch the mailbox; a processed duplicate is consumed; writers logged once
- error publisher: mailbox read only when changed; snapshot carries
applied_clear_cutoff so an older mailbox request is not shown pending
- docs and CHANGELOG (mailboxes kept for one release)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
State stream ticks carry the volatile timestamps (display.last_updated, plugins.published_at), so current-status and the plugin runtime stay fresh while one mode stays on screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds state.get / state.subscribe to the display's control socket (StateHub in src/ipc/server.py). The web interface holds one subscription per process (web_interface/display_state.py) and reads current-status, on-demand status, plugin runtime and /health's display_loop from it, falling back to the cache keys and heartbeat file. While the socket serves readers, display_current_state and plugin_runtime_snapshot are written less often (about 1.5 instead of 5 cache writes a minute for 15 s screens).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Control socket stage 2: the render thread wakes for queued commands (static screens ~1 ms, Vegas within one frame), brightness.set, and plugin.reload after a store update, with mailbox/restart fallbacks. Rig checks listed in the PR body are still to run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The display serves a control socket (/run/ledmatrix/control.sock) carrying versioned JSON commands, one per line, each answered. Stage 1 covers on-demand start, stop and status; commands are queued on the socket thread and applied on the render thread through the mailbox's own handler, and the web interface falls back to the file mailbox when the socket is unavailable. Protocol and security model: docs/IPC_CONTROL_SOCKET.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>