fix(display): a WiFi notice preempts the current screen and Vegas yields to it (#712)

A WiFi notice preempts the current screen within about a second (frame loops, post-loop check, make-up dwell), and an interrupted Vegas iteration that yielded for a notice ends the pass so the notice shows next. Goldens: wifi_notice, vegas. First of three run-loop fixes (#712, #713, #714), pre-tested together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-10-01 15:51:00 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 4be53d048b
commit 6c6394a1a7
8 changed files with 216 additions and 34 deletions
+12 -14
View File
@@ -41,12 +41,16 @@ Each pass, in order:
brightness target.
4. **Scheduled off:** blank, dwell up to 60 s. `_blank_while_scheduled_off`
5. **Follower:** render one frame from the leader. `_run_follower_frame`
6. **WiFi notice** (unless on-demand): draw it, dwell 0.5 s. `_show_wifi_notice`
6. **WiFi notice** (unless on-demand): draw it, dwell 0.5 s. `_show_wifi_notice`.
It is also polled mid-screen (`_wifi_notice_pending`): the frame loops,
the dwell sleep and an interrupted Vegas iteration end within about a
second when one arrives, and a screen cut short resumes after it.
7. **Live priority** (unless on-demand, or Vegas keeps live content in the
ticker): switch to the next live mode, or resume the rotation.
8. **Vegas** (unless on-demand, or live content preempts it): run one
iteration of up to `max_cycle_duration`. A completed iteration ends the
pass. An interrupted one falls through to step 9 in the same pass.
pass, and so does one that yielded for a WiFi notice or the schedule.
Any other interrupted one falls through to step 9 in the same pass.
9. **One screen:** pick the mode (`_resolve_active_mode`), the plugin
(`_plugin_for_mode`), draw the first frame through the executor
(`_dispatch_first_frame`). On no content, rotate at once
@@ -192,8 +196,8 @@ that the harness patches in today.
WiFi message, schedule state) are collected first, so `decide()` stays
pure.
3. Unit-test `decide()` with tables. The golden traces must not change.
This includes the missed WiFi notice described below: fixing it is a
separate PR.
The Wifi Source must keep the mid-screen preemption described in step 6
of "What `run()` does today".
Follower and Wifi go first because each is one self-contained branch that
ends the pass. They prove the plumbing without touching the frame loops.
@@ -254,20 +258,14 @@ These are recorded as they are today. Each one should be fixed in its own
PR, which updates the affected trace and explains why. None of them is
changed by the restructure.
1. **A WiFi notice is only checked between screens.** A 5 s notice posted
during a 20 s screen expires before the screen ends and is never shown
(`wifi_notice`, t=25).
2. **Vegas yields to a WiFi notice, then shows a rotation screen instead of
the notice.** An interrupted iteration falls through to step 9 in the
same pass, and the notice has expired by the next pass (`vegas`, t=200).
3. **Vegas yields to live content, then shows a rotation screen first.**
1. **Vegas yields to live content, then shows a rotation screen first.**
The live game appears one screen later (`vegas`, t=70-90).
4. **Live priority only takes over between screens.** A game that goes
2. **Live priority only takes over between screens.** A game that goes
live mid-screen waits for that screen to end (`live_priority`: live at
t=50, shown at t=60).
5. **An on-demand session that expires during scheduled-off keeps the panel
3. **An on-demand session that expires during scheduled-off keeps the panel
on** until the next minute boundary, because the schedule check runs at
most once a minute (`schedule`, t=190-210).
6. **A schedule window's end minute is inclusive**, and whether the panel
4. **A schedule window's end minute is inclusive**, and whether the panel
turns off at the start of that minute or the end depends on when in the
minute the first check runs.