Emit SSE heartbeats carrying attempt and backend state #123
No reviewers
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-proxy!123
Loading…
Reference in a new issue
No description provided.
Delete branch "sse-heartbeats"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #104, the emitting half.
A caller waiting on a streaming completion cannot tell four states apart: admitted-and-queued, retrying, generating, and hung. All four look like silence followed by either a response or a deadline.
Wire shape
Lines beginning with
:are SSE comments. Every spec-compliant client ignores them, so a consumer that does not parse them sees the samedata:frames as before - which is the reason the issue preferred comments over empty-delta chunks.PROXY_HEARTBEAT_INTERVAL(default 10s,0disables) repeats the current state so a state that persists stays visible without a transition.Retry visibility is what earns this
sirens-echo#137records three attempts burning ~9s before a turn 502s, and from outside that is indistinguishable from one slow attempt.attempt n of Nturns a silent fallback into something a caller can log, display, and alert on.test_attempt_number_surfaces_a_silent_fallbackis that case end to end.Queue position is not carried
#105 measured admission delay at 0.7-4.5ms across 29 traces while
queue.waititself varied 25-fold, so there is nothing to report at current traffic. It is also moot on this path: the streaming surface callsdispatch_streamdirectly and never touches the queue. Whether position is worth carrying under concurrency is #107's question, and the payload has room for it when that is answered.This does mean the issue's first acceptance line - "a streaming request that waits in admission receives at least one heartbeat" - is vacuously true rather than demonstrated, because a streaming request does not wait in admission today. Flagging that rather than claiming it.
How to verify
ward exec test-tests/test_heartbeats.py, 8 cases.test_attempt_state_precedes_the_first_content_deltaasserts the comment arrives before any content.test_a_consumer_ignoring_comments_sees_unchanged_outputasserts thedata:frames are unchanged against a heartbeats-disabled run.test_keepalives_fire_while_a_state_persistsasserts the shielded read is never lost to a tick.Test plan
ward exec format-check,lint,typecheck,pre-commitall cleanRisk
Low, and bounded by the SSE spec. The one real exposure is a non-spec-compliant client that chokes on comment lines;
PROXY_HEARTBEAT_INTERVAL=0still leaves the state markers, so a deployment that needs the old byte stream exactly wants the emission off rather than the interval at zero. Say the word and I will add that switch.This changes nothing a user sees on its own
The issue says so plainly and I am repeating it: a total request deadline ignores heartbeats by construction.
sirens-echomust move to an idle or read timeout before any of this alters an outcome. That half lives in that repository.Note
Branched off
backend-regime-spans(#122), which sits on #120, #119, #118. Theregimefield onattemptcomes from #122. Review the chain in order.Pull request closed