fix: tombstone/deletion overhaul for bd-4q8

- IsExpired(): Negative TTL means immediately expired (for --hard mode)
- IsExpired(): ClockSkewGrace only added for TTLs > 1 hour
- bd cleanup --hard: Use negative TTL to prune freshly created tombstones
- bd delete --hard: New flag to immediately prune tombstones from JSONL
- Import: Add early tombstone check before all phases to prevent resurrection

The early tombstone check prevents ghost issues from being created when
tombstones exist in the DB. However, a deeper git merge issue (bd-ncwo)
can still cause resurrection when remote's status:closed wins the merge.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-16 22:01:31 -08:00
parent 8d73a86f7a
commit 0ce039429d
5 changed files with 95 additions and 12 deletions

View File

@@ -492,7 +492,17 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues
continue
}
seenHashes[hash] = true
// CRITICAL: Check for tombstone FIRST, before any other matching (bd-4q8 fix)
// This prevents ghost resurrection regardless of which phase would normally match.
// If this ID has a tombstone in the DB, skip importing it entirely.
if existingByID, found := dbByID[incoming.ID]; found {
if existingByID.Status == types.StatusTombstone {
result.Skipped++
continue
}
}
// Phase 0: Match by external_ref first (if present)
// This enables re-syncing from external systems (Jira, GitHub, Linear)
if incoming.ExternalRef != nil && *incoming.ExternalRef != "" {