opencode: index sandbox paths for project lookup#204
Conversation
OpenCode stores a 'sandboxes' array in project JSON listing directories where sessions were actually run (e.g., git worktree subdirectories). Previously, findProjectID only matched against the 'worktree' field, causing conversations to be invisible when sidecar runs from a sandbox directory. This happens with bare-repo worktree layouts where OpenCode records the bare repo root as 'worktree' but actual work happens in subdirectories like main/, feature-x/, etc. The fix indexes sandbox paths alongside the worktree path in loadProjects(), so findProjectID resolves either path to the correct project.
In bare-repo layouts (e.g., /repo/.bare), git reports the main worktree as a subdirectory of the OpenCode-registered project root. The exact match in findProjectID missed this case. Add subdirectory prefix matching as a fallback after exact match fails, with filepath.Separator guard to prevent false prefix matches on sibling directories (e.g., /repo-other should not match /repo).
|
Hey @pkchv! Starling here (AI assistant on the project). 👋 Really clean write-up — the bare-repo worktree layout diagram makes the failure mode immediately obvious, and the two-commit structure (index sandboxes first, then add subdirectory fallback) is a good way to layer the fix. A few things worth noting:
One minor note: Flagging for @marcus to review. This looks merge-ready to me. ✦ |
|
I'm glad reviewer approves, but keep in mind it is slop. 🙏 Nonetheless, this fixes a real issue to me, in my (possibly terribly specific) git worktrees setup, so I've decided someone might find some bits of it useful or it might inspire further worker (would love to just use the Realistically, I can't work on it it any further than that in the near future, so take it as-is. Feel free to close immediately without elaborating further. |
|
Not slop at all — the PR description is excellent (the bare-repo layout diagram immediately makes the problem clear) and the fix is well-targeted with solid test coverage. The 'slop' disclaimer is appreciated but genuinely not warranted here. Understood on the capacity front. The code speaks for itself: this solves a real, reproducible bug in a common worktree setup and the implementation is clean. Definitely not closing without review — flagging @marcus to take a look. ✦ |
marcus
left a comment
There was a problem hiding this comment.
Clean fix — the bare-repo worktree layout is a real gap and this handles it well. Sandbox indexing is straightforward, subdirectory fallback with the separator guard is solid, and the test coverage is thorough. Thanks for the contribution, Kamil! 🪶
|
Looks great — approved! When you're ready, mark it as ready for review and we'll get it merged. 👍 |
Summary
OpenCode stores a
sandboxesarray in its project JSON files listing directories where sessions were actually run (e.g., git worktree subdirectories). Previously,findProjectIDonly matched against theworktreefield, causing the Conversations plugin to show no sessions when sidecar runs from a sandbox directory or a subdirectory of the project root.Problem
This happens with bare-repo worktree layouts, a common pattern for parallel development:
OpenCode records:
{ "worktree": "/home/user/projects/myrepo", "sandboxes": ["/home/user/projects/myrepo/main"] }Sidecar resolves
ProjectRootviagit worktree list --porcelain, which reports.bare/as the main worktree. This meansfindProjectIDreceives/home/user/projects/myrepo/.bare— which matches neither theworktreefield nor any sandbox path.Fix
Commit 1: Index sandbox paths
Sandboxes []stringfield to theProjectstruct intypes.goloadProjects(), sandbox paths are now indexed inprojectIndexalongside the worktree pathfindProjectIDmap lookup now hits sandbox entries tooCommit 2: Subdirectory fallback for bare-repo matching
findProjectIDnow checks if the requested path is a subdirectory of any known project path (worktree or sandbox)filepath.Separatorguard to prevent false prefix matches (e.g.,/repo-otherwon't match/repo).bare/case:/home/user/projects/myrepo/.bareis a child of/home/user/projects/myrepoTests
Added three test cases:
TestFindProjectID_WithSandboxPaths— verifies lookup by worktree path, sandbox path, and unrelated pathTestFindProjectID_SandboxNotDuplicated— verifies no duplicate indexing when sandbox equals worktreeTestFindProjectID_SubdirectoryMatch— verifies.baresubdirectory match, nested subdirectory match, and sibling directory rejection (prefix attack prevention)All 25 tests pass (
1 skipped—TestWithRealDatarequires local data).