Reconnecting to (or any client-side Save fetch of) an already-running
Sud showed the wrong step active and bogus remaining times, traced to
two independent bugs:
- recv()'s 'Save' handler always called send_forecast(doc), which
resimulates the *entire* schedule cold from step 0 - fine for a
not-yet-started Sud, but for one already running it silently
overwrote the forecast/forecast_step_starts that _reanchor_forecast()
had been accurately, continuously maintaining with a context-free
"starting now" guess. Now skipped whenever a run is already in
progress, re-sending what's already there instead.
- _reanchor_forecast() recomputes each step's real start time
asynchronously, so that recomputation can itself be (and routinely
is) superseded and discarded by a later transition's reanchor before
ever committing - and the next *successful* commit's "everything
before my index is real" filter would then preserve whatever stale
prediction was sitting there before, sometimes for a step that
hadn't even happened yet by the schedule's real position.
on_step_changed() now also records each step's start synchronously,
immune to that race.
- Client-side, update_sud_forecast() unconditionally reset sud_step_
index/forecast_step_starts/etc. on every 'Json' push - correct for
an actual Load, but connect()'s unconditional Save request produces
a standalone 'Json' push (no Step/State alongside it, unlike the
subscribe-triggered replay) for the *same* already-running schedule,
wiping the correct state with nothing left to restore it. Now only
resets when the incoming doc actually differs from the last one
processed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qvu5giu7gvRCyEWzf2Vpx