Problem
bin/fm-spawn.sh compares physical path strings when deciding whether a spawned endpoint is still in the project's primary checkout and when validating the resolved task worktree.
Different path spellings can identify the same directory.
On case-insensitive macOS, for example, capitalization variants have the same device and inode while retaining different path text.
POSIX also permits distinct leading-slash spellings.
That lets the primary checkout look different from itself to the current string comparisons, so a pool-full or misrouted acquisition can be accepted as an isolated task worktree.
This caused a live incident when treehouse v2.2.0 leased the primary checkout under pool exhaustion.
Required outcome
- Compare filesystem identity (device and inode), not path spelling, for the primary checkout, the resolved worktree, and its Git top-level.
- Fail closed when filesystem identity cannot be established.
- Apply the same identity check to relaunch endpoint validation and the treehouse settle loop.
- Preserve the two-consecutive-read settle requirement, but compare the consecutive directory identities.
- Add a portable public-interface regression for exact-primary refusal and an opt-in macOS case-insensitive proof.
Related PR #2562 proves repository ownership and rejects worktrees from another repository, which is complementary.
It does not make the same-directory primary-checkout comparison spelling-independent: a case-variant path can have the expected repository identity while still naming the primary checkout itself.
Fork reference: withally#60 (43fba21).
Problem
bin/fm-spawn.shcompares physical path strings when deciding whether a spawned endpoint is still in the project's primary checkout and when validating the resolved task worktree.Different path spellings can identify the same directory.
On case-insensitive macOS, for example, capitalization variants have the same device and inode while retaining different path text.
POSIX also permits distinct leading-slash spellings.
That lets the primary checkout look different from itself to the current string comparisons, so a pool-full or misrouted acquisition can be accepted as an isolated task worktree.
This caused a live incident when treehouse v2.2.0 leased the primary checkout under pool exhaustion.
Required outcome
Related PR #2562 proves repository ownership and rejects worktrees from another repository, which is complementary.
It does not make the same-directory primary-checkout comparison spelling-independent: a case-variant path can have the expected repository identity while still naming the primary checkout itself.
Fork reference: withally#60 (
43fba21).