diff --git a/src/hooks/atlas/tool-execute-after-background-launch.test.ts b/src/hooks/atlas/tool-execute-after-background-launch.test.ts
new file mode 100644
index 000000000..d7c56fdb3
--- /dev/null
+++ b/src/hooks/atlas/tool-execute-after-background-launch.test.ts
@@ -0,0 +1,98 @@
+///
+
+import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"
+import { existsSync, mkdirSync, rmSync } from "node:fs"
+import { tmpdir } from "node:os"
+import { join } from "node:path"
+import type { PluginInput } from "@opencode-ai/plugin"
+import { createOpencodeClient, type Project } from "@opencode-ai/sdk"
+
+const isCallerOrchestratorMock = mock(async () => true)
+const collectGitDiffStatsMock = mock(() => {
+ throw new Error("background launches should not trigger verification")
+})
+
+mock.module("../../shared/session-utils", () => ({
+ isCallerOrchestrator: isCallerOrchestratorMock,
+}))
+
+mock.module("../../shared/git-worktree", () => ({
+ collectGitDiffStats: collectGitDiffStatsMock,
+ formatFileChanges: mock(() => "No file changes"),
+}))
+
+const { createToolExecuteAfterHandler } = await import("./tool-execute-after")
+
+describe("createToolExecuteAfterHandler background launch detection", () => {
+ let testDirectory = ""
+
+ beforeEach(() => {
+ testDirectory = join(tmpdir(), `atlas-background-launch-${crypto.randomUUID()}`)
+
+ if (!existsSync(testDirectory)) {
+ mkdirSync(testDirectory, { recursive: true })
+ }
+
+ isCallerOrchestratorMock.mockClear()
+ collectGitDiffStatsMock.mockClear()
+ })
+
+ afterEach(() => {
+ if (testDirectory && existsSync(testDirectory)) {
+ rmSync(testDirectory, { recursive: true, force: true })
+ }
+ })
+
+ function createHandler() {
+ const project = {
+ id: "project-1",
+ worktree: testDirectory,
+ time: {
+ created: Date.now(),
+ },
+ } satisfies Project
+
+ const ctx = {
+ client: createOpencodeClient(),
+ project,
+ directory: testDirectory,
+ worktree: testDirectory,
+ serverUrl: new URL("https://example.com"),
+ $: Bun.$,
+ } satisfies PluginInput
+
+ return createToolExecuteAfterHandler({
+ ctx,
+ pendingFilePaths: new Map(),
+ pendingTaskRefs: new Map(),
+ autoCommit: true,
+ getState: () => ({ promptFailureCount: 0 }),
+ })
+ }
+
+ describe("#given a call_omo_agent background launch result", () => {
+ describe("#when tool.execute.after handles it", () => {
+ it("#then it should treat the launch as still running", async () => {
+ const handler = createHandler()
+ const output = {
+ title: "call_omo_agent",
+ output: "Background agent task launched successfully.",
+ metadata: {
+ sessionId: "ses_child123",
+ },
+ }
+
+ await handler(
+ {
+ tool: "call_omo_agent",
+ sessionID: "ses_parent",
+ },
+ output,
+ )
+
+ expect(output.output).toBe("Background agent task launched successfully.")
+ expect(collectGitDiffStatsMock).not.toHaveBeenCalled()
+ })
+ })
+ })
+})
diff --git a/src/hooks/atlas/tool-execute-after.ts b/src/hooks/atlas/tool-execute-after.ts
index 9a463534c..81d887948 100644
--- a/src/hooks/atlas/tool-execute-after.ts
+++ b/src/hooks/atlas/tool-execute-after.ts
@@ -118,6 +118,7 @@ export function createToolExecuteAfterHandler(input: {
}
const isBackgroundLaunch = outputStr.includes("Background task launched") || outputStr.includes("Background task continued")
|| outputStr.includes("Background delegate launched")
+ || outputStr.includes("Background agent task launched")
if (isBackgroundLaunch) {
return
}
diff --git a/src/hooks/task-resume-info/hook.ts b/src/hooks/task-resume-info/hook.ts
index 4eb65dc8f..1774aef6a 100644
--- a/src/hooks/task-resume-info/hook.ts
+++ b/src/hooks/task-resume-info/hook.ts
@@ -30,7 +30,7 @@ export function createTaskResumeInfoHook() {
output.output =
outputText.trimEnd() +
- `\n\nto continue: task(session_id="${sessionId}", load_skills=[], prompt="...")`
+ `\n\nto continue: task(session_id="${sessionId}", load_skills=[], run_in_background=false, prompt="...")`
}
return {
diff --git a/src/hooks/task-resume-info/index.test.ts b/src/hooks/task-resume-info/index.test.ts
index 200e29af0..2d10ef757 100644
--- a/src/hooks/task-resume-info/index.test.ts
+++ b/src/hooks/task-resume-info/index.test.ts
@@ -1,3 +1,5 @@
+///
+
import { describe, it, expect } from "bun:test"
import { createTaskResumeInfoHook } from "./index"
@@ -60,6 +62,19 @@ describe("createTaskResumeInfoHook", () => {
expect(output.output).toContain("to continue:")
expect(output.output).toContain("ses_abc123")
})
+
+ it("#then should include run_in_background in resume info", async () => {
+ const input = createInput("call_omo_agent")
+ const output = {
+ title: "delegate_task",
+ output: "Task completed.\nSession ID: ses_abc123",
+ metadata: {},
+ }
+
+ await afterHook(input, output)
+
+ expect(output.output).toContain("run_in_background=false")
+ })
})
})