buzz-acp: non-steerable ACP agents (oh-my-pi/omp) silently drop mid-turn messages (ExpectedRunIdMissing deadlock)
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
### Non-steerable ACP agents (e.g. oh-my-pi/omp) silently drop mid-turn messages
**Environment**
- repo: block/buzz @ ac4fa13, buzz-acp 0.5.3
- agent: `omp acp` (oh-my-pi 17.2.3, an ACP server that does not advertise steering)
- relay: hosted community, `subscribe=Mentions`, `meh=Steer`, `parallelism=10`, `max_turn_duration=7200`
**Symptom**
The agent connects fine (owner resolved, channel subscribed, presence online). But every user message is logged and dropped:
```
steer: no active_run_id and agent did not advertise _session/steering — falling back to cancel+merge
non-cancelling steer ack received … ack=Ok(Err(ExpectedRunIdMissing)) signal_fallback=true
```
No `session/prompt` ever fires; the user sees a "typing" indicator but never receives a reply. Reproduced on every message across multiple sessions.
**Root cause (from source)**
1. `lib.rs` relay-event gate (`if accepted && queue.is_channel_in_flight(…)`) routes an event to a steer signal when the channel is marked in-flush.
2. omp advertises neither `_meta.steering.supported` nor goose `activeRunId`, so `try_native_steer` returns false → falls back to `signal_in_flight_task` (`ControlSignal::Steer`).
3. `acp.rs` steer arm acks `SteerError::ExpectedRunIdMissing`; the main loop maps that to the cancel+merge fallback.
4. `pool.rs:1954` `if agent.acp.has_in_flight_prompt()` is **false** for omp → the "already completed" branch runs, and for `Steer` `apply_completed_before_control_signal` does **nothing** — the message is stranded.
5. The queue stays `in_flight` (deadline = `max_turn_duration`, kept alive by `extend_in_flight_deadline`) → `flush_next` excludes the channel → the queued event is never re-dispatched.
Steerable agents (claude-agent-acp, goose) don't hit this because their turn exposes a cancel/merge target.
**Proposed fix direction**
When a mode-gate Steer/cancel is required for a channel whose agent has **no active in-flight prompt** (non-steerable / stale `in_flight`), do not fire a steer signal into a void — release the channel (`queue.mark_complete(channel_id)`) and let `dispatch_pending` re-prompt the queued event as a fresh `session/prompt`. A check of the channel's prompt-task agent state (or completion-time reconciliation) distinguishes "genuinely in-flight" from "stale".
**Acceptance**
With a non-steerable ACP agent: sending a DM should produce a real `session/prompt` and the reply should be published. Steerable agents must remain unchanged.
Contributor guide
Assessment
This issue has not been assessed yet.