fix(tests): make runner worktree exclusions relative to the search root

Both runners excluded */.claude/worktrees/* by absolute path, which
filtered out every test when the repo itself is a Claude worktree.
Search from inside the root so only nested worktrees are skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-16 15:27:25 +00:00
parent 8ce539238c
commit 7380bed6da
4 changed files with 87 additions and 8 deletions

View File

@@ -45,11 +45,17 @@ fi
# land at .claude/skills/<name>/tests/ and be discovered and run a second time,
# which is ADR-0024 consequence 2 arriving here. Keeping the exclusion now is
# what stops that landing as a mystery double-run on the merge that enables it.
#
# The walk runs from inside REPO_ROOT so the exclusions match paths RELATIVE to
# it, the same universe the `git ls-files` grep below sees. Matched against
# absolute paths, `*/.claude/worktrees/*` excluded every file whenever the
# checkout itself was a Claude worktree (<repo>/.claude/worktrees/<name>/), and
# the run failed with "N of N tracked .bats file(s) were not discovered".
TEST_FILES=()
while IFS= read -r f; do
TEST_FILES+=("$f")
TEST_FILES+=("$REPO_ROOT/${f#./}")
done < <(
find "$REPO_ROOT" -name "*.bats" \
cd "$REPO_ROOT" && find . -name "*.bats" \
-not -path "*/tests/bats/*" \
-not -path "*/test_helper/*" \
-not -path "*/.claude/worktrees/*" \

View File

@@ -151,11 +151,17 @@ run_bats
# such file exists today -- the skill suites are all .bats, where run-bats.sh
# already hit this -- so the exclusion is symmetry with its sibling, kept here
# so the first shell suite added under a skill does not reintroduce it.
#
# The walk runs from inside SEARCH_ROOT so the exclusions match paths RELATIVE to
# it. Matched against absolute paths, `*/.claude/worktrees/*` excluded every
# suite whenever the checkout itself was a Claude worktree
# (<repo>/.claude/worktrees/<name>/); relative, it still skips worktrees nested
# below the root. The `./` prefix is swapped back for SEARCH_ROOT afterwards.
SCRIPTS=()
while IFS= read -r script; do
SCRIPTS+=("$script")
SCRIPTS+=("$SEARCH_ROOT/${script#./}")
done < <(
find "$SEARCH_ROOT" -name "test-*.sh" \
cd "$SEARCH_ROOT" && find . -name "test-*.sh" \
-not -path "*/.git/*" \
-not -path "*/.claude/worktrees/*" \
-not -path "*/apm_modules/*" \

View File

@@ -43,8 +43,8 @@ trap cleanup EXIT
# invokes it as `$(make_fake_repo)`, and an append made in here would land in the
# command substitution's subshell and be lost. Registration is the caller's job.
make_fake_repo() {
local dir
dir="$(mktemp -d)"
local dir="${1:-}"
[[ -n "$dir" ]] || dir="$(mktemp -d)"
mkdir -p "$dir/tests" "$dir/scripts/lib"
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
cp "$RUN_BATS" "$dir/tests/run-bats.sh"
@@ -410,6 +410,40 @@ else
fail "the run failed but not with the zero-files message: $FAKE_OUT"
fi
# --- 10. A repo root that itself sits under .claude/worktrees/ still runs. The
# worktree exclusion used to match the absolute path, so a Claude worktree --
# which lives at <repo>/.claude/worktrees/<name>/ -- excluded every file of its
# own and failed with "N of N tracked .bats file(s) were not discovered". The
# exclusion is now relative to the root, so a worktree nested BELOW the root is
# still skipped.
echo ""
echo "--- a root under .claude/worktrees/ discovers its own files and still skips nested worktrees ---"
WT_PARENT="$(mktemp -d)"
FIXTURES+=("$WT_PARENT")
DIR10="$WT_PARENT/repo/.claude/worktrees/agent-x"
make_fake_repo "$DIR10" >/dev/null
git -C "$DIR10" init -q
seed_bats_files "$DIR10"
mkdir -p "$DIR10/.claude/worktrees/nested/tests"
printf '@test "n" { false; }\n' > "$DIR10/.claude/worktrees/nested/tests/n.bats"
install_stub_bats "$DIR10" <<'EOF'
#!/usr/bin/env bash
echo "1..1"
echo "ok 1 first"
exit 0
EOF
git -C "$DIR10" add tests/a.bats tests/b.bats
run_fake "$DIR10"
if [[ $FAKE_RC -ne 0 ]]; then
fail "a root under .claude/worktrees/ failed — its own files were excluded: $FAKE_OUT"
elif ! grep -q "^=== tests/a.bats ===$" <<< "$FAKE_OUT"; then
fail "a root under .claude/worktrees/ did not run its own tests/a.bats: $FAKE_OUT"
elif grep -q "nested/tests/n.bats" <<< "$FAKE_OUT"; then
fail "a worktree nested below the root was discovered and run: $FAKE_OUT"
else
pass "a root under .claude/worktrees/ runs its own files and skips nested worktrees"
fi
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]

View File

@@ -45,8 +45,8 @@ trap cleanup EXIT
# substitution's subshell and be lost. Registration is the caller's job. Same
# convention as tests/test-run-bats.sh.
make_fake_repo() {
local dir
dir="$(mktemp -d)"
local dir="${1:-}"
[[ -n "$dir" ]] || dir="$(mktemp -d)"
mkdir -p "$dir/tests" "$dir/scripts/lib" "$dir/cases"
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
cp "$RUN_TESTS" "$dir/tests/run-tests.sh"
@@ -670,6 +670,39 @@ else
pass "--strict and RUN_TESTS_STRICT=1 both dispatch children with RUN_TESTS_STRICT absent"
fi
# --- A search root that itself sits under .claude/worktrees/ still runs. The
# worktree exclusion used to match the absolute path, so every suite in a Claude
# worktree (<repo>/.claude/worktrees/<name>/) was filtered out. It is now
# relative to the search root, so a worktree nested BELOW the root is still
# skipped.
echo ""
echo "--- a root under .claude/worktrees/ discovers its own suites and still skips nested worktrees ---"
WT_PARENT="$(mktemp -d)"
FIXTURES+=("$WT_PARENT")
WT_DIR="$WT_PARENT/repo/.claude/worktrees/agent-x"
make_fake_repo "$WT_DIR" >/dev/null
install_healthy_bats_runner "$WT_DIR"
add_case "$WT_DIR" test-own.sh <<'EOF'
#!/usr/bin/env bash
echo "own suite ran"
EOF
mkdir -p "$WT_DIR/cases/.claude/worktrees/nested"
cat > "$WT_DIR/cases/.claude/worktrees/nested/test-nested.sh" <<'EOF'
#!/usr/bin/env bash
echo "nested suite ran"
exit 1
EOF
run_fake "$WT_DIR"
if [[ $FAKE_RC -ne 0 ]]; then
fail "a root under .claude/worktrees/ failed: $FAKE_OUT"
elif ! grep -q "own suite ran" <<< "$FAKE_OUT"; then
fail "a root under .claude/worktrees/ did not run its own suite: $FAKE_OUT"
elif grep -q "nested suite ran" <<< "$FAKE_OUT"; then
fail "a worktree nested below the root was discovered and run: $FAKE_OUT"
else
pass "a root under .claude/worktrees/ runs its own suites and skips nested worktrees"
fi
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]