RUL-021 — Every feature-branch worktree owns a full environment, deleted at merge

Ruling

"every damn feature branch gets a full env until we merge then it gets deleted" (verbatim, 2026-07-27).

Concretely, for every git worktree holding a feature branch:

  1. Its .venv is a real directory it owns. Never a symlink or hardlink to another checkout's virtualenv, and never a shared interpreter reached through PYTHONPATH alone.
  2. Its vendored build inputs are present locally. vendor/wheels/ is gitignored, and [tool.uv.sources] pins wheels by relative path, so a fresh worktree resolves those paths against an empty directory. Populate it (hardlinks cost no disk) before the first uv sync.
  3. At merge, the worktree and its environment are both deleted. A merged branch that still has a worktree is stale state, not a convenience.

This supersedes the earlier "link the main .venv into worktree builders for speed" practice, which is now prohibited.

Evidence

Sharing one virtualenv across worktrees is not a saving; it is a shared mutable dependency graph with no owner.

Enforcement

Verification

scripts/check_worktree_envs.py enumerates git worktree list and fails (exit 1) when any non-primary worktree:

It is wired into scripts/health_check.py, so the standing "health check before any bulk change or commit" step covers it. --fix-wheels populates missing vendored wheels by hardlink; environment creation and worktree deletion stay manual, because both destroy or build state a human should be choosing.