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.
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
The narrow cross-runtime Database interface in src/db.ts defines the
subset of better-sqlite3 / bun:sqlite methods used throughout QMD.
Commit fee576b ("fix: migrate legacy lowercase paths on reindex")
introduced a db.transaction(...) call in src/store.ts but did not
extend the interface, breaking `tsc -p tsconfig.build.json`:
src/store.ts(2142,22): error TS2339: Property 'transaction' does
not exist on type 'Database'.
Both underlying engines expose transaction(fn), so this just makes
the type reflect reality.
Parallel test files each cold-load their own LLM model, competing for
CPU and causing timeouts even at 120s. Sequential execution eliminates
contention — tests that timed out at 30s now complete in 1-15s.
Made-with: Cursor
On Windows, `HOME` is not a standard environment variable — the
equivalent is `USERPROFILE`. When MCP clients (e.g. Claude Code)
spawn the QMD server as a subprocess, they pass `USERPROFILE` but
not `HOME`. This causes QMD to fall back to `/tmp`, opening an
empty database instead of the user's actual index.
Fix: check `USERPROFILE` before falling back to `/tmp`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a proxy or firewall intercepts HuggingFace downloads, the cached
file is an HTML page instead of a GGUF model. Previously this surfaced
as an opaque "Invalid GGUF magic" error from node-llama-cpp.
Now we validate the GGUF magic bytes right after download, detect HTML
pages specifically, delete the bad file, and show an actionable error
message with workarounds (HF_ENDPOINT mirror, manual download path).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When qmd update runs against an index created before case-preservation,
documents may exist under lowercase paths (e.g. "skill.md" for a file
actually named "SKILL.md"). Add findOrMigrateLegacyDocument() that:
- Falls back to a lowercase lookup when the canonical path is not found
- Renames the document path in-place via UPDATE OR IGNORE
- Manually rebuilds the FTS entry (FTS5 INSERT OR REPLACE does not
reliably update existing rows via triggers)
- Handles UNIQUE conflicts gracefully (returns null on conflict)
Embeddings are keyed by content hash, so the rename preserves all
existing vectors — no re-embedding required.
Both the CLI indexer and the library reindexer share the same helper,
eliminating the duplication that a previous review flagged.
Includes integration tests for: successful migration, already-lowercase
no-op, and UNIQUE conflict handling.
The blanket .toLowerCase() in handelize() drops filename casing,
which breaks path resolution on case-sensitive filesystems (Linux).
Files like README.md, CHANGELOG.md, and SKILL.md become unreachable
when the index stores them as readme.md, changelog.md, skill.md.
Since FTS5 already performs case-insensitive matching via the
unicode61 tokenizer, lowercasing the stored path provides no search
benefit — it only corrupts the metadata used to locate files on disk.
Remove .toLowerCase() and update all affected test expectations.
but that function has no callers — the CLI's outputResults() uses its
own inline JSON formatting that destructured only .snippet from
extractSnippet(), discarding .line. Extract the full SnippetResult
and spread the line field into the JSON output object.
Closes#505
Update x86_64-linux node_modules hash after dependency pinning.
Add _resetProductionModeForTesting to fix getDefaultDbPath test
that fails when bun runs all test files in a single process.
Remove duplicate path/handelize tests from store.test.ts.
Bun runs all test files in a single process, so module-level state
leaks between files. The getDefaultDbPath test now resets the
_productionMode flag before asserting it throws, fixing the flaky
failure on Bun (ubuntu-latest) in CI.
These tests are already in store.helpers.unit.test.ts. The duplicates
in store.test.ts failed in CI because _productionMode module state
leaked from earlier tests in the same bun process, causing
getDefaultDbPath to return a path instead of throwing.
Release process now checks for sqlite-vec, node-llama-cpp, and
better-sqlite3 updates before cutting a release. All deps must be
pinned to exact versions.
Cover ~25 community PRs including embedding stability fixes, BM25
field weight and hyphenation fixes, reranker context sizing, launcher
reliability, XDG compliance, and the --no-rerank flag.