@oomkapwn/enquire-mcp 3.8.7 → 3.8.8

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,79 @@
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.8.8] — 2026-05-25
6
+
7
+ > **TL;DR:** **META structural-defense scope completeness audit — closes the recurring "recursion-pair shape" class (6 documented instances since v3.6.x).** New `scripts/scope-completeness-audit.mjs` enumerates every numeric-claim defense's scope (which files it covers + which it exempts) and sweeps the entire repo for matching patterns; any file containing a tracked pattern that's NOT in the defense's scope or exempts list fails CI. Wired into both `tests/scope-completeness-invariant.test.ts` (change-driven gate) and `scripts/oia-walk.mjs` Check 8 (state-driven sweep). Discovered + fixed one immediate gap: STABILITY.md "44 tools" reference was already covered by `docs-consistency.test.ts` line 183 but missing from the audit manifest. **+5 tests (3 POSITIVE + 2 NEGATIVE controls); 893 unit tests total.**
8
+
9
+ **Patch — META structural-defense.**
10
+
11
+ ### The problem this closes
12
+
13
+ Every external auditor since v3.6.0 has found stale fragments that internal class-sweeps missed: README badges, file headers, CLAUDE.md titles, inline comments, doc fragments. After 6 documented "recursion-pair" instances we now know the root cause:
14
+
15
+ > When we add a structural defense (test invariant, OIA check, gate), the defense has a SCOPE — a set of files + claim patterns it covers. Defenses we add to close one finding almost always turn out to be NARROWER than the actual problem class. The next bug then shows the narrowness.
16
+
17
+ Examples:
18
+ - **rp-1 (v3.7.14 F1+F2)**: F1 closed overclaim #6 in `renameNote`; F2 in the same PR shipped overclaim #7 in `renameFile` (TSDoc still said "Atomic via fs.rename" after impl changed to `link()+unlink()`).
19
+ - **rp-2 (rc.14 → rc.15)**: rc.14 added 7 docs-consistency invariants for llms.txt + AGENTS.md — rc.15 found they lacked NEGATIVE controls (META violation; M-3).
20
+ - **rp-3 (rc.15 → rc.16)**: M-3 fixed the missing NEGATIVE controls per-instance — rc.16 added the META-invariant that structurally enforces NEGATIVE control coverage on EVERY invariant test going forward.
21
+ - **rp-4 (v3.8.3 → v3.8.4)**: v3.8.3 added OIA Check 7 for currency claims in `docs/+CLAUDE.md` only — v3.8.4 found the same drift in `README.md+AGENTS.md+examples/` (out of Check 7's scope).
22
+ - **rp-5 (v3.8.4 itself)**: Check 7 scope expansion claim was narrow ("closes the recursion") when it only expanded ONE defense's scope, not the meta-class.
23
+ - **rp-6 (the "every claim of closes the recursion is wrong" recursion)**: each time we say "closed the recursion" we trigger another instance.
24
+
25
+ This patch is the META fix: instead of expanding individual defenses reactively, we now have a single audit that proves SCOPE-COMPLETENESS across the entire defense set.
26
+
27
+ ### What the audit does
28
+
29
+ `scripts/scope-completeness-audit.mjs` exports a `DEFENSES` array. Each entry:
30
+ - `id`: stable short name (e.g. `test-count`, `tool-count`)
31
+ - `pattern`: regex applied per-line; matching → a "claim instance"
32
+ - `scope`: file paths the defense IS responsible for (e.g. README, llms.txt). Files in scope are gated by the matching `docs-consistency.test.ts` invariant — those are out of this audit's concern.
33
+ - `exempts`: file paths where the pattern naturally appears in historical-narrative context (CHANGELOG, CLAUDE.md status entries, docs/audits/*). These are skipped.
34
+ - `rationale`: human-readable explanation of WHY this defense exists + which previous overclaim or drift triggered it.
35
+
36
+ The audit scans every user-visible doc + manifest file (.md, .txt, .json, .cff — 20 files total). For each defense × file: if the pattern matches AND the file is NOT in scope AND NOT in exempts → that's a gap. Each gap reports the file:line, evidence, rationale, and explicit fix instructions ("either add to scope and extend docs-consistency, OR add to exempts with reasoning").
37
+
38
+ ### Initial defense set (5 patterns)
39
+
40
+ - **test-count** (`\d{3,4} (unit )?tests`) — covered files: README, llms.txt, AGENTS.md, COMPARISON.md, package.json
41
+ - **tool-count** (`\d{2} tools`) — covered files: README, llms.txt, AGENTS.md, COMPARISON.md, api.md, package.json, STABILITY.md
42
+ - **prompt-count** (`\d{2} (MCP )?prompts`) — covered files: README, llms.txt, AGENTS.md, COMPARISON.md, api.md, package.json
43
+ - **ci-gate-count** (`\d+ required (\+ \d+ advisory )?(CI )?gates`) — covered files: README, llms.txt, AGENTS.md
44
+ - **per-file-floor-count** (`\d{1,2} per-file (branch )?floors?`) — covered files: llms.txt, AGENTS.md
45
+
46
+ Extending the audit is mechanical: add a new entry to `DEFENSES` with the regex, scope, exempts, and rationale. The audit picks it up automatically.
47
+
48
+ ### Integration points
49
+
50
+ - **`tests/scope-completeness-invariant.test.ts`** (5 tests: 3 POSITIVE + 2 NEGATIVE controls):
51
+ - Live invariant: current repo has 0 gaps
52
+ - Manifest integrity: every DEFENSES entry has all required fields
53
+ - Manifest integrity: defense ids are unique
54
+ - NEGATIVE control: synthetic gap is detected by the classifier (proves audit isn't a no-op)
55
+ - NEGATIVE control: exempt mechanism actually suppresses gaps
56
+ - Tagged with `META-INVARIANT-EXEMPT` marker (this file IS the META-invariant for the audit; its NEGATIVE controls are in-file)
57
+ - **`scripts/oia-walk.mjs` Check 8**: thin wrapper that imports `runAudit()` and converts gaps into OIA findings. Same gap surfaced by both the test (change-driven) AND OIA (state-driven) — defense in depth.
58
+
59
+ ### Immediate gap closed during audit construction
60
+
61
+ `STABILITY.md` line 11 ("### MCP tool names (44 tools)") + line 13 ("44 tools total = …") were already covered by `docs-consistency.test.ts` line 183 — but missing from the audit's `tool-count` scope. Added during audit bootstrap; the first audit run flagged the gap; manifest updated; second run clean.
62
+
63
+ ### Files changed
64
+
65
+ - `scripts/scope-completeness-audit.mjs` — new file (~200 lines)
66
+ - `tests/scope-completeness-invariant.test.ts` — new file (5 tests, ~140 lines)
67
+ - `scripts/oia-walk.mjs` — Check 8 added (+22 lines)
68
+ - `README.md`, `llms.txt`, `AGENTS.md`, `docs/COMPARISON.md`, `package.json` — test-count claims 888 → 893
69
+ - version bump 3.8.7 → 3.8.8 (7 surfaces)
70
+
71
+ ### What's next
72
+
73
+ Continuing the no-deferrals run:
74
+ - **v3.9.0-rc.1** — OCR'd PDF watcher embed-sync + HNSW in-memory live update (architectural minor bump). These were the last items deferred from the v3.8.0 backlog.
75
+
76
+ ---
77
+
5
78
  ## [3.8.7] — 2026-05-25
6
79
 
7
80
  > **TL;DR:** **HTTP transport hardening — P2-10 stateful session races (3 conditions) + P2-11 close cleanup gap (registry leak).** `src/http-transport.ts` now uses an in-flight refcount on each `StatefulSession` so the idle sweep skips busy sessions instead of force-closing them mid-stream; the max-sessions cap-check includes a `pendingInits` counter so concurrent initialize POSTs can't TOCTOU past the limit; DELETE marks `closing=true` and removes from the registry BEFORE the protocol-level shutdown runs (concurrent fetchers 404 instead of joining a half-closed session). New `shutdownHttpServer(server)` helper drains the registry + closes the TCP listener + closes vault/fts/watcher/embed-db handles — the production signal handlers + tests both use it now. **+10 negative-control tests; 888 unit tests; no API breaks.**
package/README.md CHANGED
@@ -13,7 +13,7 @@
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-888%20passing-brightgreen.svg)](#trust)
16
+ [![tests](https://img.shields.io/badge/tests-893%20passing-brightgreen.svg)](#trust)
17
17
  [![stable](https://img.shields.io/badge/v3.8.x-stable-brightgreen.svg)](./STABILITY.md)
18
18
  [![SLSA-3](https://img.shields.io/badge/SLSA-3-blue.svg)](https://slsa.dev/spec/v1.0/levels#build-l3)
19
19
  [![MCP](https://img.shields.io/badge/MCP-1.29-8A2BE2.svg)](https://modelcontextprotocol.io/)
@@ -38,7 +38,7 @@ Your Obsidian vault becomes **persistent, queryable long-term memory** for any M
38
38
  > 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.
39
39
  > 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.
40
40
 
41
- **44 tools · 19 MCP prompts · 888 unit tests · 50+ languages · v3.8.x stable · semver-bound · MIT · SLSA-3 signed.**
41
+ **44 tools · 19 MCP prompts · 893 unit tests · 50+ languages · v3.8.x stable · semver-bound · MIT · SLSA-3 signed.**
42
42
 
43
43
  ---
44
44
 
@@ -176,7 +176,7 @@ Auto-generated **[API reference at oomkapwn.github.io/enquire-mcp](https://oomka
176
176
  | **GraphRAG-light** (wikilink community detection via Louvain modularity) | ✅ **only here** | ❌ | ❌ |
177
177
  | **Standalone `.base` query execution** (works without Obsidian running) | ✅ **only here** | ❌ | ❌ delegates to Obsidian |
178
178
  | **HyDE retrieval** (Gao et al 2023) + sub-question decomposition | ✅ **only here** | ❌ | ❌ |
179
- | **888 unit tests · 9 required + 4 advisory CI gates per PR** | ✅ | n/a | rare |
179
+ | **893 unit tests · 9 required + 4 advisory CI gates per PR** | ✅ | n/a | rare |
180
180
  | **SLSA-3 build provenance** | ✅ | n/a | ❌ |
181
181
  | **Semver-bound public surface** ([STABILITY.md](./STABILITY.md)) | ✅ | n/a | ❌ |
182
182
  | Standalone (no Obsidian plugin needed) | ✅ | ❌ requires Obsidian | varies |
@@ -286,7 +286,7 @@ Channel: `npm install @oomkapwn/enquire-mcp` → latest stable. Full changelog:
286
286
  ```bash
287
287
  git clone https://github.com/oomkapwn/enquire-mcp.git
288
288
  cd enquire-mcp && npm install
289
- npm test # full suite (888 tests, ~5s)
289
+ npm test # full suite (893 tests, ~5s)
290
290
  npm run lint # zero warnings
291
291
  npm run build # tsc → dist/
292
292
  ```
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.8.7";
10
+ export declare const VERSION = "3.8.8";
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.8.7";
43
+ export const VERSION = "3.8.8";
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
  | SLSA-3 build provenance on releases | **Yes** | No | No | No | No |
46
- | Test count (public) | **888** | (varies) | (varies) | (varies) | (varies) |
46
+ | Test count (public) | **893** | (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) |
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.8.7",
4
+ "version": "3.8.8",
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, 888 tests, SLSA-3, 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, 893 tests, SLSA-3, semver-bound, MIT, zero cloud calls during serve.",
7
7
  "type": "module",
8
8
  "bin": {
9
9
  "enquire-mcp": "dist/index.js"