block / block/buzz

Owner control commands are unsendable from Buzz Desktop: is_owner_control_command's exact-content + p-tag requirements are jointly unsatisfiable from every composer flow

Open
#6,014 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

The owner control commands (`!rotate`, `!cancel`, `!shutdown`) cannot be issued from Buzz Desktop at all: `is_owner_control_command` requires an event that is simultaneously (a) content exactly equal to the command and (b) p-tagged to the agent — and **no Desktop composer flow produces that combination**. A mention pollutes the content; a bare message and a reply omit the `p` tag; a DM to a desktop-managed agent routes as a normal turn. Every attempt silently becomes a prompt.

This is adjacent to but distinct from #3711, which designs feedback for commands on the premise that they work. From the Desktop, they never fire — which is likely the real substrate of the "commands feel invisible" experience: a successful command and an unsendable one are indistinguishable in chat, and today's client can only produce the second.

## The matcher vs. the docs

`crates/buzz-acp/src/lib.rs` (at `6e5c462` / v0.2.1, fn `is_owner_control_command`):

```rust
kind_u32 == KIND_STREAM_MESSAGE
&& event.content.trim() == command // exact-match — undocumented
&& event_mentions_agent(event, agent_pubkey_hex) // p tag — documented
```

`crates/buzz-acp/README.md` (owner-command section) documents: kind:9, from owner, "must mention this agent with a `p` tag". It does **not** document the exact-content requirement. The two requirements are individually reasonable and jointly unsatisfiable from the client.

## Event-level evidence

Self-hosted relay (`ghcr.io/block/buzz:sha-6e5c462` = v0.2.1), Buzz Desktop 0.5.14 amd64 (Linux), harness `buzz-acp` self-built at the same commit running `claude-agent-acp` 0.68.0. Raw events as stored by the relay, all authored by the owner key:

**Attempt 1 — bare command:**
```json
content: "!rotate"
tags: [["h", ""]]
```
Content exact ✅ · p tag ❌ (composer adds no `p` without a mention) → routed as prompt.

**Attempt 2 — mention flow (`@Aero !rotate`):**
```json
content: "@Aero !rotate"
tags: [["h", ""], ["p", "851bc7fe…"]]
```
p tag ✅ · content ❌ (mention text lands in `content`) → routed as prompt; the agent received "!rotate" as conversation.

**Attempt 3 — reply to one of the agent's messages, body exactly `!rotate`:**
```json
content: "!rotate"
tags: [["h", ""], ["e", "6fb3356f…", "", "reply"]]
```
Content exact ✅ · p tag ❌ (Desktop replies add an `e` reply marker, not a `p` for the parent author) → routed as prompt.

**Attempt 4 — DM to a desktop-managed local agent (built-in persona):** the relay log shows the classic turn choreography, not an intercept — kind:9 ingested → two kind:7 reactions (👀/💬) → kind:5 deletions of both. An intercepted command produces no reactions (the handler consumes the event before the turn machinery). Same result in a DM.

Harness logs over the same window contain zero `!rotate received` lines; every attempt instead produced a model turn in which the agent speculated about what `!rotate` might be.

## Impact

- Session rotation/cancel/shutdown are unreachable from the product's own client; the only working reset is operator-side (restart the harness process).
- Users read this as "`!rotate` does nothing" — and with a local Claude Code agent that also cannot reply (#5317/#5390/#5322), the whole exchange is silent on both sides.
- #3711's acknowledgment UX, when it lands, would acknowledge nothing: there is no way to get a command consumed in the first place.

## Suggested fixes (any one unblocks)

1. **Relax the matcher** to accept a p-tagged owner message whose *trimmed content ends with* the command (or equals it after stripping leading mention tokens) — makes the existing mention flow (`@Agent !rotate`) work with no client change. Near-misses stay conservative: require the command to be the final token.
2. **Desktop: emit the right shape** — add the parent-author `p` tag on replies (also the NIP-10 convention), or give the composer a command affordance that strips the mention text from `content` while keeping the `p` tag (pairs naturally with #3711 part 2's `!` palette).
3. **Document the exact-content requirement** in `crates/buzz-acp/README.md` meanwhile, so self-hosters can at least issue commands via the CLI with a hand-built event.

## Related

#3711 (feedback for consumed commands — premise: they work), #5317 / #5390 / #5322 (local Claude Code agents mute — the companion failure that makes this one fully silent), #3380 (`!model`, same handler block).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.