bd-4ew: Doctor detects fresh clone and recommends 'bd init'

When JSONL exists but no database (and not no-db mode), doctor now:
- Shows 'Fresh clone detected' warning
- Shows count of issues in JSONL
- Recommends 'bd init' with detected prefix

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-11-28 21:59:59 -08:00
parent d782574667
commit 46862568f6
2 changed files with 66 additions and 12 deletions

View File

@@ -8,7 +8,7 @@
{"id":"bd-3gc","title":"Audit remaining cmd/bd files for error handling consistency","description":"Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:55.890991-08:00","updated_at":"2025-11-24T00:28:55.890991-08:00"}
{"id":"bd-44e","title":"Ensure deletions.jsonl is tracked in git","description":"Parent: bd-imj\n\nEnsure deletions.jsonl is tracked in git (not ignored).\n\nUpdate bd init and gitignore upgrade logic to:\n1. NOT add deletions.jsonl to .gitignore\n2. Ensure it is committed alongside beads.jsonl\n\nThe file must be in git for cross-clone propagation to work.\n\nAcceptance criteria:\n- bd init does not ignore deletions.jsonl\n- Existing .gitignore files are not broken\n- File appears in git status when modified","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T09:57:21.663196-08:00","updated_at":"2025-11-25T14:55:43.225883-08:00","closed_at":"2025-11-25T14:55:43.225883-08:00"}
{"id":"bd-4aao","title":"Fix failing integration tests in beads-mcp","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T18:53:28.4803-05:00","updated_at":"2025-11-25T21:39:20.967106-08:00","closed_at":"2025-11-25T21:39:20.967106-08:00"}
{"id":"bd-4ew","title":"bd doctor should detect fresh clone and recommend 'bd init'","description":"When running `bd doctor` on a fresh clone (JSONL exists, no .db file), it should:\n\n1. Detect this is a fresh clone situation\n2. Recommend `bd init --prefix \u003cdetected-prefix\u003e` as the fix\n3. Show the prefix detected from the JSONL file\n\nCurrently it shows various warnings (git hooks, merge driver, etc.) but doesn't address the fundamental issue: the database needs to be hydrated.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-27T20:21:15.691764-08:00","updated_at":"2025-11-27T20:21:15.691764-08:00"}
{"id":"bd-4ew","title":"bd doctor should detect fresh clone and recommend 'bd init'","description":"When running `bd doctor` on a fresh clone (JSONL exists, no .db file), it should:\n\n1. Detect this is a fresh clone situation\n2. Recommend `bd init --prefix \u003cdetected-prefix\u003e` as the fix\n3. Show the prefix detected from the JSONL file\n\nCurrently it shows various warnings (git hooks, merge driver, etc.) but doesn't address the fundamental issue: the database needs to be hydrated.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-27T20:21:15.691764-08:00","updated_at":"2025-11-28T21:59:51.036375-08:00","closed_at":"2025-11-28T21:59:51.036375-08:00"}
{"id":"bd-4h3","title":"Add test coverage for internal/git package","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:23.497486-05:00","updated_at":"2025-11-28T21:57:22.201056-08:00","closed_at":"2025-11-28T21:55:45.2527-08:00","dependencies":[{"issue_id":"bd-4h3","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.277639-05:00","created_by":"daemon"}]}
{"id":"bd-4l5","title":"bd prime: Detect ephemeral branches and adjust workflow output","description":"When 'bd prime' runs on a branch with no upstream (ephemeral branch), it should output a different SESSION CLOSE PROTOCOL.\n\n**Current output (wrong for ephemeral branches):**\n```\n[ ] 1. git status\n[ ] 2. git add \u003cfiles\u003e\n[ ] 3. bd sync\n[ ] 4. git commit -m \"...\"\n[ ] 5. bd sync\n[ ] 6. git push\n```\n\n**Needed output for ephemeral branches:**\n```\n[ ] 1. git status\n[ ] 2. git add \u003cfiles\u003e\n[ ] 3. bd sync --from-main (pull updates from main)\n[ ] 4. git commit -m \"...\"\n[ ] 5. (no push - branch is ephemeral)\n```\n\n**Detection:** `git rev-parse --abbrev-ref --symbolic-full-name @{u}` returns error code 128 if no upstream.\n\nAlso update Sync \u0026 Collaboration section to mention `bd sync --from-main` for ephemeral branches.\n\n**Use case:** Gastown polecats work on ephemeral local branches that are never pushed. Their code gets merged to main via local merge, and beads changes stay local (communicated via gm mail to Overseer).","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-25T16:55:24.984104-08:00","updated_at":"2025-11-25T17:12:46.604978-08:00","closed_at":"2025-11-25T17:12:46.604978-08:00"}
{"id":"bd-4pv","title":"bd export only outputs 1 issue after auto-import corrupts database","description":"When auto-import runs and purges issues (due to git history backfill bug), subsequent 'bd export' only exports 1 issue even though the database should have many.\n\nReproduction:\n1. Have issues.jsonl with 55 issues\n2. Auto-import triggers and purges all issues via git history backfill\n3. Run 'bd export' - only exports 1 issue (the last one created before corruption)\n\nThe database gets into an inconsistent state where most issues are purged but export doesn't realize this.\n\nWorkaround: Rebuild database from scratch with 'rm .beads/beads.db \u0026\u0026 bd init --prefix bd'","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-26T22:28:40.828866-08:00","updated_at":"2025-11-27T22:50:35.036227-08:00","closed_at":"2025-11-27T22:50:35.036227-08:00"}

