diff --git a/CHANGELOG.md b/CHANGELOG.md index ba4d707134..a893baab59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - **fix(types):** Add explicit type annotations to sync-env test helpers and dynamic import casts to satisfy `typecheck:noimplicit:core` CI gate. - **fix(reasoning):** Implement Reasoning Replay Cache — hybrid memory/SQLite persistence for `reasoning_content` in multi-turn tool-calling flows. Automatically captures reasoning from DeepSeek V4, Kimi K2, Qwen-Thinking, and GLM models and re-injects it on follow-up turns to prevent HTTP 400 errors from strict reasoning-content validation. Includes dashboard telemetry tab, REST API, and 21 unit tests (#1628 — thanks @JasonLandbridge). - **fix(postinstall):** Extend postinstall native module repair to cover `wreq-js` — detects missing platform-specific `.node` binaries inside `app/node_modules/wreq-js/rust/` and copies them from the root install. Fixes global `pnpm` installs on macOS arm64 where the standalone app directory only contained Linux binaries (#1634 — thanks @MarcosT96). +- **fix(migration):** Prevent compat-renamed migration slots from shadowing new migrations at the same version number. After rewriting `028_provider_connection_max_concurrent` → `029`, the runner now verifies the old version slot is clear, ensuring `028_create_files_and_batches` runs on v3.6.x → v3.7.x upgrades. Adds `batches` table as a physical schema sentinel for upgrade recovery (#1637 — thanks @V8-Software). ### 📝 Documentation diff --git a/src/lib/db/migrationRunner.ts b/src/lib/db/migrationRunner.ts index f39014c764..973f3f7429 100644 --- a/src/lib/db/migrationRunner.ts +++ b/src/lib/db/migrationRunner.ts @@ -74,6 +74,7 @@ const RENAMED_MIGRATION_COMPATIBILITY = [ ] as const; const PHYSICAL_SCHEMA_SENTINELS = [ + { version: "028", tableName: "batches", description: "batches table" }, { version: "024", tableName: "sync_tokens", description: "sync_tokens table" }, { version: "022", tableName: "memory_fts", description: "memory_fts virtual table" }, { version: "019", tableName: "context_handoffs", description: "context_handoffs table" }, @@ -268,6 +269,25 @@ function reconcileRenumberedMigrations( `[Migration] Reconciled renamed migration ${compatibility.fromVersion}_${compatibility.fromName} ` + `to ${compatibility.toVersion}_${compatibility.toName} to preserve pending migrations.` ); + + // After the compat rewrite, verify the old version slot is now free. + // A residual row (from a failed prior run, manual intervention, or edge-case + // UPDATE conflict) at the old version would shadow a NEW migration file + // placed at that version number — e.g. 028_create_files_and_batches.sql + // would be skipped because getAppliedVersions() still sees version "028". + const residualRow = db + .prepare("SELECT version, name FROM _omniroute_migrations WHERE version = ?") + .get(compatibility.fromVersion) as { version: string; name: string } | undefined; + if (residualRow) { + console.warn( + `[Migration] ⚠️ Residual row at version ${compatibility.fromVersion} ` + + `(name: "${residualRow.name}") still present after compat rewrite — ` + + `removing to unblock new migration at this version slot.` + ); + db.prepare("DELETE FROM _omniroute_migrations WHERE version = ?").run( + compatibility.fromVersion + ); + } } return repaired;