The reconnect loop does not reproduce; log who falls behind

Measured against a session streaming 20 events a second. Reopening one with
an anchor 1,800 events back connects 87-119 events behind, under
CATCH_UP_LIMIT's 200 -- the restore is two requests now, the opening page
and one span covering the whole distance to the anchor, where the report
was written against a restore that took thirteen. Three provocations, no
repeat connection between them: that reopen, twenty seconds backgrounded
while 415 events were produced, and a reset forced by dropping the limit to
5, where the app cleared, refilled and carried on without reconnecting.

So the TODO entry goes. What stays is the instrument that answered it:
every SSE subscriber now logs at debug the cursor it arrived with and
whether it was continued or reset, since nothing else could say. The app
sees a window arrive and cannot tell how far it had fallen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-04 14:01:01 -04:00
1 parent 45e631ab96
commit 74110b4d72
3 files changed
+31 -14

No files matched your search

+19
View File
@@ -541,6 +541,25 @@ first if a remote spawn ever mangles an argument.
`pm grant ... POST_NOTIFICATIONS`. And a saved scroll anchor is per session
id, so the only way two builds start a scroll from the same place is a
*fresh session for each*.
- **A phone that falls behind the stream is answered with `reset`, and
`RUST_LOG=ai_server=debug` says when.** Every SSE subscriber logs the
cursor it arrived with and whether it was continued or reset
(`stream backlog:` in `send_backlog`), which is the only place that
question is answerable: the app sees a window arrive and cannot tell how
far it had fallen, and a reset is the one thing that makes its screen jump
to the newest end. Measured 2026-09-04 against a session streaming at 20
events a second: reopening one with an anchor 1,800 events back connects
**87-119 events behind**, well under `CATCH_UP_LIMIT`'s 200, because the
restore is two requests -- the opening page, then one span covering the
whole distance to the anchor. So the reset path is not reachable by
reopening a session, and **to exercise it at all you have to lower
`CATCH_UP_LIMIT`** in a throwaway server build; at 5 the app takes the
reset on a live connection, clears, refills and carries on without
reconnecting. Worth knowing alongside it: **the session screen's stream
survives backgrounding here** -- 20 seconds at the launcher while 415
events were produced brought no reconnect at all -- which is not what the
comment above that loop expects, and is most likely this emulator being
headless rather than the phone's behaviour.
- **`ai-server --delay MS` holds every response back.** Over the tunnel a
phone's requests take tens to hundreds of milliseconds, and several
faults live entirely in what the app does *while* one is outstanding. On