Merge pull request #2589 from MoerAI/fix/plan-agent-continuation-loop

fix(todo-continuation-enforcer): add plan agent to DEFAULT_SKIP_AGENTS (fixes #2526)
This commit is contained in:
YeonGyu-Kim
2026-03-25 21:45:58 +09:00
committed by GitHub
3 changed files with 36 additions and 2 deletions

View File

@@ -38,7 +38,7 @@ session.idle
## CONSTANTS
```typescript
DEFAULT_SKIP_AGENTS = ["prometheus", "compaction"]
DEFAULT_SKIP_AGENTS = ["prometheus", "compaction", "plan"]
CONTINUATION_COOLDOWN_MS = 30_000 // 30s between injections
MAX_CONSECUTIVE_FAILURES = 5 // Then 5min pause (exponential backoff)
FAILURE_RESET_WINDOW_MS = 5 * 60_000 // 5min window for failure reset

View File

@@ -2,7 +2,7 @@ import { createSystemDirective, SystemDirectiveTypes } from "../../shared/system
export const HOOK_NAME = "todo-continuation-enforcer"
export const DEFAULT_SKIP_AGENTS = ["prometheus", "compaction"]
export const DEFAULT_SKIP_AGENTS = ["prometheus", "compaction", "plan"]
export const CONTINUATION_PROMPT = `${createSystemDirective(SystemDirectiveTypes.TODO_CONTINUATION)}

View File

@@ -47,4 +47,38 @@ describe("injectContinuation", () => {
expect(capturedTools).toEqual({ question: false, bash: true })
expect(capturedText).toContain(OMO_INTERNAL_INITIATOR_MARKER)
})
test("skips injection when agent is plan (prevents Plan Mode infinite loop)", async () => {
// given
let injected = false
const ctx = {
directory: "/tmp/test",
client: {
session: {
todo: async () => ({ data: [{ id: "1", content: "todo", status: "pending", priority: "high" }] }),
promptAsync: async () => {
injected = true
return {}
},
},
},
}
const sessionStateStore = {
getExistingState: () => ({ inFlight: false, lastInjectedAt: 0, consecutiveFailures: 0 }),
}
// when
await injectContinuation({
ctx: ctx as never,
sessionID: "ses_plan_skip",
resolvedInfo: {
agent: "plan",
model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" },
},
sessionStateStore: sessionStateStore as never,
})
// then
expect(injected).toBe(false)
})
})