Add 'bd doctor' command to sanity check installation (#189)

* Add bd doctor command for installation health checks

Implements a comprehensive health check command similar to claude doctor
that validates beads installation and provides actionable recommendations.

Features:
- Installation check (.beads/ directory exists)
- Database version verification (compares with CLI version)
- ID format detection (hash-based vs sequential)
- CLI version check (fetches latest from GitHub)
- Storage type detection (SQLite vs JSONL-only mode)
- Tree-style output with color-coded warnings
- JSON output for scripting (--json flag)
- Actionable fix recommendations for each issue

Implementation improvements:
- Status constants instead of magic strings
- Semantic version comparison (fixes 0.10.0 vs 0.9.9 edge case)
- Documented defer pattern for intentional error ignore
- Comprehensive test coverage including version comparison edge cases
- Clean integration using slices.Contains for command list

Usage:
  bd doctor              # Check current directory
  bd doctor /path/to/repo # Check specific repository
  bd doctor --json       # Machine-readable output

* Simplify bd doctor documentation in README

Reduce verbose health check section to 2 lines as requested.

* Fix bd doctor to handle JSONL-only mode for ID format check

When no SQLite database exists (JSONL-only mode), skip the ID format
check instead of showing an error. This prevents the confusing
'Unable to query issues' error when the installation is actually fine.
This commit is contained in:
Ryan
2025-10-31 11:41:13 -07:00
committed by GitHub
parent 053edadf14
commit 08bfe133d0
4 changed files with 681 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"sync"
"time"
@@ -111,7 +112,8 @@ var rootCmd = &cobra.Command{
}
// Skip database initialization for commands that don't need a database
if cmd.Name() == "init" || cmd.Name() == cmdDaemon || cmd.Name() == "help" || cmd.Name() == "version" || cmd.Name() == "quickstart" {
noDbCommands := []string{"init", cmdDaemon, "help", "version", "quickstart", "doctor"}
if slices.Contains(noDbCommands, cmd.Name()) {
return
}