diff --git a/internal/store/sqlitestore/cron_crud_test.go b/internal/store/sqlitestore/cron_crud_test.go index c9b1c8b9..8423df1a 100644 --- a/internal/store/sqlitestore/cron_crud_test.go +++ b/internal/store/sqlitestore/cron_crud_test.go @@ -230,7 +230,7 @@ func TestSQLiteCronStore_ExecuteOneJob_DoesNotRestoreNextRunAfterDisable(t *test t.Fatalf("disable during run error: %v", err) } return &store.CronJobResult{Content: "ok"}, nil - }) + }, false) current := mustRawJob(t, db, jobUUID) if current.enabled { diff --git a/internal/store/sqlitestore/schema_migration_test.go b/internal/store/sqlitestore/schema_migration_test.go index 52855bbd..e3a9f6c9 100644 --- a/internal/store/sqlitestore/schema_migration_test.go +++ b/internal/store/sqlitestore/schema_migration_test.go @@ -50,20 +50,14 @@ func TestEnsureSchema_FreshDB(t *testing.T) { } } -// TestEnsureSchema_MigrationV11Only verifies the v11→12 patch (our new migration) -// applies correctly on a DB already at version 11. +// TestEnsureSchema_MigrationV11Only verifies migrations from v11 onward +// apply correctly on a DB built at version 11. func TestEnsureSchema_MigrationV11Only(t *testing.T) { - db := openTestDB(t) + db := openTestDBAtVersion(t, 11) - // Apply fresh schema first, then roll version back to 11 + // Re-apply — should run migrations 11→SchemaVersion if err := EnsureSchema(db); err != nil { - t.Fatalf("initial EnsureSchema: %v", err) - } - db.Exec("UPDATE schema_version SET version = 11") - - // Re-apply — should run only migration 11→12 - if err := EnsureSchema(db); err != nil { - t.Fatalf("EnsureSchema (v11→12) failed: %v", err) + t.Fatalf("EnsureSchema (v11→current) failed: %v", err) } var version int @@ -84,15 +78,12 @@ func TestEnsureSchema_IdempotentRerun(t *testing.T) { } } -// TestEnsureSchema_MigrationV11_SeedsAgentFiles verifies migration 11 seeds +// TestEnsureSchema_MigrationV11_SeedsAgentFiles verifies migration 11→12 seeds // AGENTS_CORE.md and AGENTS_TASK.md and removes AGENTS_MINIMAL.md. func TestEnsureSchema_MigrationV11_SeedsAgentFiles(t *testing.T) { - db := openTestDB(t) - if err := EnsureSchema(db); err != nil { - t.Fatalf("EnsureSchema: %v", err) - } + db := openTestDBAtVersion(t, 11) - // Use master tenant (seeded by EnsureSchema → seedMasterTenant) + // Use master tenant (seeded by seedMasterTenant) tenantID := "0193a5b0-7000-7000-8000-000000000001" agentID := "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" _, err := db.Exec(`INSERT INTO agents (id, tenant_id, agent_key, display_name, provider, model, agent_type, owner_id) @@ -107,10 +98,9 @@ func TestEnsureSchema_MigrationV11_SeedsAgentFiles(t *testing.T) { VALUES ('min-id', ?, 'AGENTS_MINIMAL.md', 'old minimal', ?, datetime('now'), datetime('now'))`, agentID, tenantID) - // Reset schema_version to 11 and re-apply migration - db.Exec("UPDATE schema_version SET version = 11") + // Re-apply — runs migrations 11→SchemaVersion (includes v11→12 seed) if err := EnsureSchema(db); err != nil { - t.Fatalf("EnsureSchema (re-apply v11): %v", err) + t.Fatalf("EnsureSchema (re-apply from v11): %v", err) } // Verify AGENTS_CORE.md seeded @@ -144,3 +134,49 @@ func openTestDB(t *testing.T) *sql.DB { t.Cleanup(func() { _ = db.Close() }) return db } + +// openTestDBAtVersion creates a fresh DB, applies full schema, then +// drops columns added by migrations > targetVersion so re-running +// EnsureSchema from that version exercises the real migration path. +// +// We accomplish this by applying schema at targetVersion: apply full +// schema.sql then set version = targetVersion. Migrations will ALTER +// TABLE ADD COLUMN — which only fails if the column already exists. +// To avoid that, we drop the columns that post-targetVersion migrations add. +func openTestDBAtVersion(t *testing.T, targetVersion int) *sql.DB { + t.Helper() + db := openTestDB(t) + + // Apply full schema first (creates all tables with all columns). + if err := EnsureSchema(db); err != nil { + t.Fatalf("EnsureSchema: %v", err) + } + + // Undo columns added by migrations after targetVersion. + // SQLite DROP COLUMN support varies, so recreate affected tables. + if targetVersion <= 11 { + // Migration 12 adds recall_count, recall_score, last_recalled_at. + // Recreate episodic_summaries without those columns. + db.Exec(`CREATE TABLE episodic_summaries_old AS SELECT + id, tenant_id, agent_id, user_id, session_key, summary, l0_abstract, + key_topics, source_type, source_id, turn_count, token_count, + created_at, expires_at, promoted_at + FROM episodic_summaries`) + db.Exec(`DROP TABLE episodic_summaries`) + db.Exec(`CREATE TABLE episodic_summaries ( + id TEXT NOT NULL PRIMARY KEY, tenant_id TEXT NOT NULL, agent_id TEXT NOT NULL, + user_id VARCHAR(255) NOT NULL DEFAULT '', session_key TEXT NOT NULL, + summary TEXT NOT NULL, l0_abstract TEXT NOT NULL DEFAULT '', + key_topics TEXT NOT NULL DEFAULT '[]', source_type TEXT NOT NULL DEFAULT 'session', + source_id TEXT, turn_count INTEGER NOT NULL DEFAULT 0, + token_count INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), + expires_at TEXT, promoted_at TEXT)`) + db.Exec(`INSERT INTO episodic_summaries SELECT * FROM episodic_summaries_old`) + db.Exec(`DROP TABLE episodic_summaries_old`) + } + + // Set version back to target. + db.Exec("UPDATE schema_version SET version = ?", targetVersion) + return db +}