Skip to content

fix(pool): accept dot-prefixed subdirectories in cwdInWorktree#33

Open
e-jung wants to merge 1 commit into
kunchenguid:mainfrom
e-jung:fix/cwdinworktree-dot-subdirs
Open

fix(pool): accept dot-prefixed subdirectories in cwdInWorktree#33
e-jung wants to merge 1 commit into
kunchenguid:mainfrom
e-jung:fix/cwdinworktree-dot-subdirs

Conversation

@e-jung

@e-jung e-jung commented Jun 22, 2026

Copy link
Copy Markdown

Intent

The developer wanted to fix a treehouse bug where cwdInWorktree in internal/pool/pool.go (~line 427) rejected dot-prefixed subdirectories, causing treehouse status to fail to recognize the user as "here" when their cwd is inside paths like .venv, .cache, or .git-hooks. They required replacing the buggy rel[0] != '.' check with the correct "does not escape via .." predicate (already present at internal/process/detect.go:75), and adding the first table-driven test for cwdInWorktree in internal/pool/pool_test.go covering root, regular subdir, dot-prefixed subdir, outside-worktree, and sibling-dir cases, verified with go test ./internal/pool/.... Explicit constraints: branch off upstream/main (never local main), push to the e-jung fork, open a cross-repo PR titled "fix(pool): cwdInWorktree accepts dot-prefixed subdirectories" against kunchenguid/treehouse with AI disclosure = Human-reviewed, do NOT merge, and stay confined to the worktree. The developer framed this as a status-display-only bug with very low risk.

What Changed

  • Replaced the rel[0] != '.' guard in cwdInWorktree (internal/pool/pool.go) with a "does not escape via .." predicate, so dot-prefixed subdirectories like .venv/bin or .cache/tmp are correctly recognized as inside the worktree.
  • Added the first table-driven TestCwdInWorktree covering worktree root, regular subdir, dot-prefixed subdirs, parent, and sibling paths.

Risk Assessment

✅ Low: The fix is a minimal, correct one-liner that mirrors the already-proven predicate in detect.go:75 and is exercised by a well-chosen table-driven test; its only consumer is the StatusHere display flag (pool.go:269), so blast radius is purely cosmetic.

Testing

The fix works end-to-end as an end user would experience it: running treehouse status from inside .venv/bin or .cache/tmp of a pooled worktree now correctly prints "you're here" instead of the buggy "in-use". The new table-driven unit test passes all six cases, the entire go test ./... suite is green, and Windows/macOS cross-builds succeed. A side-by-side run of the buggy base binary versus the fixed binary on the identical scenario directly demonstrates the status-display bug being resolved.

Evidence: status transcript - FIXED binary (target commit)

treehouse status from cwd inside dot-prefixed subdirs (fixed binary): --- cwd = worktree/ --- -> 1 you're here --- cwd = worktree/src/foo --- -> 1 you're here --- cwd = worktree/.venv/bin --- -> 1 you're here (was 'in-use' before fix) --- cwd = worktree/.cache/tmp --- -> 1 you're here (was 'in-use' before fix)

treehouse status transcripts (cwd inside dot-prefixed subdirs)
binary: /tmp/no-mistakes-evidence/01KW9VEMQHM7A4ND2HG8XE0VGG/treehouse
worktree: /tmp/tmp.FY1fFXgfQs/home/.treehouse/myrepo-c3de26/1/myrepo
created worktree banner/get output:
🌳 Setting up worktree...
🌳 Entered worktree at ~/.treehouse/myrepo-c3de26/1/myrepo. Type 'exit' to return.
🌳 Worktree returned to pool.

--- cwd = worktree/ ---
1     you're here  ~/.treehouse/myrepo-c3de26/1/myrepo
                   bash (174856), treehouse (174857)

--- cwd = worktree/src/foo ---
1     you're here  ~/.treehouse/myrepo-c3de26/1/myrepo
                   bash (174866), treehouse (174867)

--- cwd = worktree/.venv/bin ---
1     you're here  ~/.treehouse/myrepo-c3de26/1/myrepo
                   bash (174876), treehouse (174877)

--- cwd = worktree/.cache/tmp ---
1     you're here  ~/.treehouse/myrepo-c3de26/1/myrepo
                   bash (174886), treehouse (174887)
Evidence: status transcript - BASE (buggy) binary

