Fix bd-ar2 code review issues: metadata tracking and multi-repo support

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>
This commit is contained in:
Steve Yegge
2025-11-21 11:25:49 -05:00
parent ff2a2250f3
commit cd8cb8b86a
8 changed files with 284 additions and 70 deletions

View File

@@ -94,10 +94,20 @@ func computeJSONLHash(jsonlPath string) (string, error) {
// Performance optimization: Checks mtime first as a fast-path. Only computes expensive
// SHA256 hash if mtime changed. This makes 99% of checks instant (mtime unchanged = content
// unchanged) while still catching git operations that restore old content with new mtimes.
func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath string) bool {
//
// In multi-repo mode, keySuffix should be the stable repo identifier (e.g., ".", "../frontend").
func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath string, keySuffix string) bool {
// Build metadata keys with optional suffix for per-repo tracking (bd-ar2.10, bd-ar2.11)
hashKey := "last_import_hash"
mtimeKey := "last_import_mtime"
if keySuffix != "" {
hashKey += ":" + keySuffix
mtimeKey += ":" + keySuffix
}
// Fast-path: Check mtime first to avoid expensive hash computation
// Get last known mtime from metadata
lastMtimeStr, err := store.GetMetadata(ctx, "last_import_mtime")
lastMtimeStr, err := store.GetMetadata(ctx, mtimeKey)
if err == nil && lastMtimeStr != "" {
// We have a previous mtime - check if file mtime changed
jsonlInfo, statErr := os.Stat(jsonlPath)
@@ -122,7 +132,7 @@ func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath strin
}
// Get last import hash from metadata
lastHash, err := store.GetMetadata(ctx, "last_import_hash")
lastHash, err := store.GetMetadata(ctx, hashKey)
if err != nil {
// No previous import hash - this is the first run or metadata is missing
// Assume changed to trigger import
@@ -138,7 +148,9 @@ func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath strin
func validatePreExport(ctx context.Context, store storage.Storage, jsonlPath string) error {
// Check if JSONL content has changed since last import - if so, must import first
// Uses content-based detection (bd-xwo fix) instead of mtime-based to avoid false positives from git operations
if hasJSONLChanged(ctx, store, jsonlPath) {
// Use getRepoKeyForPath to get stable repo identifier for multi-repo support (bd-ar2.10, bd-ar2.11)
repoKey := getRepoKeyForPath(jsonlPath)
if hasJSONLChanged(ctx, store, jsonlPath, repoKey) {
return fmt.Errorf("refusing to export: JSONL content has changed since last import (import first to avoid data loss)")
}