fix: ralph tracker — 3 bugs: first-occurrence completion, double-counting, TodoWrite pattern

Bug 1 (CRITICAL): canonicalCount >= 1 always fired on first <promise> tag
(prompt echo). Changed to >= 2 so only 2nd+ occurrence triggers completion.

Bug 2: checkMultiLinePatterns() re-detected complete tags already handled
by processLine(), double-counting. Now only tries completion when partial
buffer is non-empty (cross-chunk scenario).

Bug 3: TodoWrite ✔ patterns required "Task #N" but real Claude Code output
is plain "✔ content". Added TODO_PLAIN_CHECKMARK_PATTERN fallback.

Includes 71 new deep tests + real-life verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-02-19 14:00:10 +01:00
co-authored by Claude Opus 4.6
parent 926e77b1c2
commit fe1f665531
9 changed files with 1535 additions and 30 deletions
+3 -3
View File
@@ -99,11 +99,11 @@ const BUILTIN_RESPAWN_PRESETS = [
description: 'Unattended overnight runs with full context reset between cycles',
config: {
idleTimeoutMs: 10000,
updatePrompt: 'summarize what you accomplished so far and write key progress notes to CLAUDE.md, then continue working on the task.',
updatePrompt: 'summarize what you accomplished so far and write key progress notes to CLAUDE.md so the next cycle can pick up where you left off.',
interStepDelayMs: 3000,
sendClear: true,
sendInit: true,
kickstartPrompt: 'read CLAUDE.md for context on what was accomplished in previous cycles, then pick up where you left off.',
kickstartPrompt: 'continue working on the task. Pick up where you left off based on the context above.',
autoAcceptPrompts: true,
},
durationMinutes: 480,
@@ -7471,7 +7471,7 @@ class ClaudemanApp {
if (config.enableRespawn) {
const ralphUpdatePrompt = 'Before /clear: Update CLAUDE.md with discoveries and notes, mark completed tasks in @fix_plan.md, write a brief progress summary to a file so the next iteration can continue seamlessly.';
const ralphKickstartPrompt = `You are in a Ralph Wiggum loop. Read @fix_plan.md for task status, check CLAUDE.md for notes from previous iterations, continue on the next uncompleted task, output <promise>${config.completionPhrase}</promise> when ALL tasks are complete.`;
const ralphKickstartPrompt = `You are in a Ralph Wiggum loop. Read @fix_plan.md for task status, continue on the next uncompleted task, output <promise>${config.completionPhrase}</promise> when ALL tasks are complete.`;
await fetch(`/api/sessions/${sessionId}/respawn/enable`, {
method: 'POST',