Fix bd init to auto-import issues from git on fresh clone

Prevents agents from creating duplicate low-numbered issues when starting
with a fresh git clone that already has issues.jsonl in git history.

Changes:
- bd init now checks for existing issues in git after DB creation
- Auto-imports with collision resolution if found
- Updates AGENTS.md to simplify onboarding (just 'bd init')

Fixes the scenario where:
1. Fresh clone has .beads/issues.jsonl in git (212 issues)
2. Agent runs bd init (creates empty DB)
3. Agent starts creating bd-1, bd-2, etc (collisions with git)

Now bd init automatically imports all issues from git on first run.

Amp-Thread-ID: https://ampcode.com/threads/T-8a41f14d-d4c3-4c50-a18b-5f112110f138
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-21 20:38:35 -07:00
parent 36bd877e7c
commit 7f82708b90
4 changed files with 243 additions and 227 deletions

File diff suppressed because one or more lines are too long

View File

@@ -456,11 +456,9 @@ Happy coding! 🔗
### Quick Start
**FIRST TIME?** Import existing issues from git:
**FIRST TIME?** Just run `bd init` - it auto-imports issues from git:
```bash
bd import -i .beads/issues.jsonl --json
# Or if issues.jsonl is empty in working tree but exists in git:
git show HEAD:.beads/issues.jsonl | bd import -i /dev/stdin --json
bd init --prefix bd
```
**Check for ready work:**

View File

@@ -43,7 +43,7 @@ func checkAndAutoImport(ctx context.Context, store storage.Storage) bool {
}
// Import from git
if err := importFromGit(ctx, store, jsonlPath); err != nil {
if err := importFromGit(ctx, dbPath, store, jsonlPath); err != nil {
if !jsonOutput {
fmt.Fprintf(os.Stderr, "Warning: auto-import failed: %v\n", err)
fmt.Fprintf(os.Stderr, "Try manually: git show HEAD:%s | bd import -i /dev/stdin\n", jsonlPath)
@@ -130,7 +130,7 @@ func findGitRoot() string {
}
// importFromGit imports issues from git HEAD
func importFromGit(ctx context.Context, store storage.Storage, jsonlPath string) error {
func importFromGit(ctx context.Context, dbFilePath string, store storage.Storage, jsonlPath string) error {
// Get content from git
cmd := exec.Command("git", "show", fmt.Sprintf("HEAD:%s", jsonlPath))
jsonlData, err := cmd.Output()
@@ -167,6 +167,6 @@ func importFromGit(ctx context.Context, store storage.Storage, jsonlPath string)
SkipPrefixValidation: true, // Auto-import is lenient about prefixes
}
_, err = importIssuesCore(ctx, dbPath, store, issues, opts)
_, err = importIssuesCore(ctx, dbFilePath, store, issues, opts)
return err
}

View File

@@ -85,18 +85,36 @@ bd.db
// Store the bd version in metadata (for version mismatch detection)
if err := store.SetMetadata(ctx, "bd_version", Version); err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to store version metadata: %v\n", err)
// Non-fatal - continue anyway
fmt.Fprintf(os.Stderr, "Warning: failed to store version metadata: %v\n", err)
// Non-fatal - continue anyway
}
if err := store.Close(); err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to close database: %v\n", err)
// Check if git has existing issues to import (fresh clone scenario)
issueCount, jsonlPath := checkGitForIssues()
if issueCount > 0 {
if !quiet {
fmt.Fprintf(os.Stderr, "\n✓ Database initialized. Found %d issues in git, importing...\n", issueCount)
}
if err := importFromGit(ctx, dbPath, store, jsonlPath); err != nil {
if !quiet {
fmt.Fprintf(os.Stderr, "Warning: auto-import failed: %v\n", err)
fmt.Fprintf(os.Stderr, "Try manually: git show HEAD:%s | bd import -i /dev/stdin\n", jsonlPath)
}
// Non-fatal - continue with empty database
} else if !quiet {
fmt.Fprintf(os.Stderr, "✓ Successfully imported %d issues from git.\n\n", issueCount)
}
}
// Skip output if quiet mode
if quiet {
return
}
if err := store.Close(); err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to close database: %v\n", err)
}
// Skip output if quiet mode
if quiet {
return
}
green := color.New(color.FgGreen).SprintFunc()
cyan := color.New(color.FgCyan).SprintFunc()