From a26dc8a8492b69fe921a70a2d72ba09081ece1d0 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Wed, 15 Oct 2025 00:43:25 -0700 Subject: [PATCH] feat: Add version mismatch detection for outdated binaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent user confusion when running outdated bd binaries by detecting version mismatches between the binary and database. Features: - Store bd version in metadata table on init - Check version on every command (PersistentPreRun) - Warn if binary is outdated with rebuild instructions - Auto-upgrade database if binary is newer - Silent operation when versions match Fixes confusion from bd-182 (auto-export not working with old binary) Implements bd-197 Files changed: - cmd/bd/init.go: Store version on init - cmd/bd/main.go: checkVersionMismatch() + integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- cmd/bd/init.go | 6 ++++++ cmd/bd/main.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/cmd/bd/init.go b/cmd/bd/init.go index b52389a5..04533900 100644 --- a/cmd/bd/init.go +++ b/cmd/bd/init.go @@ -56,6 +56,12 @@ and database file. Optionally specify a custom issue prefix.`, os.Exit(1) } + // Store the bd version in metadata (for version mismatch detection) + if err := store.SetMetadata(ctx, "bd_version", Version); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to store version metadata: %v\n", err) + // Non-fatal - continue anyway + } + if err := store.Close(); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to close database: %v\n", err) } diff --git a/cmd/bd/main.go b/cmd/bd/main.go index 63bd305b..06cc2b9f 100644 --- a/cmd/bd/main.go +++ b/cmd/bd/main.go @@ -95,6 +95,9 @@ var rootCmd = &cobra.Command{ } } + // Check for version mismatch (warn if binary is older than DB) + checkVersionMismatch() + // Auto-import if JSONL is newer than DB (e.g., after git pull) // Skip for import command itself to avoid recursion if cmd.Name() != "import" && autoImportEnabled { @@ -295,6 +298,52 @@ func autoImportIfNewer() { _ = store.SetMetadata(ctx, "last_import_hash", currentHash) } +// checkVersionMismatch checks if the binary version matches the database version +// and warns the user if they're running an outdated binary +func checkVersionMismatch() { + ctx := context.Background() + + // Get the database version (version that last wrote to this DB) + dbVersion, err := store.GetMetadata(ctx, "bd_version") + if err != nil { + // Metadata error - skip check (shouldn't happen, but be defensive) + if os.Getenv("BD_DEBUG") != "" { + fmt.Fprintf(os.Stderr, "Debug: version check skipped, metadata error: %v\n", err) + } + return + } + + // If no version stored, this is an old database - store current version and continue + if dbVersion == "" { + _ = store.SetMetadata(ctx, "bd_version", Version) + return + } + + // Compare versions: warn if binary is older than database + if dbVersion != Version { + // Simple string comparison is sufficient for detecting version mismatch + // We're not trying to parse semantic versions, just detect "different" + yellow := color.New(color.FgYellow, color.Bold).SprintFunc() + fmt.Fprintf(os.Stderr, "\n%s\n", yellow("⚠️ WARNING: Version mismatch detected!")) + fmt.Fprintf(os.Stderr, "%s\n", yellow(fmt.Sprintf("⚠️ Your bd binary (v%s) differs from the database version (v%s)", Version, dbVersion))) + + // Determine if binary is likely older (heuristic: lower version number) + if Version < dbVersion { + fmt.Fprintf(os.Stderr, "%s\n", yellow("⚠️ Your binary appears to be OUTDATED.")) + fmt.Fprintf(os.Stderr, "%s\n\n", yellow("⚠️ Some features may not work correctly. Rebuild: go build -o bd ./cmd/bd")) + } else { + fmt.Fprintf(os.Stderr, "%s\n", yellow("⚠️ Your binary appears NEWER than the database.")) + fmt.Fprintf(os.Stderr, "%s\n\n", yellow("⚠️ The database will be upgraded automatically.")) + // Update stored version to current + _ = store.SetMetadata(ctx, "bd_version", Version) + } + } + + // Always update the version metadata to track last-used version + // This is safe even if versions match (idempotent operation) + _ = store.SetMetadata(ctx, "bd_version", Version) +} + // markDirtyAndScheduleFlush marks the database as dirty and schedules a flush func markDirtyAndScheduleFlush() { if !autoFlushEnabled {