diff --git a/src/headless-query.ts b/src/headless-query.ts index cc7c134c3..00816e103 100644 --- a/src/headless-query.ts +++ b/src/headless-query.ts @@ -38,7 +38,9 @@ async function loadExtensionModules() { const dispatchModule = await jiti.import(gsdExtensionPath('auto-dispatch.ts'), {}) as any const sessionModule = await jiti.import(gsdExtensionPath('session-status-io.ts'), {}) as any const prefsModule = await jiti.import(gsdExtensionPath('preferences.ts'), {}) as any + const autoStartModule = await jiti.import(gsdExtensionPath('auto-start.ts'), {}) as any return { + openProjectDbIfPresent: autoStartModule.openProjectDbIfPresent as (basePath: string) => Promise, deriveState: stateModule.deriveState as (basePath: string) => Promise, resolveDispatch: dispatchModule.resolveDispatch as (opts: any) => Promise, readAllSessionStatuses: sessionModule.readAllSessionStatuses as (basePath: string) => any[], @@ -76,7 +78,14 @@ export interface QueryResult { // ─── Implementation ───────────────────────────────────────────────────────── export async function handleQuery(basePath: string): Promise { - const { deriveState, resolveDispatch, readAllSessionStatuses, loadEffectiveGSDPreferences } = await loadExtensionModules() + const { + openProjectDbIfPresent, + deriveState, + resolveDispatch, + readAllSessionStatuses, + loadEffectiveGSDPreferences, + } = await loadExtensionModules() + await openProjectDbIfPresent(basePath) const state = await deriveState(basePath) // Derive next dispatch action diff --git a/src/tests/headless-query-db-open.test.ts b/src/tests/headless-query-db-open.test.ts new file mode 100644 index 000000000..c562455ad --- /dev/null +++ b/src/tests/headless-query-db-open.test.ts @@ -0,0 +1,29 @@ +/** + * Regression test for #4123: headless-query must open the project DB + * before deriveState(), otherwise it falls back to filesystem parsing. + */ + +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const src = readFileSync(join(__dirname, "..", "headless-query.ts"), "utf-8"); + +test("headless-query loads openProjectDbIfPresent from extension modules (#4123)", () => { + assert.match( + src, + /openProjectDbIfPresent:\s*autoStartModule\.openProjectDbIfPresent/, + "headless-query should load openProjectDbIfPresent from auto-start.ts", + ); +}); + +test("headless-query opens the DB before deriveState (#4123)", () => { + const openIdx = src.indexOf("await openProjectDbIfPresent(basePath)"); + const deriveIdx = src.indexOf("const state = await deriveState(basePath)"); + assert.ok(openIdx !== -1, "headless-query should open the project DB"); + assert.ok(deriveIdx !== -1, "headless-query should still derive state"); + assert.ok(openIdx < deriveIdx, "headless-query should open the DB before deriveState()"); +});