← the record

Review 4d83ed44bab5

internal/adequacy at de0d9860ee, reviewed by gemini-3.6-flash, verified by claude-code.

repo
git@github.com:pdbethke/corralai
commit
de0d9860eef70a3620288e9dd3d62c71660e5023
scope
internal/adequacy · go
reviewer
gemini-3.6-flash
verifier
claude-code (2.1.263 (Claude Code)) different model than the reviewer different vendor: google → anthropic
substrate
workspace (a detached worktree at the commit; not a jail)
started
2026-09-07 22:24 UTC
audited party
Peter D Bethke · co-authored: Peter D Bethke Claude Code
files shown
25 file(s) truncated

Findings (1)

R1 medium reproduced confirmed by a person

WorkspacePool.copyTree fails to skip top-level dependency directories present in git universe, causing pool copy to fail and downgrade to single-tree execution.

where
internal/adequacy/pool.go:295
tier
REPRODUCED (declared REPRODUCED)
the script that was executed
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
fi
what it printed
Demonstrated 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
FAIL

refutation — claude-code STANDS

I 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.

human verdict

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

Looked at and could not break (5)

Recorded so that "found nothing here" can be told apart from "never looked here".

Reviewer's opinion

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.

Verifier's opinion

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.