v0.8.4
The dense+sparse hybrid retrieval arm — and the correction of an earlier wrong "infeasible" call.
Added
- Hybrid dense+sparse retrieval (BM25 full-text + 3-way RRF). A lexical/sparse arm now joins the dense vector arm and the keyword/tag arm in the injection pipeline.
schema.surqldefines afts_analyzer(blank/class/camel/punct tokenizers + snowball English stemming) and FULLTEXT BM25 indexes onconcept.content,turn.text,memory.text,artifact.description,skill.description.SurrealStore.fulltextSearch()runs a per-term@n@OR query (recall) ranked by summedsearch::score, unioned into the candidate pool and folded into the graph-seed Reciprocal Rank Fusion. This adds recall of exact-term / rare-token / code-identifier rows the dense embedding misses entirely. (BGE-M3's sparse heads aren't reachable via node-llama-cpp, so the sparse arm is SurrealDB-native BM25 — no model sparse head needed.) - Offline retrieval benchmark (
scripts/retrieval-benchmark.mjs) — NDCG/MRR/Recall over the labeledretrieval_outcometable, to gate ranker changes with a number instead of a guess. scripts/drop-test-namespaces.sh— durable cleanup for the vitest temp namespaces (kctest_*) that accumulate on the local SurrealDB instance.
Changed
- Managed SurrealDB binary pinned 3.0.5 → 3.1.4 (
bin-manifest.json) — aligns fresh installs with the version everything is tested against. Deliberately not 3.1.5: issue #7383 is a 3.1.5-specific RocksDB OOM under full-text load that would regress the new hybrid. All 5 per-platform sha256 from the GitHub release digests; linux-x64 download-verified.
Notes
- SurrealDB 3.x full-text BM25 uses
FULLTEXT ANALYZER(renamed from 2.xSEARCH ANALYZERin 3.0.0-beta).search::scorereturns 0 on a near-empty index (#7290 fresh-DB corpus-stats edge) but is correct at real scale —fulltextSearch()falls back to a term-frequency rank for the empty-index case.skillindexesdescription, notbody(full skill bodies are large enough to stall the FULLTEXT build / schema-apply).