View File

@@ -636,26 +636,55 @@ func checkDatabaseVersion(path string) doctorCheck {
// Check if database file exists
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
// Check if JSONL exists (--no-db mode)
// Check if JSONL exists
// Check canonical (issues.jsonl) first, then legacy (beads.jsonl)
issuesJSONL := filepath.Join(beadsDir, "issues.jsonl")
beadsJSONL := filepath.Join(beadsDir, "beads.jsonl")
var jsonlPath string
if _, err := os.Stat(issuesJSONL); err == nil {
return doctorCheck{
Name: "Database",
Status: statusOK,
Message: "JSONL-only mode",
Detail: "Using issues.jsonl (no SQLite database)",
}
jsonlPath = issuesJSONL
} else if _, err := os.Stat(beadsJSONL); err == nil {
jsonlPath = beadsJSONL
}
if _, err := os.Stat(beadsJSONL); err == nil {
if jsonlPath != "" {
// JSONL exists but no database - check if this is no-db mode or fresh clone
// Check config.yaml for no-db: true
configPath := filepath.Join(beadsDir, "config.yaml")
isNoDbMode := false
if configData, err := os.ReadFile(configPath); err == nil {
// Simple check for no-db: true in config.yaml
isNoDbMode = strings.Contains(string(configData), "no-db: true")
}
if isNoDbMode {
return doctorCheck{
Name: "Database",
Status: statusOK,
Message: "JSONL-only mode",
Detail: "Using issues.jsonl (no SQLite database)",
}
}
// This is a fresh clone - JSONL exists but no database and not no-db mode
// Count issues and detect prefix for helpful suggestion
issueCount := countIssuesInJSONLFile(jsonlPath)
prefix := detectPrefixFromJSONL(jsonlPath)
message := "Fresh clone detected (no database)"
detail := fmt.Sprintf("Found %d issue(s) in JSONL that need to be imported", issueCount)
fix := "Run 'bd init' to hydrate the database from JSONL"
if prefix != "" {
fix = fmt.Sprintf("Run 'bd init' to hydrate the database (detected prefix: %s)", prefix)
}
return doctorCheck{
Name: "Database",
Status: statusOK,
Message: "JSONL-only mode",
Detail: "Using issues.jsonl (no SQLite database)",
Status: statusWarning,
Message: message,
Detail: detail,
Fix: fix,
}
}
@@ -2221,6 +2250,31 @@ func checkUntrackedBeadsFiles(path string) doctorCheck {
}
}
// countIssuesInJSONLFile counts the number of issues in a JSONL file
func countIssuesInJSONLFile(jsonlPath string) int {
count, _, _ := countJSONLIssues(jsonlPath)
return count
}
// detectPrefixFromJSONL detects the most common issue prefix from a JSONL file
func detectPrefixFromJSONL(jsonlPath string) string {
_, prefixes, _ := countJSONLIssues(jsonlPath)
if len(prefixes) == 0 {
return ""
}
// Find the most common prefix
var mostCommonPrefix string
maxCount := 0
for prefix, count := range prefixes {
if count > maxCount {
maxCount = count
mostCommonPrefix = prefix
}
}
return mostCommonPrefix
}
func init() {
rootCmd.AddCommand(doctorCmd)
doctorCmd.Flags().BoolVar(&perfMode, "perf", false, "Run performance diagnostics and generate CPU profile")