From 56be458eded42237665b995de5dad91088a276a7 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 16 Apr 2026 23:13:34 +0900 Subject: [PATCH] fix(config): remove obsolete maxDescendants config --- assets/oh-my-opencode.schema.json | 5 ---- src/config/schema/background-task.test.ts | 24 ----------------- src/config/schema/background-task.ts | 1 - src/features/background-agent/manager.test.ts | 26 +++++++------------ 4 files changed, 9 insertions(+), 47 deletions(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index 89a60406d..056c84342 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -5673,11 +5673,6 @@ "minimum": 1, "maximum": 9007199254740991 }, - "maxDescendants": { - "type": "integer", - "minimum": 1, - "maximum": 9007199254740991 - }, "staleTimeoutMs": { "type": "number", "minimum": 60000 diff --git a/src/config/schema/background-task.test.ts b/src/config/schema/background-task.test.ts index ddfcbafec..e7f1a3f8c 100644 --- a/src/config/schema/background-task.test.ts +++ b/src/config/schema/background-task.test.ts @@ -27,30 +27,6 @@ describe("BackgroundTaskConfigSchema", () => { }) }) - describe("maxDescendants", () => { - describe("#given valid maxDescendants (50)", () => { - test("#when parsed #then returns correct value", () => { - const result = BackgroundTaskConfigSchema.parse({ maxDescendants: 50 }) - - expect(result.maxDescendants).toBe(50) - }) - }) - - describe("#given maxDescendants below minimum (0)", () => { - test("#when parsed #then throws ZodError", () => { - let thrownError: unknown - - try { - BackgroundTaskConfigSchema.parse({ maxDescendants: 0 }) - } catch (error) { - thrownError = error - } - - expect(thrownError).toBeInstanceOf(ZodError) - }) - }) - }) - describe("syncPollTimeoutMs", () => { describe("#given valid syncPollTimeoutMs (120000)", () => { test("#when parsed #then returns correct value", () => { diff --git a/src/config/schema/background-task.ts b/src/config/schema/background-task.ts index 44d16b505..4b62612fa 100644 --- a/src/config/schema/background-task.ts +++ b/src/config/schema/background-task.ts @@ -11,7 +11,6 @@ export const BackgroundTaskConfigSchema = z.object({ providerConcurrency: z.record(z.string(), z.number().min(0)).optional(), modelConcurrency: z.record(z.string(), z.number().min(0)).optional(), maxDepth: z.number().int().min(1).optional(), - maxDescendants: z.number().int().min(1).optional(), /** Stale timeout in milliseconds - interrupt tasks with no activity for this duration (default: 180000 = 3 minutes, minimum: 60000 = 1 minute) */ staleTimeoutMs: z.number().min(60000).optional(), /** Timeout for tasks that never received any progress update, falling back to startedAt (default: 1800000 = 30 minutes, minimum: 60000 = 1 minute) */ diff --git a/src/features/background-agent/manager.test.ts b/src/features/background-agent/manager.test.ts index b0fffbf6b..d76ab8aa2 100644 --- a/src/features/background-agent/manager.test.ts +++ b/src/features/background-agent/manager.test.ts @@ -2327,7 +2327,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(result).rejects.toThrow("background_task.maxDepth=3") }) - test("should ignore legacy maxDescendants config when launching multiple descendants", async () => { + test("allows multiple descendants without a root spawn cap", async () => { // given manager.shutdown() manager = new BackgroundManager( @@ -2337,7 +2337,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) const input = { @@ -2357,7 +2356,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(result).resolves.toBeDefined() }) - test("should allow spawn assertions after reserveSubagentSpawn even with legacy maxDescendants config", async () => { + test("allows spawn assertions after reserveSubagentSpawn without a root spawn cap", async () => { // given manager.shutdown() manager = new BackgroundManager( @@ -2367,7 +2366,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) await manager.reserveSubagentSpawn("session-root") @@ -2395,7 +2393,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { ), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) const input = { @@ -2413,7 +2410,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(result).rejects.toThrow("background_task.maxDepth cannot be enforced safely") }) - test("should release descendant quota when queued task is cancelled before session starts", async () => { + test("allows replacement launch when a queued task is cancelled before session starts", async () => { // given manager.shutdown() manager = new BackgroundManager( @@ -2423,7 +2420,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { defaultConcurrency: 1, maxDescendants: 2 }, + { defaultConcurrency: 1 }, ) const input = { @@ -2448,7 +2445,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { expect(replacementTask.status).toBe("pending") }) - test("should release descendant quota when session creation fails before session starts", async () => { + test("allows retry after session creation fails before session starts", async () => { // given let createAttempts = 0 manager.shutdown() @@ -2475,7 +2472,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }, directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) const input = { @@ -2890,7 +2886,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { } }) - test("should release descendant quota when task completes", async () => { + test("allows relaunch after task completes", async () => { manager.shutdown() manager = new BackgroundManager( { @@ -2899,7 +2895,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) stubNotifyParentSession(manager) @@ -2923,7 +2918,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(manager.launch(input)).resolves.toBeDefined() }) - test("should release descendant quota when running task is cancelled", async () => { + test("allows relaunch after running task is cancelled", async () => { manager.shutdown() manager = new BackgroundManager( { @@ -2932,7 +2927,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) const input = { @@ -2953,7 +2947,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(manager.launch(input)).resolves.toBeDefined() }) - test("should release descendant quota when task errors", async () => { + test("allows relaunch after task errors", async () => { manager.shutdown() manager = new BackgroundManager( { @@ -2962,7 +2956,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 1 }, ) const input = { @@ -2987,7 +2980,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { await expect(manager.launch(input)).resolves.toBeDefined() }) - test("should not double-decrement quota when pending task is cancelled", async () => { + test("allows repeated relaunch after pending tasks are cancelled", async () => { manager.shutdown() manager = new BackgroundManager( { @@ -2996,7 +2989,6 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }), directory: tmpdir(), } as unknown as PluginInput, - { maxDescendants: 2 }, ) const input = {