Commit Graph
11 Commits
Author SHA1 Message Date
2477d992f4 release: lock-disciplined STREAMS reads (#7339) (#7488)
* fix(streaming): lock-disciplined STREAMS reads via peek_stream()

Writers pop STREAMS under STREAMS_LOCK, but four hot reads used bare
STREAMS.get(): the streaming worker start, the gateway run start, and the two
SSE attach paths in routes.py. Each is individually saved today by GIL-atomic
dict.get plus a None-guard, but the check-then-act windows (get → register,
get → subscribe) race teardown pops, and the bare pattern invites unprotected
copies. peek_stream() centralizes the locked read; all four sites migrate with
no behavioral change.

* test: dual-patch config.STREAMS alongside routes.STREAMS in SSE seam tests

peek_stream() reads the canonical api.config.STREAMS registry; tests that
inject a fake registry by patching only the routes-level re-export left the
helper reading the real (empty) registry and hung the SSE loop to the
pytest-timeout ceiling. Mirror the test_issue6623 pattern: patch both
bindings.

* docs(changelog): stamp #7339 lock-disciplined STREAMS reads

---------

Co-authored-by: Sebastian B <sb@wmc.sh>
Co-authored-by: n <a@n>
2026-09-09 20:22:36 +00:00
tandrodboev 3188f88599 fix(#4812): break live SSE loop on a terminal event even when deduped at cutoff
Codex round-3 finding #2 [CORE]: when reconciliation replayed the active run's
terminal event at the subscribe cutoff, the live queue's copy hit the cutoff/dedup
'continue' BEFORE the terminal 'break' check — so the handler never broke, stayed
blocked on the dead run's queue, and missed subsequent session runs. Check the
terminal event type before the already-delivered continue: a terminal always ends
the loop (after emitting if not already sent). Regression test asserts the handler
unsubscribes (doesn't hang) when the terminal is deduped. 24/24 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:47:06 +00:00
tandrodboev 3ac19a5518 fix(#4812): capture idle SSE fingerprint baseline BEFORE first attach (TOCTOU)
Final-gate Codex caught a TOCTOU race in the prior idle-seam fix: the fingerprint
baseline was captured AFTER the first attach_active_stream() lookup, so a run
completing DURING that first attach folded into the baseline and was silently
missed (only : keepalive emitted, no snapshot). Move the baseline capture before
the first attach so any completion from that point on is detected. Add an ordering
regression test (baseline fp precedes the idle-loop attach + advance still emits
one snapshot). 23/23 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:24:47 +00:00
tandrodboev 2829843a2a fix(#4812): re-sync idle no-cursor SSE subscriber on run completing during keepalive wait
Fable gate found a seam Codex's 3 boundary findings didn't cover: an idle no-cursor
subscriber to /api/sessions/{id}/events misses a run that starts AND finishes inside a
single keepalive tick — the wait loop only looked for a live in-memory STREAMS entry to
attach, never noticing the journal advanced, so the run's transcript was silently missing
until manual refresh.

Add a cheap bounded session_journal_fingerprint() (file-count/max-mtime/total-size from
stat only, never parses bodies) and, inside the idle attach-wait loop, emit a session_snapshot
re-sync whenever the fingerprint advances with no live stream to attach — the same honest
recovery contract used for a failed reconciliation. Re-baselines after each re-sync so a quiet
idle connection never spams snapshots. 2 regression tests; 22/22 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:15:49 +00:00
Rod Boev 956c276362 fix(#4812): close session SSE replay recovery gaps 2026-07-10 10:46:47 -04:00
Rod Boev da885659bd fix(streaming): satisfy session SSE lint gate 2026-07-10 07:37:16 -04:00
Rod Boev b2a9ca28ad fix(streaming): harden session SSE replay (#4812) 2026-07-10 07:31:00 -04:00
Rod Boev 54ce5932f2 fix(streaming): clean up session SSE subscribers on replay disconnect (#4812) 2026-07-06 15:49:14 -04:00
Rod Boev 9b3538f1a6 fix(streaming): reject hostile session SSE cursors (#4812) 2026-07-06 11:25:59 -04:00
Rod Boev 4bc405d708 Keep cursorless active SSE backlog from disappearing 2026-07-06 05:42:03 -04:00
Rod Boev 720e4191ad feat(#4812): add resumable session SSE stream 2026-07-06 05:16:18 -04:00