diff --git a/plugins/ralph-loop/hooks/stop-hook.sh b/plugins/ralph-loop/hooks/stop-hook.sh index bf3a1ff..ef83af4 100755 --- a/plugins/ralph-loop/hooks/stop-hook.sh +++ b/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 diff --git a/plugins/ralph-loop/scripts/setup-ralph-loop.sh b/plugins/ralph-loop/scripts/setup-ralph-loop.sh index 3d41db4..c0897d4 100755 --- a/plugins/ralph-loop/scripts/setup-ralph-loop.sh +++ b/plugins/ralph-loop/scripts/setup-ralph-loop.sh @@ -141,6 +141,7 @@ cat > .claude/ralph-loop.local.md <