A fine enough dt over a multi-hour brew can produce a single Forecast
message several MB in size - large enough to exceed the websockets
library's default 1 MiB max_size and get the connection closed outright
(code 1009) right after Load. Confirmed by reproducing with dt=0.1: the
276KB message at dt=1 was safe, but the equivalent ~2.7MB at dt=0.1
reliably disconnected the client.
SudTask._send_forecast() now thins T/Theta to at most MAX_FORECAST_POINTS
(1000) via simple decimation before sending - self.forecast_t/
forecast_theta themselves stay at full simulated resolution, since
_continue_forecast_after_confirm()'s bisect-based truncation needs exact
t-value matches, and SudLogTask's logs/forecast_*.json wants full
fidelity. Only the copy actually sent to clients is thinned, which the
GUI's few-hundred-pixel-wide plot can't show the difference from anyway.
Verified against a live server+client over the real WebSocket connection
with the dt=0.1 config that originally triggered the disconnect: 4/4
clean runs, forecast arrives capped under 1000 points, and the rendered
plot is visually identical to the un-downsampled version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk