Move LocalProvider from cmd/bd/doctor/git.go to internal/storage/local_provider.go
where it belongs alongside StorageProvider. Both implement IssueProvider for
orphan detection - LocalProvider for direct SQLite access (--db flag),
StorageProvider for the global Storage interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(orphans): honor --db flag for cross-repo orphan detection
Problem:
- `bd orphans --db /path` ignored the --db flag entirely
- FindOrphanedIssues() hardcoded local .beads/ directory
Solution:
- Introduce IssueProvider interface for abstract issue lookup
- Add StorageProvider adapter wrapping Storage instances
- Update FindOrphanedIssues to accept provider instead of path
- Wire orphans command to create provider from --db flag
Closes: steveyegge/beads#1196
* test(orphans): add cross-repo and provider tests for --db flag fix
- Add TestFindOrphanedIssues_WithMockProvider (table-driven, UT-01 through UT-09)
- Add TestFindOrphanedIssues_CrossRepo (validates --db flag honored)
- Add TestFindOrphanedIssues_LocalProvider (backward compat RT-01)
- Add TestFindOrphanedIssues_ProviderError (error handling UT-07)
- Add TestFindOrphanedIssues_IntegrationCrossRepo (IT-02 full)
- Add TestLocalProvider_* unit tests
Coverage for IssueProvider interface and cross-repo orphan detection.
* docs: add bd orphans command to CLI reference
Document the orphan detection command including the cross-repo
workflow enabled by the --db flag fix in this PR.
The "Sync Branch Health" check incorrectly warned when the sync branch
differed from main on source files. Since the sync branch only tracks
.beads/ data, source file differences are expected behavior.
The associated --fix action (reset sync branch to main and force push)
was destructive and destroyed legitimate sync branch history.
Removed Check 2 entirely - only Check 1 (detecting divergence from remote
after force-push) remains, which is a legitimate issue.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd init installs hooks with chaining, it renames the user's original
hook to .old and creates a new bd hook that chains to it. If bd doctor
later runs bd hooks install --chain, it would:
1. Not recognize the inline bd hook (from bd init) as a bd hook
2. Rename it to .old, overwriting the user's original hook
3. Install a new shim hook
This fix addresses two root causes:
1. Detection mismatch: areBdShimsInstalled() and getHookVersion() now
recognize inline bd hooks (which have "# bd (beads)" marker) in
addition to shim hooks (which have "# bd-shim" marker)
2. No .old protection: bd hooks install --chain now checks if .old
already exists before renaming, preserving the user's original hook
Fixes#1120
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Git hooks are shared across all worktrees and live in the common git
directory (e.g., /repo/.git/hooks), not the worktree-specific directory
(e.g., /repo/.git/worktrees/feature/hooks).
The core issue was in GetGitHooksDir() which used GetGitDir() instead
of GetGitCommonDir(). This caused hooks to be installed to/read from
the wrong location when running in a worktree.
Additionally, several places in the codebase manually constructed
hooks paths using gitDir + "hooks" instead of calling GetGitHooksDir().
These have been updated to use the proper worktree-aware path.
Affected areas:
- GetGitHooksDir() now uses GetGitCommonDir()
- CheckGitHooks() uses GetGitHooksDir()
- installHooks/uninstallHooks use GetGitHooksDir()
- runChainedHook() uses GetGitHooksDir()
- Doctor checks use git-common-dir for hooks paths
- Reset command uses GetGitCommonDir() for hooks and beads-worktrees
Symptoms that this fixes:
- Chained hooks (pre-commit.old) not running in worktrees
- bd hooks install not finding/installing hooks correctly in worktrees
- bd hooks list showing incorrect status in worktrees
- bd doctor reporting incorrect hooks status in worktrees
Co-authored-by: Zain Rizvi <4468967+ZainRizvi@users.noreply.github.com>
When an external hook manager config file (like .pre-commit-config.yaml) exists
but the actual hooks are bd shims, doctor now correctly reports OK instead of
warning that the manager doesn't call bd.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd doctor detects hook managers we can't fully check (pre-commit,
overcommit, yorkie, simple-git-hooks), it now shows an informational
message instead of a warning:
✓ pre-commit detected (cannot verify bd integration)
└─ Ensure your hook config calls 'bd hooks run <hook>'
Previously it incorrectly warned that these managers were "not calling bd"
when we simply couldn't verify their config.
Changes:
- Add DetectionOnly field to HookIntegrationStatus
- Set DetectionOnly=true for unsupported managers in CheckExternalHookManagerIntegration
- Update CheckGitHooks and CheckSyncBranchHookCompatibility to show
informational message for detection-only managers
- Add test coverage for DetectionOnly behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add detection for external git hook managers (lefthook, husky, pre-commit,
overcommit, yorkie, simple-git-hooks) and check if they have bd hooks
integration configured.
- Detect manager config files in various locations/formats
- Parse lefthook YAML/TOML/JSON to check for `bd hooks run` commands
- Check husky hook scripts for bd integration
- Report which hooks have bd integration vs missing
- Use --chain flag in `bd doctor --fix` when external managers detected
- Detect active manager from git hooks when multiple present
Executed-By: mayor
Role: mayor
The CheckSyncBranchHookCompatibility was checking core.hooksPath first,
while CheckGitHooks always uses .git/hooks/. This caused inconsistent
results when core.hooksPath was set globally.
Fix: Remove core.hooksPath check from CheckSyncBranchHookCompatibility
to match CheckGitHooks behavior. Both now consistently use .git/hooks/.
Note: A future improvement could make both respect core.hooksPath.
Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog
entries. The descriptions remain meaningful without the ephemeral
issue IDs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extended bd-tvus fix to all doctor check functions that access .beads/
directory. In Gas Town multi-clone setups, crew/polecat clones use
.beads/redirect files to point to the shared mayor/rig beads directory.
Doctor checks now use resolveBeadsDir() to follow these redirects:
- daemon.go: CheckDaemonStatus
- git.go: CheckSyncBranchConfig, FindOrphanedIssues, CheckOrphanedIssues
- installation.go: CheckMultipleDatabases, CheckPermissions
- integrity.go: CheckIDFormat, CheckDependencyCycles, CheckTombstones,
CheckDeletionsManifest, CheckRepoFingerprint
- jsonl_integrity.go: CheckJSONLIntegrity
- legacy.go: CheckFreshClone
- maintenance.go: CheckStaleClosedIssues, CheckExpiredTombstones,
CheckCompactionCandidates
- perf.go: RunPerformanceDiagnostics, CollectPlatformInfo
- validation.go: CheckMergeArtifacts, CheckOrphanedDependencies,
CheckDuplicateIssues, CheckTestPollution, CheckChildParentDependencies,
CheckGitConflicts
- version.go: CheckMetadataVersionTracking
Intentionally NOT changed (check local files):
- CheckInstallation: checks local .beads/ exists
- CheckUntrackedBeadsFiles: checks git tracking of local files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the 'bd orphans' command to identify issues referenced in commits
but still open in the database, and refactors to eliminate code duplication.
- Creates cmd/bd/orphans.go with Cobra command structure
- Identifies orphaned issues (referenced in git commits but still open/in_progress)
- Supports multiple output formats (human, JSON, detailed)
- Auto-close with --fix flag
DRY refactoring:
- Extracted FindOrphanedIssues() to cmd/bd/doctor/git.go as shared core logic
- Moved OrphanIssue type to cmd/bd/doctor/types.go
- Refactored CheckOrphanedIssues() to use FindOrphanedIssues()
Cherry-picked from PR #767
Co-authored-by: Amp <amp@ampcode.com>
Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"
Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds automatic database recovery when bd doctor --fix detects corruption:
- Detects SQLite corruption (malformed database, SQLITE_CORRUPT errors)
- Backs up corrupted database before recovery attempt
- Rebuilds from JSONL if available (issues.jsonl, deletions.jsonl)
- Falls back to fresh database if JSONL unavailable
- Reports recovery results (issues imported, success/failure)
Recovery is triggered automatically by --fix when corruption is detected.
No manual intervention required.
feat(doctor): add count-based database size check
Adds CheckDatabaseSize (Check 29) that warns when closed issues exceed a configurable threshold (default: 5000). The check is informational only - no auto-fix since pruning is destructive.
Also improves fix guidance for sync-branch hook compatibility and legacy JSONL filename checks.
PR #724 by @rsnodgrass
- Add CheckOrphanedIssues to detect issues referenced in commits but still open
- Pattern matches (prefix-xxx) in git log against open issues in database
- Reports warning with issue IDs and commit hashes
- Add 8 comprehensive tests for the new check
Also:
- Add tests for mol spawn --attach functionality (bd-f7p1)
- Document commit message convention in AGENT_INSTRUCTIONS.md
- Fix CheckpointWAL to use wrapDBError for consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(doctor): split doctor.go into modular package files
Split the 3,171-line doctor.go into logical sub-files within the
cmd/bd/doctor/ package, reducing the main file to 834 lines (74% reduction).
New package structure:
- types.go: DoctorCheck struct and status constants
- installation.go: CheckInstallation, CheckMultipleDatabases, CheckPermissions
- git.go: CheckGitHooks, CheckMergeDriver, CheckSyncBranch* checks
- database.go: CheckDatabaseVersion, CheckSchemaCompatibility, CheckDatabaseJSONLSync
- version.go: CheckCLIVersion, CheckMetadataVersionTracking, CompareVersions
- integrity.go: CheckIDFormat, CheckDependencyCycles, CheckTombstones
- daemon.go: CheckDaemonStatus, CheckVersionMismatch
- quick.go: Quick checks for sync-branch and hooks
Updated tests to use exported doctor.CheckXxx() functions and
doctor.StatusXxx constants.
* fix(doctor): suppress gosec G204 false positives
Add #nosec G204 comments to exec.Command calls in CheckSyncBranchHealth
where variables come from trusted sources (config files or hardcoded
values like "main"/"master"/"origin"), not untrusted user input.