Repository navigation
[Bug]: agent_prompt_stalled is reported for prompts that were delivered and submitted, and the retry pastes onto the leftovers #15976
Description
Summary
sendTerminalAgentPrompt reports agent_prompt_stalled when the prompt was delivered and Enter did land, if the agent answers without starting a turn. And because the paste concatenates onto whatever is already in the composer, each retry corrupts the next attempt — so a single false stall escalates into a garbled one.
Both halves were reproduced on v1.4.188 today.
The verification accepts exactly one kind of evidence
src/main/runtime/agent-prompt-submission-verification.ts:
function agentPromptLifecycleChanged(baseline, current): boolean {
return current.workingSequence > baseline.workingSequence
}workingSequence advances only in recordAgentPromptLifecycleState (orca-runtime.ts:12165-12185), on a null | idle | permission → working transition fed from OSC 9999 / OSC title status.
So the guard does not ask "was the prompt submitted?". It asks "did the agent start a turn within 5 s?". Those are different questions, and every submission the agent answers without starting a turn — a slash command, an unknown-command reply, anything handled locally by the TUI — is reported as a stall that did not happen.
Reproduction (2026-08-22, 14:20:37 → 14:20:45)
Composer pre-loaded with /hel, completion menu open. Then the exact Orca agent-prompt path — orca terminal send --text … --enter, which sets agentPrompt: true at src/cli/handlers/terminal.ts:114 and routes to sendTerminalAgentPrompt:
$ orca terminal send --terminal <h> --text 'Responda apenas: OK4' --enter --json
"error": { "code": "agent_prompt_stalled", "message": "agent_prompt_stalled" }
Screen immediately after:
● Unknown command: /helResponda
● Args from unknown skill: apenas: OK4
❯
Three things are visible at once:
- The paste concatenated.
/hel+Responda apenas: OK4became/helResponda apenas: OK4. Residual composer content silently corrupts an injected preamble. - The carriage return landed and submitted. Claude Code consumed the input and answered. The bracketed-paste race described in [Bug]: injected/sent prompts land in agent composer but are never submitted. Send reports success, worker sits idle. #14822 is not what happened here.
- Orca still reported
agent_prompt_stalled, because an unknown-command reply is not a turn, soworkingSequencenever advanced.
Why the two halves compound
A first attempt returns agent_prompt_stalled and leaves its text parked in the composer. The documented recovery is to retry — and the retry pastes on top of the leftovers. The second attempt is now both garbled and stalled, and each further retry makes the composer worse.
In a multi-lane run today this produced twelve failed dispatches against ten successful ones, on both Claude and Codex agents. Every recovery required clearing the composer by hand before the retry could work.
Why this is not the issues it resembles
- [Bug]: injected/sent prompts land in agent composer but are never submitted. Send reports success, worker sits idle. #14822 / [Bug]: worker-start injected prompt lands as unsubmitted draft in Claude worker (packaged Windows), blocking unattended orchestration #14505 — the
\rlanding inside the bracketed-paste window so the prompt is never submitted. Here the prompt was submitted; the failure is in the verdict, not the delivery. - fix(terminal): verify agent prompt submission #14962 — the change that introduced this verification. It closed a real defect: before it, an unsubmitted preamble was recorded as
accepted. That fix is correct and should stay. This report is about its false-positive edge, not about reverting it. - [Bug]: local worker-start stalls at dispatch_input before lifecycle preamble; release can end in tab_not_found #15920 — a dispatch failing at
dispatch_inputin the field, which is the downstream consequence when this fires duringworker-start.
Suggested direction
Two independent changes; either helps, both together close it.
Do not paste onto residual content. Clear the composer, or refuse and report, rather than concatenating an injected prompt onto whatever a previous attempt or a human left behind. Silent concatenation is the part that turns one failure into a cascade.
Widen the accepted evidence, or narrow the claim. A submission that produced any agent output is not a stall. If the guard cannot tell "answered without a turn" from "never received it", then the verdict it reports should say so — agent_prompt_unverified is honest where agent_prompt_stalled is not, and a coordinator retries very differently on each.
Environment
Windows 11 Pro 26200, Orca v1.4.188, Claude Code v2.1.240. The reproduction used a throwaway Orca terminal and the public CLI only. Not platform-specific: the verification and the paste path are shared.
Activity
AdamClaassens commentedon Aug 22, 2026
Additional Linux/OpenCode reproduction from Orca
1.4.188and OpenCode1.18.21. This strengthens the false-stall half of this issue and matches the downstream fenced-worker shape in #15920.Observed
Three lifecycle-bearing injections were classified
agent_prompt_stalledafter 5-7 seconds even though OpenCode had received the task and begun visible reasoning. Orca then revoked each capability while terminal output continued for another 10-20 seconds. All three processes were stopped before repository work occurred.ctx_2c80132b5a74worker-start --agent opencodedispatch_input3b34e55b9bb2d36293c556f9ecc2b34fa1262d48be33a5213ae0269b46898049Planning parallel repository inspections; output continued about 20s after revocationctx_1373faa62f62worker-start --retry-ofdispatch_inputdecffb17af7f91e77d9b4d8aa9790b6d11c09bc6263226aae103d418d672c46cctx_55fee9e30615dispatch --injectinjected5580c4b683452465f801a0ce69f381d5641d84bc589f110b093a689cfbdb181aRuntime:
fb9c8810-d416-4163-8d21-3992f9a59d6f. Full persisted process identities matched their exact terminal PTY/incarnation on every attempt:ctx_2c80132b5a74: PTY suffix@@c8d36afe, incarnation455b5b73-1cae-40eb-88ec-793c8d8a1348ctx_1373faa62f62: PTY suffix@@b612e5de, incarnationd84dc985-f414-4e45-a6a6-8ff786092a17ctx_55fee9e30615: PTY suffix@@55c57dec, incarnationf45e0234-e6b9-4077-9d6a-27e0ce237fa0A successful earlier OpenCode control,
ctx_8f9f23f65224, ran 15m45s, sent a heartbeat and validworker_done, and completed. It wasstage=context_onlywithcapability_hash=null, so it proves runtime/agent viability but does not exercise lifecycle injection settlement. Eight same-Run OpenCode successes had that same context-only/null-capability shape. All three lifecycle-bearing attempts failed.Simple task-spec length does not separate them: the failed specs were 4,356 and 4,728 bytes; successful same-Run OpenCode specs ranged from 2,677 to 7,187 bytes. Fresh versus pre-warmed readiness also did not separate them. The Orca process and OpenCode binary did not restart or change between the successful control and failures.
Telemetry request
Could the integration owner correlate these existing IDs through the settlement observer, without another reproduction? For each failed dispatch, the discriminating event chain is:
agent_prompt_stalledand revoked the capability.The installed guide/schema,
worker-show/worker-read, daemon log, and main trace expose none of that acknowledgement/correlation/timer chain. The remaining explanations are therefore bounded to missing, late, misrouted, or misinterpreted settlement evidence; the public records cannot distinguish them.Safety consequence: visible reasoning is not safe evidence of lifecycle readiness. In this reproduction the agents could continue acting after Orca had fenced them, so blindly retrying risks concurrent or unsupervised writers.
Tauri-EPO commentedon Sep 2, 2026
Another data point (Windows 11, Claude Code agent in the worker terminal,
orca orchestration worker-start --task <t> --worktree path:<lane> --terminal <handle>on an already-running agent terminal), 2026-09-01/02:state: failed,stage: dispatch_input,last_failure: agent_prompt_stalled. All 4 were delivered and executed minutes later (the agent's own screen showed the task text and a working spinner; two produced aworker_done). One was dispatched twice on the assumption it had failed, and the agent received both copies ("despacho duplicado — trabalho feito uma vez").heartbeatmessages never reached the coordinator run (only the finalworker_donedid) — consistent with the capability being revoked at the false stall ([Bug]: Orchestration preamble tells workers to IGNORE revoked capability, so coordinators waiting on worker_done never settle #16903).stage: input_acceptednormally. The difference seems to be delivery latency while the agent was finishing its previous turn, not agent boot.Net effect for a coordinator:
failed/dispatch_inputcannot be read as "not delivered"; re-dispatching duplicates work. Adelivered-lateoutcome (or a longer ack wait when the terminal is a known live agent) would remove the ambiguity.Tauri-EPO commentedon Sep 10, 2026
Retested on Orca 1.4.199 (Windows 11 Pro 26200, Claude Code 2.1.267, throwaway Orca terminal, public CLI only), 4 attempts, same shape as the original report:
/helpre-loaded in the composer, thenorca terminal send --terminal <h> --text 'Responda apenas: OK4' --enter --wait-submit 10 --json.Half 2 (false stall) no longer reproduces: 0/4. Every attempt returned
ok: truewithstages: ["input_accepted"]and noturn_started, no error, after the 10 s observation window. That is the receipt shape from #16904 (in 1.4.199): "accepted, submission not observed" instead ofagent_prompt_stalled.Half 1 (concatenation onto residual composer content) still reproduces: 4/4. Claude answered
Unknown command: /helResponda/Args from unknown skill: apenas: OK4each time, i.e. the injected text was pasted on top of the leftover/heland submitted as one line.Receipt from attempt 2 (others identical apart from ids):
So the remaining gap here is the composer hygiene part (clear or refuse on residual content), not the verdict.
brynnclaw commentedon Oct 1, 2026
Status on current
main, plus a proposed fix for the half that still reproduces.Half 2 (false
agent_prompt_stalled) looks addressed onmain. Every orchestration caller ofsendTerminalAgentPrompt(coordinator dispatch,dispatch --inject, worker start and federation throughdispatchPreambleSendOptions, plusterminal.sendwhen it runs under an orchestration mutation) and the agent-launch prompt now passacceptQueued+requestId. An unobserved turn start on those paths comes back as aninput_acceptedreceipt, not an error. The coordinator also keeps a second guard: if a stall still surfaces, it maps it todispatched-unobservedand does not resend. A plainterminal.sendagent prompt with no orchestration mutation still verifies strictly, so it can still report a stall. That matches the 1.4.199 retest above (0/4).Half 1 (paste concatenates onto residual composer text) still holds on
main. From reading the code:writeTerminalAgentPromptwrites the bracketed paste without looking at the composer. Nothing on the prompt path reads the screen before the paste. So/hel+Responda apenas: OK4still becomes/helResponda apenas: OK4. Any retry after an unobserved submit pastes a second copy onto the first.Orca already has the piece needed to see this:
detectTerminalComposerDraft(used byterminal readto split a composer draft out of the screen) recognizes the framed❯and bold›/»composers on the headless emulator. A fix on top of it, in the prompt path only:agent_prompt_composer_not_emptyand write nothing. This is the "refuse and report" option: a draft a human typed is never destroyed and never corrupted, and the caller gets a verdict it can act on.A long paste that the agent shows as a placeholder (for example
[Pasted text #1 +N lines]) cannot be proven to be ours. It falls under (2): the retry is refused instead of pasting a second copy.Tests drive the real headless emulator with a Claude-shaped framed composer:
/helin the composer: the send is refused and zero bytes are written. Onmainthe paste goes out.\r. Onmainthe prompt is pasted a second time.Not verified against a live Claude Code or Codex session. No captured PTY transcript of the Claude composer exists in the repo yet, so the frame in the tests is modeled on the shapes the existing
detectTerminalComposerDrafttests cover.PR #24245 implements this direction.
fix(agent-prompt): do not paste onto residual composer text
fix(agent-prompt): do not paste onto residual composer text