From 54262f566cf57ab7e7e55564952d5be9128a48e2 Mon Sep 17 00:00:00 2001 From: Pi Date: Thu, 23 Apr 2026 15:57:02 +0000 Subject: [PATCH 1/2] fix(mcp): do not enable production mode at module import time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The top-level enableProductionMode() call added in #537 fixed a real issue (MCP server resolving the wrong database path at startup) but introduced test-isolation breakage as a side effect: merely importing src/mcp/server.ts flipped the global _productionMode flag, which then broke unrelated tests that depend on the default (development) database path resolution. This shows up concretely as "Store Creation > createStore throws without explicit path in test mode" failing on Bun (ubuntu-latest) in CI, because test/mcp.test.ts imports startMcpHttpServer from this module. Move the enableProductionMode() call from module scope into the two server entry points (startMcpServer and startMcpHttpServer). The fix originally intended by #537 — ensuring production mode is active before getDefaultDbPath runs — is preserved because both call sites still flip the flag before createStore / getDefaultDbPath. Importing the module for its exports no longer mutates global state. Verified locally against current main: CI failure on Bun (ubuntu-latest) reproduces on unmodified upstream main (14+ consecutive failed runs since #537 merged on 2026-04-09) and is resolved by this change. Refs: #537 --- src/mcp/server.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mcp/server.ts b/src/mcp/server.ts index 0cfb607..4fd0d77 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -32,8 +32,6 @@ import { import { getConfigPath } from "../collections.js"; import { enableProductionMode } from "../store.js"; -enableProductionMode(); - // ============================================================================= // Types for structured content // ============================================================================= @@ -541,6 +539,12 @@ Intent-aware lex (C++ performance, not sports): // ============================================================================= export async function startMcpServer(): Promise { + // Opt into production mode when the MCP server is actually started, not + // when this module is merely imported for its exports. Importing the module + // at the top level flipped the global production flag and broke test + // isolation for downstream suites that expect the default (development) + // database path behaviour. + enableProductionMode(); const configPath = getConfigPath(); const store = await createStore({ dbPath: getDefaultDbPath(), @@ -566,6 +570,10 @@ export type HttpServerHandle = { * Binds to localhost only. Returns a handle for shutdown and port discovery. */ export async function startMcpHttpServer(port: number, options?: { quiet?: boolean }): Promise { + // See startMcpServer() for the rationale — flip production mode here so the + // HTTP transport resolves the real database path, without leaking state into + // callers that only import this module for its exports (e.g. tests). + enableProductionMode(); const configPath = getConfigPath(); const store = await createStore({ dbPath: getDefaultDbPath(), From a0c460333b6d2bd316472c47b66dc2a10e0a6b14 Mon Sep 17 00:00:00 2001 From: Pi Date: Thu, 23 Apr 2026 17:41:10 +0000 Subject: [PATCH 2/2] fix(cli): do not enable production mode at module import time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/cli/qmd.ts has the same module-scope enableProductionMode() call that src/mcp/server.ts had — and the same test-isolation leak. test/cli.test.ts imports buildEditorUri and termLink from this module, which executes the top-level enableProductionMode() as a side effect of import, flipping the global _productionMode flag for every later test file in the Bun process. This is the actual driver of the Store Creation > createStore throws without explicit path in test mode failure — test/cli.test.ts runs alphabetically before test/store.test.ts, so the flag is already true by the time store.test.ts checks it. Mirror the fix applied to src/mcp/server.ts in the previous commit: move enableProductionMode() from module scope into the if (isMain) guard so the flag is only flipped when qmd is actually invoked as the CLI entrypoint, not when the module is imported for its exports. --- src/cli/qmd.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cli/qmd.ts b/src/cli/qmd.ts index bfcd392..f42d1be 100755 --- a/src/cli/qmd.ts +++ b/src/cli/qmd.ts @@ -101,9 +101,12 @@ import { } from "../collections.js"; import { getEmbeddedQmdSkillContent, getEmbeddedQmdSkillFiles } from "../embedded-skills.js"; -// Enable production mode - allows using default database path -// Tests must set INDEX_PATH or use createStore() with explicit path -enableProductionMode(); +// NOTE: enableProductionMode() is intentionally NOT called at module scope here. +// Importing this module for its exports (e.g. buildEditorUri, termLink from +// test/cli.test.ts) must not flip the global production flag, as that leaks +// into unrelated tests that rely on the default (development) database path +// resolution. The flag is flipped inside the CLI's main-module guard below so +// it only fires when qmd is actually invoked as a script. // ============================================================================= // Store/DB lifecycle (no legacy singletons in store.ts) @@ -2821,6 +2824,11 @@ const isMain = argv1 === __filename || argv1?.endsWith("/qmd.js") || (argv1 != null && realpathSync(argv1) === __filename); if (isMain) { + // Flip to production mode only when this module is executed as the CLI + // entrypoint, not when imported for its exports. Tests must set INDEX_PATH + // or use createStore() with an explicit path. + enableProductionMode(); + const cli = parseCLI(); if (cli.values.version) {