diff --git a/nix/agent-modules/default.nix b/nix/agent-modules/default.nix index 003e58d0..6f4f5705 100644 --- a/nix/agent-modules/default.nix +++ b/nix/agent-modules/default.nix @@ -40,7 +40,9 @@ let # store path over at container start as `HYPERHIVE_CLAUDE_CODE_PATH`, and # the host's system closure keeps it alive: nothing in this container # references it. With no pin, or a path that is not there, this container's - # own claude-code runs. `exec -a claude` keeps the bare name in argv[0], + # own claude-code runs; a pin that is set but gone (collected after a bump + # while this container still holds the old facts) says so on stderr, since + # the two builds can differ. `exec -a claude` keeps the bare name in argv[0], # which is how the harness finds its claude child (`find_claude_child`). ownClaude = import ../claude-code-no-alsa.nix lib pkgs.claude-code; claude = pkgs.writeShellScriptBin "claude" '' @@ -48,6 +50,9 @@ let if [ -n "$pinned" ] && [ -x "$pinned/bin/claude" ]; then exec -a claude "$pinned/bin/claude" "$@" fi + if [ -n "$pinned" ]; then + echo "claude: $pinned/bin/claude, the hive's pinned claude-code, is missing; running this container's own" >&2 + fi exec -a claude ${ownClaude}/bin/claude "$@" ''; in diff --git a/nix/host-modules/hive-c0re/options.nix b/nix/host-modules/hive-c0re/options.nix index 7de352ed..17267da8 100644 --- a/nix/host-modules/hive-c0re/options.nix +++ b/nix/host-modules/hive-c0re/options.nix @@ -366,7 +366,8 @@ that generation's path until its next start, and only the old generation roots it: collect old generations after restarting the agents, or an agent still running the old path falls back to - its own `claude-code` at its next `claude` spawn. + its own `claude-code` at its next `claude` spawn, saying so on + stderr. The swarm's `swarm-claude-login` and `swarm-review-classifier` containers, where this host runs them, follow the same pin and diff --git a/nix/script-tests/agent-hive-facts.sh b/nix/script-tests/agent-hive-facts.sh index 48768387..58f57ac7 100644 --- a/nix/script-tests/agent-hive-facts.sh +++ b/nix/script-tests/agent-hive-facts.sh @@ -112,18 +112,22 @@ chmod +x "$dir/own/bin/claude" "$dir/pinned/bin/claude" printf '%s' "$CLAUDE_WRAPPER" | sed -E "s|/nix/store/[^ ]+/bin/claude|$dir/own/bin/claude|" >"$dir/claude" case="claude setup" if ! grep -qF "$dir/own/bin/claude" "$dir/claude"; then fail "the rewrite did not reach the fallback claude"; fi +# claude_check claude_check() { case=$1 count=$((count + 1)) - local got pin=() + local got said pin=() if [ -n "$2" ]; then pin=("HYPERHIVE_CLAUDE_CODE_PATH=$2"); fi # Under this shell: the shebang names the build's bash, not in this sandbox. - got=$(env -i "${pin[@]}" "$BASH" "$dir/claude" -p hi) + got=$(env -i "${pin[@]}" "$BASH" "$dir/claude" -p hi 2>"$dir/stderr") + said=$(cat "$dir/stderr") if [ "$got" != "$3 -p hi" ]; then fail "ran: $got, wanted: $3 -p hi"; fi + if [ "$said" != "$4" ]; then fail "said on stderr: '$said', wanted: '$4'"; fi } -claude_check "the pinned claude when the hive hands one over" "$dir/pinned" pinned -claude_check "the container's own claude with no pin" "" own -claude_check "the container's own claude when the pinned path is gone" "$dir/gone" own +claude_check "the pinned claude when the hive hands one over, silently" "$dir/pinned" pinned "" +claude_check "the container's own claude with no pin, silently" "" own "" +claude_check "the container's own claude when the pinned path is gone, saying so" "$dir/gone" own \ + "claude: $dir/gone/bin/claude, the hive's pinned claude-code, is missing; running this container's own" echo "$count cases, $failures failed" [ "$failures" -eq 0 ]