feat(tombstone): add P2 code review improvements (bd-saa, bd-1bu, bd-nyt)

- Add partial index on deleted_at for efficient TTL queries
- Exclude tombstones from SearchIssues by default (new IncludeTombstones filter)
- Report tombstone count separately in GetStatistics
- Display tombstone count in bd stats output

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-05 15:48:46 -08:00
parent b689ea1b28
commit 5c49c25e9e
6 changed files with 30 additions and 4 deletions

View File

@@ -110,15 +110,16 @@ func (s *SQLiteStorage) GetEvents(ctx context.Context, issueID string, limit int
func (s *SQLiteStorage) GetStatistics(ctx context.Context) (*types.Statistics, error) {
var stats types.Statistics
// Get counts
// Get counts (bd-nyt: exclude tombstones from TotalIssues, report separately)
err := s.db.QueryRowContext(ctx, `
SELECT
COUNT(*) as total,
COALESCE(SUM(CASE WHEN status != 'tombstone' THEN 1 ELSE 0 END), 0) as total,
COALESCE(SUM(CASE WHEN status = 'open' THEN 1 ELSE 0 END), 0) as open,
COALESCE(SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END), 0) as in_progress,
COALESCE(SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END), 0) as closed
COALESCE(SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END), 0) as closed,
COALESCE(SUM(CASE WHEN status = 'tombstone' THEN 1 ELSE 0 END), 0) as tombstone
FROM issues
`).Scan(&stats.TotalIssues, &stats.OpenIssues, &stats.InProgressIssues, &stats.ClosedIssues)
`).Scan(&stats.TotalIssues, &stats.OpenIssues, &stats.InProgressIssues, &stats.ClosedIssues, &stats.TombstoneIssues)
if err != nil {
return nil, fmt.Errorf("failed to get issue counts: %w", err)
}

View File

@@ -43,5 +43,12 @@ func MigrateTombstoneColumns(db *sql.DB) error {
}
}
// Add partial index on deleted_at for efficient TTL queries (bd-saa)
// Only indexes non-NULL values, making it very efficient for tombstone filtering
_, err := db.Exec(`CREATE INDEX IF NOT EXISTS idx_issues_deleted_at ON issues(deleted_at) WHERE deleted_at IS NOT NULL`)
if err != nil {
return fmt.Errorf("failed to create deleted_at index: %w", err)
}
return nil
}

View File

@@ -1186,6 +1186,10 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
if filter.Status != nil {
whereClauses = append(whereClauses, "status = ?")
args = append(args, *filter.Status)
} else if !filter.IncludeTombstones {
// Exclude tombstones by default unless explicitly filtering for them (bd-1bu)
whereClauses = append(whereClauses, "status != ?")
args = append(args, types.StatusTombstone)
}
if filter.Priority != nil {

View File

@@ -919,6 +919,10 @@ func (t *sqliteTxStorage) SearchIssues(ctx context.Context, query string, filter
if filter.Status != nil {
whereClauses = append(whereClauses, "status = ?")
args = append(args, *filter.Status)
} else if !filter.IncludeTombstones {
// Exclude tombstones by default unless explicitly filtering for them (bd-1bu)
whereClauses = append(whereClauses, "status != ?")
args = append(args, types.StatusTombstone)
}
if filter.Priority != nil {