feat(ralph-loop): add strategy option for fresh context per iteration

Closes #1901

Add 'default_strategy' config option (default: 'continue') to control whether ralph-loop creates a new session per iteration ('reset') or keeps the same session ('continue'). The 'reset' strategy keeps the model in the smart zone by starting with fresh context for each iteration.

Supports --strategy flag for per-command override.
This commit is contained in:
YeonGyu-Kim
2026-02-21 02:27:57 +09:00
parent 14edde17c5
commit e7697567d5
16 changed files with 323 additions and 49 deletions
+6 -13
View File
@@ -5,6 +5,7 @@ import { hasConnectedProvidersCache } from "../shared"
import { setSessionModel } from "../shared/session-model-state"
import { setSessionAgent } from "../features/claude-code-session-state"
import { applyUltraworkModelOverrideOnMessage } from "./ultrawork-model-override"
import { parseRalphLoopArguments } from "../hooks/ralph-loop/command-arguments"
import type { CreatedHooks } from "../create-hooks"
@@ -119,20 +120,12 @@ export function createChatMessageHandler(args: {
if (isRalphLoopTemplate) {
const taskMatch = promptText.match(/<user-task>\s*([\s\S]*?)\s*<\/user-task>/i)
const rawTask = taskMatch?.[1]?.trim() || ""
const quotedMatch = rawTask.match(/^["'](.+?)["']/)
const prompt =
quotedMatch?.[1] ||
rawTask.split(/\s+--/)[0]?.trim() ||
"Complete the task as instructed"
const parsedArguments = parseRalphLoopArguments(rawTask)
const maxIterMatch = rawTask.match(/--max-iterations=(\d+)/i)
const promiseMatch = rawTask.match(
/--completion-promise=["']?([^"'\s]+)["']?/i,
)
hooks.ralphLoop.startLoop(input.sessionID, prompt, {
maxIterations: maxIterMatch ? parseInt(maxIterMatch[1], 10) : undefined,
completionPromise: promiseMatch?.[1],
hooks.ralphLoop.startLoop(input.sessionID, parsedArguments.prompt, {
maxIterations: parsedArguments.maxIterations,
completionPromise: parsedArguments.completionPromise,
strategy: parsedArguments.strategy,
})
} else if (isCancelRalphTemplate) {
hooks.ralphLoop.cancelLoop(input.sessionID)
+11 -22
View File
@@ -4,6 +4,7 @@ import { getMainSessionID } from "../features/claude-code-session-state"
import { clearBoulderState } from "../features/boulder-state"
import { log } from "../shared"
import { resolveSessionAgent } from "./session-agent-resolver"
import { parseRalphLoopArguments } from "../hooks/ralph-loop/command-arguments"
import type { CreatedHooks } from "../create-hooks"
@@ -51,36 +52,24 @@ export function createToolExecuteBeforeHandler(args: {
if (command === "ralph-loop" && sessionID) {
const rawArgs = rawName?.replace(/^\/?(ralph-loop)\s*/i, "") || ""
const taskMatch = rawArgs.match(/^["'](.+?)["']/)
const prompt =
taskMatch?.[1] ||
rawArgs.split(/\s+--/)[0]?.trim() ||
"Complete the task as instructed"
const parsedArguments = parseRalphLoopArguments(rawArgs)
const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i)
const promiseMatch = rawArgs.match(/--completion-promise=["']?([^"'\s]+)["']?/i)
hooks.ralphLoop.startLoop(sessionID, prompt, {
maxIterations: maxIterMatch ? parseInt(maxIterMatch[1], 10) : undefined,
completionPromise: promiseMatch?.[1],
hooks.ralphLoop.startLoop(sessionID, parsedArguments.prompt, {
maxIterations: parsedArguments.maxIterations,
completionPromise: parsedArguments.completionPromise,
strategy: parsedArguments.strategy,
})
} else if (command === "cancel-ralph" && sessionID) {
hooks.ralphLoop.cancelLoop(sessionID)
} else if (command === "ulw-loop" && sessionID) {
const rawArgs = rawName?.replace(/^\/?(ulw-loop)\s*/i, "") || ""
const taskMatch = rawArgs.match(/^["'](.+?)["']/)
const prompt =
taskMatch?.[1] ||
rawArgs.split(/\s+--/)[0]?.trim() ||
"Complete the task as instructed"
const parsedArguments = parseRalphLoopArguments(rawArgs)
const maxIterMatch = rawArgs.match(/--max-iterations=(\d+)/i)
const promiseMatch = rawArgs.match(/--completion-promise=["']?([^"'\s]+)["']?/i)
hooks.ralphLoop.startLoop(sessionID, prompt, {
hooks.ralphLoop.startLoop(sessionID, parsedArguments.prompt, {
ultrawork: true,
maxIterations: maxIterMatch ? parseInt(maxIterMatch[1], 10) : undefined,
completionPromise: promiseMatch?.[1],
maxIterations: parsedArguments.maxIterations,
completionPromise: parsedArguments.completionPromise,
strategy: parsedArguments.strategy,
})
}
}