diff --git a/crates/buzz-acp/src/base_prompt.md b/crates/buzz-acp/src/base_prompt.md index 83b935717..3dd4945ae 100644 --- a/crates/buzz-acp/src/base_prompt.md +++ b/crates/buzz-acp/src/base_prompt.md @@ -72,6 +72,10 @@ When in doubt, prefer the reply destination explicitly supplied in `[Context]`. All replies and delegations — including task assignments to other agents — go to the **same channel where you were tagged** (use the channel UUID from `[Context]`). Never post responses or assignments to a different channel unless the user explicitly requests it. +### Forum Channels + +Forum channels are not stream channels, and the reply kind must match the thread root. Before replying, inspect the root kind in `[Context]`; if `[Context]` gives only a root event ID, fetch that root with `buzz messages thread --channel --event ` before choosing a kind. Use the stream default kind `9` for replies beneath a kind-`9` root, even if the channel also hosts forum posts. For a new forum thread, send kind `45001`: `buzz messages send --channel --kind 45001 --content "..."`. Only beneath a kind-`45001` forum root, send replies as kind `45003` with the supplied `--reply-to `. Never send kind `45003` beneath a kind-`9` root. + ### General - Respond promptly to @mentions. Be direct — no preamble. Name what you did, what you found, or what you need. diff --git a/crates/buzz-acp/src/lib.rs b/crates/buzz-acp/src/lib.rs index 7fd40b83d..abac9bba2 100644 --- a/crates/buzz-acp/src/lib.rs +++ b/crates/buzz-acp/src/lib.rs @@ -4463,6 +4463,18 @@ mod agent_draft_prompt_tests { .contains("add them explicitly with `buzz channels add-member` only when authorized")); assert!(prompt.contains("never changes membership automatically")); } + + #[test] + fn shared_base_prompt_distinguishes_forum_kinds_from_stream_messages() { + let prompt = include_str!("base_prompt.md"); + assert!(prompt.contains("Forum channels are not stream channels")); + assert!(prompt.contains("kind `45001`")); + assert!(prompt.contains("kind `45003`")); + assert!(prompt.contains("stream default kind `9`")); + assert!(prompt.contains("if `[Context]` gives only a root event ID")); + assert!(prompt.contains("buzz messages thread --channel --event ")); + assert!(prompt.contains("Never send kind `45003` beneath a kind-`9` root")); + } } fn default_heartbeat_prompt() -> String { diff --git a/crates/buzz-cli/src/lib.rs b/crates/buzz-cli/src/lib.rs index 2b041da57..2c137faab 100644 --- a/crates/buzz-cli/src/lib.rs +++ b/crates/buzz-cli/src/lib.rs @@ -371,7 +371,7 @@ buzz agents archived" pub enum MessagesCmd { /// Send a message to a channel #[command( - after_help = "Examples:\n buzz messages send --channel --content \"hello\"\n buzz messages send --channel --content \"@alice check this\"\n echo \"hello from stdin\" | buzz messages send --channel --content -" + after_help = "Examples:\n buzz messages send --channel --content \"hello\"\n buzz messages send --channel --content \"@alice check this\"\n buzz messages send --channel --kind 45001 --content \"new forum thread\"\n buzz messages send --channel --kind 45003 --reply-to --content \"forum reply\"\n echo \"hello from stdin\" | buzz messages send --channel --content -" )] Send { /// Channel UUID (from 'buzz channels list') diff --git a/desktop/src-tauri/src/managed_agents/nest.rs b/desktop/src-tauri/src/managed_agents/nest.rs index a57676f0a..d1d85f281 100644 --- a/desktop/src-tauri/src/managed_agents/nest.rs +++ b/desktop/src-tauri/src/managed_agents/nest.rs @@ -50,7 +50,7 @@ const NEST_AGENTS_VERSION: u32 = 4; /// Template content version for SKILL.md. /// Bump this when changing `nest_skill.md` to trigger refresh on existing installs. -const NEST_SKILL_VERSION: u32 = 5; +const NEST_SKILL_VERSION: u32 = 6; const BEGIN_MARKER: &str = ""; diff --git a/desktop/src-tauri/src/managed_agents/nest/tests.rs b/desktop/src-tauri/src/managed_agents/nest/tests.rs index cbef171f6..299b1af27 100644 --- a/desktop/src-tauri/src/managed_agents/nest/tests.rs +++ b/desktop/src-tauri/src/managed_agents/nest/tests.rs @@ -41,6 +41,14 @@ fn nest_skill_contains_safe_mention_workflow() { assert!(BUZZ_CLI_SKILL_MD.contains("never changes membership automatically")); } +#[test] +fn nest_skill_contains_forum_workflow() { + assert!(BUZZ_CLI_SKILL_MD.contains("forum root as kind `45001`")); + assert!(BUZZ_CLI_SKILL_MD.contains("forum reply as kind `45003`")); + assert!(BUZZ_CLI_SKILL_MD.contains("reply kind must match the thread root")); + assert!(BUZZ_CLI_SKILL_MD.contains("Never use kind `45003` beneath a kind-`9` root")); +} + #[test] fn ensure_nest_creates_all_dirs_and_agents_md() { let tmp = tempfile::tempdir().unwrap(); diff --git a/desktop/src-tauri/src/managed_agents/nest_skill.md b/desktop/src-tauri/src/managed_agents/nest_skill.md index 79a5ea301..264b16743 100644 --- a/desktop/src-tauri/src/managed_agents/nest_skill.md +++ b/desktop/src-tauri/src/managed_agents/nest_skill.md @@ -94,6 +94,14 @@ buzz messages send --channel \ --content "@Alice check this" --mention ``` +**Forum messages:** Forum roots and comments are distinct from stream messages, and the reply kind must match the thread root. Check the root kind before replying: omit `--kind` (or use kind `9`) beneath a kind-`9` stream root, even in a forum-capable channel. Send a forum root as kind `45001`; only beneath a kind-`45001` forum root, send a forum reply as kind `45003` with `--reply-to `. Never use kind `45003` beneath a kind-`9` root. + +```bash +buzz messages send --channel --kind 45001 --content "New discussion" +buzz messages send --channel --kind 45003 \ + --reply-to --content "Reply" +``` + ## DM Management `dms hide --channel ` hides a DM from the agent's DM list. Restore by re-opening with `dms open --pubkey `.