Problem
A git worktree under .worktrees/ that has no .venv of its own silently resolves imports from the primary checkout. Tests run there exercise main's code, not the branch's, and a branch-local regression reads green.
Found while verifying PR #3028. Reproduced:
$ ls -d .worktrees/wave1-hotfix-sweep/.venv
NO .venv in worktree
$ cd .worktrees/wave1-hotfix-sweep
$ python -c "import tools.push_ancestry_guard as g; print(g.__file__)"
/Users/valorengels/src/ai/tools/push_ancestry_guard.py # <-- PRIMARY checkout
With PYTHONPATH pinned to the worktree it resolves correctly, and a test that had been passing fails:
$ PYTHONPATH=$PWD python -m pytest tests/unit/test_push_ancestry_guard.py -q
FAILED tests/unit/test_push_ancestry_guard.py::TestPushTargetParsing::test_empty_stdin_falls_back_to_head
1 failed, 16 passed
Without the pin the same file reported 17 passed.
Why this matters more than one PR
This is a verification-integrity bug, the same family as Wave 0 in docs/bug-backlog-waves.md. A lane that runs its suite in a worktree and reports "N tests pass" may be reporting on main. In PR #3028's case it produced a confidently false claim ("1545 unit tests pass") in a PR body, and the failing test was only caught by an independent reviewer who happened to force PYTHONPATH.
Any lane, on any branch, is exposed. The failure is silent and biased toward green, which is the worst direction: it hides exactly the regressions the run exists to catch.
Why the existing guard does not catch it
docs/features/worktree-venv-isolation.md and scripts/pytest-clean.sh guard the off-pin venv case — a venv on the wrong interpreter aborts the run. There is no guard for the absent venv case, which degrades silently to the primary checkout's environment instead of failing closed.
The editable install is what makes it silent: the primary venv carries an editable path entry pointing at /Users/valorengels/src/ai, so import tools... always finds a real module and never raises.
Suggested direction
Fail closed rather than fall back. scripts/pytest-clean.sh already aborts on an off-pin venv; extend it to abort when invoked from a git worktree whose root has no .venv, naming the remedy (uv sync in the worktree). A green run from a worktree should be impossible unless the code under test is that worktree's.
Worth checking whether agent/worktree_manager.py should provision a venv at worktree creation, so lanes are correct by construction rather than by a check.
Acceptance criteria
Found during: PR #3028 review (#3028 (comment))
Problem
A git worktree under
.worktrees/that has no.venvof its own silently resolves imports from the primary checkout. Tests run there exercisemain's code, not the branch's, and a branch-local regression reads green.Found while verifying PR #3028. Reproduced:
With
PYTHONPATHpinned to the worktree it resolves correctly, and a test that had been passing fails:Without the pin the same file reported
17 passed.Why this matters more than one PR
This is a verification-integrity bug, the same family as Wave 0 in
docs/bug-backlog-waves.md. A lane that runs its suite in a worktree and reports "N tests pass" may be reporting onmain. In PR #3028's case it produced a confidently false claim ("1545 unit tests pass") in a PR body, and the failing test was only caught by an independent reviewer who happened to forcePYTHONPATH.Any lane, on any branch, is exposed. The failure is silent and biased toward green, which is the worst direction: it hides exactly the regressions the run exists to catch.
Why the existing guard does not catch it
docs/features/worktree-venv-isolation.mdandscripts/pytest-clean.shguard the off-pin venv case — a venv on the wrong interpreter aborts the run. There is no guard for the absent venv case, which degrades silently to the primary checkout's environment instead of failing closed.The editable install is what makes it silent: the primary venv carries an editable path entry pointing at
/Users/valorengels/src/ai, soimport tools...always finds a real module and never raises.Suggested direction
Fail closed rather than fall back.
scripts/pytest-clean.shalready aborts on an off-pin venv; extend it to abort when invoked from a git worktree whose root has no.venv, naming the remedy (uv syncin the worktree). A green run from a worktree should be impossible unless the code under test is that worktree's.Worth checking whether
agent/worktree_manager.pyshould provision a venv at worktree creation, so lanes are correct by construction rather than by a check.Acceptance criteria
.venvaborts with a named remedy instead of running against the primary checkout..venv.docs/features/worktree-venv-isolation.mddocuments the absent-venv case alongside the off-pin case.Found during: PR #3028 review (#3028 (comment))