Until this sprint, memory_search was a contiguous SQL LIKE. A question that shared no literal substring with the stored entity — a Russian paraphrase of an English ADR title, a reordered identifier — returned nothing. Assistants then opened files they did not need.
Sprint 21 keeps the keyword path as the fast default and adds a bundled, offline embedding fallback when LIKE is empty (ADR-0020).
Keyword first, meaning when it misses
Exact id / name / summary hits are unchanged. Only an empty keyword result runs cosine over that project's vectors. There is no Hugging Face fetch at runtime: intfloat/multilingual-e5-small (int8 ONNX, 384-d) is vendored next to the process, one model per process, one memory.db per project. Unchanged entities are not re-embedded.
The number this sprint claimed to move, on a fixed bilingual suite with zero substring overlap:
| Path | Recall |
|---|---|
Keyword LIKE
|
0 |
| Bundled e5 fallback | 1.0 |
Ranking that matches meaning, not heat
On a live ~170-entity graph, e5 compresses almost every row into cosine 0.76–0.82. Adding vitality (up to +9) on top of that range returned the hottest components — the project node at strength 423 — instead of Sprint 21. Semantic fallback now ranks cosine first, keeps neighbours within 0.02 of the best hit, and uses vitality only as a tie-break.
Routine chore / ci / lockfile commits stay on the keyword path. feat / fix / ADR-touching commits remain eligible, with a small cosine penalty so a sprint or ADR of similar meaning wins the near-tie. ADR entities now carry a Context (else Decision) paragraph, so the embed-string is no longer title-only.
Dogfood query «найти знания когда точное совпадение строки ничего не даёт»: Sprint 21 first, sprint tasks next, important fix(scanner) commits still present, version bumps gone.
Licence and packaging
Meronq is Apache-2.0. The bundled model is MIT (intfloat); transformers.js is Apache-2.0. End users do not download e5 from Hugging Face. Developers clone once and run pnpm --filter @meronq/embeddings vendor-model. If weights are missing, search degrades to keywords without failing the session.
Desktop copies the model into installer resources. @huggingface/transformers stays external to the sidecar — a packaged build that cannot resolve the WASM module remains keyword-only. MCP and pnpm dev use the local vendored weights. That installer gap is the next sprint.
Principle
Keep the exact match when it exists. When it does not, look up meaning locally — and do not let heat or a version bump outrank the decision.
Read the full post on meronq.pages.dev · Source on GitHub
Top comments (0)