buzz-acp: SubscribeMode::All subscribes to every event kind — typing indicators (kind:20002) open agent turns and cancel pending wakeups
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Environment
- Buzz Desktop v0.5.5 (`8342dfcc`), bundled `buzz-acp`
- Managed agent, `backend: local`, Claude runtime (`claude-agent-acp` 0.65.0)
- `BUZZ_ACP_SUBSCRIBE=all` (set so the agent answers the owner without requiring a mention)
## Observed
With `subscribe=all`, the agent's turns are repeatedly triggered by **kind:20002 typing indicators** (empty content, ephemeral):
1. Four separate turns in one session were opened by typing events — the user only started typing; the actual kind:9 message arrived mid-turn as a separate notification.
2. The harness passed the ephemeral event as the trigger and set it as the reply target (`--reply-to <20002 event id>`). Ephemeral events are not persisted, so replies would thread against a nonexistent root.
3. A pending scheduled wakeup (Claude Code `ScheduleWakeup`, due in 109s) was at risk of cancellation when a typing indicator opened a turn: pending wakeups are cancelled on incoming user activity by design, but here *pressing a key* — without ever sending a message — was enough to count as user activity.
## Root cause
`crates/buzz-acp/src/config.rs`, subscription filter construction:
- `SubscribeMode::Mentions` defaults to an explicit kind list: `[KIND_STREAM_MESSAGE (9), KIND_WORKFLOW_APPROVAL_REQUESTED (46010), KIND_STREAM_REMINDER (40007)]`.
- `SubscribeMode::All` builds `ChannelFilter { kinds: config.kinds_override.clone(), require_mention: false }` — when `BUZZ_ACP_KINDS` is not set, `kinds` is `None`, which the relay subscription treats as **wildcard (all kinds)**.
So "all" silently changes meaning from *"all messages (no mention required)"* to *"all event kinds"*, pulling in ephemeral kinds (typing 20002, etc.) as turn triggers.
## Expected
`All` should mean "the same message kinds as Mentions, without the mention requirement". Suggested fix:
```rust
SubscribeMode::All => {
let kinds = config.kinds_override.clone().unwrap_or_else(|| vec![
KIND_STREAM_MESSAGE,
KIND_WORKFLOW_APPROVAL_REQUESTED,
KIND_STREAM_REMINDER,
]);
// kinds: Some(kinds), require_mention: false
}
```
## Impact
- Every keystroke-start burns an agent turn (quota + noise for subscription-billed runtimes).
- Scheduled wakeups die when the user touches the keyboard — breaks any agent that timers long-running work.
- Replies threaded to ephemeral events produce broken threads.
## Workaround
`BUZZ_ACP_KINDS=9,40007,46010` alongside `BUZZ_ACP_SUBSCRIBE=all` restores the intended behavior.
Contributor guide
Assessment
This issue has not been assessed yet.