From e3be656f868d84d9863c34d5093ad4e7dd5b92e8 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Sun, 28 Dec 2025 16:02:04 +0900 Subject: [PATCH] fix: disable todo-continuation for plan mode agents (#303) * fix: disable todo-continuation for plan mode agents Plan mode agents (e.g., 'plan', 'Planner-Sisyphus') only analyze and plan, they don't implement. The todo-continuation hook was incorrectly triggering for these agents because the existing write permission check only looked at the stored message's tools field, not the agent's permission configuration. This fix adds an explicit check for plan mode agents by name to skip the todo continuation prompt injection. Fixes #293 * chore: changes by sisyphus-dev-ai * fix: address review comments for plan mode agent check - Use exact match for plan mode agents instead of substring match to prevent false positives on agents like 'deployment-planner' - Add plan mode agent check to preemptive injection path (non-interactive mode) which was missing from the initial fix --------- Co-authored-by: sisyphus-dev-ai --- assets/oh-my-opencode.schema.json | 2 +- bun.lock | 4 ++-- src/hooks/todo-continuation-enforcer.ts | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index 200889c..308d53a 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -1487,7 +1487,7 @@ } } }, - "dcp_on_compaction_failure": { + "dcp_for_compaction": { "type": "boolean" } } diff --git a/bun.lock b/bun.lock index ea24f0a..3b58071 100644 --- a/bun.lock +++ b/bun.lock @@ -8,7 +8,7 @@ "@ast-grep/cli": "^0.40.0", "@ast-grep/napi": "^0.40.0", "@clack/prompts": "^0.11.0", - "@code-yeongyu/comment-checker": "^0.6.0", + "@code-yeongyu/comment-checker": "^0.6.1", "@openauthjs/openauth": "^0.4.3", "@opencode-ai/plugin": "^1.0.162", "@opencode-ai/sdk": "^1.0.162", @@ -73,7 +73,7 @@ "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], - "@code-yeongyu/comment-checker": ["@code-yeongyu/comment-checker@0.6.0", "", { "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "comment-checker": "bin/comment-checker" } }, "sha512-VtDPrhbUJcb5BIS18VMcY/N/xSLbMr6dpU9MO1NYQyEDhI4pSIx07K4gOlCutG/nHVCjO+HEarn8rttODP+5UA=="], + "@code-yeongyu/comment-checker": ["@code-yeongyu/comment-checker@0.6.1", "", { "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "comment-checker": "bin/comment-checker" } }, "sha512-BBremX+Y5aW8sTzlhHrLsKParupYkPOVUYmq9STrlWvBvfAme6w5IWuZCLl6nHIQScRDdvGdrAjPycJC86EZFA=="], "@openauthjs/openauth": ["@openauthjs/openauth@0.4.3", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw=="], diff --git a/src/hooks/todo-continuation-enforcer.ts b/src/hooks/todo-continuation-enforcer.ts index 2ab3245..b9c2abd 100644 --- a/src/hooks/todo-continuation-enforcer.ts +++ b/src/hooks/todo-continuation-enforcer.ts @@ -272,8 +272,19 @@ export function createTodoContinuationEnforcer( (prevMessage.tools.write !== false && prevMessage.tools.edit !== false) if (!agentHasWritePermission) { - log(`[${HOOK_NAME}] Skipped: agent lacks write permission`, { - sessionID, agent: prevMessage?.agent, tools: prevMessage?.tools + log(`[${HOOK_NAME}] Skipped: agent lacks write permission`, { + sessionID, agent: prevMessage?.agent, tools: prevMessage?.tools + }) + state.mode = "idle" + return + } + + // Plan mode agents only analyze and plan, not implement - skip todo continuation + const agentName = prevMessage?.agent?.toLowerCase() ?? "" + const isPlanModeAgent = agentName === "plan" || agentName === "planner-sisyphus" + if (isPlanModeAgent) { + log(`[${HOOK_NAME}] Skipped: plan mode agent detected`, { + sessionID, agent: prevMessage?.agent }) state.mode = "idle" return