VelesQL Ecosystem Parity Matrix
August 19, 2026 · View on GitHub
Last updated: 2026-08-19 (v5.1.0; velesdb-memory 0.14.0)
This matrix tracks runtime contract and feature parity across the VelesDB ecosystem.
Contract Baseline
- Canonical REST contract:
docs/reference/VELESQL_CONTRACT.md - Canonical conformance fixture:
conformance/velesql_contract_cases.json - Contract version:
3.0.0
Endpoint and Payload Parity
| Surface | /query | /aggregate | /collections/{name}/match | Error model (code/message/hint/details) | Contract meta |
|---|---|---|---|---|---|
velesdb-server | yes | yes | yes | yes | yes (meta.velesql_contract_version) |
| TypeScript SDK (REST backend) | yes | yes (auto-routed for aggregate queries) | indirect | yes (nested error parsing) | yes |
| WASM SDK | no (/query unsupported by design) | no | no | n/a | n/a |
CLI (velesdb-cli) | yes via server/core path | yes via server/core path | indirect | partial passthrough | partial assertion |
Python bindings (velesdb-python) | core path (non-REST) | core path (non-REST) | core path (non-REST) | n/a REST | n/a REST |
| LangChain integration | via Python binding | via Python binding | via Python binding | n/a REST | n/a REST |
| LlamaIndex integration | via Python binding | via Python binding | via Python binding | n/a REST | n/a REST |
| Haystack integration | via Python binding | via Python binding | via Python binding | n/a REST | n/a REST |
Feature Parity Matrix (86 features, 11 components)
Legend: ✅ full support | ⚠️ partial / limited | ❌ not supported | N/A not applicable
| Feature Group | Core | Server | Python | WASM | Mobile | CLI | TS SDK | Tauri | LangChain | LlamaIndex | Haystack |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Vector CRUD (insert, upsert, delete, get) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Batch Operations (batch_insert, batch_upsert) | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Streaming Ingestion (enableStreaming / stream_insert) | ✅ | ✅ | ✅ | ❌ | ✅ | ⚠️ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| Vector Search (k-NN, filtered, batch) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Multi-Query Fusion (RRF) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Multi-Query Fusion (RSF / Weighted) | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Hybrid Search (dense+sparse, dense+text) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Text Search BM25 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Sparse Vector Search (sparse index) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Sparse Vector Search (named indexes) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
| Graph Operations (nodes, edges, traversal) | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
Cross-Collection MATCH (@collection) | ✅ | ✅ | ⚠️ | ❌ | ❌ | ✅ | ⚠️ | ❌ | ❌ | ❌ | ❌ |
| VelesQL (parser + executor) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| Collection Types (Vector) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Collection Types (Graph) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
| Collection Types (Metadata) | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| Property Indexes (secondary, trigram) | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Quantization (SQ8 / Binary / PQ) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Quantization (RaBitQ) | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| Agent Memory (semantic, episodic, procedural) | ✅ | ⚠️ | ✅ | ⚠️ | ⚠️ | N/A | ✅ | ✅ | ⚠️ | ⚠️ | N/A |
| Persistence (WAL / mmap) | ✅ | ✅ | ✅ | ❌ | ✅ | N/A | N/A | N/A | N/A | N/A | N/A |
| GPU Acceleration (wgpu) | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Notes
-
Cross-Collection MATCH: Core and Server support
@collectionannotation on MATCH node patterns. Python bindings support via_collectionparam. CLI supports via\use. Mobile reaches it throughexecute_query(full VelesQL pass-through,crates/velesdb-mobile/src/lib.rs:342). WASM, Tauri, and integrations do not yet expose this feature. -
Batch Operations: WASM and Mobile use streaming chunked inserts instead of single-call bulk to stay within memory constraints. WASM additionally exposes a single-call raw-bulk path via
VectorStore.insertBatchRaw(see the Raw-Bulk Insert note). -
Streaming Ingestion (2026-07-23): Core, Server (
POST /collections/{name}/stream/enable+/stream/insert), Python, Tauri, Mobile (enableStreaming()/streamInsert()on its own tokio streaming runtime), and the TS SDK (enableStreaming()/streamInsert(), REST backend) support the bounded ingestion channel. The CLI reaches it ⚠️ via the embedded core path with no dedicated REPL command. WASM throwsNOT_SUPPORTED(no persistence layer). LangChain and LlamaIndex expose ⚠️ streaming viastream_insert()/add_texts_streaming()/add_streaming(), which forward tocollection.stream_insert(caller is responsible forenable_streaming; covered by mock-collection unit tests). Haystack now exposes the same ⚠️ shape viaVelesDBDocumentStore.stream_insert()/write_documents_streaming()(issue #1548), forwarding tocollection.stream_insertwith the same caller-managedenable_streamingcontract. -
Raw-Bulk Insert (2026-06-14): the zero-copy raw-bulk path is now exposed by Core (
upsert_bulk_from_raw), Server (POST /collections/{name}/points/raw, VRB1 binary), the TS SDK (upsertBatchRaw), WASM (VectorStore.insertBatchRaw(ids, vectors, dim), writing into its in-memory buffer), and the CLI (velesdb data import <file.bin>, VRB1 binary). Mobile remains a follow-up. All surfaces share the onevelesdb_core::wire::vrb1codec. -
Multi-Query Fusion (RSF/Weighted) (2026-06-14): WASM's multi-query
fuse_resultsnow delegates 4 of its 5 strategies (average,maximum,weighted,rrf) to the canonicalvelesdb_core::FusionStrategy::fuse, so the browser engine reproduces core's ranking 1:1 for those (crates/velesdb-wasm/src/fusion.rs; equivalence pinned bytest_fuse_results_matches_core_ordering). The fifth strategy,relative_score/rsf, is intentionally kept WASM-local: core'sRelativeScoreis a two-branch (dense + sparse) weighted sum that zero-fills documents missing from a branch and discards branches beyond index 1, whereas WASM's is an N-branch equal-weight average that skips missing branches. The two semantics yield different rankings, so converging WASM onto core would silently change WASM search results — that convergence is a product decision deferred to a follow-up, andrelative_scorebehaviour is unchanged. (This is the multi-query fusion entry point; the VelesQLUSING FUSION (...)clause executor invelesql_fusion.rsalready builds every strategy — including RSF — directly fromvelesdb_core::fusion::FusionStrategy.) LangChain and LlamaIndex expose RSF/Weighted throughmulti_query_search(fusion=...), which delegates to the sharedvelesdb_common.fusion.build_fusion_strategy(buildsweighted()andrelative_score()). Haystack reaches RSF/Weighted/RRF/etc. fusion via its ownVelesDBDocumentStore.embedding_retrieval(fusion=..., fusion_params=...), which delegates tovelesdb_common.fusion.build_fusion_strategyandCollection.multi_query_search. -
Sparse Vector Search (named indexes) — LangChain/LlamaIndex: ⚠️ query-side only. Both integrations forward a
sparse_index_nameargument to the underlyingcollection.search/hybrid_search, so an existing named sparse index can be queried. Named sparse indexes are also created on the upsert/write path: passing a named mapping such as{"bge_m3": {0: 1.5}}toadd_texts/add/add_bulk(LC/LI) orwrite_documents(Haystack) creates the named index, validated byvelesdb_common.security.validate_named_sparse_vector. -
LangGraph integration (2026-07-23, updated #1546):
integrations/langgraphships ten memory tools viamake_memory_tools—remember(withlinks/metadata/ttl_seconds),recall,recall_where,recall_fused(incl.date_field=dated timelines),relate,forget,feedback,why, andsave_working_context/load_working_context. That is not the whole wedge:entity,unrelate, and the context-compiler tools are not exposed (see the memory-surface gap block below). It is deliberately narrow — no vector-store surface — and is not yet a column in the matrices above. Remaining gap:list_working_contextsis not exposed by the LangGraph toolkit, though thevelesdbPython binding (MemoryService.list_working_contexts) does have it since 0.11.x —load_working_context'sother_sessionsnow covers the typo-recovery case the listing was mainly wanted for. The package'svelesdb>=3.12.0floor is deliberately kept there pending the 5.0.0 release that carries theload_working_contextenvelope (CHANGELOG [Unreleased]) — latervelesdbreleases exist on PyPI, but floors move with the 5.0.0 release train;feedback,save_working_context,load_working_context, and the_veles_dateauto-stamp below landed in source after the 3.12.0 cut and need that release to work (see the integration's README "Compatibility" section). -
Auto
_veles_datestamp (introduced in velesdb-memory 0.11.0): everyremembernow auto-stamps a reserved_veles_datemetadata field (YYYYMMDD, caller-set value never overwritten), makingrecall_fused(date_field=…)work with zero setup. Surfaced by delegation in Python (tests/test_memory_service.pyasserts the stamp) and Node (recallFusedDated). WASM is read-side only: no clock exists onwasm32-unknown-unknown, so the WASM write path never stamps_veles_date(MemoryService::remember_with_ttl's contract) —recallFusedDatedexists there, but zero-setup dating does not; a caller must set_veles_dateexplicitly for the timeline to fill. The TS SDK (which wraps WASM) types and documents the_veles_datekey (sdks/typescript/src/memory.ts,MemoryMetadata._veles_date) and shipsrecallFusedDated, under the same explicit-stamp caveat. LangGraph now exposesrecall_where/recall_fused(date_field=…)to reach it too (see above), pending avelesdbrelease past 3.12.0. -
load_working_contextreturns an ENVELOPE on every surface (velesdb-memory 0.12.0):{found, working, other_sessions}— the MCP tool, the Node, Python and WASM bindings, and the TS SDK. Breaking for the three bindings and the SDK, which until 0.12.0 returned the bare working context (ornull/None): read.workingfor that value. The bare form could not express the difference between "nothing was ever saved" and "a typo insessionmissed a session that exists" —other_sessionsnames the near-misses, and is filled in on a hit too, since a typo landing on another REAL session is the case a caller can least detect. Shape parity is now enforced, not just method-name parity:crates/velesdb-memory/tests/binding_parity_bdd.rsreads each tool'soutput_schemaroot keys off the LIVE server and requires every binding to relay them or declare the divergence. Three pre-existing divergences it surfaced were declared there as known gaps (six entries, since two of them spanned more than one binding): all three bindings droppedentity.relations_in(added server-side by #1681), the Node binding'sCompiledContextJsdroppedcompile_context.warnings, and both the Node and Python bindings droppedremember_extracted.skipped_over_cap. All six are closed (#1690, #1691, #1692);SHAPE_DIVERGENCESnow holds deliberate unwraps only. -
The TypeScript SDK is inside a guard's perimeter (#1721): it had never been in one, and shipped 17 of the 19 methods the WASM binding exposed for its whole life —
entityandunrelatewere simply absent. It is checked as a SECOND LINK rather than as a fourth binding: the SDK wraps the WASM bundle and can never publish more than it does, so the invariant is "the SDK relays every tool that reaches WASM", composed with the existing "WASM relays every tool the server advertises". Framing it as a fourth binding would have duplicated WASM'sfeedbackexemption into a second list — and a decision recorded twice is a decision that will drift. The reader is a small TypeScript-aware scan in the same file, because the tool list comes from a REAL running MCP server; a check living in the SDK's own test suite would have had to hard-code that list, which is the very defect #1721 reports. -
Graph Operations (WASM): Basic node/edge CRUD is supported; multi-hop traversal and MATCH queries are limited.
-
VelesQL (LangChain/LlamaIndex/Haystack): Pass-through to Python bindings works for simple queries; full parser integration is not surfaced in the integration API.
-
Haystack DocumentStore protocol limits: The Haystack 2.x
DocumentStoreABC exposeswrite_documents,filter_documents,embedding_retrieval,count_documents, anddelete_documents. Dense retrieval in pipelines ships as the dedicatedVelesDBEmbeddingRetrievercomponent (integrations/haystack/src/haystack_velesdb/retriever.py); BM25/hybrid retriever components remain a follow-up. Graph collections, agent memory, and sparse-named indexes are intentionallyN/Abecause they have no idiomatic mapping in Haystack's protocol and are reachable through the rawvelesdbPython wrapper if needed. -
Collection Types (Metadata): WASM and integration SDKs expose metadata collections with reduced column-type support.
-
Property Indexes (WASM): Disabled by design — no persistence layer means indexes cannot survive page reloads.
-
Quantization (RaBitQ): Experimental across all surfaces; API is unstable.
-
Agent Memory (Server): ⚠️ — durable point TTL is exposed over REST (
PATCH /collections/{name}/points/{id}/ttl, persisted as_veles_expires_atand enforced on every read surface — search/get/scroll/ query/MATCH), and relation edges are managed viaPOST /collections/{name}/relations,DELETE .../relations/{edge_id}, andGET .../points/{id}/relations. Still embedded-only: temporal/confidence-only queries, reinforcement, and snapshots. Per-binding parity for the relation + durable-TTL surface:Operation REST TS SDK (REST backend) TS SDK (WASM backend) Python relate()(create edge)✅ POST .../relations✅ client.relate()❌ ( wasmRelatethrowsNOT_SUPPORTED— REST backend only)❌ (use GraphCollection.add_edgeor the core API)unrelate()(delete edge)✅ DELETE .../relations/{edge_id}✅ client.unrelate()❌ (throws NOT_SUPPORTED)❌ getRelations()(list outgoing)✅ GET .../points/{id}/relations✅ client.getRelations()❌ (throws NOT_SUPPORTED)❌ Durable TTL set/refresh ✅ PATCH .../points/{id}/ttl✅ client.setTtlDurable()❌ (throws NOT_SUPPORTED)✅ set_semantic/episodic/procedural_ttl_durable,store_with_ttl,record_with_ttl,learn_with_ttlTemporal recall facades n/a (use /query)✅ recallRecent/recallOlderThan❌ (throws NOT_SUPPORTED)✅ episodic.recent/episodic.older_than -
Agent Memory (WASM / Mobile): WASM now ships the high-level
MemoryServicewedge (remember — incl. per-factttlSeconds— /recall/recallWhere/recallFused/relate/unrelate/forget/entity/why/rememberExtracted; in-memory only, no persistence under WASM, #1310) alongside the primitiveSemanticMemory.rememberExtractedon WASM (and on the TS SDK wrapping it) runs the deterministic, network-freeoutlineextractor ONLY — a generative backend ("ollama") is refused by name rather than silently substituted, because it would put a network call in the bundle (crates/velesdb-wasm/src/memory_service.rs,sdks/typescript/src/memory.tsrememberExtracted).feedbackremains deliberately absent on WASM (it sits behind thepersistencefeature; a durable learned confidence is meaningless for a store that disappears on page reload). Mobile remains ⚠️ semantic-only (VelesSemanticMemory). Episodic/procedural memory, the standalone TTL setters (setTtlDurable-style), and snapshots are not exposed on these bindings. -
Auto-extraction (text → graph): lives in the high-level
velesdb-memoryMCP server, not in this core-feature matrix.MemoryService::remember_extracted(and theremember_extractedMCP tool) run anExtractorover raw text and auto-wire the fact↔topic graph; MCP accepts the backend per call, with the daemon's configured backend as the default andoutlinealways available. The reusable core primitive it builds on isSemanticMemory::query_excluding(negative-filter vector search, used to keep internal entity hubs out of recall/why). The MCPrecall/whytools inherit hub-exclusion transparently. The high-levelMemoryServicewedge (remember/recall/recall_where/relate/forget/why/remember_extracted) is now exposed beyond the MCP server in Python (velesdb-python, #1242), Node.js (velesdb-node/ npm@wiscale/velesdb-memory-node, #1245), and the TS/WASM SDK (MemoryServiceover the in-browser backend, #1310 —rememberExtractedincluded there via the deterministicoutlineextractor only; a generative backend is refused, see the Agent Memory (WASM / Mobile) note). -
Persistence (WASM): Disabled by design —
persistencefeature flag is excluded forwasm32-unknown-unknowntargets. -
GPU: Requires
gpufeature flag; only available in crates that linkwgpu(core, server, Python bindings).
Feature Execution Parity (Core Runtime)
| Feature | Parser | Executor | Status |
|---|---|---|---|
SELECT ... FROM ... WHERE ... | yes | yes | stable |
MATCH (...) RETURN ... | yes | yes | stable |
MATCH via /query with collection | yes | yes | stable |
JOIN ... ON | yes | yes | stable |
JOIN ... USING (...) | yes | yes (single-column) | stable |
LEFT/RIGHT/FULL JOIN | yes | yes | stable |
GROUP BY, HAVING | yes | yes | stable |
UNION/INTERSECT/EXCEPT | yes | yes | stable |
Conformance Test Coverage
| Surface | Fixture | Test |
|---|---|---|
| Server REST contract | conformance/velesql_contract_cases.json | crates/velesdb-server/tests/velesql_conformance_tests.rs |
| TypeScript SDK contract mapping | conformance/velesql_contract_cases.json | sdks/typescript/tests/velesql-contract-fixtures.test.ts |
| Core executor (rows/counts/ordering) | conformance/velesql_executor_cases.json | crates/velesdb-core/tests/velesql_executor_conformance.rs |
| CLI executor (rows/counts/ordering) | conformance/velesql_executor_cases.json | crates/velesdb-cli/tests/velesql_executor_conformance.rs |
| WASM executor (rows/counts/ordering) | conformance/velesql_executor_cases.json | crates/velesdb-wasm/src/velesql_executor_conformance_tests.rs |
| Core parser | conformance/velesql_parser_cases.json | crates/velesdb-core/tests/velesql_parser_conformance.rs |
| CLI parser | conformance/velesql_parser_cases.json | crates/velesdb-cli/tests/velesql_parser_conformance.rs |
| WASM parser | conformance/velesql_parser_cases.json | crates/velesdb-wasm/tests/velesql_parser_conformance.rs |
The executor fixture (added 2026-06-14, extended 2026-06-20) asserts the exact
result set (ids, count, ordering) each executor produces for a fixed dataset. As
of 2026-06-20 the WASM and CLI executors are fixture-checked against the same
goldens too — the CLI drives the real binary end-to-end and WASM runs its own
SELECT/ORDER BY pipeline — so a result-shape divergence on those surfaces fails
CI rather than going unnoticed. Coverage includes scalar WHERE filters, single-
and multi-column ORDER BY, the ascending-id tie-break, and bounded top-k
(ORDER BY ... LIMIT k); see
KNOWN_LIMITATIONS #13
(resolved).
Enum Propagation Matrix
Tracks whether core enums are fully propagated to each ecosystem component.
Legend: ✅ full (all variants) | N/A not applicable (brute-force only, no HNSW)
DistanceMetric — 10/10 (100%)
All 5 variants (Cosine, Euclidean, DotProduct, Hamming, Jaccard) are supported in all 10 components (Haystack inherits via the Python binding pass-through).
| Component | Status |
|---|---|
| Core | ✅ (source of truth) |
| Server | ✅ |
| Python | ✅ |
| WASM | ✅ |
| Mobile | ✅ |
| CLI | ✅ |
| TS SDK | ✅ |
| Tauri | ✅ |
| LangChain | ✅ |
| LlamaIndex | ✅ |
| Haystack | ✅ |
StorageMode — 10/10 (100%)
All 5 variants (Full, SQ8, Binary, ProductQuantization, RaBitQ) are supported in all 10 components (Haystack inherits via the Python binding pass-through).
| Component | Status |
|---|---|
| Core | ✅ (source of truth) |
| Server | ✅ |
| Python | ✅ |
| WASM | ✅ |
| Mobile | ✅ |
| CLI | ✅ |
| TS SDK | ✅ |
| Tauri | ✅ |
| LangChain | ✅ |
| LlamaIndex | ✅ |
| Haystack | ✅ |
FusionStrategy — 10/10 (100%)
All 4 strategies (RRF, Weighted, Maximum, RSF) plus Average are supported in all 10 components (Haystack reaches RSF/Weighted/RRF/etc. fusion via its own VelesDBDocumentStore.embedding_retrieval(fusion=..., fusion_params=...), which delegates to velesdb_common.fusion.build_fusion_strategy and Collection.multi_query_search).
| Component | Status |
|---|---|
| Core | ✅ (source of truth) |
| Server | ✅ |
| Python | ✅ |
| WASM | ✅ |
| Mobile | ✅ |
| CLI | ✅ |
| TS SDK | ✅ |
| Tauri | ✅ |
| LangChain | ✅ |
| LlamaIndex | ✅ |
| Haystack | ✅ |
SearchQuality — 9/10
4 HNSW presets (Fast, Balanced, Accurate, Perfect) plus Custom(usize) and Adaptive. WASM uses brute-force search (no HNSW), so SearchQuality is not applicable there; Mobile and Tauri are HNSW-backed via core defaults and expose the presets (crates/velesdb-mobile/src/types.rs SearchQuality, crates/tauri-plugin-velesdb/src/helpers.rs parse_search_quality).
| Component | Status | Notes |
|---|---|---|
| Core | ✅ (source of truth) | |
| Server | ✅ | |
| Python | ✅ | |
| WASM | N/A | Brute-force only, no HNSW index |
| Mobile | ✅ | SearchQuality enum mapped to core (search_with_quality) |
| CLI | ✅ | |
| TS SDK | ✅ | |
| Tauri | ✅ | search_quality param + hnsw_m/hnsw_ef_construction at creation |
| LangChain | ✅ | |
| LlamaIndex | ✅ | |
| Haystack | ✅ |
CollectionType — 9/10
3 types (Vector, MetadataOnly, Graph). All native crates expose graph
collection creation; only Haystack is limited by its DocumentStore protocol.
| Component | Status | Notes |
|---|---|---|
| Core | ✅ (source of truth) | |
| Server | ✅ | |
| Python | ✅ | |
| WASM | ✅ | |
| Mobile | ✅ | create_graph_collection / create_graph_collection_with_embeddings exposed via #[uniffi::export] |
| CLI | ✅ | |
| TS SDK | ✅ | |
| Tauri | ✅ | |
| LangChain | ✅ | |
| LlamaIndex | ✅ | |
| Haystack | ⚠️ 1/3 | Vector only — Graph and MetadataOnly have no idiomatic mapping in the Haystack DocumentStore protocol |
Propagation Summary
| Enum | Coverage | Status |
|---|---|---|
DistanceMetric | 10/10 | 100% |
StorageMode | 10/10 | 100% |
FusionStrategy | 10/10 | 100% |
SearchQuality | 9/10 | N/A for WASM only (brute-force, no HNSW) |
CollectionType | 9/10 | Haystack Vector only by protocol; all native crates full |
Recently Landed (2026-06-14)
- WASM fusion now delegates 4/5 strategies to core.
average/maximum/weighted/rrfmap ontovelesdb_core::FusionStrategy::fuse(ranking identical to core, pinned by an equivalence test);relative_score/rsfstays WASM-local by design because its N-branch equal-weight semantics differ from core's two-branch dense+sparse weighted sum. See the RSF/Weighted note above. - Executor-level conformance now exists for core.
conformance/velesql_executor_cases.json+crates/velesdb-core/tests/velesql_executor_conformance.rsassert result rows/counts/ordering (not just that a query parses). Extended to the WASM and CLI executors on 2026-06-20 (action item 2 — now done). - Scalar
ORDER BY+LIMITcorrectness bug fixed. A scalar (non-similarity())ORDER BY <col> ... LIMIT kpreviously truncated tokin storage order before sorting; it now fetches the full matching set so the sort precedes truncation, restoring the KNOWN_LIMITATIONS #9 bounded==unbounded guarantee. Thesimilarity()-ordered HNSW fast path was untouched, so recall is unaffected. (Surfaced by the new executor conformance net above.) - Point-ID hashing single-sourced for Haystack. The Haystack
DocumentStorenow imports the canonicalvelesdb_common.ids.stable_hash_idinstead of a bit-identical forked copy (behaviour-preserving; removes a re-implemented hash from an MIT package). The intentional remaining divergence —velesdb-migrate's distinctstable_point_id— is documented in KNOWN_LIMITATIONS #12. - (2026-07-23) FNV-1a stable-hash dedup, plus an opt-in Python alignment path (#1542).
velesdb-corenow exports a publichash_id_bytes;velesdb-memory::id::stable_id[_bytes]andvelesdb-migrate::pipeline::fnv1a64delegate to it instead of each re-declaring the FNV-1a offset/prime constants — behaviour-preserving (golden-vector regression tests pin the pre-refactor output for ASCII and multi-byte UTF-8). This removes the duplication risk flagged by the parity audit but does not change the ecosystem-level divergence:velesdb_common.ids.stable_hash_id's SHA-256 default is intentionally unchanged (flipping it would orphan every string ID already stored via LangChain/LlamaIndex/Haystack). It gains an opt-inalgorithm="fnv1a"parameter, pure-Python and MIT-licensed, verified byte-for-byte against core's published golden vectors, for callers that need a Python-derived ID to agree with core/velesdb-migrate's FNV-1a for the same string.velesdb-migrate's numeric-preserve fast-path is now explicitly documented as a third, deliberately distinct semantics. Full contract in KNOWN_LIMITATIONS #12.
Remaining Gaps and Action Items
- ✅ Done (2026-06-24). Explicit server-side assertions for the full REST
VelesqlErrorResponseshape (code/message/hint/details) are now enforced incrates/velesdb-server/tests/velesql_conformance_tests.rsvia the shared fixture. Cases C002 (VELESQL_MISSING_COLLECTION), C003 (VELESQL_COLLECTION_NOT_FOUND), and C007 (VELESQL_AGGREGATION_ERROR) each assert all four fields, pinning the complete error body contract for the/queryand/aggregatesemantic-error paths. Parse errors (QueryErrorResponse) retain their own parser-specific shape and are tested separately by C004/C013 (status code only, by design — the parser error format is defined atE0XXlayer). (The CLI has no HTTP layer — it executes against embedded core — so this contract belongs exclusively tovelesdb-server.) - ✅ Done (2026-06-20). The executor-level conformance net now covers core, WASM, and CLI — all three run
conformance/velesql_executor_cases.json, including scalar WHERE filters, single- and multi-column ORDER BY, the ascending-id tie-break, and bounded top-k. See KNOWN_LIMITATIONS #13 (resolved). - Keep docs, fixtures, and examples synchronized on every contract version change.
- Promote RaBitQ from experimental to stable once the API is finalized.
- ✅ Done. RSF/Weighted fusion is exposed in Haystack via
embedding_retrieval(fusion=...)throughvelesdb_common.fusion(already exposed in LangChain and LlamaIndex via the sharedvelesdb_common.fusionmodule). - ✅ Done. Named-sparse-index creation is exposed on the upsert/write path
of LangChain, LlamaIndex, and Haystack (query-side
sparse_index_nametargeting already works). - Propagate
@collectioncross-collection MATCH to WASM, Mobile, Tauri, LangChain, LlamaIndex, and Haystack. - Add cross-collection vector search (
similarity()on@collection-annotated nodes). - Memory-surface gaps (2026-08 audit).
- Autograph exposure: the decoupled autograph path
(
MemoryService::spawn_autograph_worker) is spawned only by the MCP server/daemon (McpServer::new); the Python, Node, and TS-SDK bindings expose no way to enable autograph at all — neither the inline mode nor the worker. Follow-up decision: expose it, or record the daemon-only scoping as deliberate. - LangGraph toolkit omissions:
make_memory_toolsexposes ten tools and deliberately omitsentity,unrelate, and every context-compiler tool (pluslist_working_contexts, tracked above). Presumed by-design toolkit scoping — to be confirmed and recorded, not inferred. - Mobile:
velesdb-mobileships only a thin semantic-memory slice (VelesSemanticMemory) plus its own RAM-onlyMobileGraphStore; no doc records whether full memory-wedge parity on mobile is wanted or declined. Open decision. - REST relation/TTL divergences from the memory wedge
(documented pending a decision, not silently): REST
relate(POST /collections/{name}/relations,crates/velesdb-server/src/handlers/points/relations.rs:114) is non-idempotent — a fresh auto-assigned edge id per POST, and no self-loop refusal — where the wedge derives the edge id from(from, relation, to)and refusesfrom == to; RESTunrelate(DELETE .../relations/{edge_id},relations.rs:204) answers 404 on an absent edge where the wedge replays safely withfound: false; REST TTL (PATCH .../points/{id}/ttl,relations.rs:290) acceptsttl_seconds: 0as expire-now where the wedge refusesSome(0)(ZeroTtl).
- Autograph exposure: the decoupled autograph path
(
- Read-path gate (observer) parity (audit F-5.4). The 3.10.0 read-path gate —
velesdb_core::observer+database::gated_search/authorize_read(scope AND-composed with the caller filter, fail-closed on non-filterable paths) — is wired intovelesdb-server(search/match/graph handlers) andvelesdb-python(.search()gating).tauri-plugin-velesdbships a notify-only observer (no deny).velesdb-mobilenow ships a deny-capable observer (open_with_observer+MobileObserver/MobileAccessDecision,crates/velesdb-mobile/src/lib.rs:145).velesdb-node(memory-only, out of scope by design) andvelesdb-wasmexpose no observer, so the gate is inactive there. This is a parity gap, not a vulnerability: the core contract is fail-open only when no observer is registered (no policy ⇒ no denial to enforce), so an ungated binding simply has no governance layer to bypass. Governance-sensitive deployments must use the server or Python surface. Wiring an observer hook into mobile/wasm is a follow-up; node is intentionally excluded (it never touches the gated coreCollection).