Objective
SessionController models six states. The device renders two of them, and the other
four resolve to the dashboard, so a driver gets no indication that a session has ended.
What happens today
ScreenRouter::service_session in firmware/main/screen_router.cpp reduces the whole
state machine to one boolean:
const auto active = snapshot.state == session::SessionState::running ||
snapshot.state == session::SessionState::overtime;
...
lv_screen_load(active ? trackday_root_ : home_screen());
The consequences:
| State |
Modelled |
On device |
running |
yes |
Track Day countdown |
overtime |
yes |
the same screen as running, with no indication the session is over |
review |
yes |
silently returns to the dashboard |
rest |
yes |
silently returns to the dashboard |
So the session simply vanishes when the clock expires. The driver is not told the
session ended, is not offered the review they were promised, and the rest period they
configured never appears — rest_duration_minutes is a live, editable setting that
currently has no observable effect on the device at all.
Overtime is the sharper problem of the two. It renders identically to running, so at
the moment the session ends the display gives no signal whatsoever. On a Track Day this
is exactly when the driver needs to know to come in.
Why this was not caught
These screens exist and are tested — #79 and #30 built rest, overtime, deliberate-stop
and post-session review, and #77 built the editors behind them. They were built against
the simulator, which has since been frozen (#134). The device never grew the routing to
reach them, and no test asserts that a device state maps to a screen, so nothing failed.
This is worth noting as a class of gap rather than a one-off: simulator-era screens
may be present, tested and unreachable on hardware. Other screens from the same
milestones should be audited the same way.
Scope
Depends on
Review content is thin until GNSS lands, but the routing, the overtime signal and the
rest period are all independent of it and are the driver-visible part.
Objective
SessionControllermodels six states. The device renders two of them, and the otherfour resolve to the dashboard, so a driver gets no indication that a session has ended.
What happens today
ScreenRouter::service_sessioninfirmware/main/screen_router.cppreduces the wholestate machine to one boolean:
The consequences:
runningovertimereviewrestSo the session simply vanishes when the clock expires. The driver is not told the
session ended, is not offered the review they were promised, and the rest period they
configured never appears —
rest_duration_minutesis a live, editable setting thatcurrently has no observable effect on the device at all.
Overtime is the sharper problem of the two. It renders identically to running, so at
the moment the session ends the display gives no signal whatsoever. On a Track Day this
is exactly when the driver needs to know to come in.
Why this was not caught
These screens exist and are tested — #79 and #30 built rest, overtime, deliberate-stop
and post-session review, and #77 built the editors behind them. They were built against
the simulator, which has since been frozen (#134). The device never grew the routing to
reach them, and no test asserts that a device state maps to a screen, so nothing failed.
This is worth noting as a class of gap rather than a one-off: simulator-era screens
may be present, tested and unreachable on hardware. Other screens from the same
milestones should be audited the same way.
Scope
SessionStateto a screen, with a test that fails when a state hasno mapping — an exhaustive
switchover the enum rather than a booleanthe running layout, and the countdown's behaviour once remaining time reaches zero
needs deciding (hold at 00:00, or count up)
appear only once the session has finished (Add a top-level Mode selection: Track Day, Race and G-Only #132)
Depends on
Review content is thin until GNSS lands, but the routing, the overtime signal and the
rest period are all independent of it and are the driver-visible part.