diff --git a/src/resources/extensions/sf/commands-uok.js b/src/resources/extensions/sf/commands-uok.js index 50a8ced79..eb4e39234 100644 --- a/src/resources/extensions/sf/commands-uok.js +++ b/src/resources/extensions/sf/commands-uok.js @@ -45,9 +45,7 @@ export async function collectUokStatus( basePath = process.cwd(), nowMs = Date.now(), ) { - if (!isDbAvailable()) { - await ensureDbOpen(basePath); - } + await ensureDbOpen(basePath); const dbAvailable = isDbAvailable(); let runs = []; if (dbAvailable) { @@ -227,9 +225,7 @@ export async function handleUok(args, ctx) { } if (trimmed === "circuit-breakers" || trimmed === "circuit_breakers") { const basePath = process.cwd(); - if (!isDbAvailable()) { - await ensureDbOpen(basePath); - } + await ensureDbOpen(basePath); if (!isDbAvailable()) { ctx.ui.notify("Database unavailable", "error"); return; @@ -256,9 +252,7 @@ export async function handleUok(args, ctx) { } if (trimmed === "gates") { const basePath = process.cwd(); - if (!isDbAvailable()) { - await ensureDbOpen(basePath); - } + await ensureDbOpen(basePath); if (!isDbAvailable()) { ctx.ui.notify("Database unavailable", "error"); return; @@ -280,9 +274,7 @@ export async function handleUok(args, ctx) { } if (trimmed === "messages" || trimmed.startsWith("messages ")) { const basePath = process.cwd(); - if (!isDbAvailable()) { - await ensureDbOpen(basePath); - } + await ensureDbOpen(basePath); if (!isDbAvailable()) { ctx.ui.notify("Database unavailable", "error"); return; diff --git a/src/resources/extensions/sf/tests/uok-status-command.test.mjs b/src/resources/extensions/sf/tests/uok-status-command.test.mjs index 48de0ffeb..766f5b4ad 100644 --- a/src/resources/extensions/sf/tests/uok-status-command.test.mjs +++ b/src/resources/extensions/sf/tests/uok-status-command.test.mjs @@ -18,8 +18,10 @@ import { const NOW = Date.parse("2026-05-06T00:00:00.000Z"); const tmpRoots = []; +const originalCwd = process.cwd(); afterEach(() => { + process.chdir(originalCwd); closeDatabase(); for (const dir of tmpRoots.splice(0)) { rmSync(dir, { recursive: true, force: true }); @@ -35,7 +37,7 @@ function makeProject() { test("collectUokStatus_reads_ledger_and_reports_clear_startup_gate", async () => { const projectRoot = makeProject(); - openDatabase(":memory:"); + openDatabase(join(projectRoot, ".sf", "sf.db")); recordUokRunStart({ runId: "uok-status-ok", sessionId: "session-uok", @@ -67,7 +69,7 @@ test("collectUokStatus_reads_ledger_and_reports_clear_startup_gate", async () => test("collectUokStatus_reports_last_error_and_blocked_startup_gate", async () => { const projectRoot = makeProject(); - openDatabase(":memory:"); + openDatabase(join(projectRoot, ".sf", "sf.db")); recordUokRunStart({ runId: "uok-status-error", path: "uok-kernel", @@ -90,6 +92,29 @@ test("collectUokStatus_reports_last_error_and_blocked_startup_gate", async () => assert.deepEqual(status.current.criticalMismatches, 1); }); +test("collectUokStatus_when_process_switches_projects_reads_requested_project_db", async () => { + const first = makeProject(); + const second = makeProject(); + openDatabase(join(first, ".sf", "sf.db")); + recordUokRunStart({ + runId: "first-project-run", + path: "uok-kernel", + startedAt: new Date(NOW - 20_000).toISOString(), + }); + recordUokRunExit({ + runId: "first-project-run", + path: "uok-kernel", + status: "ok", + endedAt: new Date(NOW - 10_000).toISOString(), + }); + + const status = await collectUokStatus(second, NOW); + + assert.equal(status.dbAvailable, true); + assert.equal(status.lastRun, null); + assert.equal(status.ledgerRunCount, 0); +}); + test("formatUokStatus_shows_operator_fields_without_raw_json", () => { const rendered = formatUokStatus( { @@ -142,6 +167,8 @@ test("formatUokStatus_shows_operator_fields_without_raw_json", () => { }); test("handleUok_gates_when_empty_shows_no_recorded_gate_runs", async () => { + const projectRoot = makeProject(); + process.chdir(projectRoot); const notifications = []; const ctx = { ui: { @@ -154,7 +181,9 @@ test("handleUok_gates_when_empty_shows_no_recorded_gate_runs", async () => { }); test("handleUok_gates_lists_observed_gate_runs", async () => { - openDatabase(":memory:"); + const projectRoot = makeProject(); + process.chdir(projectRoot); + openDatabase(join(projectRoot, ".sf", "sf.db")); insertGateRun({ traceId: "trace-gates", turnId: "turn-gates", @@ -190,8 +219,9 @@ test("handleUok_gates_lists_observed_gate_runs", async () => { }); test("handleUok_messages_shows_bus_metrics", async () => { - makeProject(); - openDatabase(":memory:"); + const projectRoot = makeProject(); + process.chdir(projectRoot); + openDatabase(join(projectRoot, ".sf", "sf.db")); const notifications = []; const ctx = { ui: {