fix(acp): restore output_rx on every do_prompt exit path - #6665
Merged
Conversation
do_prompt only restored entry.output_rx on the success path after drain_agent_events completed. An input_tx.send failure, or the turn's task being aborted while suspended inside drain_agent_events, left the receiver permanently unrestored, wedging the session with "prompt already in progress" on every subsequent request. A PromptChannelGuard now owns the receiver for the whole do_prompt call and restores it on Drop, covering every exit path; drain_agent_events borrows the receiver instead of consuming it so the guard never loses ownership across the drain loop's await points.
bug-ops
force-pushed
the
fix/6661-acp-output-rx-leak
branch
from
July 27, 2026 22:36
7d514a6 to
4d7a5f1
Compare
bug-ops
enabled auto-merge (squash)
July 27, 2026 22:36
6 tasks
bug-ops
added a commit
that referenced
this pull request
Aug 16, 2026
* docs(readme): sync crate READMEs with commits since v0.22.3 Reconciles all 24 changed crate READMEs against the actual shipped implementation for the v0.22.3..HEAD range: new subsystems (risk-chain detection, capability scoping, plugin dependency graph, session spawn cap), several pre-existing factual errors unrelated to this release (inverted file-sandbox precedence, fabricated MCP config keys, wrong anomaly-detector defaults, stale trust-level names), and terminology/ API renames that had drifted out of sync with the code. * docs(specs): reconcile spec drift for commits since v0.22.3 Closes drift left after the skill-quarantine trust fixes (#6701, #6702, #6706, #6707, #6713), the subagent session-wide spawn cap (#6545), four post-ACP-2.0.0-migration bugfixes (#6660, #6665, #6672, #6684), the mention-picker and TUI interrupt-hint updates, the MAX_RETRY_SECS compile-time bound, the sanitizer secret-shape masking extension, the tracing-guard-flush invariants, and the VigilGate per-process pattern-compile fix. Updates specs/README.md's index to match. * docs(book): sync user docs with commits since v0.22.3 Updates the TUI keybindings and mention-picker pages for the new Ctrl+C semantics, the inline @ mention picker, and the input separator's busy indicator; documents the new [tools.shell] risk_chain_window_turns config key; corrects the ACP protocol version reference (was stale at 0.11.1); bumps the sub-agent frontmatter breaking-change note to v0.22.4. * fix(serve): give build_combined_deps_wires_policy_gate test a dedicated stack cargo nextest run --features full could crash with a stack overflow (SIGABRT) on serve::agent_factory::tests::build_combined_deps_wires_policy_gate_through_to_session_agent. Same defect class already fixed once in this file for issue #6699: building a full Agent under --features full's unboxed AnyProvider variants (Candle/Gonka/Cocoon) reaches the same VigilGate::try_new stack depth that overflows the default 2 MiB test-thread stack in an unoptimized build. The #6699 fix only wrapped the one test it was filed against, leaving this one - added in PR #6007, unrelated to any change in this release - unprotected. CI's test job never caught it because it runs the curated feature set, not full, so the deeper AnyProvider frames never materialize there. Runs the test body on a dedicated 32 MiB-stack thread instead of directly under #[tokio::test], reusing the existing TEST_THREAD_STACK_SIZE constant. * release: prepare v0.22.4 Bump version across the workspace, finalize the CHANGELOG.md [0.22.4] section, refresh the README tests badge, and re-accept the splash-screen snapshots (embed the version string).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
do_prompt(crates/zeph-acp/src/agent/turn.rs) only restoredentry.output_rxon the success path afterdrain_agent_eventscompleted. Aninput_tx.sendfailure returned early without restoring it, and the enclosing task being aborted while suspended insidedrain_agent_events(reachable since ACP permission gate deadlocks on every permission-gated tool call #6656 spawns the turn instead of awaiting it inline) dropped the receiver entirely — both permanently wedged the session with "prompt already in progress" on every subsequentsession/promptcall.PromptChannelGuard, an RAII guard that owns the session'soutput_rxreceiver for the entiredo_promptcall and restores it into the session onDrop, covering every exit path (normal return, early return, task abort/drop).drain_agent_eventsto borrow&mut mpsc::Receiver<LoopbackEvent>instead of consuming it by value, so the guard never loses ownership across the drain loop's await points.Closes #6661
Test plan
input_tx_send_failure_does_not_wedge_session— reproduces the issue's literal repro (dropped agent-loop channel causesinput_tx.sendfailure), asserts the specific"agent channel closed"error, and confirms the session recovers (acquire_prompt_channelssucceeds afterward).abort_mid_drain_does_not_wedge_session— spawnsdo_prompt, deterministically parks it insidedrain_agent_events'srx.recv(), aborts the task, and confirms the session recovers.two_consecutive_prompts_succeed_without_wedging_session— happy-path non-regression check.cargo +nightly fmt --checkcleancargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warningscleancargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins— full suite greenRUSTFLAGS="-D warnings" RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --workspace --features "desktop,ide,server,chat,pdf,scheduler") cleansignificantinitially (2 test gaps), both resolved and re-verifiedapproved, full CI-matching suite independently re-run