Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion src/agent/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,7 +1759,13 @@ impl Channel {

// Listen-first guardrail:
// ingest all messages, but only reply when explicitly invoked.
if self.listen_only_mode && message.source != "system" && !self.is_dm() {
// Cron-originated messages carry a platform source (e.g., "slack") for adapter
// routing but use sender_id="system" — exempt them from suppression.
if self.listen_only_mode
&& message.source != "system"
&& message.sender_id != "system"
&& !self.is_dm()
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{
(invoked_by_command, invoked_by_mention, invoked_by_reply) =
self.compute_listen_mode_invocation(&message, &raw_text);

Expand Down Expand Up @@ -3684,6 +3690,36 @@ mod tests {
assert!(!invoked_by_reply);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test recomputes a local boolean instead of driving the actual channel suppression logic, so it can still pass even if handle_message or the batch path regresses. This bug class needs a behavior-level regression test that exercises the real guard branch, and it should include the coalesced batch case because that is the remaining unprotected path.

}

#[test]
fn listen_only_guard_allows_cron_messages_through() {
// Cron messages have source="slack" (for adapter routing) but sender_id="system".
// The listen-only guard must not suppress them.
let mut message = inbound_message("slack", &[], "Check the weather");
message.sender_id = "system".into();
message.conversation_id = "cron:daily-weather".into();

// compute_listen_mode_invocation returns all false — no command/mention/reply
let (cmd, mention, reply) =
compute_listen_mode_invocation(&message, "Check the weather");
assert!(!cmd);
assert!(!mention);
assert!(!reply);

// The guard condition should NOT enter suppression because sender_id == "system"
let listen_only = true;
let source_is_system = message.source == "system"; // false
let sender_is_system = message.sender_id == "system"; // true
let is_dm = is_dm_conversation_id(&message.conversation_id); // false

// Full guard: all four conditions must be true to suppress
let would_suppress =
listen_only && !source_is_system && !sender_is_system && !is_dm;
assert!(
!would_suppress,
"cron messages (sender_id=system) must bypass listen-only suppression"
);
}

#[test]
fn discord_quiet_mode_ping_ack_requires_directed_ping() {
let directed_message = inbound_message(
Expand Down