What
travel.py tracks campaign.time_of_day but build_combat_surface (viewer/server.py) does not surface it — so the renderer's day-plate selection (#1298) ships on a box-side sentinel instead of the engine's own clock. Add time_of_day to the /combat-surface payload (additive, defaulted) and switch the renderer's day-selection to prefer the surfaced field over the sentinel (sentinel stays as the QA override).
Acceptance
- /combat-surface carries time_of_day (additive; absent == today)
- renderer prefers surface field; _time_of_day.txt sentinel = explicit override only
- single-process tests on the surface builder + fast_gate green
Invariants
Wire-contract additive-only; engine = sole writer (the renderer READS the clock, never sets it).
What
travel.py tracks campaign.time_of_day but build_combat_surface (viewer/server.py) does not surface it — so the renderer's day-plate selection (#1298) ships on a box-side sentinel instead of the engine's own clock. Add time_of_day to the /combat-surface payload (additive, defaulted) and switch the renderer's day-selection to prefer the surfaced field over the sentinel (sentinel stays as the QA override).
Acceptance
Invariants
Wire-contract additive-only; engine = sole writer (the renderer READS the clock, never sets it).