Bladeren bron

fix(ralph-loop): isolate loop state to the session that started it

The state file lives at .claude/ralph-loop.local.md — project-scoped,
not session-scoped. The plugin's Stop hook fires in every Claude Code
session open in that project directory. So if session A starts a loop,
session B's Stop events also find the state file and block, feeding A's
prompt into B and consuming A's iteration budget.

This was masked by the transcript-parsing bug fixed in the previous
commit: that bug deleted the state file on the first Stop in any
session, so neither session looped. Fixing it exposed the leak.

Fix: setup writes CLAUDE_CODE_SESSION_ID into the frontmatter; the hook
compares against .session_id from its stdin JSON and exits silently on
mismatch. State files without session_id (written by old setup scripts)
fall through to preserve existing behavior.
sfishman 6 maanden geleden
bovenliggende
commit
8644df9ad5
2 gewijzigde bestanden met toevoegingen van 11 en 0 verwijderingen
  1. 10 0
      plugins/ralph-loop/hooks/stop-hook.sh
  2. 1 0
      plugins/ralph-loop/scripts/setup-ralph-loop.sh

+ 10 - 0
plugins/ralph-loop/hooks/stop-hook.sh

@@ -24,6 +24,16 @@ MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iter
 # Extract completion_promise and strip surrounding quotes if present
 COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
 
+# Session isolation: the state file is project-scoped, but the Stop hook
+# fires in every Claude Code session in that project. If another session
+# started the loop, this session must not block (or touch the state file).
+# Legacy state files without session_id fall through (preserves old behavior).
+STATE_SESSION=$(echo "$FRONTMATTER" | grep '^session_id:' | sed 's/session_id: *//' || true)
+HOOK_SESSION=$(echo "$HOOK_INPUT" | jq -r '.session_id // ""')
+if [[ -n "$STATE_SESSION" ]] && [[ "$STATE_SESSION" != "$HOOK_SESSION" ]]; then
+  exit 0
+fi
+
 # Validate numeric fields before arithmetic operations
 if [[ ! "$ITERATION" =~ ^[0-9]+$ ]]; then
   echo "⚠️  Ralph loop: State file corrupted" >&2

+ 1 - 0
plugins/ralph-loop/scripts/setup-ralph-loop.sh

@@ -141,6 +141,7 @@ cat > .claude/ralph-loop.local.md <<EOF
 ---
 active: true
 iteration: 1
+session_id: ${CLAUDE_CODE_SESSION_ID:-}
 max_iterations: $MAX_ITERATIONS
 completion_promise: $COMPLETION_PROMISE_YAML
 started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"