Problem
worktree-create.sh's containment guard is bypassed by a Windows drive-relative root of the form C:foo (a drive letter + path with NO separator after the colon). Git-for-Windows resolves C:foo against that drive's per-drive current directory to <toplevel>/foo, landing the worktree checkout INSIDE the repository — while the containment ancestor-walk is skipped (parent==probe on a separatorless string, so the [[ -e ]] probe is false and the guard block never runs). Fail-open.
Repro
bash worktree-create.sh --name feat/x --root 'C:foo' --repo-dir "$repo" from a shell whose C: drive CWD is inside $repo → exit 0, checkout at <toplevel>/foo.
Scope / why this is a SEPARATE follow-up (not a #898 regression)
Confirmed by independent verification of PR #898 (backslash-root fix, head 1ff6d69):
Deferred under the #650 model (repro + fix direction + origin cite), permitted because it fails on a pathological non-default input, not because it's a merge-gate/security-posture fail-open on the default path.
Fix direction
Handle drive-relative C:x input in the anchor/normalize stage: detect a drive-letter prefix NOT followed by a separator, and either reject (fail closed) or canonicalize it to absolute (e.g. via cygpath -m/-w resolving the drive CWD) BEFORE the append + normalize_path + ancestor walk, so the guard and git worktree add see the same absolute form. The anchor test (?:*) and the walk both need to treat C:x as drive-relative, not absolute.
Origin
Independent verifier of PR #898 (tower out-of-loop review, 2026-07-22 ~06:40Z), flagged for-awareness as a non-blocker.
Problem
worktree-create.sh's containment guard is bypassed by a Windows drive-relative root of the formC:foo(a drive letter + path with NO separator after the colon). Git-for-Windows resolvesC:fooagainst that drive's per-drive current directory to<toplevel>/foo, landing the worktree checkout INSIDE the repository — while the containment ancestor-walk is skipped (parent==probeon a separatorless string, so the[[ -e ]]probe is false and the guard block never runs). Fail-open.Repro
bash worktree-create.sh --name feat/x --root 'C:foo' --repo-dir "$repo"from a shell whose C: drive CWD is inside$repo→ exit 0, checkout at<toplevel>/foo.Scope / why this is a SEPARATE follow-up (not a #898 regression)
Confirmed by independent verification of PR #898 (backslash-root fix, head 1ff6d69):
\→/swap).C:foohas no separator at all — the swap is a verified no-op on it. Different root cause (drive-relative resolution vs separator grammar).worktree_rootis a directory-typed config; every realistic source (a Windows folder picker, an absolute path, a forward/back-slash path) is absolute.C:foodrive-relative-with-no-separator is not a form a picker or user plausibly supplies for a root — a human won't hit it on the default path. Bounded blast radius (the user's own worktree lands in a wrong-but-reversible location).Deferred under the #650 model (repro + fix direction + origin cite), permitted because it fails on a pathological non-default input, not because it's a merge-gate/security-posture fail-open on the default path.
Fix direction
Handle drive-relative
C:xinput in the anchor/normalize stage: detect a drive-letter prefix NOT followed by a separator, and either reject (fail closed) or canonicalize it to absolute (e.g. viacygpath -m/-wresolving the drive CWD) BEFORE the append +normalize_path+ ancestor walk, so the guard andgit worktree addsee the same absolute form. The anchor test (?:*) and the walk both need to treatC:xas drive-relative, not absolute.Origin
Independent verifier of PR #898 (tower out-of-loop review, 2026-07-22 ~06:40Z), flagged for-awareness as a non-blocker.