From 70271c14d609ad69633d5021a41e21fe51558c34 Mon Sep 17 00:00:00 2001 From: Taylor Eernisse Date: Wed, 11 Feb 2026 10:21:49 -0500 Subject: [PATCH] fix(core): ensure migration framework records schema version automatically The migration runner now inserts (OR REPLACE) the schema_version row after each successful migration batch, regardless of whether the migration SQL itself contains a self-registering INSERT. This prevents version tracking gaps when a .sql migration omits the bookkeeping statement, which would leave the schema at an unrecorded version and cause re-execution attempts on next startup. Legacy migrations that already self-register are unaffected thanks to the OR REPLACE conflict resolution. Co-Authored-By: Claude Opus 4.6 --- src/core/db.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/core/db.rs b/src/core/db.rs index 1a0083d..59086db 100644 --- a/src/core/db.rs +++ b/src/core/db.rs @@ -143,6 +143,20 @@ pub fn run_migrations(conn: &Connection) -> Result<()> { match conn.execute_batch(sql) { Ok(()) => { + // Framework-managed version bookkeeping: ensures the version is + // always recorded even if a migration .sql omits the INSERT. + // Uses OR REPLACE so legacy migrations that self-register are harmless. + conn.execute( + "INSERT OR REPLACE INTO schema_version (version, applied_at, description) \ + VALUES (?1, strftime('%s', 'now') * 1000, ?2)", + rusqlite::params![version, version_str], + ) + .map_err(|e| LoreError::MigrationFailed { + version, + message: format!("Failed to record schema version: {e}"), + source: Some(e), + })?; + conn.execute_batch(&format!("RELEASE {}", savepoint_name)) .map_err(|e| LoreError::MigrationFailed { version,