Commit Graph

9 Commits

Author SHA1 Message Date
Charles P. Cross
2b031b9441 fix(worktree): add -f flag to handle missing but registered state (#609)
Problem:
When the daemon auto-sync runs with --auto-commit --auto-push, the sync
branch pull operation consistently fails with:

  fatal: '.git/beads-worktrees/beads-metadata' is a missing but already
  registered worktree; use 'add -f' to override, or 'prune' or 'remove'
  to clear

This occurs because:
1. Daemon creates worktree at .git/beads-worktrees/<branch>
2. Git registers it in .git/worktrees/<branch>
3. After the operation, worktree contents are removed
4. Git registration persists, pointing to the now-empty path
5. Subsequent CreateBeadsWorktree calls fail because os.Stat() returns
   error (path missing), so no cleanup happens, then git worktree add
   fails because git still has it registered

Root cause:
The git worktree add commands in CreateBeadsWorktree() did not use the
-f (force) flag, which is needed to override the "missing but already
registered" state.

Solution:
Add -f flag to both git worktree add commands (for existing branch and
new branch cases). Per git documentation, -f overrides the safeguard
that prevents creating a worktree when the path is already registered
but missing.

The existing git worktree prune call (line 30-32) was intended to handle
this, but it runs before the path check and may not always clear the
registration in time. The -f flag provides a robust fallback.

Testing:
- All existing worktree tests pass
- Added regression test TestCreateBeadsWorktree_MissingButRegistered
  that simulates the exact issue #609 scenario

Fixes #609

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-18 20:29:32 -08:00
Steve Yegge
69d14e21d8 fix(git): find .beads from nested worktrees (GH#509)
When worktrees are nested under the main repo (e.g.,
/project/.worktrees/feature/), bd now correctly finds .beads/ in the
parent repo.

The fix simplifies GetMainRepoRoot() to use `git rev-parse --git-common-dir`
which always returns the main repo's .git directory, regardless of whether
we're in a regular repo, a worktree, or a nested worktree.

- Simplified GetMainRepoRoot() implementation
- Added tests for nested worktree scenarios
- Updated CHANGELOG.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 17:20:46 -08:00
matt wilkie
e01b7412d9 feat: add Git worktree compatibility (PR #478)
Adds comprehensive Git worktree support for beads issue tracking:

Core changes:
- New internal/git/gitdir.go package for worktree detection
- GetGitDir() returns proper .git location (main repo, not worktree)
- Updated all hooks to use git.GetGitDir() instead of local helper
- BeadsDir() now prioritizes main repository's .beads directory

Features:
- Hooks auto-install in main repo when run from worktree
- Shared .beads directory across all worktrees
- Config option no-install-hooks to disable auto-install
- New bd worktree subcommand for diagnostics

Documentation:
- New docs/WORKTREES.md with setup instructions
- Updated CHANGELOG.md and AGENT_INSTRUCTIONS.md

Testing:
- Updated tests to use exported git.GetGitDir()
- Added worktree detection tests

Co-authored-by: Claude <noreply@anthropic.com>
Closes: #478
2025-12-13 12:50:33 -08:00
Charles P. Cross
eb988fcb21 Fix daemon auto-sync delete mutation not reflected in sync branch (#537)
Fix daemon auto-sync delete mutation not reflected in sync branch

When deleting an issue with `bd delete <id> --force`, the daemon auto-sync now properly removes the deleted issue from the sync branch.

**Problem:** The merge logic saw fewer local issues (due to deletion) and would re-add the deleted issue.

**Solution:** Add `ForceOverwrite` option to bypass merge logic when mutations occur. Mutation-triggered exports are authoritative and should overwrite, not merge.

Reviewed-by: stevey
2025-12-13 10:53:09 -08:00
Steve Yegge
26b8013908 fix(sync): merge instead of overwrite in SyncJSONLToWorktree (bd-52q)
When syncing JSONL to worktree, if the worktree has more issues than
local, merge them instead of blindly overwriting. This prevents fresh
clones from accidentally deleting remote issues when they sync with
fewer issues than the sync branch.

Root cause of GitHub #464: A fresh clone with sync-branch configured
would start with an empty database (since JSONL is on sync-branch, not
HEAD). When syncing, the local 1-issue JSONL would overwrite the
remotes 10-issue JSONL, and the subsequent 3-way merge would see this
as local deleted 9 issues causing deletion to win.

The fix compares issue counts and triggers a merge when local has fewer
issues than the worktree (remote). Uses 3-way merge with empty base to
combine both sets of issues.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:33:34 -08:00
Steve Yegge
247672be54 test: improve coverage for config and git packages
- config: Add tests for GetStringSlice, GetMultiRepoConfig, and nil viper
  behavior. Coverage improved from 65.3% to 84.0%.
- git: Add tests for error paths in RemoveBeadsWorktree, SyncJSONLToWorktree,
  CheckWorktreeHealth, and sparse checkout functions. Coverage improved
  from 72.9% to 82.7%.

Closes: bd-t3b, bd-4h3, bd-ge7

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:56:52 -08:00
Steve Yegge
8bbb710e6a Fix branchExists test after signature change
Updated tests to match the new branchExists() signature that returns
bool instead of (bool, error).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 20:30:31 -08:00
Steve Yegge
86c645603e Fix all gosec, misspell, and unparam linter errors
- Add #nosec directives with explanations for all gosec warnings in worktree operations
- Tighten directory permissions from 0755 to 0750 for better security
- Fix misspellings: archaeological -> archeological, cancelled -> canceled
- Remove unused jsonlPath parameter from syncBranchCommitAndPush
- Change branchExists to return bool instead of (bool, error) - error was never used

All changes maintain backward compatibility and improve code quality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 20:06:05 -08:00
Steve Yegge
c6bf6331ec Implement git worktree management with sparse checkout (bd-a4b5)
- Created internal/git package with WorktreeManager
- Implements CreateBeadsWorktree with sparse checkout (.beads/ only)
- Implements RemoveBeadsWorktree with cleanup and pruning
- Implements CheckWorktreeHealth with repair capability
- Implements SyncJSONLToWorktree for JSONL syncing
- Comprehensive tests with 100% coverage
- Handles symlinks correctly (macOS /tmp -> /private/tmp)
- Idempotent worktree creation
- Sparse checkout excludes all files except .beads/
2025-11-02 15:49:36 -08:00