Stream drop races the whole turn after a 5s grace (M-01)
Surfaced by the gpt-5.6-sol final review (reproduced: SSE dropped at 30ms + /message succeeding at 6.2s → turn failed at ~5.8s with terminated and an empty final message).
In captureTurn() (opencode.mjs), eventStreamDropPromise gives a closed event stream only DEFAULT_STREAM_DROP_GRACE_MS (5s) before resolving the outer race; then a single recoverFinalMessageFromServer() attempt runs, and if it comes back empty the turn is failed — even while the held-open /message request is still pending and would succeed. The existing regression fixture delays the response by only 300ms, below the boundary.
Fix: treat stream closure as loss of one observation channel, not turn completion. Keep waiting on the pending /message response and/or poll message state until the outer turn timeout, a terminal error, or a verified completed message.
Tests: response completing just below, at, and above the grace boundary; a long simulated turn with accelerated timers.
Source: gpt-5.6-sol final review M-01 (opencode-plugin-cc-analysis.md). Builds on #12/#15.
Stream drop races the whole turn after a 5s grace (M-01)
Surfaced by the gpt-5.6-sol final review (reproduced: SSE dropped at 30ms +
/messagesucceeding at 6.2s → turn failed at ~5.8s withterminatedand an empty final message).In
captureTurn()(opencode.mjs),eventStreamDropPromisegives a closed event stream onlyDEFAULT_STREAM_DROP_GRACE_MS(5s) before resolving the outer race; then a singlerecoverFinalMessageFromServer()attempt runs, and if it comes back empty the turn is failed — even while the held-open/messagerequest is still pending and would succeed. The existing regression fixture delays the response by only 300ms, below the boundary.Fix: treat stream closure as loss of one observation channel, not turn completion. Keep waiting on the pending
/messageresponse and/or poll message state until the outer turn timeout, a terminal error, or a verified completed message.Tests: response completing just below, at, and above the grace boundary; a long simulated turn with accelerated timers.
Source: gpt-5.6-sol final review M-01 (
opencode-plugin-cc-analysis.md). Builds on #12/#15.