Skip to content

fix: closing one worktree closes every repo's same-numbered worktree - #1015

Closed
SmolSmolStar wants to merge 1 commit into
web3dev1337:mainfrom
SmolSmolStar:fix/close-session-worktree-collision
Closed

fix: closing one worktree closes every repo's same-numbered worktree#1015
SmolSmolStar wants to merge 1 commit into
web3dev1337:mainfrom
SmolSmolStar:fix/close-session-worktree-collision

Conversation

@SmolSmolStar

Copy link
Copy Markdown
Contributor

Summary

In a mixed-repo workspace, closing a single worktree's terminal (the close-process × button) can close every other repo's worktree that shares the same number. Reproduced in the wild: clicking close on sandbox/work1 also closed agent-workspace/work1, USDUC/work1, and Cat-Code-Academy/work1, leaving only Test-game/work4 (the one worktree on a different number).

Root cause

SessionManager.getSessionGroupIds builds its close-list from two keys:

const keys = [composedKey, parsedWorktreeId].filter(Boolean);

composedKey is repo-scoped (sandbox-work1, correct), but parsedWorktreeId is the bare worktree number (work1). parseWorktreeKey only treats <repo>-work<N> as repo-scoped, so a bare work1 lookup in getSessionIdsForWorktree matches every repo's work1 in the workspace.

The existing tests only covered cross-workspace scoping (already handled by the workspace filter), so this same-workspace / different-repo collision slipped through. It's the same class of hazard the repo's own docs call out for remove-worktree (bare worktree ids nuke all repos).

Fix

Only ever key on repo-scoped identifiers:

  • the composed ${repositoryName}-${worktreeId} key, and
  • the session id's own repo-scoped prefix (e.g. sandbox-work1).

Never the bare worktree number.

Test plan

  • Adds a regression test that seeds several repos sharing work1 (plus one work4) in a single workspace and asserts getSessionGroupIds('sandbox-work1-claude') returns only sandbox's own sessions.
  • Verified the test fails on the old code (returns 4 extra sessions) and passes with the fix.
  • Full sessionManager.closeSession suite green (9/9), node --check clean.

🤖 Generated with Claude Code

… worktree

In a mixed-repo workspace, closing a single worktree's terminal (the close-process
button) could close every OTHER repo's worktree that shared the same number — e.g.
clicking close on sandbox/work1 also closed agent-workspace/work1, USDUC/work1 and
Cat-Code-Academy/work1, leaving only the one repo on a different number (work4).

Root cause: SessionManager.getSessionGroupIds looked up the group by two keys —
the repo-scoped `${repo}-${worktree}` AND the bare worktree number (`work1`). The
bare number is not repo-scoped (parseWorktreeKey only treats `<repo>-work<N>` as
scoped), so getSessionIdsForWorktree matched every repo's work1 in the workspace.
The existing tests only covered cross-WORKSPACE scoping (handled by the workspace
filter), so the same-workspace/different-repo collision slipped through.

Fix: only ever key on repo-scoped identifiers — the composed `${repo}-${worktree}`
key and the session id's own repo-scoped prefix (e.g. `sandbox-work1`). Never the
bare worktree number.

Adds a regression test seeding several repos that share `work1` (plus one `work4`)
in one workspace and asserting getSessionGroupIds('sandbox-work1-claude') returns
only sandbox's own sessions. Verified it fails on the old code (returns 4 extra
sessions) and passes with the fix; full suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
web3dev1337 added a commit to SmolSmolStar/agent-workspace that referenced this pull request Jul 18, 2026
…web3dev1337#1015

Cherry-picks the richer 4-repos-plus-work4 regression test from the sibling
PR web3dev1337#1015 so its coverage survives even though that PR's production change is
superseded by this one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@web3dev1337

Copy link
Copy Markdown
Owner

Reviewed side-by-side with sibling PR #1014 — both fix the same bug in the same lines of getSessionGroupIds, so only one can land. A behavioral harness comparison came out in #1014's favor: it never uses a bare (unscoped) lookup key when repo info is derivable from any source, while this PR's unconditional worktreePrefix second key re-opens the cross-repo match in one edge case (bare sid + populated repositoryName) and double-queries when the keys coincide. Your 4-repo regression test was valuable though — it's been cherry-picked into #1014 so the coverage lands. Recommending this PR be closed as superseded once #1014 merges.

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.

2 participants