Skip to content

feat(penpal): live-detect worktree additions and removals#548

Merged
loganj merged 5 commits intomainfrom
penpal-builderbot-worktree-dis
Apr 9, 2026
Merged

feat(penpal): live-detect worktree additions and removals#548
loganj merged 5 commits intomainfrom
penpal-builderbot-worktree-dis

Conversation

@loganj
Copy link
Copy Markdown
Collaborator

@loganj loganj commented Mar 30, 2026

Summary

Previously, Penpal discovered git worktrees once at startup and never refreshed the list. If you ran git worktree add or git worktree remove while Penpal was running, the sidebar's worktree list went stale — showing deleted worktrees and missing new ones.

Now, worktree additions and removals are detected automatically via the existing workspace directory watch. When git worktree add ../foo creates a new sibling directory, the workspace watch fires a rescan that discovers the new worktree. Removal works the same way. No restart needed — the sidebar updates within moments.

Design: zero-cost detection

The implementation adds no additional inotify watches, no subprocess calls in the watcher hot path, and no lock acquisitions in the event loop. It piggybacks entirely on the workspace directory watch that was already in place:

  1. git worktree add ../foo creates a new directory in the workspace
  2. Workspace watch fires → debounced rediscoverProjects
  3. Discovery runs git worktree list, updates cache, broadcasts SSE projects event
  4. Frontend re-fetches /api/projects and the sidebar reflects the change

Changes

  • discovery/worktree.gogitCommonDirFS resolves the shared .git directory using pure filesystem reads (os.Lstat + os.ReadFile) instead of spawning git rev-parse. Used by discovery, not by the watcher.
  • watcher/watcher.go — Extracted rediscoverProjects helper (serialized with rediscoverMu), tightened .md-only event filter, removed dead code. No worktree-specific watches or event handling.
  • discovery/worktree.go — Removed dead code (FindMainWorktree, ResolveWorktree)
  • PRODUCT.md / ERD.md / TESTING.md — Added E-PENPAL-WORKTREE-WATCH requirement and updated P-PENPAL-WORKTREE to specify live updates

🤖 Generated with Claude Code

loganj and others added 5 commits March 30, 2026 00:23
Watch each project's .git/worktrees/ directory so that `git worktree
add` and `git worktree remove` are detected without restarting the
server. On change, full re-discovery runs and an SSE event pushes the
updated worktree list to the frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract rediscoverProjects() helper to eliminate duplicated boilerplate
  across worktree, workspace, and source-detection event handlers
- Protect worktreeWatchDirs and gitDirWatches reads in handleEvent with
  focusMu to prevent concurrent map read/write panic
- Watch .git/ directory for projects without existing worktrees so the
  first `git worktree add` (which creates .git/worktrees/) is detected
- Add GitCommonDir() helper extracted from GitWorktreesDir()
- Add test for first-worktree creation detection via .git/ watch
- Update no-worktrees test to verify .git/ is watched

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove dead code (FindMainWorktree, ResolveWorktree)
- Tighten .md-only event filter (drop Create bypass for non-.md files)
- Filter .git/ events to only react to worktrees/ creation
- Add tests for rediscoverProjects cache update and event filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace .git/worktrees/ inotify watches and per-project subprocess
calls with zero-cost workspace directory detection. Unexport unused
GitCommonDir/GitWorktreesDir, serialize rediscoverProjects, remove
redundant .md check, add tests for error paths and Write events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ktree-dis

* origin/main: (45 commits)
  feat(penpal): persist recent files activity across restarts (#595)
  feat: persist open windows, tabs, and geometry across app restarts (#588)
  feat(staged): generate next prefill text when generating notes (#594)
  feat(staged): add "Run again" button to action output dialog (#593)
  feat: queue repo sessions in project MCP with async cancellation fix (#591)
  fix(staged): lowercase "building" subtitle for consistency (#592)
  fix(staged): use completedAt for commit prefill timeline ranking (#590)
  fix: add per-branch mutex to prevent worktree setup race condition (#589)
  feat: add diff commit session launcher (#585)
  fix: avoid error state for empty titled code reviews (#587)
  fix: cancel in-flight auto reviews before manual sessions (#584)
  feat(settings): add repo context search (#583)
  fix(staged): sort timeline items by completion time so queued items appear before completed ones (#568)
  fix: drain queued branch sessions from backend lifecycle (#579)
  fix: restore resume session metadata for resumed actions (#580)
  feat(staged): add purple diff comment theme (#578)
  fix(ui): hide branch actions during setup (#572)
  fix: validate parsed PR URLs before extraction (#577)
  fix: centralize staged relative time updates (#576)
  fix: avoid UI freezes when starting background sessions (#575)
  ...

# Conflicts:
#	apps/penpal/internal/watcher/watcher.go
@loganj loganj marked this pull request as ready for review April 9, 2026 16:20
@loganj loganj merged commit aa3e58e into main Apr 9, 2026
5 checks passed
@loganj loganj deleted the penpal-builderbot-worktree-dis branch April 9, 2026 16:23
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