You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ACP "redirect" fabricates empty ~1ms turn_completes when the agent advertises steering=false, wedging the conversation (cancelled/pending_review) and swallowing the send #590
When a user sends a prompt to an ACP agent that does not support mid-turn steering, Codeg's "Redirected the active turn with your correction" flow fabricates an empty turn_complete ~1ms later, moves the conversation to cancelled or pending_review (the status is not deterministic), and leaves the row unable to send. The prompt is either lost entirely, or — worse — it does land in the agent's store and gets answered, but the reply never streams back because the turn was already closed client-side.
Observed with: codeg-server v0.28.1 (native binary), agent = Hermes 0.20.5 via hermes acp, which advertises steering: advertised=false. Four incidents on our fleet in 48 hours (JAR-1103, JAR-1133, JAR-990, and another today), all on the same production server.
Two sends while the agent had a live turn that was invisible to Codeg's session state (an out-of-band background-process notification had just been injected into the session at 00:30:00Z):
After that: the conversation row stayed pending_review (an earlier incident flipped to cancelled instead — non-deterministic), every further send failed with no surfaced error, and the agent's real turn_complete never arrived (row still stuck 10+ minutes later; auto-reconcile is not guaranteed).
The insidious part — the first send (00:31:26) was lost for good (never reached the agent store), but the second (00:33:29.680Z, same instant as the synthetic completion) landed and was answered: the agent persisted its reply at 00:34:10 (finish_reason=stop), and it never streamed to the tab because the turn had already been closed client-side.
Diagnostic signature for anyone reproducing: grep the server log for the session uuid and look for Prompting → turn_complete pairs with sub-2ms deltas (an earlier incident had three swallowed sends within 8s).
Trigger hypothesis
The redirect path appears to be attempted unconditionally when a send races an agent turn, even when the agent advertised steering: advertised=false. Two candidate triggers, both observed today:
Invisible live turn — a background-process notification was injected out-of-band into the session (user-role message, 00:30:00Z), so the agent was mid-turn while Codeg's session state said idle. The send became a "redirect" that could not be delivered.
Stale session identity after compression rotation — Hermes rotated its session id mid-conversation (compression, 11:48Z); Codeg's row still maps the old id. Lineage resolution makes load_session work, but the conversational redirect/status logic may key on stale state.
Either way the agent cannot accept the correction, so an empty completion is synthesized and the row's status is flipped — which is the destructive part.
Suggested fixes (any one of these materially helps)
When steering: advertised=false, never attempt the redirect flow for mid-turn sends. Queue the prompt for the next turn, or surface a clear "agent is busy" state, instead of fabricating a completion.
Don't flip a regular conversation's status (cancelled/pending_review) from an empty synthetic completion — keep the row sendable and the client-stream in sync.
Summary
When a user sends a prompt to an ACP agent that does not support mid-turn steering, Codeg's "Redirected the active turn with your correction" flow fabricates an empty
turn_complete~1ms later, moves the conversation tocancelledorpending_review(the status is not deterministic), and leaves the row unable to send. The prompt is either lost entirely, or — worse — it does land in the agent's store and gets answered, but the reply never streams back because the turn was already closed client-side.Observed with: codeg-server v0.28.1 (native binary), agent = Hermes 0.20.5 via
hermes acp, which advertisessteering: advertised=false. Four incidents on our fleet in 48 hours (JAR-1103, JAR-1133, JAR-990, and another today), all on the same production server.Wire evidence (server log, connection
d7f4cd4d-…, conversation "Tackle App Launch review batch")Real turns take seconds to minutes:
Two sends while the agent had a live turn that was invisible to Codeg's session state (an out-of-band background-process notification had just been injected into the session at 00:30:00Z):
After that: the conversation row stayed
pending_review(an earlier incident flipped tocancelledinstead — non-deterministic), every further send failed with no surfaced error, and the agent's realturn_completenever arrived (row still stuck 10+ minutes later; auto-reconcile is not guaranteed).The insidious part — the first send (00:31:26) was lost for good (never reached the agent store), but the second (00:33:29.680Z, same instant as the synthetic completion) landed and was answered: the agent persisted its reply at 00:34:10 (
finish_reason=stop), and it never streamed to the tab because the turn had already been closed client-side.Diagnostic signature for anyone reproducing: grep the server log for the session uuid and look for
Prompting → turn_completepairs with sub-2ms deltas (an earlier incident had three swallowed sends within 8s).Trigger hypothesis
The redirect path appears to be attempted unconditionally when a send races an agent turn, even when the agent advertised
steering: advertised=false. Two candidate triggers, both observed today:Either way the agent cannot accept the correction, so an empty completion is synthesized and the row's status is flipped — which is the destructive part.
Suggested fixes (any one of these materially helps)
steering: advertised=false, never attempt the redirect flow for mid-turn sends. Queue the prompt for the next turn, or surface a clear "agent is busy" state, instead of fabricating a completion.cancelled/pending_review) from an empty synthetic completion — keep the row sendable and the client-stream in sync.turn_completeto the conversation instead of discarding it (same direction as Complete grok turns when the session/prompt response is lost #553 for grok).#539(journal sent prompts) would at least make recovery lossless.Environment
--supervise), agent Hermes 0.20.5 viahermes acp(steering: advertised=false,native=false)pending_reviewend-state, different trigger), fix(acp): journal sent prompts so an interrupted chat cannot reopen blank #539, Complete grok turns when the session/prompt response is lost #553, [Bug] 旧 generation 的 cancelled 事件会清空新 generation 的待处理请求 #564/fix(tasks): preserve current waits after stale generation completion #567 (fixed)