@oomkapwn/enquire-mcp 3.9.0 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  All notable changes to this project will be documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [3.9.1] — 2026-06-01
6
+
7
+ > **TL;DR:** **First post-stable patch — closes 2 of the 3 named-uncovered behavioral classes from the rc.36 meta-audit + the v3.8.2-style docs-currency flip.** The meta-audit named three behavioral dimensions the drift-driven apparatus still didn't patrol; this ships structural gates for two: **supply-chain `run:`-download** (OIA **Check 9b** `RUN-DOWNLOAD-UNPINNED` — a `curl`/`wget` must not pull from a moving `releases/latest` URL; the M-9 mcp-publisher class on a surface Check 9's `uses:` SHA-pin didn't cover) and **paired-sink behavior parity** (`tests/sink-parity-invariant.test.ts` — paired sinks that handle the same concept must agree on fail-closed error semantics; H-3 class, the rc.33 PDF-vs-OCR page-range gap). Plus the **docs-currency flip**: now that `@latest = 3.9.0`, the current-stable pointers move "v3.8.x → v3.9.x" (README hero/badge/channel, ROADMAP, api.md, QUICKSTART) — the dated COMPARISON snapshot vintage is **intentionally left at v3.8.x** (it's accurate history; flipping it would imply a v3.9.0 re-verification that didn't happen). **1039 → 1044 tests.**
8
+
9
+ **Patch — post-stable hardening (meta-audit behavioral classes) + docs-currency.**
10
+
11
+ ### Added — structural defenses (close named-uncovered behavioral classes)
12
+
13
+ - **OIA Check 9b (`RUN-DOWNLOAD-UNPINNED`)** — supply-chain. Check 9 SHA-pins `uses:` action refs, but a binary fetched in a `run:` block via `curl`/`wget` from a moving `releases/latest` URL is the SAME risk on a different surface (the exact M-9 shape: `mcp-publisher` was pulled from `releases/latest` until rc.33 pinned it to `v1.7.9`). Flags any non-comment `curl`/`wget` line whose URL contains `releases/latest` (or `releases/download/latest`); version/tag-pinned assets pass; comment lines that merely mention `releases/latest` are skipped (so the guard can't flag its own rationale). Detection-power verified (injected `releases/latest` → flagged; the live `v1.7.9` pin → clean). Folded under Check 9 (9b) — canonical OIA count stays 12.
14
+ - **`tests/sink-parity-invariant.test.ts`** — H-3 class. Generalizes the one-off rc.33 fix (PDF returned `pages:[]` on an inverted `pageRange` while OCR threw) into a manifest of paired sinks that must agree on fail-closed semantics. Behavioral on the pure member (`resolveOcrPageRange` throws on `[50,10]`, passes on `[1,3]`) + structural source-parity on both members (each body must contain an inverted-range `throw`; the regex is an alternation over the two sites' syntaxes — `to < from` vs `to - from + 1 < 1`). Positive + NEGATIVE controls (a silent no-throw sink + a guard-less body are both flagged). Enrolled in the META-invariant.
15
+
16
+ ### Changed — docs-currency (post-publish, v3.8.2 precedent)
17
+
18
+ - Current-stable pointers flipped `v3.8.x → v3.9.x`: README hero credential + `stable` badge + npm-channel line + version-history `(on @rc)` → `stable`; ROADMAP "Where we are"; `docs/api.md` channel header (+ dropped the stale "in-flight v3.9.0 RCs" phrase); `docs/QUICKSTART.md` version example. **Intentionally NOT flipped:** the dated `docs/COMPARISON.md` + README comparison-note snapshot vintage ("as of 2026-05-24, v3.8.x stable") — that's accurate history; re-stamping it v3.9.x without re-running the comparison would be an overclaim. Line-level `v3.9.x` (not `v3.9.0`) is used so the pointers stay correct across patches.
19
+
20
+ ### Method note
21
+
22
+ First post-stable patch, mirroring v3.8.0 → v3.8.2 (currency flip after the dist-tag actually moved). The two structural gates follow the rc.36 meta-audit rule: internalize each external lens as an inventory invariant, don't just patch the instance. **Deferred (the 3rd named class):** a generalized enforcement-verb → code-guard taxonomy (greps SECURITY.md/TSDoc for "blocked / zero outbound / fails closed / throws if" and requires each to point at a named guard) — it needs careful low-false-positive design (many TSDoc legitimately say "throws if" with the guard inline), so it gets its own focused patch rather than a rushed regex here.
23
+
24
+ ### Tests (1044)
25
+
26
+ `tests/sink-parity-invariant.test.ts` +5 source `it()` (1 behavioral + 1 valid-range NEGATIVE + 1 structural-parity loop + 2 NEGATIVE controls). 1039 → 1044; claims synced (README ×4, package.json, llms.txt, AGENTS, COMPARISON, ROADMAP).
27
+
28
+ ### Files changed
29
+
30
+ - `scripts/oia-walk.mjs` (Check 9b + enumeration/marker-order update), `tests/sink-parity-invariant.test.ts` (new), README/ROADMAP/api.md/QUICKSTART (currency flip), test-count claims → 1044.
31
+ - version bump 3.9.0 → 3.9.1.
32
+
33
+ ---
34
+
5
35
  ## [3.9.0] — 2026-06-01
6
36
 
7
37
  > **TL;DR:** **v3.9.0 STABLE — promoted `@rc → @latest` after 37 RCs.** The v3.9.0 minor delivers the last architectural items from the v3.8.0 backlog plus the deepest security/correctness hardening cascade in the project's history. **Headline features:** OCR'd-PDF watcher embed-sync (rc.1), **HNSW in-memory live update** so search reflects vault edits within the watcher debounce window (~250 ms) without a serve restart (rc.2) + close-time disk persistence (rc.6), and **R-10 adaptive HNSW refill** that doubles `k` under heavy privacy-filtering (rc.3). **Hardening cascade (rc.7→rc.37):** the ReDoS guard for `obsidian_open_questions` taken from a single instance to a permanent generative-fuzz CI gate (rc.21/24/25), OCR offline-enforcement actually built to match the docs (rc.10), watcher/HNSW concurrency races closed (rc.11), and a comprehensive in-house audit (rc.36/37) that fixed the open siblings of every recent class **and internalized the missing privacy/DoS lenses as permanent inventory invariants** (erasure-completeness, resource-bound-completeness, orphan-dist). **Promotion basis:** the v3.6.1 ≥2-independent-external-auditor gate is met by the rc.32 deep-audit (Mavis 10-track STRIDE/privacy) + the rc.34 from-scratch audit (different methodology), each re-verified per-item against the pinned commit; the maintainer elected to promote on these two rather than commission a third on the rc.37 commit (the rc.35→37 delta is hardening + docs only). **1039 tests, 89.61% line coverage, all 9 required CI gates green.**
package/README.md CHANGED
@@ -13,8 +13,8 @@
13
13
  [![CI](https://github.com/oomkapwn/enquire-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/oomkapwn/enquire-mcp/actions/workflows/ci.yml)
14
14
  [![npm](https://img.shields.io/npm/v/@oomkapwn/enquire-mcp.svg?label=npm&color=cb3837)](https://www.npmjs.com/package/@oomkapwn/enquire-mcp)
15
15
  [![downloads](https://img.shields.io/npm/dm/@oomkapwn/enquire-mcp.svg?color=cb3837)](https://www.npmjs.com/package/@oomkapwn/enquire-mcp)
16
- [![tests](https://img.shields.io/badge/tests-1039%20passing-brightgreen.svg)](#trust)
17
- [![stable](https://img.shields.io/badge/v3.8.x-stable-brightgreen.svg)](./STABILITY.md)
16
+ [![tests](https://img.shields.io/badge/tests-1044%20passing-brightgreen.svg)](#trust)
17
+ [![stable](https://img.shields.io/badge/v3.9.x-stable-brightgreen.svg)](./STABILITY.md)
18
18
  [![build provenance](https://img.shields.io/badge/build_provenance-SLSA_L2-blue.svg)](https://slsa.dev/spec/v1.0/levels#build-l2)
19
19
  [![MCP](https://img.shields.io/badge/MCP-1.29-8A2BE2.svg)](https://modelcontextprotocol.io/)
20
20
  [![License](https://img.shields.io/badge/license-MIT-yellow.svg)](./LICENSE)
@@ -46,7 +46,7 @@ Your Obsidian vault becomes **persistent, queryable long-term memory** for any M
46
46
  > 2. **Best-in-class retrieval.** Hybrid BM25 + multilingual embeddings + BGE cross-encoder reranker fused via RRF, scaled with HNSW + int8 quantization. The same IR stack a search startup would build — open-sourced, in one binary.
47
47
  > 3. **Zero cloud calls during serve.** Models cached locally (one-time download from HuggingFace). Your vault content never leaves your machine. Air-gap-safe by default.
48
48
 
49
- **44 tools · 19 MCP prompts · 1039 unit tests · 50+ languages · v3.8.x stable · semver-bound · MIT · npm build provenance (SLSA L2).**
49
+ **44 tools · 19 MCP prompts · 1044 unit tests · 50+ languages · v3.9.x stable · semver-bound · MIT · npm build provenance (SLSA L2).**
50
50
 
51
51
  ---
52
52
 
@@ -184,7 +184,7 @@ Auto-generated **[API reference at oomkapwn.github.io/enquire-mcp](https://oomka
184
184
  | **GraphRAG-light** (wikilink community detection via Louvain modularity) | ✅ **only here** | ❌ | ❌ |
185
185
  | **Standalone `.base` query execution** (works without Obsidian running) | ✅ **only here** | ❌ | ❌ delegates to Obsidian |
186
186
  | **HyDE retrieval** (Gao et al 2023) + sub-question decomposition | ✅ **only here** | ❌ | ❌ |
187
- | **1039 unit tests · 9 required + 4 advisory CI gates per PR** | ✅ | n/a | rare |
187
+ | **1044 unit tests · 9 required + 4 advisory CI gates per PR** | ✅ | n/a | rare |
188
188
  | **Signed build provenance** (npm + Sigstore, SLSA Build L2) | ✅ | n/a | ❌ |
189
189
  | **Semver-bound public surface** ([STABILITY.md](./STABILITY.md)) | ✅ | n/a | ❌ |
190
190
  | Standalone (no Obsidian plugin needed) | ✅ | ❌ requires Obsidian | varies |
@@ -283,9 +283,9 @@ Full posture: **[SECURITY.md](./SECURITY.md)** · Stability surface: **[STABILIT
283
283
 
284
284
  **v3.0.0 — stable channel.** The v2.x retrieval roadmap is complete and the public surface is now [semver-bound](./STABILITY.md). Highlight reel:
285
285
 
286
- `v2.0` hybrid retrieval (BM25+TF-IDF+embeddings via RRF) · `v2.6` remote MCP · `v2.7-2.8` PDFs blended · `v2.9` BGE reranker · `v2.10` OCR · `v2.11` doctor + setup · `v2.12` eval harness · `v2.13` HNSW · `v2.14` stateful sessions · `v2.15` late-chunking · `v2.16` HNSW persistence · `v2.17` int8 quantization · `v3.8.0` stable · `v3.8.7` HTTP transport hardening · **`v3.9.0` (on `@rc`)**: OCR'd PDF watcher embed-sync, HNSW in-memory live update on file changes, R-10 adaptive HNSW refill (closes the >66% excluded under-return).
286
+ `v2.0` hybrid retrieval (BM25+TF-IDF+embeddings via RRF) · `v2.6` remote MCP · `v2.7-2.8` PDFs blended · `v2.9` BGE reranker · `v2.10` OCR · `v2.11` doctor + setup · `v2.12` eval harness · `v2.13` HNSW · `v2.14` stateful sessions · `v2.15` late-chunking · `v2.16` HNSW persistence · `v2.17` int8 quantization · `v3.8.0` stable · `v3.8.7` HTTP transport hardening · **`v3.9.0` stable**: OCR'd PDF watcher embed-sync, HNSW in-memory live update on file changes, R-10 adaptive HNSW refill (closes the >66% excluded under-return).
287
287
 
288
- Channel: `npm install @oomkapwn/enquire-mcp` → latest stable (`@latest` = v3.8.x). Pre-release: `npm install @oomkapwn/enquire-mcp@rc` (the latest release candidate — see [CHANGELOG.md](./CHANGELOG.md)). Full changelog: **[CHANGELOG.md](./CHANGELOG.md)** · Forward plan: **[ROADMAP.md](https://github.com/oomkapwn/enquire-mcp/blob/main/ROADMAP.md)**.
288
+ Channel: `npm install @oomkapwn/enquire-mcp` → latest stable (`@latest` = v3.9.x). Pre-release: `npm install @oomkapwn/enquire-mcp@rc` (the latest release candidate — see [CHANGELOG.md](./CHANGELOG.md)). Full changelog: **[CHANGELOG.md](./CHANGELOG.md)** · Forward plan: **[ROADMAP.md](https://github.com/oomkapwn/enquire-mcp/blob/main/ROADMAP.md)**.
289
289
 
290
290
  ---
291
291
 
@@ -294,7 +294,7 @@ Channel: `npm install @oomkapwn/enquire-mcp` → latest stable (`@latest` = v3.8
294
294
  ```bash
295
295
  git clone https://github.com/oomkapwn/enquire-mcp.git
296
296
  cd enquire-mcp && npm install
297
- npm test # full suite (1039 tests, ~12s)
297
+ npm test # full suite (1044 tests, ~12s)
298
298
  npm run lint # zero warnings
299
299
  npm run build # tsc → dist/
300
300
  ```
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * + `McpServer({version})`) and `src/tool-registry.ts` (used in the
8
8
  * `vault-info` resource payload).
9
9
  */
10
- export declare const VERSION = "3.9.0";
10
+ export declare const VERSION = "3.9.1";
11
11
  export { main } from "./cli.js";
12
12
  export { buildEmbedText, buildMcpServer, formatReadyBanner, prepareServerDeps, type ServeOptions, type ServerDeps, startServer } from "./server.js";
13
13
  export { parsePositiveInt, parseQuantizationMode } from "./tool-registry.js";
package/dist/index.js CHANGED
@@ -40,7 +40,7 @@ import { main } from "./cli.js";
40
40
  * + `McpServer({version})`) and `src/tool-registry.ts` (used in the
41
41
  * `vault-info` resource payload).
42
42
  */
43
- export const VERSION = "3.9.0";
43
+ export const VERSION = "3.9.1";
44
44
  // Re-exports — preserve the v3.5.x public surface so http-transport.ts and
45
45
  // tests don't need to know about the new module layout. The set below
46
46
  // exactly matches the v3.5.x `export` declarations: `main`,
@@ -43,7 +43,7 @@ The four axes the external audit (#3, 2026-05) called out as decisive — **REST
43
43
  | Read open editor state, active note, etc. | **No** | **Yes** | Limited | No | No |
44
44
  | Zero outbound network calls in serve mode | **Yes** (default) | Local-only (REST)| Local-only (REST)| Yes | Yes |
45
45
  | Signed build provenance on releases (SLSA L2) | **Yes** | No | No | No | No |
46
- | Test count (public) | **1039** | (varies) | (varies) | (varies) | (varies) |
46
+ | Test count (public) | **1044** | (varies) | (varies) | (varies) | (varies) |
47
47
  | Tool count | 44 | ~25 | ~8 | ~10 | 3–5 |
48
48
  | MCP prompt count | 19 | 0 | 0 | 0 | 0 |
49
49
  | License | MIT | Apache-2.0 | MIT | MIT | (varies) |
@@ -29,7 +29,7 @@ Verify the install:
29
29
  enquire-mcp --version
30
30
  ```
31
31
 
32
- Expected output: the current version string (e.g. `3.9.0-rc.N` on `@rc` or `3.8.8` on `@latest`).
32
+ Expected output: the current version string (e.g. `3.9.x` on `@latest`).
33
33
 
34
34
  ## Step 2 — Smoke test (30 seconds)
35
35
 
package/docs/api.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **enquire is the most advanced Obsidian MCP — a long-term memory layer for AI agents, built on your Obsidian vault.** Open-source, MCP-native, vendor-neutral persistence: agents (Claude Code / Claude Desktop / Cursor / ChatGPT / Codex / OpenClaw / any MCP client) get durable, queryable recall across sessions, models, and providers — your knowledge lives in plain markdown you own, not a vendor cloud. 44 MCP tools (33 always-on read + 4 opt-in read + 7 opt-in write); the 4 opt-ins are: 1 via `--persistent-index` + `--diagnostic-search-tools` (`obsidian_full_text_search` — needs BOTH flags: persistent-index for the FTS5 index, diagnostic-search-tools to surface it as a single-ranker tool alongside the hybrid default `obsidian_search`) + 3 via `--diagnostic-search-tools` (the single-ranker `obsidian_search_text` / `obsidian_semantic_search` / `obsidian_embeddings_search` — gated by default in v2.0+ since `obsidian_search` auto-detects + fuses signals). 2 + 1 opt-in MCP resources, 19 MCP prompts. **v3.1.0+ adds `obsidian_hyde_search`** (HyDE-augmented retrieval, Gao et al 2023; agent supplies a synthetic answer, server embeds it for retrieval) plus the `vault_research` (sub-question decomposition) and `vault_synthesis_page` (Karpathy LLM-Wiki synthesis loop) prompts. v2.6.0+ also speaks Streamable HTTP via `serve-http` (bearer auth + rate-limit + CORS). v2.7.0+ indexes PDFs as a separate read tool surface; **v2.8.0+ blends PDF chunks into `obsidian_search` hybrid retrieval** with `--include-pdfs` — every hit carries a `kind: "md" | "pdf"` flag and PDF snippets include `[page: N]` markers for citation. **v2.9.0+ adds BGE cross-encoder reranking** on top of RRF with `--enable-reranker` — measured +15.5 NDCG@10 / +24.7 MRR (60-query ablation). **v2.10.0+ adds Tesseract OCR for image-only / scanned PDFs** via `obsidian_ocr_pdf` — completes the PDF retrieval story.
4
4
 
5
- > **Channels:** stable since v3.8.x (`@latest` on npm) ships 44 tools including `obsidian_search` (hybrid BM25 + TF-IDF + ML embeddings, RRF-fused) with optional BGE cross-encoder reranking, `obsidian_embeddings_search`, `obsidian_hyde_search`, plus the `install-model` / `build-embeddings` / `clear-embeddings` / `setup` / `doctor` / `eval` subcommands. The `@rc` dist-tag carries the most recent release candidate (see [CHANGELOG.md](../CHANGELOG.md) for the current RC and its features — recent RCs add OCR'd PDF watcher embed-sync, HNSW in-memory live update, adaptive HNSW refill, OCR offline enforcement, and watcher concurrency hardening). Benchmarks live behind `npm run bench:retrieval` (not a CLI subcommand). This document covers the **stable v3.8.x** surface plus the in-flight v3.9.0 RCs — see [CHANGELOG.md](../CHANGELOG.md) for full release history.
5
+ > **Channels:** the `@latest` stable channel (v3.9.x on npm) ships 44 tools including `obsidian_search` (hybrid BM25 + TF-IDF + ML embeddings, RRF-fused) with optional BGE cross-encoder reranking, `obsidian_embeddings_search`, `obsidian_hyde_search`, plus the `install-model` / `build-embeddings` / `clear-embeddings` / `setup` / `doctor` / `eval` subcommands. The `@rc` dist-tag carries the most recent release candidate (see [CHANGELOG.md](../CHANGELOG.md) for the current RC and its features — recent RCs add OCR'd PDF watcher embed-sync, HNSW in-memory live update, adaptive HNSW refill, OCR offline enforcement, and watcher concurrency hardening). Benchmarks live behind `npm run bench:retrieval` (not a CLI subcommand). This document covers the **stable v3.9.x** surface — see [CHANGELOG.md](../CHANGELOG.md) for full release history.
6
6
 
7
7
  > Versioned dynamically — see [`CHANGELOG.md`](../CHANGELOG.md) for the current release.
8
8
 
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@oomkapwn/enquire-mcp",
4
- "version": "3.9.0",
4
+ "version": "3.9.1",
5
5
  "mcpName": "io.github.oomkapwn/enquire-mcp",
6
- "description": "MCP server giving AI agents (Claude Code, Claude Desktop, Cursor, ChatGPT, Codex, OpenClaw) persistent long-term memory backed by your local Obsidian markdown vault. Hybrid retrieval (BM25 + ML embeddings + BGE reranker, RRF-fused), HNSW + int8 quantization, agentic RAG (HyDE + sub-question decomposition), GraphRAG-light (Louvain), standalone Obsidian Bases, PDFs + Tesseract OCR. Vendor-neutral memory layer for any MCP-compatible agent. 44 tools, 19 MCP prompts, 1039 tests, signed npm build provenance (SLSA L2), semver-bound, MIT, zero cloud calls during serve.",
6
+ "description": "MCP server giving AI agents (Claude Code, Claude Desktop, Cursor, ChatGPT, Codex, OpenClaw) persistent long-term memory backed by your local Obsidian markdown vault. Hybrid retrieval (BM25 + ML embeddings + BGE reranker, RRF-fused), HNSW + int8 quantization, agentic RAG (HyDE + sub-question decomposition), GraphRAG-light (Louvain), standalone Obsidian Bases, PDFs + Tesseract OCR. Vendor-neutral memory layer for any MCP-compatible agent. 44 tools, 19 MCP prompts, 1044 tests, signed npm build provenance (SLSA L2), semver-bound, MIT, zero cloud calls during serve.",
7
7
  "type": "module",
8
8
  "bin": {
9
9
  "enquire-mcp": "dist/index.js"