treehouse status from cwd inside dot-prefixed subdirs (buggy base binary): --- cwd = worktree/ --- -> 1 you're here --- cwd = worktree/src/foo --- -> 1 you're here --- cwd = worktree/.venv/bin --- -> 1 in-use (BUG: should be 'you're here') --- cwd = worktree/.cache/tmp --- -> 1 in-use (BUG: should be 'you're here')

treehouse status transcripts (cwd inside dot-prefixed subdirs)
binary: /tmp/tmp.TWFYrysdNa/treehouse-base
worktree: /tmp/tmp.430113JFwm/home/.treehouse/myrepo-8900c0/1/myrepo
created worktree banner/get output:
🌳 Setting up worktree...
🌳 Entered worktree at ~/.treehouse/myrepo-8900c0/1/myrepo. Type 'exit' to return.
🌳 Worktree returned to pool.

--- cwd = worktree/ ---
1     you're here  ~/.treehouse/myrepo-8900c0/1/myrepo
                   bash (175056), treehouse-base (175057)

--- cwd = worktree/src/foo ---
1     you're here  ~/.treehouse/myrepo-8900c0/1/myrepo
                   bash (175072), treehouse-base (175073)

--- cwd = worktree/.venv/bin ---
1     in-use       ~/.treehouse/myrepo-8900c0/1/myrepo
                   bash (175082), treehouse-base (175083)

--- cwd = worktree/.cache/tmp ---
1     in-use       ~/.treehouse/myrepo-8900c0/1/myrepo
                   bash (175092), treehouse-base (175093)
Evidence: TestCwdInWorktree unit test result
=== RUN TestCwdInWorktree
--- PASS: TestCwdInWorktree (0.00s)
--- PASS: worktree_root
--- PASS: regular_subdir
--- PASS: dot-prefixed_subdir_.venv/bin
--- PASS: dot-prefixed_subdir_.cache/tmp
--- PASS: parent_of_worktree_(rel_starts_with_..)
--- PASS: sibling_dir
PASS
ok github.com/kunchenguid/treehouse/internal/pool
Evidence: reproducible e2e demo script
#!/usr/bin/env bash
# End-to-end demonstration that `treehouse status` correctly reports
# "you're here" when the user's cwd is inside a dot-prefixed subdirectory
# (e.g. .venv/bin, .cache/tmp) of a pooled worktree.
set -u

BIN="$1"          # path to the treehouse binary under test
EVDIR="$2"        # evidence output dir

DEMO="$(mktemp -d)"
DEMO="$(cd "$DEMO" && pwd)"

# Minimal "exit-shell" so `treehouse get` does not block waiting on a TTY.
EXITSHELL_SRC="$DEMO/exitshell-src"
mkdir -p "$EXITSHELL_SRC"
printf 'module exitshell\n\ngo 1.21\n' > "$EXITSHELL_SRC/go.mod"
printf 'package main\n\nfunc main() {}\n' > "$EXITSHELL_SRC/main.go"
EXITSHELL="$DEMO/exitshell"
( cd "$EXITSHELL_SRC" && go build -o "$EXITSHELL" . ) || { echo "exitshell build failed"; exit 1; }

# Isolated HOME so we don't touch real user pool state.
HOME_ISOLATED="$DEMO/home"
mkdir -p "$HOME_ISOLATED"

# --- Set up a real git repo with a bare remote (mirrors e2e_test.go setup) ---
BARE="$DEMO/remote.git"
REPO="$DEMO/myrepo"
git init --bare --initial-branch=main "$BARE" >/dev/null
git init --initial-branch=main "$REPO" >/dev/null
git -C "$REPO" config user.email test@test.com
git -C "$REPO" config user.name Test
git -C "$REPO" remote add origin "$BARE"
printf 'hello\n' > "$REPO/README.md"
git -C "$REPO" add .
git -C "$REPO" commit -m "initial commit" >/dev/null
git -C "$REPO" push -u origin main >/dev/null 2>&1

export HOME="$HOME_ISOLATED"
SHELL="$EXITSHELL"

run() {
  # run <workdir> <args...>
  local wd="$1"; shift
  ( cd "$wd" && HOME="$HOME_ISOLATED" SHELL="$EXITSHELL" "$BIN" "$@" )
}

echo "============================================================"
echo "Scenario: treehouse status from inside dot-prefixed subdirs"
echo "============================================================"

