bd sync: 2025-11-24 21:16:44
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
{"id":"bd-iq7n","content_hash":"e6058e742c029c684d63f91a13f2a1e4a95bb461d82f765b652f5a97cf236c6a","title":"Audit and fix JSONL filename mismatches across all repo clones","description":"## Problem\n\nMultiple clones of repos are configured with different JSONL filenames (issues.jsonl vs beads.jsonl), causing:\n1. JSONL files to be resurrected after deletion (one clone pushes issues.jsonl, another pushes beads.jsonl)\n2. Agents unable to see issues filed by other agents after sync\n3. Merge conflicts and data inconsistencies\n\n## Root Cause\n\nWhen repos were \"bd doctored\" or initialized at different times, some got issues.jsonl (old default) and others got beads.jsonl (Beads repo specific). These clones push their respective files, creating duplicates.\n\n## Task\n\nScan all repo clones under ~/src/ (1-2 levels deep) and standardize their JSONL configuration.\n\n### Step 1: Find all beads-enabled repos\n\n```bash\n# Find all directories named 'beads' at levels 1-2 under ~/src/\nfind ~/src -maxdepth 2 -type d -name beads\n```\n\n### Step 2: For each repo found, check configuration\n\nFor each directory from Step 1, check:\n- Does `.beads/metadata.json` exist?\n- What is the `jsonl_export` value?\n- What JSONL files actually exist in `.beads/`?\n- Are there multiple JSONL files (problem!)?\n\n### Step 3: Create audit report\n\nGenerate a report showing:\n```\nRepo Path | Config | Actual Files | Status\n----------------------------------- | ------------- | ---------------------- | --------\n~/src/beads | beads.jsonl | beads.jsonl | OK\n~/src/dave/beads | issues.jsonl | issues.jsonl | MISMATCH\n~/src/emma/beads | issues.jsonl | issues.jsonl, beads.jsonl | DUPLICATE!\n```\n\n### Step 4: Determine canonical name for each repo\n\nFor repos that are the SAME git repository (check `git remote -v`):\n- Group them together\n- Determine which JSONL filename should be canonical (majority wins, or beads.jsonl for the beads repo itself)\n- List which clones need to be updated\n\n### Step 5: Generate fix script\n\nCreate a script that for each mismatched clone:\n1. Updates `.beads/metadata.json` to use the canonical name\n2. If JSONL file needs renaming: `git mv .beads/old.jsonl .beads/new.jsonl`\n3. Removes any duplicate JSONL files: `git rm .beads/duplicate.jsonl`\n4. Commits the change\n5. Syncs: `bd sync`\n\n### Expected Output\n\n1. Audit report showing all repos and their config status\n2. List of repos grouped by git remote (same repository)\n3. Fix script or manual instructions for standardizing each repo\n4. Verification that after fixes, all clones of the same repo use the same JSONL filename\n\n### Edge Cases\n\n- Handle repos without metadata.json (use default discovery)\n- Handle repos with no git remote (standalone/local)\n- Handle repos that are not git repositories\n- Don't modify repos with uncommitted changes (warn instead)\n\n### Success Criteria\n\n- All clones of the same git repository use the same JSONL filename\n- No duplicate JSONL files in any repo\n- All configurations documented in metadata.json\n- bd doctor passes on all repos","status":"open","priority":0,"issue_type":"task","created_at":"2025-11-21T23:58:35.044762-08:00","updated_at":"2025-11-21T23:58:35.044762-08:00","source_repo":"."}
|
||||
{"id":"bd-j3zt","content_hash":"531ad51101f41375a93d66b8d22105ce7c4913261db78b662bb759e802bc01e2","title":"Fix mypy errors in beads-mcp","description":"Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-20T18:53:28.557708-05:00","updated_at":"2025-11-24T20:59:28.634597-08:00","closed_at":"2025-11-24T20:59:28.634597-08:00","source_repo":"."}
|
||||
{"id":"bd-jgxi","content_hash":"9af80db7f04944bbc55f2d77e3576028c553c936e9d40266ccbf169eec47eb9f","title":"Auto-migrate database on CLI version bump","description":"When CLI is upgraded (e.g., 0.24.0 → 0.24.1), database version becomes stale. Add auto-migration in PersistentPreRun or daemon startup. Check dbVersion != CLIVersion and run bd migrate automatically. Fixes recurring UX issue where bd doctor shows version mismatch after every CLI upgrade.","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-11-21T23:16:09.004619-08:00","updated_at":"2025-11-24T20:56:10.599438-08:00","closed_at":"2025-11-24T20:56:10.599438-08:00","source_repo":".","dependencies":[{"issue_id":"bd-jgxi","depends_on_id":"bd-tbz3","type":"parent-child","created_at":"2025-11-21T23:16:09.005513-08:00","created_by":"daemon"}]}
|
||||
{"id":"bd-l0r","content_hash":"40b3c893ad5e3170d0b586bc2911632bafff58fdb47047a96ad5df605cc58ef8","title":"CRITICAL: bd sync pushes stale DB state instead of trusting JSONL truth on pull","description":"When a clone has stale DB (688 issues) and pulls fresh JSONL (62 issues), bd sync detects 1009.7% divergence but proceeds to re-export the stale DB and push it, overwriting the correct JSONL state. \n\nRepro:\n1. Clone has 688 issues in DB (628 closed)\n2. git pull brings JSONL with 62 issues (cleanup applied)\n3. bd sync warns about divergence but exports DB→JSONL\n4. Pushes 688 issues back to remote, undoing cleanup\n\nExpected: JSONL is source of truth after pull. DB should be wiped and reimported.\nActual: DB overwrites JSONL, pushing stale state upstream.\n\nImpact: Breaks multi-clone coordination. Cleanup work gets undone.","status":"open","priority":0,"issue_type":"bug","created_at":"2025-11-23T22:29:37.668882-08:00","updated_at":"2025-11-24T20:54:40.113264-08:00","source_repo":"."}
|
||||
{"id":"bd-l0r","content_hash":"ee68006dadd763375e8e5e6e4fb3d84cabb4b55407d834314a40bdffe89ebdd1","title":"CRITICAL: bd sync pushes stale DB state instead of trusting JSONL truth on pull","description":"When a clone has stale DB (688 issues) and pulls fresh JSONL (62 issues), bd sync detects 1009.7% divergence but proceeds to re-export the stale DB and push it, overwriting the correct JSONL state. \n\nRepro:\n1. Clone has 688 issues in DB (628 closed)\n2. git pull brings JSONL with 62 issues (cleanup applied)\n3. bd sync warns about divergence but exports DB→JSONL\n4. Pushes 688 issues back to remote, undoing cleanup\n\nExpected: JSONL is source of truth after pull. DB should be wiped and reimported.\nActual: DB overwrites JSONL, pushing stale state upstream.\n\nImpact: Breaks multi-clone coordination. Cleanup work gets undone.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-23T22:29:37.668882-08:00","updated_at":"2025-11-24T21:16:40.273828-08:00","closed_at":"2025-11-24T21:16:40.273828-08:00","source_repo":"."}
|
||||
{"id":"bd-l954","content_hash":"263dd2111cf0353b307f2e47489aa42ecf607e49b1316b54a6497cad9d3722b0","title":"Performance Testing Framework","description":"Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\n\nComponents:\n- Benchmark suite for critical operations at 10K-20K scale\n- Fixture generator for realistic test data (epic hierarchies, cross-links)\n- User diagnostics via bd doctor --perf\n- Always-on profiling integration\n\nGoals:\n- Identify bottlenecks for optimization work\n- Validate performance at 10K+ issue scale\n- Enable users to collect diagnostics for bug reports\n- Support both SQLite and JSONL import paths","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-13T22:22:11.203467-08:00","updated_at":"2025-11-13T22:22:11.203467-08:00","source_repo":"."}
|
||||
{"id":"bd-lce","content_hash":"201ef708eb0d285eb4b1939aa5c920d811c2babd5ed11168c0cd401e3ff0fd9a","title":"Handle errors from GetLabelsForIssues in search.go","description":"In cmd/bd/search.go lines 274-275, errors from label and dependency loading are silently ignored:\n\n```go\nlabelsMap, _ := store.GetLabelsForIssues(ctx, issueIDs)\ndepCounts, _ := store.GetDependencyCounts(ctx, issueIDs)\n```\n\nThese should at least be logged to help diagnose issues. Silent failures make debugging difficult.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-24T20:35:09.377487-08:00","updated_at":"2025-11-24T20:38:10.571617-08:00","closed_at":"2025-11-24T20:38:10.571617-08:00","source_repo":".","labels":["cli","error-handling"],"dependencies":[{"issue_id":"bd-lce","depends_on_id":"bd-8bq","type":"parent-child","created_at":"2025-11-24T20:35:24.262213-08:00","created_by":"daemon"}]}
|
||||
{"id":"bd-m0w","content_hash":"e8641e225f1d4cf13fbd97c4a83046e3597df180d3ee134125e4a35abc6941cd","title":"Add test coverage for internal/validation package","description":"","design":"Validation package has 1 test file. Critical for data integrity. Target: 80% coverage","acceptance_criteria":"- At least 4 test files\n- Package coverage \u003e= 80%\n- Tests cover all validation rules","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:24.129559-05:00","updated_at":"2025-11-20T21:21:24.129559-05:00","source_repo":".","dependencies":[{"issue_id":"bd-m0w","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.350477-05:00","created_by":"daemon"}]}
|
||||
|
||||
@@ -72,10 +72,6 @@ Examples:
|
||||
priorityMinStr, _ := cmd.Flags().GetString("priority-min")
|
||||
priorityMaxStr, _ := cmd.Flags().GetString("priority-max")
|
||||
|
||||
// Sort flags
|
||||
sortBy, _ := cmd.Flags().GetString("sort")
|
||||
reverse, _ := cmd.Flags().GetBool("reverse")
|
||||
|
||||
// Normalize labels
|
||||
labels = util.NormalizeLabels(labels)
|
||||
labelsAny = util.NormalizeLabels(labelsAny)
|
||||
@@ -396,9 +392,5 @@ func init() {
|
||||
searchCmd.Flags().String("priority-min", "", "Filter by minimum priority (inclusive, 0-4 or P0-P4)")
|
||||
searchCmd.Flags().String("priority-max", "", "Filter by maximum priority (inclusive, 0-4 or P0-P4)")
|
||||
|
||||
// Sort flags
|
||||
searchCmd.Flags().String("sort", "", "Sort by field: priority, created, updated, closed, status, id, title, type, assignee")
|
||||
searchCmd.Flags().BoolP("reverse", "r", false, "Reverse sort order")
|
||||
|
||||
rootCmd.AddCommand(searchCmd)
|
||||
}
|
||||
|
||||
@@ -299,40 +299,60 @@ Use --merge to merge the sync branch back to main branch.`,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Post-pull ZFC check (bd-l0r fix): if DB has significantly more issues
|
||||
// than pulled JSONL, trust JSONL as source of truth and skip re-export.
|
||||
// This prevents resurrection of deleted issues when syncing stale clones.
|
||||
skipReexport := false
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
dbCountPostImport, dbErr := countDBIssuesFast(ctx, store)
|
||||
jsonlCountPostPull, jsonlErr := countIssuesInJSONL(jsonlPath)
|
||||
if dbErr == nil && jsonlErr == nil && jsonlCountPostPull > 0 {
|
||||
if dbCountPostImport > jsonlCountPostPull*2 { // DB has >2x issues
|
||||
fmt.Printf("→ DB (%d) has >2x more issues than JSONL (%d) after pull\n",
|
||||
dbCountPostImport, jsonlCountPostPull)
|
||||
fmt.Println("→ Trusting JSONL as source of truth (skipping re-export)")
|
||||
fmt.Println(" Hint: Run 'bd import --delete-missing' to fully sync DB with JSONL")
|
||||
skipReexport = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4.5: Check if DB needs re-export (only if DB differs from JSONL)
|
||||
// This prevents the infinite loop: import → export → commit → dirty again
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
needsExport, err := dbNeedsExport(ctx, store, jsonlPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to check if export needed: %v\n", err)
|
||||
// Conservative: assume export needed
|
||||
needsExport = true
|
||||
}
|
||||
|
||||
if needsExport {
|
||||
fmt.Println("→ Re-exporting after import to sync DB changes...")
|
||||
if err := exportToJSONL(ctx, jsonlPath); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error re-exporting after import: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Step 4.6: Commit the re-export if it created changes
|
||||
hasPostImportChanges, err := gitHasChanges(ctx, jsonlPath)
|
||||
if !skipReexport {
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
needsExport, err := dbNeedsExport(ctx, store, jsonlPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error checking git status after re-export: %v\n", err)
|
||||
os.Exit(1)
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to check if export needed: %v\n", err)
|
||||
// Conservative: assume export needed
|
||||
needsExport = true
|
||||
}
|
||||
if hasPostImportChanges {
|
||||
fmt.Println("→ Committing DB changes from import...")
|
||||
if err := gitCommit(ctx, jsonlPath, "bd sync: apply DB changes after import"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error committing post-import changes: %v\n", err)
|
||||
|
||||
if needsExport {
|
||||
fmt.Println("→ Re-exporting after import to sync DB changes...")
|
||||
if err := exportToJSONL(ctx, jsonlPath); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error re-exporting after import: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
hasChanges = true // Mark that we have changes to push
|
||||
|
||||
// Step 4.6: Commit the re-export if it created changes
|
||||
hasPostImportChanges, err := gitHasChanges(ctx, jsonlPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error checking git status after re-export: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if hasPostImportChanges {
|
||||
fmt.Println("→ Committing DB changes from import...")
|
||||
if err := gitCommit(ctx, jsonlPath, "bd sync: apply DB changes after import"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error committing post-import changes: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
hasChanges = true // Mark that we have changes to push
|
||||
}
|
||||
} else {
|
||||
fmt.Println("→ DB and JSONL in sync, skipping re-export")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("→ DB and JSONL in sync, skipping re-export")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user