internal/adequacy at de0d9860ee, reviewed by gemini-3.6-flash, verified by claude-code.
WorkspacePool.copyTree fails to skip top-level dependency directories present in git universe, causing pool copy to fail and downgrade to single-tree execution.
cat << 'EOF' > internal/adequacy/z_pool_symlink_bug_test.go
package adequacy
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
)
func TestTrackedDepDirSymlinkFailsPoolCopy(t *testing.T) {
root := newGitRepo(t, map[string]string{"a.py": "x=1\n"}, nil)
target := filepath.Join(t.TempDir(), "external_venv")
if err := os.MkdirAll(target, 0755); err != nil {
t.Fatal(err)
}
if err := os.Symlink(target, filepath.Join(root, ".venv")); err != nil {
t.Fatal(err)
}
runGit := func(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = root
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
}
runGit("add", ".venv")
runGit("-c", "user.email=t@t", "-c", "user.name=t", "commit", "-m", "add venv symlink")
p, d, err := NewWorkspacePool(context.Background(), root, 2, time.Minute)
if err != nil {
t.Fatalf("NewWorkspacePool error: %v", err)
}
defer p.Close()
if d.Trees != 2 {
t.Fatalf("WorkspacePool failed to copy workspace and downgraded to %d trees: %s", d.Trees, d.Note)
}
}
EOF
output=$(go test -v ./internal/adequacy -run TestTrackedDepDirSymlinkFailsPoolCopy 2>&1)
exit_code=$?
rm -f internal/adequacy/z_pool_symlink_bug_test.go
if echo "$output" | grep -q "WorkspacePool failed to copy workspace and downgraded"; then
echo "Demonstrated defect: WorkspacePool downgraded due to duplicate copy attempt:"
echo "$output"
exit 0
else
echo "Defect not reproduced:"
echo "$output"
exit 1
fiDemonstrated defect: WorkspacePool downgraded due to duplicate copy attempt:
=== RUN TestTrackedDepDirSymlinkFailsPoolCopy
z_pool_symlink_bug_test.go:37: WorkspacePool failed to copy workspace and downgraded to 1 trees: could not copy the checkout: adequacy: linking /tmp/corral-tree-714764789/.venv: symlink /tmp/TestTrackedDepDirSymlinkFailsPoolCopy1871428187/002/external_venv /tmp/corral-tree-714764789/.venv: file exists
--- FAIL: TestTrackedDepDirSymlinkFailsPoolCopy (0.02s)
FAIL
FAIL github.com/pdbethke/corralai/internal/adequacy 0.025s
FAILI could not refute the finding. copyTree symlinks each existing dep dir into the tree first (pool.go:376-385), then copies every universe entry; the skip guard at pool.go:387 only matches entries *beneath* a linked dir because it requires `ok` from strings.Cut on "/". A tracked top-level symlink named `.venv` is itself a universe entry (gitUniverse accepts symlinks at pool.go:356 by explicit design), has no "/", is not skipped, and reaches copyFile's symlink branch (pool.go:408-419), where os.Symlink onto the already-created link returns EEXIST. NewWorkspacePool then falls into `could not copy the checkout` (pool.go:239) and returns a one-tree pool, exactly the error string and downgrade the reviewer's run produced. I looked for a guard elsewhere (an exclusion in gitUniverse, a pre-clean of the tree, an idempotent-symlink helper) and found none. Two overstatements worth noting but not sufficient to refute: a tracked dep *directory* with files under it is handled correctly (its entries carry a "/" and are skipped), so only the symlink form breaks; and the downgrade is disclosed via Disclosure.Note rather than silent — the reviewer's own output quoted that note.
confirmed by pdbethke — real, reproduced: copyTree does not skip a dependency directory that is tracked in git; the pool copy fails and the run drops to one tree
ref 4d83ed44bab5c916b8cb580691869f8520b19e6063427992bd6f798eb01770b2#R1
Recorded so that "found nothing here" can be told apart from "never looked here".
Review of `internal/adequacy` revealed a defect in `WorkspacePool.copyTree` where tracked dependency directories or symlinks (such as `.venv`, `node_modules`, or `vendor`) cause tree creation to fail with a 'file exists' error, forcing `NewWorkspacePool` to silently downgrade from $N$ trees to sequential single-tree execution. The rest of the workspace pool, deduplication logic, hunk rendering, and mutant set serialization mechanisms were examined and found to be well-constructed.
R1: I tried three ways to refute this and could not. (1) I checked whether copyTree's skip guard covers the case: at internal/adequacy/pool.go:387 the guard is `strings.Cut(filepath.ToSlash(rel), "/")` with `ok` required, so it only skips paths that live *under* a linked dep dir. A universe entry that IS the dep dir itself — i.e. a tracked top-level symlink named `.venv`/`node_modules`/`vendor`/`venv`/`.bundle` — yields ok=false and falls through to copyFile. (2) I checked whether such an entry can reach the universe at all: gitUniverse (pool.go:356) was deliberately widened to accept symlinks (`fi.Mode()&os.ModeSymlink != 0`), so a tracked symlink is included by design. (3) I checked the ordering: copyTree links the dep dirs first (pool.go:376-385) and only then copies the universe, so copyFile's os.Symlink at pool.go:416 hits an existing path and returns EEXIST, matching the reviewer's observed 'linking …/.venv: file exists' verbatim; NewWorkspacePool then takes the `could not copy the checkout` branch at pool.go:239 and returns a one-tree pool. The claim is correct on the input it names and the reviewer's script exercises exactly that input. Two parts of the phrasing are looser than the code: a tracked dependency *directory* (files under `.venv/…`) does NOT trigger this — those entries have a `/` and are correctly skipped, so only the top-level tracked-symlink form fails; and the downgrade is not literally 'silent' — Disclosure.Note carries the reason (pool.go:26-28, and it is what the reviewer's own assertion printed). Neither of those overturns the defect, so I record STANDS rather than a narrowing refutation.