diff --git a/tests/adapters/omp-plugin.test.ts b/tests/adapters/omp-plugin.test.ts index 094490f62..7589028c1 100644 --- a/tests/adapters/omp-plugin.test.ts +++ b/tests/adapters/omp-plugin.test.ts @@ -20,6 +20,13 @@ import "../setup-home"; */ import { describe, it, expect, beforeEach, afterEach } from "vitest"; + +const activeDBs: Array<{ close?: () => void }> = []; +afterEach(() => { + for (const db of activeDBs) { try { db.close?.(); } catch {} } + activeDBs.length = 0; +}); + import { mkdtempSync, rmSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; @@ -206,6 +213,7 @@ describe("OMP plugin", () => { sessionsDir: adapter.getSessionDir(), }), }); + activeDBs.push(db as any); const latest = db.getLatestSessionId(); expect(latest).not.toBeNull(); const events = db.getEvents(latest as string); @@ -252,6 +260,7 @@ describe("OMP plugin", () => { sessionsDir: adapter.getSessionDir(), }), }); + activeDBs.push(db as any); const latest = db.getLatestSessionId(); expect(latest).not.toBeNull(); }); @@ -309,6 +318,7 @@ describe("OMP plugin", () => { sessionsDir: adapter.getSessionDir(), }), }); + activeDBs.push(db as any); const resume = db.getResume(sid); expect(resume).not.toBeNull(); expect(resume?.snapshot.length).toBeGreaterThan(0); @@ -357,7 +367,10 @@ describe("OMP plugin", () => { expect(fileExists(canonicalPath)).toBe(true); // Verify the canonical file is the one with our session_start row. - const db = new SessionDB({ dbPath: canonicalPath }); + const db = new SessionDB({ dbPath: canonicalPath }); + activeDBs.push(db as any); + activeDBs.push(db as any); + activeDBs.push(db as any); try { const latest = db.getLatestSessionId(); expect(latest).not.toBeNull(); diff --git a/tests/core/search-project-filter.test.ts b/tests/core/search-project-filter.test.ts index a58498e58..c62d9617a 100644 --- a/tests/core/search-project-filter.test.ts +++ b/tests/core/search-project-filter.test.ts @@ -17,7 +17,7 @@ * null (no filter), explicit string → that string. */ -import { describe, test, expect } from "vitest"; +import { describe, test, expect, afterEach } from "vitest"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { randomUUID } from "node:crypto"; @@ -25,12 +25,24 @@ import { ContentStore } from "../../src/store.js"; import { SessionDB } from "../../src/session/db.js"; import { searchAllSources } from "../../src/search/unified.js"; +const activeDBs: Array<{ close?: () => void, cleanup?: () => void }> = []; + +afterEach(() => { + for (const db of activeDBs) { + try { db.cleanup?.(); } catch {} + try { db.close?.(); } catch {} + } + activeDBs.length = 0; +}); + function createStore(): ContentStore { const path = join( tmpdir(), `ctx-issue737-store-${Date.now()}-${Math.random().toString(36).slice(2)}.db`, ); - return new ContentStore(path); + const store = new ContentStore(path); + activeDBs.push(store as any); + return store; } function createSessionDB(): SessionDB { @@ -38,7 +50,9 @@ function createSessionDB(): SessionDB { tmpdir(), `ctx-issue737-session-${Date.now()}-${Math.random().toString(36).slice(2)}.db`, ); - return new SessionDB({ dbPath: path }); + const db = new SessionDB({ dbPath: path }); + activeDBs.push(db as any); + return db; } // ═══════════════════════════════════════════════════════════ diff --git a/tests/integration/commit-message-symmetry.test.ts b/tests/integration/commit-message-symmetry.test.ts index bc90c3b1d..568bccea0 100644 --- a/tests/integration/commit-message-symmetry.test.ts +++ b/tests/integration/commit-message-symmetry.test.ts @@ -12,6 +12,13 @@ */ import { describe, test, beforeEach, afterEach, expect, vi } from "vitest"; + +const activeDBs: Array<{ close?: () => void }> = []; +afterEach(() => { + for (const db of activeDBs) { try { db.close?.(); } catch {} } + activeDBs.length = 0; +}); + import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs"; import { join, dirname } from "node:path"; import { tmpdir } from "node:os"; @@ -78,6 +85,7 @@ describe("session-loaders — Bug 2 repro: commit_message symmetric stamp", () = test("session with 1 commit + 3 file edits — every body MUST carry commit_message alongside has_commit", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sid = "commit-msg-symmetry-" + Date.now(); db.ensureSession(sid, fakeHome); diff --git a/tests/integration/cross-project-attribution.test.ts b/tests/integration/cross-project-attribution.test.ts index 95f66c897..f2d9a9e89 100644 --- a/tests/integration/cross-project-attribution.test.ts +++ b/tests/integration/cross-project-attribution.test.ts @@ -17,6 +17,13 @@ */ import { describe, test, beforeEach, afterEach, expect, vi } from "vitest"; + +const activeDBs: Array<{ close?: () => void }> = []; +afterEach(() => { + for (const db of activeDBs) { try { db.close?.(); } catch {} } + activeDBs.length = 0; +}); + import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs"; import { join, dirname } from "node:path"; import { tmpdir } from "node:os"; @@ -102,7 +109,8 @@ describe("cross-project attribution — Bug 7 repro", () => { }); test("tracer: cwd=projA but file_edit on projB/foo.ts → body.project resolves to projB's canonical id", async () => { - const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + activeDBs.push(db as any); const sid = "cross-proj-" + Date.now(); db.ensureSession(sid, projA); @@ -145,7 +153,8 @@ describe("cross-project attribution — Bug 7 repro", () => { }); test("batched events split across projA + projB → each attributes to its own repo", async () => { - const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + activeDBs.push(db as any); const sid = "cross-proj-batch-" + Date.now(); db.ensureSession(sid, projA); @@ -172,7 +181,8 @@ describe("cross-project attribution — Bug 7 repro", () => { }); test("Bug 8 — Bash 'git -C /projB status' via real extractEvents → project=projB", async () => { - const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + activeDBs.push(db as any); const sid = "bash-c-" + Date.now(); db.ensureSession(sid, projA); @@ -212,7 +222,8 @@ describe("cross-project attribution — Bug 7 repro", () => { }); test("Bug 8 — Bash 'cd /projB && npm test' → project=projB", async () => { - const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + activeDBs.push(db as any); const sid = "bash-cd-" + Date.now(); db.ensureSession(sid, projA); @@ -242,7 +253,8 @@ describe("cross-project attribution — Bug 7 repro", () => { }); test("Bash without any path indicator → falls back to cwd (projA) — expected behavior", async () => { - const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + const db = new SessionDB({ dbPath: join(fakeHome, "test.db") }); + activeDBs.push(db as any); const sid = "bash-no-path-" + Date.now(); db.ensureSession(sid, projA); diff --git a/tests/integration/seed-parity-coverage.test.ts b/tests/integration/seed-parity-coverage.test.ts index 9ca4ff011..dc4b80ab1 100644 --- a/tests/integration/seed-parity-coverage.test.ts +++ b/tests/integration/seed-parity-coverage.test.ts @@ -12,6 +12,13 @@ */ import { describe, test, beforeEach, afterEach, expect, vi } from "vitest"; + +const activeDBs: Array<{ close?: () => void }> = []; +afterEach(() => { + for (const db of activeDBs) { try { db.close?.(); } catch {} } + activeDBs.length = 0; +}); + import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs"; import { dirname, join } from "node:path"; import { tmpdir } from "node:os"; @@ -132,6 +139,7 @@ describe("seed-parity coverage gate", () => { test("every outgoing event carries all 21 universal seed-parity columns", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sessionId = "parity-session-" + Date.now(); db.ensureSession(sessionId, fakeHome); @@ -181,6 +189,7 @@ describe("seed-parity coverage gate", () => { test("variant columns populate by category", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sessionId = "parity-variants-" + Date.now(); db.ensureSession(sessionId, fakeHome); @@ -224,6 +233,7 @@ describe("seed-parity coverage gate", () => { test("rollup snapshot reflects session-wide aggregates", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sessionId = "parity-rollup-" + Date.now(); db.ensureSession(sessionId, fakeHome); @@ -263,6 +273,7 @@ describe("seed-parity coverage gate", () => { test("Bash metadata: command_type/command_tool/exit_code derived algorithmically", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sid = "bash-meta-" + Date.now(); db.ensureSession(sid, fakeHome); @@ -301,6 +312,7 @@ describe("seed-parity coverage gate", () => { test("blocker_status: derived from canonical event type, not regex", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sid = "blocker-" + Date.now(); db.ensureSession(sid, fakeHome); @@ -328,6 +340,7 @@ describe("seed-parity coverage gate", () => { test("latency_ms: read from PreToolUse marker, duration_bucket derived", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sid = "latency-" + Date.now(); db.ensureSession(sid, fakeHome); @@ -358,6 +371,7 @@ describe("seed-parity coverage gate", () => { test("variant matrix — coverage report", async () => { const db = new SessionDB({ dbPath }); + activeDBs.push(db as any); const sessionId = "parity-matrix-" + Date.now(); db.ensureSession(sessionId, fakeHome);