Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog
entries. The descriptions remain meaningful without the ephemeral
issue IDs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Modernize sorting code to use Go 1.21+ slices package:
- Replace sort.Slice with slices.SortFunc across 16 files
- Use cmp.Compare for orderable types (strings, ints)
- Use time.Time.Compare for time comparisons
- Use cmp.Or for multi-field sorting
- Use slices.SortStableFunc where stability matters
Benefits: cleaner 3-way comparison, slightly better performance,
modern idiomatic Go.
Part of GH#692 refactoring epic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The countDBIssuesFast() fallback path used SearchIssues without
IncludeTombstones, returning only live issues (161). Meanwhile
countIssuesInJSONL counts all lines including tombstones (221).
This mismatch caused false "stale DB detected" warnings on every
sync, even when DB and JSONL were in sync.
Fix: Set IncludeTombstones: true in the fallback SearchIssues call.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: bd sync exports DB to JSONL BEFORE pulling from remote.
If the local DB is stale (fewer issues than JSONL), the stale data gets
exported and committed, potentially corrupting the remote when pushed.
The existing ZFC (Zero-Fill Check) only detected when DB had MORE issues
than JSONL, missing the dangerous reverse case.
Fix: Added "reverse ZFC" check in sync.go that detects when JSONL has
significantly more issues than DB (>20% divergence or empty DB).
When detected, it imports JSONL first to sync the database before
any export occurs.
This prevents stale/fresh clones from exporting their incomplete
database state over a well-populated JSONL file.
Version bump: 0.26.0 -> 0.26.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The metadata key 'last_import_hash' was misleading because it's updated on
both import AND export. Renamed to 'jsonl_content_hash' which more accurately
describes its purpose - tracking the content hash of the JSONL file.
Added migration support: read operations try new key first, then fall back
to old key for backwards compatibility with existing databases.
Files modified:
- cmd/bd/integrity.go: Update key name with migration support
- cmd/bd/import.go: Update key name
- cmd/bd/sync.go: Update key name
- cmd/bd/autoflush.go: Update key name with migration support
- cmd/bd/daemon_sync.go: Update key name
- cmd/bd/daemon_event_loop.go: Update key name with migration support
- internal/autoimport/autoimport.go: Update key name with migration support
- Updated all related tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CloseReason field to Issue struct in types.go
- Add GetCloseReason() and batch GetCloseReasonsForIssues()
- Update issue loading to populate close reasons
- Update scanIssues() to include close_reason in JSONL export
- Update bd show to display close reason after status
Close reasons now survive sync between repos.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The sync validation was incorrectly triggering 'data loss detected' when
issue count decreased after import, even for legitimate deletions recorded
in deletions.jsonl.
Changes:
- Modified validatePostImport to accept jsonlPath and check deletions manifest
- When issue count decreases, check if decrease is within recorded deletions
- Updated all call sites in sync.go and daemon_sync.go
- Added comprehensive tests for deletion-aware validation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses critical code review findings from bd-dvd and bd-ymj fixes:
## Completed Tasks
### bd-ar2.1: Extract duplicated metadata update code
- Created `updateExportMetadata()` helper function
- Eliminated 22-line duplication between createExportFunc and createSyncFunc
- Single source of truth for metadata updates
### bd-ar2.2: Add multi-repo support to export metadata updates
- Added per-repo metadata key tracking with keySuffix parameter
- Both export and sync functions now update metadata for all repos
### bd-ar2.3: Fix tests to use actual daemon functions
- TestExportUpdatesMetadata now calls updateExportMetadata() directly
- Added TestUpdateExportMetadataMultiRepo() for multi-repo testing
- Fixed export_mtime_test.go tests to call updateExportMetadata()
### bd-ar2.9: Fix variable shadowing in GetNextChildID
- Changed `err` to `resurrectErr` to avoid shadowing
- Improves code clarity and passes linter checks
### bd-ar2.10: Fix hasJSONLChanged to support per-repo keys
- Updated hasJSONLChanged() to accept keySuffix parameter
- Reads metadata with correct per-repo keys
- All callers updated (validatePreExport, daemon import, sync command)
### bd-ar2.11: Use stable repo identifiers instead of paths
- Added getRepoKeyForPath() helper function
- Uses stable identifiers like ".", "../frontend" instead of absolute paths
- Metadata keys now portable across machines and clones
- Prevents orphaned metadata when repos are moved
## Files Changed
- cmd/bd/daemon_sync.go: Helper functions, metadata updates
- cmd/bd/integrity.go: hasJSONLChanged() with keySuffix support
- cmd/bd/sync.go: Updated to use getRepoKeyForPath()
- cmd/bd/*_test.go: Tests updated for new signatures
- internal/storage/sqlite/hash_ids.go: Fixed variable shadowing
## Testing
All export, sync, and integrity tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The function was declared twice:
- Line 80: New version (simpler, no error wrapping)
- Line 390: Old version (with error wrapping)
This caused compilation failure in CI. Removed the old declaration at line 390.
Also fixed integrity_content_test.go to pass context.Context to sqlite.New()
as required by the updated API.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace mtime-based staleness detection with content-based (SHA256 hash) to prevent
git operations from resurrecting deleted issues.
**Problem:**
Auto-import used file modification time to detect if JSONL was "newer" than database.
Git operations (checkout, merge, pull) restore old files with recent mtimes, causing
auto-import to load stale data over current database state, resurrecting deleted issues.
**Solution:**
- Added computeJSONLHash() to compute SHA256 of JSONL content
- Added hasJSONLChanged() with two-tier check:
1. Fast-path: Check mtime first (99% of checks are instant)
2. Slow-path: Compute hash only if mtime changed (catches git operations)
- Store metadata: last_import_hash, last_import_mtime, last_import_time
- Updated auto-import in daemon_sync.go to use content-based check
- Updated validatePreExport to use content-based check (bd-xwo)
- Graceful degradation: metadata failures are non-fatal warnings
**Changes:**
- cmd/bd/integrity.go: Add computeJSONLHash(), hasJSONLChanged()
- cmd/bd/integrity_test.go: Add comprehensive tests for new functions
- cmd/bd/import.go: Update metadata after import
- cmd/bd/sync.go: Use hasJSONLChanged() instead of isJSONLNewer()
- cmd/bd/daemon_sync.go: Use hasJSONLChanged() in auto-import
**Testing:**
- Unit tests pass (TestHasJSONLChanged with 7 scenarios)
- Integration test passes (test_bd_khnb_fix.sh)
- Verified git resurrection scenario prevented
Fixes: bd-khnb
Related: bd-3bg, bd-xwo, bd-39o, bd-56p, bd-m8t, bd-rfj, bd-t5o
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This change fixes the issue where 'bd sync' would fail with a false-positive
"JSONL is newer than database" error after the daemon auto-exports.
Root Cause:
- Daemon exports local changes to JSONL, updating its timestamp
- bd sync sees JSONL.mtime > DB.mtime and incorrectly assumes external changes
- This blocks export even though content is identical
Solution:
- Modified isJSONLNewer() to use SHA256 content hash comparison
- Only triggers auto-import when JSONL is newer AND content differs
- Prevents false positives from daemon auto-export timestamp updates
- Maintains conservative fallback if hashes can't be computed
Changes:
- Added computeJSONLHash() and computeDBHash() helper functions
- Created isJSONLNewerWithStore() to support testing with explicit store
- Added comprehensive tests for content-based comparison logic
- All existing tests pass, including export_mtime tests
Fixes: bd-lm2q
Previously, bd sync would fail with "Pre-export validation failed:
refusing to export: JSONL is newer than database" when JSONL was
modified (e.g., after git pull).
Now bd sync intelligently handles this by:
- Detecting when JSONL is newer than the database
- Automatically importing before exporting
- Continuing with the normal sync flow
This makes the workflow much smoother - users can just run 'bd sync'
and it figures out what needs to be done.
Changes:
- Added isJSONLNewer() helper to check file timestamps
- Modified sync command to auto-import when JSONL is newer
- Extracted timestamp check logic for reusability
Resolves: bd-ca0b
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Added dbNeedsExport() to check if DB and JSONL are in sync
- Only re-export after import if DB has changes that differ from JSONL
- Prevents unconditional re-export that caused infinite dirty state
- Added comprehensive tests for sync validation
Fixes recurring dirty state after merge conflicts that plagued users for weeks.
Amp-Thread-ID: https://ampcode.com/threads/T-f4f8c8c6-07bc-4334-9109-4626b4fd7a24
Co-authored-by: Amp <amp@ampcode.com>
- Add JSONL timestamp check in validatePreExport
- Refuse export if JSONL is newer than database
- Force daemon to import before exporting when JSONL updated
- Add test case for JSONL-newer-than-DB scenario
- Fixes bd-89e2
- Added validatePreExport to prevent data loss
- Added checkDuplicateIDs to detect corruption
- Added checkOrphanedDeps to find orphaned dependencies (both sides)
- Added validatePostImport to ensure imports don't lose data
- CRITICAL FIX: Removed post-pull export that clobbered fresh JSONL
- Conservative checks when JSONL is unreadable
- Efficient COUNT(*) SQL path instead of loading all issues
- Comprehensive test coverage including edge cases