--- key: process.shared-tree-readonly title: 2026-07-21 — The shared tree at /Users/timothy/ersatztv is read-only and tells you nothing about `main` (#542) status: active since: '2026-07-21' supersedes: none superseded-by: none rule: Never commit in `/Users/timothy/ersatztv` and never read its `git log`/`git status`/HEAD to infer anything about `main` — work in a worktree off `origin/main`, which is the only source of truth. signals: 'shared checkout · "main checkout" · worktree discipline · stale HEAD · origin/main is truth · node_modules copy · paths: `/Users/timothy/ersatztv`, `.claude/worktrees/`, `.worktrees/` · issues: #542' mechanics: '`git worktree add -b origin/main`; `git fetch origin main` and reference `origin/main` explicitly — the local `main` ref lags and nobody is obliged to update it. The one sanctioned use of the shared tree is read-only: copying `web/node_modules` out of it (keep that fresh — a stale copy broke typecheck in a #198 worktree).' --- There is no "main checkout". `/Users/timothy/ersatztv` is a shared mutable working tree whose HEAD is whatever the last session left there; its name lies. The rule holds even for a one-line docs fix — make a worktree. This is a design flaw, not a discipline failure: do not "fix" it by telling sessions to check harder, because a check does not stay true. It broke for two different sessions on the same day, 2026-07-17, both doing the obvious thing. Session A assumed it was on `main` — correct when it pulled at 12:46, stale by 14:17 — and committed; the commit landed on the CI session's `ci/604-lane-rebalance`, 24 seconds after that session's own commit at 14:17:28. Two writers, one tree; nothing tangled, by luck. Session B ran `git log` there, read that same branch's HEAD, and concluded `main` was "4 behind origin" — a phantom. A session-start `git status` *appears to confirm* the false assumption, which makes it worse than a plainly wrong claim. Cross-reference `session.shared-checkout-refresh`, which covers the complementary failure mode: any FILE (including a pasted kickoff prompt) read out of that tree may be stale, and the session-end refresh script that mitigates it. This record covers the git-state failure mode only.