-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Summary
When running bd rename-prefix from a git worktree, the command updates the shared DB and the main worktree's issues.jsonl correctly, but leaves the current worktree's issues.jsonl with stale (old-prefix) IDs. Neither bd sync, bd sync --flush-only, nor bd export resolves the desync — they all write to the main worktree's path.
The same behavior occurs with or without --no-daemon.
Steps to Reproduce
# 1. Create test repo with issues
mkdir /tmp/test-rename && cd /tmp/test-rename
git init && git checkout -b main
export BEADS_NO_DAEMON=1
bd --no-daemon init --prefix=alpha
bd --no-daemon create --title="Issue one" --type=task --priority=2
bd --no-daemon create --title="Issue two" --type=bug --priority=3
bd --no-daemon export
git add -A && git commit -m "initial"
# 2. Create a worktree
git worktree add /tmp/test-worktree -b wt-branch
cd /tmp/test-worktree
# 3. Rename prefix from the worktree
bd --no-daemon rename-prefix beta
# 4. Observe the desync
cat .beads/issues.jsonl # Still alpha-* (stale!)
cat /tmp/test-rename/.beads/issues.jsonl # beta-* (correct)
bd --no-daemon list # beta-* (reads from shared DB)Expected Behavior
The current worktree's .beads/issues.jsonl should be updated with the new prefix, or the command should refuse to run in a worktree.
Actual Behavior
- Shared DB: updated correctly
- Main worktree JSONL: updated correctly
- Current worktree JSONL: stale, retains old prefix IDs
bd sync,bd sync --flush-only,bd export: all write to main's JSONL, not worktree'sbd list: shows correct IDs (reads from DB)
The worktree's JSONL becomes permanently diverged. On merge, git may auto-resolve (if changes don't conflict) or produce merge conflicts with stale IDs.
Root Cause
findJSONLPath() in cmd/bd/autoflush.go resolves the JSONL path via the database location. Since beads.db is gitignored and only exists in the main worktree, the path always resolves to the main worktree's .beads/issues.jsonl. The worktree redirect (getWorktreeJSONLPath) only activates when sync-branch is configured.
In a plain git worktree without sync-branch, all JSONL writes (rename, export, sync) go to the main worktree's file, leaving the worktree's git-checked-out copy untouched.
Suggested Fixes
Option A — Update all worktree JSONL files
- Enumerate all git worktrees after renaming in DB and main JSONL
- Update each worktree's
.beads/issues.jsonlwith renamed IDs - Complete fix, but open questions:
- Arbitrary count of worktrees — performance implications unknown
- Other per-worktree state may also need updating (e.g.,
interactions.jsonl, cache tables per rename-prefix doesn't update blocked_issues_cache table #1016) - As external contributors we lack full visibility into these trade-offs
Option B — Block rename in worktrees
- Detect worktree at the start of
rename-prefix - Exit with error: "Cannot rename prefix from a worktree. Please run from the main worktree."
- Surfaces a silent desync as an explicit error
- Zero risk to existing behavior
Option C — Fix findJSONLPath() to resolve relative to cwd in worktrees
- Change
findJSONLPath()incmd/bd/autoflush.goto resolve JSONL path from the current working directory when in a worktree, instead of from the DB path - Fixes the root cause — not just
rename-prefixbut alsoexportandsync --flush-only - Most architecturally correct, but largest blast radius — could affect other worktree behavior that depends on the current resolution logic
Environment
| Component | Version |
|---|---|
| bd | 0.49.6 (Homebrew) |
| Platform | macOS 15.4 (Darwin 25.2.0, arm64) |
Related Issues
- rename-prefix doesn't update blocked_issues_cache table #1016 —
rename-prefixdoesn't updateblocked_issues_cachetable