diff --git a/src/features/background-agent/background-task-notification-template.test.ts b/src/features/background-agent/background-task-notification-template.test.ts
new file mode 100644
index 000000000..5555e909a
--- /dev/null
+++ b/src/features/background-agent/background-task-notification-template.test.ts
@@ -0,0 +1,130 @@
+import { describe, expect, test } from "bun:test"
+import { buildBackgroundTaskNotificationText } from "./background-task-notification-template"
+
+describe("buildBackgroundTaskNotificationText", () => {
+ describe("#given one task still running after a completed task notification", () => {
+ test("#when building the partial notification #then it preserves the existing completed-task format", () => {
+ // given
+ const notification = buildBackgroundTaskNotificationText({
+ task: {
+ id: "task-1",
+ description: "Index repo",
+ status: "completed",
+ },
+ duration: "42s",
+ statusText: "COMPLETED",
+ allComplete: false,
+ remainingCount: 1,
+ completedTasks: [],
+ })
+
+ // when
+ const expectedNotification = `
+[BACKGROUND TASK COMPLETED]
+**ID:** \`task-1\`
+**Description:** Index repo
+**Duration:** 42s
+
+**1 task still in progress.** You WILL be notified when ALL complete.
+Do NOT poll - continue productive work.
+
+Use \`background_output(task_id="task-1")\` to retrieve this result when ready.
+`
+
+ // then
+ expect(notification).toBe(expectedNotification)
+ })
+ })
+
+ describe("#given one task still running after a failed task notification", () => {
+ test("#when building the partial notification #then it preserves the existing failure format", () => {
+ // given
+ const notification = buildBackgroundTaskNotificationText({
+ task: {
+ id: "task-2",
+ description: "Summarize logs",
+ status: "error",
+ error: "Timed out",
+ },
+ duration: "3m 4s",
+ statusText: "ERROR",
+ allComplete: false,
+ remainingCount: 2,
+ completedTasks: [],
+ })
+
+ // when
+ const expectedNotification = `
+[BACKGROUND TASK ERROR]
+**ID:** \`task-2\`
+**Description:** Summarize logs
+**Duration:** 3m 4s
+**Error:** Timed out
+
+**2 tasks still in progress.** You WILL be notified when ALL complete.
+**ACTION REQUIRED:** This task failed. Check the error and decide whether to retry, cancel remaining tasks, or continue.
+
+Use \`background_output(task_id="task-2")\` to retrieve this result when ready.
+`
+
+ // then
+ expect(notification).toBe(expectedNotification)
+ })
+ })
+
+ describe("#given all sibling tasks completed with mixed outcomes", () => {
+ test("#when building the final notification #then it preserves the existing summary format", () => {
+ // given
+ const notification = buildBackgroundTaskNotificationText({
+ task: {
+ id: "task-3",
+ description: "Fallback task",
+ status: "error",
+ error: "Denied",
+ },
+ duration: "10s",
+ statusText: "ERROR",
+ allComplete: true,
+ remainingCount: 0,
+ completedTasks: [
+ {
+ id: "task-1",
+ description: "Index repo",
+ status: "completed",
+ },
+ {
+ id: "task-2",
+ description: "Summarize logs",
+ status: "cancelled",
+ error: "User aborted",
+ },
+ {
+ id: "task-3",
+ description: "Fallback task",
+ status: "error",
+ error: "Denied",
+ },
+ ],
+ })
+
+ // when
+ const expectedNotification = `
+[ALL BACKGROUND TASKS FINISHED - 2 FAILED]
+
+**Completed:**
+- \`task-1\`: Index repo
+
+**Failed:**
+- \`task-2\`: Summarize logs [CANCELLED] - User aborted
+- \`task-3\`: Fallback task [ERROR] - Denied
+
+Use \`background_output(task_id="")\` to retrieve each result.
+
+**ACTION REQUIRED:** 2 task(s) failed. Check errors above and decide whether to retry or proceed.
+`
+
+ // then
+ expect(notification).toBe(expectedNotification)
+ })
+ })
+})
diff --git a/src/features/background-agent/background-task-notification-template.ts b/src/features/background-agent/background-task-notification-template.ts
index e2e74cc78..240efe9c0 100644
--- a/src/features/background-agent/background-task-notification-template.ts
+++ b/src/features/background-agent/background-task-notification-template.ts
@@ -1,14 +1,21 @@
-import type { BackgroundTask } from "./types"
+import type { BackgroundTaskStatus } from "./types"
export type BackgroundTaskNotificationStatus = "COMPLETED" | "CANCELLED" | "INTERRUPTED" | "ERROR"
+export interface BackgroundTaskNotificationTask {
+ id: string
+ description: string
+ status: BackgroundTaskStatus
+ error?: string
+}
+
export function buildBackgroundTaskNotificationText(input: {
- task: BackgroundTask
+ task: BackgroundTaskNotificationTask
duration: string
statusText: BackgroundTaskNotificationStatus
allComplete: boolean
remainingCount: number
- completedTasks: BackgroundTask[]
+ completedTasks: BackgroundTaskNotificationTask[]
}): string {
const { task, duration, statusText, allComplete, remainingCount, completedTasks } = input
@@ -50,14 +57,12 @@ Use \`background_output(task_id="")\` to retrieve each result.${hasFailures
`
}
- const agentInfo = task.category ? `${task.agent} (${task.category})` : task.agent
const isFailure = statusText !== "COMPLETED"
return `
[BACKGROUND TASK ${statusText}]
**ID:** \`${task.id}\`
**Description:** ${task.description}
-**Agent:** ${agentInfo}
**Duration:** ${duration}${errorInfo}
**${remainingCount} task${remainingCount === 1 ? "" : "s"} still in progress.** You WILL be notified when ALL complete.