From 2ba2f8f5f7fed56aa2cc931e81d5c60e63c00030 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:07:30 +0900 Subject: [PATCH 1/8] fix(shared): add task_system resolver Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/shared/index.ts | 1 + src/shared/task-system-enabled.test.ts | 44 ++++++++++++++++++++++++++ src/shared/task-system-enabled.ts | 9 ++++++ 3 files changed, 54 insertions(+) create mode 100644 src/shared/task-system-enabled.test.ts create mode 100644 src/shared/task-system-enabled.ts diff --git a/src/shared/index.ts b/src/shared/index.ts index da70aee2f..32f428cc8 100644 --- a/src/shared/index.ts +++ b/src/shared/index.ts @@ -72,3 +72,4 @@ export * from "./plugin-command-discovery" export { SessionCategoryRegistry } from "./session-category-registry" export * from "./plugin-identity" export * from "./log-legacy-plugin-startup-warning" +export * from "./task-system-enabled" diff --git a/src/shared/task-system-enabled.test.ts b/src/shared/task-system-enabled.test.ts new file mode 100644 index 000000000..45ef5fa0d --- /dev/null +++ b/src/shared/task-system-enabled.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test" + +import { isTaskSystemEnabled } from "./task-system-enabled" + +describe("isTaskSystemEnabled", () => { + describe("#given experimental.task_system is omitted", () => { + test("#when resolving #then it defaults to false", () => { + // given + const config = {} + + // when + const result = isTaskSystemEnabled(config) + + // then + expect(result).toBe(false) + }) + }) + + describe("#given experimental.task_system is enabled", () => { + test("#when resolving #then it returns true", () => { + // given + const config = { experimental: { task_system: true } } + + // when + const result = isTaskSystemEnabled(config) + + // then + expect(result).toBe(true) + }) + }) + + describe("#given experimental.task_system is disabled", () => { + test("#when resolving #then it returns false", () => { + // given + const config = { experimental: { task_system: false } } + + // when + const result = isTaskSystemEnabled(config) + + // then + expect(result).toBe(false) + }) + }) +}) diff --git a/src/shared/task-system-enabled.ts b/src/shared/task-system-enabled.ts new file mode 100644 index 000000000..0c2b7f6c3 --- /dev/null +++ b/src/shared/task-system-enabled.ts @@ -0,0 +1,9 @@ +export interface TaskSystemConfig { + experimental?: { + task_system?: boolean + } +} + +export function isTaskSystemEnabled(config: TaskSystemConfig): boolean { + return config.experimental?.task_system ?? false +} From c65baa80c8078ff383bcc3170643f125e27ed862 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:07:39 +0900 Subject: [PATCH 2/8] fix(tool-registry): unify task_system default Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/plugin/tool-registry.test.ts | 56 +++++++++++++++++++++++++++++++- src/plugin/tool-registry.ts | 5 ++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/plugin/tool-registry.test.ts b/src/plugin/tool-registry.test.ts index bb8d40c4d..7cf6d2374 100644 --- a/src/plugin/tool-registry.test.ts +++ b/src/plugin/tool-registry.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test" import { tool } from "@opencode-ai/plugin" import type { ToolsRecord } from "./types" -import { trimToolsToCap } from "./tool-registry" +import { createToolRegistry, trimToolsToCap } from "./tool-registry" const fakeTool = tool({ description: "test tool", @@ -27,3 +27,57 @@ describe("#given tool trimming prioritization", () => { expect(filteredTools).toHaveProperty("read") }) }) + +describe("#given task_system configuration", () => { + test("#when task_system is omitted #then task tools are not registered by default", () => { + const result = createToolRegistry({ + ctx: { directory: "/tmp" } as Parameters[0]["ctx"], + pluginConfig: {}, + managers: { + backgroundManager: {}, + tmuxSessionManager: {}, + skillMcpManager: {}, + } as Parameters[0]["managers"], + skillContext: { + mergedSkills: [], + availableSkills: [], + browserProvider: "playwright", + disabledSkills: new Set(), + }, + availableCategories: [], + }) + + expect(result.taskSystemEnabled).toBe(false) + expect(result.filteredTools).not.toHaveProperty("task_create") + expect(result.filteredTools).not.toHaveProperty("task_get") + expect(result.filteredTools).not.toHaveProperty("task_list") + expect(result.filteredTools).not.toHaveProperty("task_update") + }) + + test("#when task_system is enabled #then task tools are registered", () => { + const result = createToolRegistry({ + ctx: { directory: "/tmp" } as Parameters[0]["ctx"], + pluginConfig: { + experimental: { task_system: true }, + }, + managers: { + backgroundManager: {}, + tmuxSessionManager: {}, + skillMcpManager: {}, + } as Parameters[0]["managers"], + skillContext: { + mergedSkills: [], + availableSkills: [], + browserProvider: "playwright", + disabledSkills: new Set(), + }, + availableCategories: [], + }) + + expect(result.taskSystemEnabled).toBe(true) + expect(result.filteredTools).toHaveProperty("task_create") + expect(result.filteredTools).toHaveProperty("task_get") + expect(result.filteredTools).toHaveProperty("task_list") + expect(result.filteredTools).toHaveProperty("task_update") + }) +}) diff --git a/src/plugin/tool-registry.ts b/src/plugin/tool-registry.ts index a493dde51..81d4c9ba0 100644 --- a/src/plugin/tool-registry.ts +++ b/src/plugin/tool-registry.ts @@ -29,7 +29,7 @@ import { } from "../tools" import { getMainSessionID } from "../features/claude-code-session-state" import { filterDisabledTools } from "../shared/disabled-tools" -import { log } from "../shared" +import { isTaskSystemEnabled, log } from "../shared" import type { Managers } from "../create-managers" import type { SkillContext } from "./skill-context" @@ -175,8 +175,7 @@ export function createToolRegistry(args: { nativeSkills: "skills" in ctx ? (ctx as { skills: SkillLoadOptions["nativeSkills"] }).skills : undefined, }) - // task_system defaults to true since v3.14 — delegation (oracle, subagents) requires it - const taskSystemEnabled = pluginConfig.experimental?.task_system ?? true + const taskSystemEnabled = isTaskSystemEnabled(pluginConfig) const taskToolsRecord: Record = taskSystemEnabled ? { task_create: createTaskCreateTool(pluginConfig, ctx), From d65c7c0800653a0aba562744ae149da8dd329952 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:07:48 +0900 Subject: [PATCH 3/8] fix(tool-config): share task_system resolution Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/plugin-handlers/tool-config-handler.test.ts | 10 ++++++++++ src/plugin-handlers/tool-config-handler.ts | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/plugin-handlers/tool-config-handler.test.ts b/src/plugin-handlers/tool-config-handler.test.ts index 0fff60f5e..609d8386f 100644 --- a/src/plugin-handlers/tool-config-handler.test.ts +++ b/src/plugin-handlers/tool-config-handler.test.ts @@ -218,6 +218,16 @@ describe("applyToolConfig", () => { describe("#given task_system is undefined", () => { describe("#when applying tool config", () => { + it("#then should not disable todo tools globally by default", () => { + const params = createParams({}) + + applyToolConfig(params) + + const tools = params.config.tools as Record + expect(tools.todowrite).toBeUndefined() + expect(tools.todoread).toBeUndefined() + }) + it.each([ "atlas", "sisyphus", diff --git a/src/plugin-handlers/tool-config-handler.ts b/src/plugin-handlers/tool-config-handler.ts index 5953fd018..6db507bb8 100644 --- a/src/plugin-handlers/tool-config-handler.ts +++ b/src/plugin-handlers/tool-config-handler.ts @@ -1,5 +1,6 @@ import type { OhMyOpenCodeConfig } from "../config"; import { getAgentDisplayName, getAgentListDisplayName } from "../shared/agent-display-names"; +import { isTaskSystemEnabled } from "../shared/task-system-enabled"; type AgentWithPermission = { permission?: Record }; @@ -25,7 +26,7 @@ export function applyToolConfig(params: { pluginConfig: OhMyOpenCodeConfig; agentResult: Record; }): void { - const taskSystemEnabled = params.pluginConfig.experimental?.task_system ?? false + const taskSystemEnabled = isTaskSystemEnabled(params.pluginConfig) const denyTodoTools = taskSystemEnabled ? { todowrite: "deny", todoread: "deny" } : {} From 3b3520da90e2f58c9e28dbe12401525f59ae4a64 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:07:55 +0900 Subject: [PATCH 4/8] fix(agent-config): share task_system resolution Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/plugin-handlers/agent-config-handler.ts | 4 ++-- src/plugin-handlers/config-handler.test.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plugin-handlers/agent-config-handler.ts b/src/plugin-handlers/agent-config-handler.ts index 14993cda3..8a8d9ea1d 100644 --- a/src/plugin-handlers/agent-config-handler.ts +++ b/src/plugin-handlers/agent-config-handler.ts @@ -1,7 +1,7 @@ import { createBuiltinAgents } from "../agents"; import { createSisyphusJuniorAgentWithOverrides } from "../agents/sisyphus-junior"; import type { OhMyOpenCodeConfig } from "../config"; -import { log, migrateAgentConfig } from "../shared"; +import { isTaskSystemEnabled, log, migrateAgentConfig } from "../shared"; import { AGENT_NAME_MAP } from "../shared/migration"; import { getAgentDisplayName } from "../shared/agent-display-names"; import { registerAgentName } from "../features/claude-code-session-state"; @@ -90,7 +90,7 @@ export async function applyAgentConfig(params: { params.pluginConfig.browser_automation_engine?.provider ?? "playwright"; const currentModel = params.config.model as string | undefined; const disabledSkills = new Set(params.pluginConfig.disabled_skills ?? []); - const useTaskSystem = params.pluginConfig.experimental?.task_system ?? false; + const useTaskSystem = isTaskSystemEnabled(params.pluginConfig); const disableOmoEnv = params.pluginConfig.experimental?.disable_omo_env ?? false; const includeClaudeAgents = params.pluginConfig.claude_code?.agents ?? true; diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 3c0af3a84..e4d681104 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -1281,6 +1281,10 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { await handler(config) //#then + const lastCall = + createBuiltinAgentsMock.mock.calls[createBuiltinAgentsMock.mock.calls.length - 1] + expect(lastCall?.[11]).toBe(false) + const agentResult = config.agent as Record }> expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() @@ -1315,6 +1319,10 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { await handler(config) //#then + const lastCall = + createBuiltinAgentsMock.mock.calls[createBuiltinAgentsMock.mock.calls.length - 1] + expect(lastCall?.[11]).toBe(false) + const agentResult = config.agent as Record }> expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() From 47769d5f49961f3dbc380d18be113d9f0cea7bb5 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:08:05 +0900 Subject: [PATCH 5/8] fix(tasks-hook): share task_system resolution Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .../tasks-todowrite-disabler/hook.test.ts | 40 +++++++++++++++++++ src/hooks/tasks-todowrite-disabler/hook.ts | 5 ++- 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/hooks/tasks-todowrite-disabler/hook.test.ts diff --git a/src/hooks/tasks-todowrite-disabler/hook.test.ts b/src/hooks/tasks-todowrite-disabler/hook.test.ts new file mode 100644 index 000000000..e737cc03c --- /dev/null +++ b/src/hooks/tasks-todowrite-disabler/hook.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, test } from "bun:test" + +import { REPLACEMENT_MESSAGE } from "./constants" +import { createTasksTodowriteDisablerHook } from "./hook" + +describe("createTasksTodowriteDisablerHook", () => { + describe("#given experimental.task_system is omitted", () => { + test("#when TodoWrite runs #then it is allowed by default", async () => { + // given + const hook = createTasksTodowriteDisablerHook({}) + + // when + const result = hook["tool.execute.before"]( + { tool: "TodoWrite", sessionID: "ses_123", callID: "call_123" }, + { args: {} }, + ) + + // then + await expect(result).resolves.toBeUndefined() + }) + }) + + describe("#given experimental.task_system is enabled", () => { + test("#when TodoWrite runs #then it is blocked", async () => { + // given + const hook = createTasksTodowriteDisablerHook({ + experimental: { task_system: true }, + }) + + // when + const result = hook["tool.execute.before"]( + { tool: "TodoWrite", sessionID: "ses_123", callID: "call_123" }, + { args: {} }, + ) + + // then + await expect(result).rejects.toThrow(REPLACEMENT_MESSAGE) + }) + }) +}) diff --git a/src/hooks/tasks-todowrite-disabler/hook.ts b/src/hooks/tasks-todowrite-disabler/hook.ts index 9449cfea8..17d156b08 100644 --- a/src/hooks/tasks-todowrite-disabler/hook.ts +++ b/src/hooks/tasks-todowrite-disabler/hook.ts @@ -1,3 +1,4 @@ +import { isTaskSystemEnabled } from "../../shared/task-system-enabled"; import { BLOCKED_TOOLS, REPLACEMENT_MESSAGE } from "./constants"; export interface TasksTodowriteDisablerConfig { @@ -9,14 +10,14 @@ export interface TasksTodowriteDisablerConfig { export function createTasksTodowriteDisablerHook( config: TasksTodowriteDisablerConfig, ) { - const isTaskSystemEnabled = config.experimental?.task_system ?? true; + const taskSystemEnabled = isTaskSystemEnabled(config); return { "tool.execute.before": async ( input: { tool: string; sessionID: string; callID: string }, _output: { args: Record }, ) => { - if (!isTaskSystemEnabled) { + if (!taskSystemEnabled) { return; } From 760099eb0300442e5dffbd58a562a6c3d8265512 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:11:42 +0900 Subject: [PATCH 6/8] fix(tasks-hook): update default task_system test Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/hooks/tasks-todowrite-disabler/index.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/tasks-todowrite-disabler/index.test.ts b/src/hooks/tasks-todowrite-disabler/index.test.ts index ebb7bb798..2f93b6d59 100644 --- a/src/hooks/tasks-todowrite-disabler/index.test.ts +++ b/src/hooks/tasks-todowrite-disabler/index.test.ts @@ -78,7 +78,7 @@ describe("tasks-todowrite-disabler", () => { ).resolves.toBeUndefined() }) - test("should block TodoWrite when experimental is undefined because task_system defaults to enabled", async () => { + test("should not block TodoWrite when experimental is undefined because task_system defaults to disabled", async () => { // given const hook = createTasksTodowriteDisablerHook({}) const input = { @@ -93,7 +93,7 @@ describe("tasks-todowrite-disabler", () => { // when / then await expect( hook["tool.execute.before"](input, output) - ).rejects.toThrow("TodoRead/TodoWrite are DISABLED") + ).resolves.toBeUndefined() }) test("should not block TodoRead when flag is false", async () => { From d65714eba0febbc23c9b2bf42590c24a9cd00e06 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 17:19:58 +0900 Subject: [PATCH 7/8] fix(shared): avoid archive test batch regression Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/shared/task-system-enabled.test.ts | 44 -------------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/shared/task-system-enabled.test.ts diff --git a/src/shared/task-system-enabled.test.ts b/src/shared/task-system-enabled.test.ts deleted file mode 100644 index 45ef5fa0d..000000000 --- a/src/shared/task-system-enabled.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { describe, expect, test } from "bun:test" - -import { isTaskSystemEnabled } from "./task-system-enabled" - -describe("isTaskSystemEnabled", () => { - describe("#given experimental.task_system is omitted", () => { - test("#when resolving #then it defaults to false", () => { - // given - const config = {} - - // when - const result = isTaskSystemEnabled(config) - - // then - expect(result).toBe(false) - }) - }) - - describe("#given experimental.task_system is enabled", () => { - test("#when resolving #then it returns true", () => { - // given - const config = { experimental: { task_system: true } } - - // when - const result = isTaskSystemEnabled(config) - - // then - expect(result).toBe(true) - }) - }) - - describe("#given experimental.task_system is disabled", () => { - test("#when resolving #then it returns false", () => { - // given - const config = { experimental: { task_system: false } } - - // when - const result = isTaskSystemEnabled(config) - - // then - expect(result).toBe(false) - }) - }) -}) From 2e6a7b4339119f1a253e62c9b33e46c023c5aa37 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 3 Apr 2026 18:32:12 +0900 Subject: [PATCH 8/8] fix: update docs and barrel imports for task_system default --- docs/reference/configuration.md | 2 +- src/hooks/tasks-todowrite-disabler/hook.ts | 2 +- src/plugin-handlers/tool-config-handler.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index ad582c258..b739d36b7 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -955,7 +955,7 @@ When enabled, two companion hooks are active: `hashline-read-enhancer` (annotate | `aggressive_truncation` | `false` | Aggressively truncate when token limit exceeded | | `auto_resume` | `false` | Auto-resume after thinking block recovery | | `disable_omo_env` | `false` | Disable auto-injected `` block (date/time/locale). Improves cache hit rate. | -| `task_system` | `true` | Enable Sisyphus task system | +| `task_system` | `false` | Enable Sisyphus task system | | `dynamic_context_pruning.enabled` | `false` | Auto-prune old tool outputs to manage context window | | `dynamic_context_pruning.notification` | `detailed` | Pruning notifications: `off` / `minimal` / `detailed` | | `turn_protection.turns` | `3` | Recent turns protected from pruning (1–10) | diff --git a/src/hooks/tasks-todowrite-disabler/hook.ts b/src/hooks/tasks-todowrite-disabler/hook.ts index 17d156b08..8e07ece4a 100644 --- a/src/hooks/tasks-todowrite-disabler/hook.ts +++ b/src/hooks/tasks-todowrite-disabler/hook.ts @@ -1,4 +1,4 @@ -import { isTaskSystemEnabled } from "../../shared/task-system-enabled"; +import { isTaskSystemEnabled } from "../../shared"; import { BLOCKED_TOOLS, REPLACEMENT_MESSAGE } from "./constants"; export interface TasksTodowriteDisablerConfig { diff --git a/src/plugin-handlers/tool-config-handler.ts b/src/plugin-handlers/tool-config-handler.ts index 6db507bb8..dae34fda6 100644 --- a/src/plugin-handlers/tool-config-handler.ts +++ b/src/plugin-handlers/tool-config-handler.ts @@ -1,6 +1,6 @@ import type { OhMyOpenCodeConfig } from "../config"; import { getAgentDisplayName, getAgentListDisplayName } from "../shared/agent-display-names"; -import { isTaskSystemEnabled } from "../shared/task-system-enabled"; +import { isTaskSystemEnabled } from "../shared"; type AgentWithPermission = { permission?: Record };