From 43fceb9117f0e25e9c04ae7bd87643df4d7088be Mon Sep 17 00:00:00 2001 From: Jiayuan Date: Tue, 31 Mar 2026 12:26:26 +0800 Subject: [PATCH] fix(inbox): skip inbox notification for task:completed events Task completion is already visible from the issue status change, so a separate inbox notification is unnecessary noise. --- server/cmd/server/notification_listeners.go | 37 +------------------ .../cmd/server/notification_listeners_test.go | 16 +++----- 2 files changed, 6 insertions(+), 47 deletions(-) diff --git a/server/cmd/server/notification_listeners.go b/server/cmd/server/notification_listeners.go index 0f471806..0443b37a 100644 --- a/server/cmd/server/notification_listeners.go +++ b/server/cmd/server/notification_listeners.go @@ -543,42 +543,7 @@ func registerNotificationListeners(bus *events.Bus, queries *db.Queries) { ) }) - // task:completed — notify all subscribers except the agent - bus.Subscribe(protocol.EventTaskCompleted, func(e events.Event) { - payload, ok := e.Payload.(map[string]any) - if !ok { - return - } - agentID, _ := payload["agent_id"].(string) - issueID, _ := payload["issue_id"].(string) - if issueID == "" { - return - } - - // Look up issue to get the title - issue, err := queries.GetIssue(ctx, parseUUID(issueID)) - if err != nil { - slog.Error("task:completed notification: failed to get issue", "issue_id", issueID, "error", err) - return - } - - // Use the agent ID as an exclusion (since the agent did the work) - exclude := map[string]bool{} - if agentID != "" { - exclude[agentID] = true - } - - notifySubscribers(ctx, queries, bus, issueID, issue.Status, e.WorkspaceID, - events.Event{ - Type: e.Type, - WorkspaceID: e.WorkspaceID, - ActorType: "agent", - ActorID: agentID, - }, - exclude, "task_completed", "attention", - issue.Title, "", - emptyDetails) - }) + // task:completed — no inbox notification (completion is visible from status change) // task:failed — notify all subscribers except the agent bus.Subscribe(protocol.EventTaskFailed, func(e events.Event) { diff --git a/server/cmd/server/notification_listeners_test.go b/server/cmd/server/notification_listeners_test.go index 441f11f9..88529123 100644 --- a/server/cmd/server/notification_listeners_test.go +++ b/server/cmd/server/notification_listeners_test.go @@ -471,8 +471,8 @@ func TestNotification_AssigneeChanged(t *testing.T) { } } -// TestNotification_TaskCompleted verifies that subscribers get a "task_completed" -// notification when a task completes, excluding the agent. +// TestNotification_TaskCompleted verifies that task:completed events do NOT +// create inbox notifications (completion is visible from the status change). func TestNotification_TaskCompleted(t *testing.T) { queries := db.New(testPool) bus := newNotificationBus(t, queries) @@ -503,16 +503,10 @@ func TestNotification_TaskCompleted(t *testing.T) { }, }) - // Creator should get a task_completed notification + // No inbox notification should be created for task:completed creatorItems := inboxItemsForRecipient(t, queries, testUserID) - if len(creatorItems) != 1 { - t.Fatalf("expected 1 inbox item for creator, got %d", len(creatorItems)) - } - if creatorItems[0].Type != "task_completed" { - t.Fatalf("expected type 'task_completed', got %q", creatorItems[0].Type) - } - if creatorItems[0].Severity != "attention" { - t.Fatalf("expected severity 'attention', got %q", creatorItems[0].Severity) + if len(creatorItems) != 0 { + t.Fatalf("expected 0 inbox items for creator on task:completed, got %d", len(creatorItems)) } }