CloseIssue was storing the reason only in the events table, not in the
issues.close_reason column. This caused `bd show --json` to return an
empty close_reason even when one was provided.
- Update CloseIssue in queries.go and transaction.go to set close_reason
- Clear close_reason when reopening issues (in manageClosedAt)
- Add tests for close_reason in storage and CLI JSON output
- Document the dual-storage of close_reason (issues + events tables)
- Handle file.Close() errors in deletions.go and deletions_test.go
- Simplify boolean logic to apply De Morgan's law in common.go
- All golangci-lint checks now pass
Root cause: bd doctor hydrate was re-adding migrated tombstones to the
deletions manifest because getCurrentJSONLIDs() included all issues,
including tombstones. When compared against git history, tombstones
appeared as 'deleted' and were incorrectly added to the manifest as new
deletions, corrupting the database on next sync.
Fix: Skip tombstone-status issues in getCurrentJSONLIDs() so they don't
participate in deletion detection. Tombstones represent already-recorded
deletions/migrations and shouldn't be treated as active issues.
Changes:
- cmd/bd/doctor/fix/deletions.go: Skip tombstones in getCurrentJSONLIDs()
- cmd/bd/doctor/fix/deletions_test.go: New tests for tombstone skipping
- cmd/bd/migrate_tombstones_test.go: Test that tombstones are valid
This fixes the bug where 'bd migrate-tombstones' followed by 'bd sync'
would add thousands of deletion records with author 'bd-doctor-hydrate'
Adds a new command that displays a thank you page listing all human
contributors to the beads project. Features:
- Static list of contributors (compiled into binary)
- Top 20 featured contributors displayed in columns
- Additional contributors in wrapped list
- Styled output using lipgloss (colored box, sections)
- Dynamic width based on content
- JSON output support (--json flag)
- Excludes bots and AI agents by email pattern
The sync sanitize process was incorrectly removing newly created issues
when they happened to have IDs matching entries in the deletions manifest.
This could occur with hash-based IDs when content is similar to previously
deleted issues.
The fix adds protection for issues that were in the left snapshot (local
export before pull). These represent local work and should not be removed
by sanitize, even if they match entries in the deletions manifest.
Changes:
- Load left snapshot in sanitizeJSONLWithDeletions() to build protection set
- Add protection check before removing issues from JSONL
- Add ProtectedCount/ProtectedIDs to SanitizeResult for tracking
- Log protected issues during sync for visibility
- Add comprehensive test coverage for the fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>