fix(subagent): remove permission.question=deny override that caused zombie sessions

Child session creation was injecting permission: { question: 'deny' } which
conflicted with OpenCode's child session permission handling, causing subagent
sessions to hang with 0 messages after creation (zombie state).

Remove the permission override from all session creators (BackgroundManager,
sync-session-creator, call-omo-agent) and rely on prompt-level tool restrictions
(tools.question=false) to maintain the intended policy.

Closes #1711
This commit is contained in:
YeonGyu-Kim
2026-02-11 11:55:56 +09:00
parent 73c0fc9bb5
commit cd0e2e5190
12 changed files with 106 additions and 33 deletions
@@ -1520,7 +1520,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
})
describe("task transitions pending→running when slot available", () => {
test("should inherit parent session permission rules (and force deny question)", async () => {
test("does not override parent session permission when creating child session", async () => {
// given
const createCalls: any[] = []
const parentPermission = [
@@ -1562,11 +1562,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
// then
expect(createCalls).toHaveLength(1)
const permission = createCalls[0]?.body?.permission
expect(permission).toEqual([
{ permission: "plan_enter", action: "deny", pattern: "*" },
{ permission: "question", action: "deny", pattern: "*" },
])
expect(createCalls[0]?.body?.permission).toBeUndefined()
})
test("should transition first task to running immediately", async () => {
-7
View File
@@ -236,17 +236,10 @@ export class BackgroundManager {
const parentDirectory = parentSession?.data?.directory ?? this.directory
log(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${parentDirectory}`)
const inheritedPermission = (parentSession as any)?.data?.permission
const permissionRules = Array.isArray(inheritedPermission)
? inheritedPermission.filter((r: any) => r?.permission !== "question")
: []
permissionRules.push({ permission: "question", action: "deny" as const, pattern: "*" })
const createResult = await this.client.session.create({
body: {
parentID: input.parentSessionID,
title: `${input.description} (@${input.agent} subagent)`,
permission: permissionRules,
} as any,
query: {
directory: parentDirectory,
@@ -3,7 +3,7 @@ import { describe, test, expect } from "bun:test"
import { createTask, startTask } from "./spawner"
describe("background-agent spawner.startTask", () => {
test("should inherit parent session permission rules (and force deny question)", async () => {
test("does not override parent session permission rules when creating child session", async () => {
//#given
const createCalls: any[] = []
const parentPermission = [
@@ -57,9 +57,6 @@ describe("background-agent spawner.startTask", () => {
//#then
expect(createCalls).toHaveLength(1)
expect(createCalls[0]?.body?.permission).toEqual([
{ permission: "plan_enter", action: "deny", pattern: "*" },
{ permission: "question", action: "deny", pattern: "*" },
])
expect(createCalls[0]?.body?.permission).toBeUndefined()
})
})
-7
View File
@@ -58,17 +58,10 @@ export async function startTask(
const parentDirectory = parentSession?.data?.directory ?? directory
log(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${parentDirectory}`)
const inheritedPermission = (parentSession as any)?.data?.permission
const permissionRules = Array.isArray(inheritedPermission)
? inheritedPermission.filter((r: any) => r?.permission !== "question")
: []
permissionRules.push({ permission: "question", action: "deny" as const, pattern: "*" })
const createResult = await client.session.create({
body: {
parentID: input.parentSessionID,
title: `Background: ${input.description}`,
permission: permissionRules,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
query: {
@@ -15,7 +15,6 @@ export async function createBackgroundSession(options: {
const body = {
parentID: input.parentSessionID,
title: `Background: ${input.description}`,
permission: [{ permission: "question", action: "deny" as const, pattern: "*" }],
}
const createResult = await client.session
@@ -69,7 +69,6 @@ export async function startQueuedTask(args: {
body: {
parentID: input.parentSessionID,
title: `${input.description} (@${input.agent} subagent)`,
permission: [{ permission: "question", action: "deny" as const, pattern: "*" }],
} as any,
query: {
directory: parentDirectory,