From b516492a91e67cf37b96b6d65cd6110cdcf6d2c4 Mon Sep 17 00:00:00 2001 From: Sheldon Finlay Date: Thu, 2 Apr 2026 10:51:48 -0400 Subject: [PATCH] fix: install Stop hook once at loop startup, not per-iteration Per-iteration install/remove had a race condition: settings.local.json was written immediately before CC started, and CC could read the old file (without the hook) on the first iteration. Now the hook is installed once when loop.sh starts and removed on exit. The AGENT_LOOP_ACTIVE env var guard ensures it only fires for CC sessions spawned by the loop, so keeping it installed the whole time is safe. --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- loop.sh | 12 +++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 09e8af7..6554029 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "agent-loop", "source": "./", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan interactively, then execute with full visibility.", - "version": "0.10.1", + "version": "0.10.2", "author": { "name": "Sheldon" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 6de794e..fc2dfce 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agent-loop", - "version": "0.10.1", + "version": "0.10.2", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Run /agent-loop:run to start.", "author": { "name": "Sheldon" diff --git a/loop.sh b/loop.sh index e593c17..2b51a81 100755 --- a/loop.sh +++ b/loop.sh @@ -158,8 +158,11 @@ finish() { read -r -t 30 2>/dev/null || true exit "$exit_code" } -# NOTE: Stop hook is installed/removed per-agent in run_agent(), not globally. -# This prevents the hook from killing the orchestrating CC session. +# Install Stop hook once at startup. The AGENT_LOOP_ACTIVE env var guard ensures +# it only fires for CC sessions spawned by this loop (not the user's other sessions). +# Installing once avoids a race condition where per-iteration install_hooks writes +# settings.local.json just before CC starts, and CC reads the old file. +[ "$AUTO_HOOKS" = true ] && install_hooks trap cleanup EXIT INT TERM check_archive @@ -204,9 +207,6 @@ run_agent() { rm -f "$LOOP_DIR/.verdict" local agent_exit=0 - # Install Stop hook just before claude starts, remove after it exits. - # This scopes the hook to only affect the loop's claude sessions. - [ "$AUTO_HOOKS" = true ] && install_hooks ( case "$TOOL" in @@ -222,8 +222,6 @@ run_agent() { ;; esac ) || agent_exit=$? - - [ "$AUTO_HOOKS" = true ] && remove_hooks sleep 2 # Brief pause between sessions # Read verdict from file if evaluator wrote one