# Create a pooled worktree.
GET_OUT="$(run "$REPO" get 2>&1)" || true
# The worktree lives under $HOME_ISOLATED/.treehouse/myrepo-<hash>/<n>/myrepo.
WT="$(find "$HOME_ISOLATED/.treehouse" -maxdepth 4 -type d -name myrepo 2>/dev/null | head -n1)"
if [ -z "${WT:-}" ] || [ ! -d "$WT" ]; then
  echo "Could not locate created worktree. get output:"; printf '%s\n' "$GET_OUT"; exit 1
fi
echo "Created pooled worktree: $WT"

# Create the dot-prefixed subdirs an end user would have.
mkdir -p "$WT/.venv/bin" "$WT/.cache/tmp" "$WT/src/foo"

probe() {
  # probe <subdir-relative> <label>
  local sub="$1" label="$2"
  local target="$WT/$sub"
  echo ""
  echo "--- cwd = worktree/$sub  ($label) ---"
  ( cd "$target" && HOME="$HOME_ISOLATED" SHELL="$EXITSHELL" "$BIN" status ) 2>&1
}

probe ""            "worktree root"
probe "src/foo"     "regular subdir"
probe ".venv/bin"   "dot-prefixed subdir (the bug case)"
probe ".cache/tmp"  "dot-prefixed subdir (the bug case)"

# Persist the full transcript for the artifact.
{
  echo "treehouse status transcripts (cwd inside dot-prefixed subdirs)"
  echo "binary: $BIN"
  echo "worktree: $WT"
  echo "created worktree banner/get output:"
  printf '%s\n' "$GET_OUT"
  for s in "" "src/foo" ".venv/bin" ".cache/tmp"; do
    echo ""
    echo "--- cwd = worktree/$s ---"
    ( cd "$WT/$s" && HOME="$HOME_ISOLATED" SHELL="$EXITSHELL" "$BIN" status ) 2>&1
  done
} > "$EVDIR/status-e2e-transcript.txt"

echo ""
echo "Transcript saved to $EVDIR/status-e2e-transcript.txt"

# Cleanup the demo scratch (keep evidence dir intact).
rm -rf "$DEMO"

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

🔧 **Rebase** - 1 issue found → auto-fixed ✅
  • ⚠️ internal/pool/pool_test.go - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

⚠️ **Review** - 1 info
  • ℹ️ internal/pool/pool.go:362 - The new predicate rel == &#34;.&#34; || (rel != &#34;..&#34; &amp;&amp; !strings.HasPrefix(rel, &#34;..&#34;+string(filepath.Separator))) is now byte-for-byte identical to the inline check in internal/process/detect.go:75. Since package pool already imports process (pool.go:14), the two could share an exported helper (e.g. process.IsPathInsideWorktree) to guarantee the two containment checks never diverge again. The divergence was the root cause of this bug, so consolidating would prevent recurrence. Optional, low-value follow-up given it's a one-liner.
✅ **Test** - passed

✅ No issues found.

  • go test ./internal/pool/... -run TestCwdInWorktree -v
  • go test ./...
  • GOOS=windows GOARCH=amd64 go build ./...
  • GOOS=darwin GOARCH=arm64 go build ./...
  • e2e: built fixed binary, ran treehouse get to create a pooled worktree, then treehouse status with cwd in worktree root, src/foo, .venv/bin, and .cache/tmp -> all show 'you're here' (status-e2e-FIXED.txt)
  • e2e contrast: built the base-commit (buggy) binary and ran the identical scenario -> .venv/bin and .cache/tmp wrongly show 'in-use' (status-e2e-BASE-buggy.txt), proving the bug and the fix
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

The cwdInWorktree predicate rejected any relative path starting with a
dot, so being inside a dot-prefixed subdirectory of a worktree (e.g.
.venv/bin, .cache/tmp, .git-hooks) was treated as "not here", causing
treehouse status to fail to mark the user as present in the worktree.

Replace the rel[0] != '.' check with the same "does not escape via .."
predicate already used by internal/process/detect.go: rel must be "."
or must not start with "..". This is a status-display-only regression,
so the impact is limited to the "you're here" marker.

Add the first test for cwdInWorktree as a table-driven test covering
the worktree root, regular subdirs, dot-prefixed subdirs (the bug
case), and paths outside the worktree.
@e-jung e-jung force-pushed the fix/cwdinworktree-dot-subdirs branch from 6932c87 to b06835e Compare June 29, 2026 14:55
@e-jung e-jung changed the title fix(pool): cwdInWorktree accepts dot-prefixed subdirectories fix(pool): accept dot-prefixed subdirectories in cwdInWorktree Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant