@oomkapwn/enquire-mcp 3.11.0-rc.21 → 3.11.0-rc.22
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 +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
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.11.0-rc.22] — 2026-06-26
|
|
6
|
+
|
|
7
|
+
> **TL;DR:** **The rc.20 timing-RATIO hardening itself flaked — re-fixed durably to an absolute floor on the OLD (slow) time + ships the comparison-ready external-audit brief for the v3.11.0 → `@latest` promotion gate.** **(1) TEST-INFRA [release-blocker, recursion of rc.20].** rc.20 converted the 6 wall-clock timing tests' NEGATIVE controls to `quad / linear > 8` ("ratio, robust to runner speed"). But on a docs-only PR's `coverage` job the wikilink dense-`[[a]]` NEGATIVE flaked: `quad/linear = 7.50 < 8`. Root cause: the **`linear` denominator is a sub-millisecond op whose wall-clock is noise-dominated on a contended CI runner** (read ~43 ms there vs ~2.5 ms locally), compressing the ratio below the threshold — the rc.20 fix moved the flake from the POSITIVE budget to the ratio's noisy denominator. Re-fixed durably: the 3 NEGATIVE controls (`wikilink-scan` ×2 + `write` ×1) now assert an **absolute FLOOR on the OLD catastrophic time** (`expect(quad).toBeGreaterThan(50)`) and drop the `linear` baseline entirely. Calibrated empirically: the old functions are ~325 ms (dense `\n`-scan), ~430 ms (lazy-regex unclosed run), ~830 ms (O(n²) slice+concat) on a dev laptop; **a CI runner is only SLOWER, so a 50 ms floor can only fail if the runner ran the quadratic 6–16× FASTER than a laptop (impossible)** — and load pushes the quad's time UP, never below the floor. The POSITIVE budgets (rc.20's generous `< 2000 ms` ceilings) were already robust and are unchanged. **(2) DOCS — comprehensive comparison-ready external-audit brief** (`docs/audits/AUDIT-REQUEST-FULL-FROM-SCRATCH-v3.11.0-rc.21-2026-06-26.md`, targeting the `v3.11.0-rc.21` tag) for the promotion gate. Redesigned from the rc.17 brief after a 3-report Workflow analysis of what 4 LLM auditors did well/badly: **obligation-GATING** tables (the per-always-on-tool sink-trace + the prior-finding re-probe cap the score at 2/5 if unfilled — so a "ship/clean" verdict is expensive to claim), **named worst-case shapes** (dense-CLOSED `[[a]]` run, not an unclosed one — the wrong probe 3 auditors used to re-bless the wikilink quadratic), a **wrong-probe 3-point complexity-curve self-check**, **evidence-or-downgrade** (no self-reported effort scalars; empirical requires a pasted harness + ≥3-point timing + stderr-clean run), a **severity rubric anchored to the real rc.18→20 outcomes** + reachability-proof, an **anti-anchoring novel-class tier**, and a fix to the rc.17 brief's own `40 src/*.ts` count drift (it's 33 top-level / 40 recursive). **No `src/` behavior change** (only the `VERSION` constant); **1416 tests unchanged** (3 NEGATIVE-control assertions rewritten in place). **Lesson: a RATIO timing test is only robust if BOTH terms are above the measurement-noise floor — dividing by a sub-ms baseline reintroduces the very flake the ratio was meant to kill; the durable form for a "the old code is slow" NEGATIVE control is an absolute floor on the OLD (genuinely-slow) time, which load can only push further from failing.**
|
|
8
|
+
|
|
5
9
|
## [3.11.0-rc.21] — 2026-06-26
|
|
6
10
|
|
|
7
11
|
> **TL;DR:** **Post-rc.20 re-sweep — 3 confirmed SIBLINGS of the rc.18 fix classes (the session's signature "instance fixed, adjacent sibling missed" pattern), each 3/3 adversarial-skeptic-confirmed.** A focused 4-lens behavioral re-sweep of the shipped rc.18→rc.20 commit (`41dc699`) hunting recursions of the four fix classes found them in adjacent code the rc.18 sweep didn't reach. **Fixed:** **(1) MED — `obsidian_frontmatter_search` value predicates uncapped (input-cap class, rc.18 sibling).** rc.13 capped the `key` arg but left `equals`/`contains` as `z.unknown()` — and the handler `JSON.stringify`s the predicate and string-compares it against EVERY note's frontmatter across the whole vault, so a multi-MB value is a bearer-reachable O(notes × valueLen) CPU/event-loop amplifier (measured ~3.9 s for a 4 MB `contains` over a 2k-note vault). This is the exact class rc.18 closed for `obsidian_full_text_search`, in the VALUE dimension the inventory missed. Fixed at two layers: a `.refine()` length bound (`MAX_FRONTMATTER_VALUE_LEN` = 8 KiB) rejects an over-cap predicate at the schema boundary, AND the per-note `JSON.stringify(arg)` is hoisted OUT of the loop (it is loop-invariant). The `parser-input-cap-invariant` inventory + its detector were extended to recognize the `.refine()` cap form (the value is arbitrary JSON, so `.max()` doesn't apply) and now pin both `equals`/`contains`. **(2) LOW ×2 — fold-offset in the read/snippet path (`replaceLineOnce` class, rc.18 sibling).** `semanticSearch` (bearer-reachable via the always-on `obsidian_search` TF-IDF arm) and `searchText` (`--diagnostic-search-tools`-gated) both computed a snippet offset with `text.toLowerCase().indexOf(term)` and then sliced the ORIGINAL `text` at that offset — but `toLowerCase()` is NOT length-preserving (`İ` U+0130 → `i̇`, 1 unit → 2; final-sigma; …), so a length-expanding fold char before the match drifts the offset, mis-centring the snippet window and miscounting the line number. Both now route through a shared `foldWithMap` / `foldedIndexOf` (search.ts) that returns offsets into the ORIGINAL string; a `tests/fold-offset.test.ts` unit + behavioral test + an anti-pattern inventory guard (no `toLowerCase().indexOf` offset feeds `sliceSnippet`) pins both sites. **Re-sweep verdict:** the CRLF-drop class was independently confirmed CLEAN (no uncovered sibling — the rc.17/rc.19 inventory guard is complete); `filter_frontmatter`'s uncapped value was checked and is NOT the same DoS (it runs only on the bounded fused candidate pool, O(limit × len), not a whole-vault scan). **1410 → 1416 tests** (+6 fold-offset; the cap is structurally pinned via the input-cap inventory, the hoist is behavior-verified by the existing `frontmatter-ops` equals/contains tests). **Lesson: the post-merge re-sweep is non-negotiable — rc.18 closed the input-cap class for `full_text_search` and the fold-offset class for `replaceLineOnce`, but each had a live sibling one module over (`frontmatter_search` value predicates; the read-path snippet offsets); the durable close for the fold-offset class is the shared offset-safe helper, and for the input-cap class the inventory invariant generalized to the `.refine()` form.**
|
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.11.0-rc.
|
|
10
|
+
export declare const VERSION = "3.11.0-rc.22";
|
|
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.11.0-rc.
|
|
43
|
+
export const VERSION = "3.11.0-rc.22";
|
|
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`,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@oomkapwn/enquire-mcp",
|
|
4
|
-
"version": "3.11.0-rc.
|
|
4
|
+
"version": "3.11.0-rc.22",
|
|
5
5
|
"mcpName": "io.github.oomkapwn/enquire-mcp",
|
|
6
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. 46 tools, 19 MCP prompts, 1416 tests, signed npm build provenance (SLSA L2), semver-bound, MIT, zero cloud calls during serve.",
|
|
7
7
|
"type": "module",
|