Add comments feature (bd-162)

- Add comments table to SQLite schema
- Add Comment type to internal/types
- Implement AddIssueComment and GetIssueComments in storage layer
- Update JSONL export/import to include comments
- Add comments to 'bd show' output
- Create 'bd comments' CLI command structure
- Fix UpdateIssueID to update comments table and defer FK checks
- Add GetIssueComments/AddIssueComment to Storage interface

Note: CLI command needs daemon RPC support (tracked in bd-163)
Amp-Thread-ID: https://ampcode.com/threads/T-ece10dd1-cf64-48ff-9adb-dd304d0bcb25
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-19 18:28:41 -07:00
parent 34cf361b2b
commit a28d4fe4c7
11 changed files with 320 additions and 4 deletions

View File

@@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"time"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/storage/sqlite"
@@ -275,5 +276,39 @@ func importIssuesCore(ctx context.Context, dbPath string, store storage.Storage,
}
}
// Phase 7: Import comments
for _, issue := range issues {
if len(issue.Comments) == 0 {
continue
}
// Get current comments to avoid duplicates
currentComments, err := sqliteStore.GetIssueComments(ctx, issue.ID)
if err != nil {
return nil, fmt.Errorf("error getting comments for %s: %w", issue.ID, err)
}
// Build a set of existing comments (by author+text+timestamp)
existingComments := make(map[string]bool)
for _, c := range currentComments {
key := fmt.Sprintf("%s:%s:%s", c.Author, c.Text, c.CreatedAt.Format(time.RFC3339))
existingComments[key] = true
}
// Add missing comments
for _, comment := range issue.Comments {
key := fmt.Sprintf("%s:%s:%s", comment.Author, comment.Text, comment.CreatedAt.Format(time.RFC3339))
if !existingComments[key] {
if _, err := sqliteStore.AddIssueComment(ctx, issue.ID, comment.Author, comment.Text); err != nil {
if opts.Strict {
return nil, fmt.Errorf("error adding comment to %s: %w", issue.ID, err)
}
// Non-strict mode: skip this comment
continue
}
}
}
}
return result, nil
}