# Worktree path comparisons use exact string equality, so symlinked paths split identity on macOS · Issue \#9245 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/issues/9245)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: backlog

Priority: 0

## Description

[Discussion and activity](https://git.cafe/pingdotgg/t3code/issues/9245)

---

### Before submitting

- [x] I searched existing issues and did not find a duplicate.
- [x] I included enough detail to reproduce or investigate the problem.

### Area

Server / checkpointing

### Steps to reproduce

1. On macOS, register a project whose root lives under `/tmp/...` (which is a symlink to `/private/tmp/...`).
2. Get two threads pointing at the same worktree directory, where one stored its `worktreePath` as `/tmp/foo` and the other as `/private/tmp/foo` (for example one created through a path the user typed and one through a resolved picker path).
3. Trigger the branch drift check after a turn completes.

### Expected behavior

Both threads are treated as sharing one worktree, so the drift check refuses to adopt a drifted checkout and any shared-worktree guard counts both references.

### Actual behavior

The comparison is raw string equality (`other.worktreePath === thread.worktreePath` in `CheckpointReactor.ts`), so the two spellings of the same directory count as different worktrees. The guard proposed in #9185 compares the same way in SQL (`worktree_path = ?`), so it would inherit the same blind spot: a removal that should be refused can slip through.

### Impact

Low in practice, most people keep projects under their home directory. But when it hits, the failure mode is the bad one these checks exist to prevent: a worktree removed or a branch adopted while another thread still points at the same directory through a different spelling. Normalizing with `realpath` before comparing (or at write time) would close it. Happy to send a small PR if this is worth fixing.

