Two remaining stuck/incorrect busy-state edge cases from the post-#483
spinner audit (OPE-193):
- B1: when a turn ended but the session.idle SSE event was delayed or
lost, the busy spinner kept showing until the next watchdog poll tick
(~5s) and its escalation (~10s). An assistant message.updated that
carries time.completed now triggers one immediate directory status
poll (monotonic confirm, authoritative settle when the snapshot
reports the session idle) — recovery drops to a single round-trip,
with one in-flight fetch per directory and the watchdog poll as the
backstop.
- C1: the streaming derivation marked the trailing assistant message as
streaming while the session stayed busy even after the server stamped
time.completed (whole response incl. tools finished) — the typing
indicator and streaming part-update suspension lingered on finished
content until the session settled or the next message started. A
completed trailing message is now never marked streaming; both the
full and incremental derivations complete the previous streaming
message instead.
Refs OPE-193