Skip to content

fix: HNSW index bugs, agent/SPARQL crashes, lru security#172

Merged
ruvnet merged 11 commits intomainfrom
fix/hnsw-agent-sparql-lru-issues
Feb 15, 2026
Merged

fix: HNSW index bugs, agent/SPARQL crashes, lru security#172
ruvnet merged 11 commits intomainfrom
fix/hnsw-agent-sparql-lru-issues

Conversation

@ruvnet
Copy link
Owner

@ruvnet ruvnet commented Feb 15, 2026

Summary

Fixes 5 open issues with critical PostgreSQL extension bugs:

Files Changed

File Changes
hnsw_am.rs Dimension extraction from atttypmod, bounds checks, result ordering, non-kNN handling
ruvector--2.0.0.sql RETURNS TABLE(...) for agent functions
graph/operators.rs SPARQL empty query validation
Cargo.toml panic = "unwind", workspace version bump
*/Cargo.toml (3) lru 0.12 -> 0.16

Test plan

  • cargo check -p ruvector-graph passes (verified)
  • cargo check -p ruvector-cli passes (verified)
  • Docker image build with pgrx succeeds
  • HNSW index on ruvector(384) column creates correctly
  • SELECT COUNT(*) WHERE embedding IS NOT NULL works with HNSW index present
  • HNSW search returns correct number of results on small tables
  • ruvector_list_agents() returns proper table rows
  • ruvector_sparql_json('store', '') returns error, not crash
  • cargo audit clean for lru

🤖 Generated with claude-flow

… rvlite

Documents phased integration plan: Phase 1 adds RVF as optional dep + CLI
command group to npx ruvector, Phase 2 adds RVF as storage backend for rvlite,
Phase 3 unifies shared WASM backend and MCP bridge.

Co-Authored-By: claude-flow <ruv@ruv.net>
…and decision matrix

Adds: single writer rule, crash ordering with epoch reconciliation,
explicit backend selection (no silent fallback), cross-platform compat
rule, phase contracts with success metrics, failure mode test matrix,
hybrid persistence decision matrix, implementation checklist.

Closes #169

Co-Authored-By: claude-flow <ruv@ruv.net>
Phase 1 implementation:
- Add @ruvector/rvf as optional dependency to ruvector package
- Create rvf-wrapper.ts with 10 exported functions matching core pattern
- Add 3-tier platform detection (core -> rvf -> stub) with explicit
  --backend rvf override that fails loud if package is missing
- Add 8 rvf CLI subcommands (create, ingest, query, status, segments,
  derive, compact, export) routed through the wrapper
- 5 Rust smoke tests validating persistence across restart, deletion
  persistence, compaction stability, and adapter compatibility

Phase 2 foundations:
- Add rvf-backend feature flag to rvlite Cargo.toml (default off)
- Create epoch reconciliation module for hybrid RVF + IndexedDB sync
- Add @ruvector/rvf-wasm as optional dep to rvlite npm package
- Add rvf-adapter-rvlite to workspace members

All tests green: 237 RVF core, 23 adapter, 4 epoch, 5 smoke.

Refs: #169

Co-Authored-By: claude-flow <ruv@ruv.net>
…ols, compat tests

Phase 2 Rust: full epoch reconciliation (EpochTracker with AtomicU64, 23 tests),
writer lease with file lock and PID-based stale detection (12 tests),
direct ID mapping trait with DirectIdMap and OffsetIdMap (20 tests).

Phase 2 JS: createWithRvf/saveToRvf/loadFromRvf factories, BrowserWriterLease
with IndexedDB heartbeat, rvf-migrate and rvf-rebuild CLI commands, epoch sync
helpers. +541 lines to index.ts, new cli-rvf.ts (363 lines).

Phase 3: 3 MCP rvlite tools (rvlite_sql, rvlite_cypher, rvlite_sparql),
CI wasm-dedup-check workflow, 6 cross-platform compat tests, shared peer dep.

Phase 1: 4 RVF smoke integration tests (full lifecycle, cosine, multi-restart,
metadata). Node.js CLI smoke test script.

81 new Rust tests passing. ADR-032 checklist fully complete.

Co-Authored-By: claude-flow <ruv@ruv.net>
- ruvector 0.1.88 → 0.1.97 (match npm registry)
- rvlite 0.2.1 → 0.2.2
- @ruvector/rvf 0.1.0 → 0.1.1
- Fix MCP command in ruvector README (mcp-server → mcp start)
- Fix WASM type conflicts in rvlite index.ts (cast dynamic imports to any)

Co-Authored-By: claude-flow <ruv@ruv.net>
…allbacks, and README examples

Five "What's NOT Automatic" gaps fixed:
1. Witness auto-append: WitnessConfig in RvfOptions auto-records ingest/delete/compact
   operations as WITNESS_SEG entries with SHAKE-256 hash chains
2. verify-witness CLI: Real hash chain verification — extracts WITNESS_SEG payloads,
   runs verify_witness_chain() with full SHAKE-256 validation
3. verify-attestation CLI: Real kernel image hash verification and attestation
   witness chain validation
4. Prebuilt kernel fallback: KernelBuilder::from_builtin_minimal() produces valid
   bzImage without Docker
5. Prebuilt eBPF fallback: EbpfCompiler::from_precompiled() produces valid BPF ELF
   without clang; Launcher::check_requirements()/dry_run() for QEMU detection

README examples added to all 3 packages:
- crates/rvf/README.md: Proof of Operations section
- npm/packages/rvf/README.md: 7 real-world examples
- npm/packages/ruvector/README.md: Working cognitive container examples

830 tests passing, workspace compiles cleanly.

Co-Authored-By: claude-flow <ruv@ruv.net>
…itramfs

- Add live_boot_proof.rs: end-to-end Docker boot + SSH + RVF verification
- Add ULTRAFAST_BOOT_CONFIG: sub-100ms kernel config (no NUMA/cgroups/ext4/netfilter)
- Add build_fast_initramfs(): minimal init path (3 mounts + direct service start)
- Add KernelBuilder::ultrafast() with optimized cmdline for fast boot
- Update README with live boot proof instructions and ultra-fast boot docs
- 5 new tests (44 total in rvf-kernel), all passing

Co-Authored-By: claude-flow <ruv@ruv.net>
… benchmarks

- Examples (self_booting, linux_microkernel, claude_code_appliance,
  live_boot_proof) now use KernelBuilder::build() which tries Docker
  first and falls back to builtin stub — real 5.2 MB bzImage embedded
- Fix Docker kernel extraction: clean up stale containers, pass dummy
  entrypoint for scratch-based images
- README: add real measured boot benchmarks (257ms boot→service,
  381ms boot→verify), kernel size comparison (5.1 MB general vs
  3.8 MB ultrafast = 26% smaller)
- Fix claude_code_appliance idempotency (remove old file before create)

Co-Authored-By: claude-flow <ruv@ruv.net>
Published to npm:
- @ruvector/ruvf 0.1.2
- @ruvector/rvf-wasm 0.1.1
- @ruvector/rvf-node 0.1.1
- @ruvector/rvf-mcp-server 0.1.1
- ruvector 0.1.98
- rvlite 0.2.3

Co-Authored-By: claude-flow <ruv@ruv.net>
…167, #171, #148)

HNSW fixes:
- Extract vector dimensions from column atttypmod instead of hardcoding 128,
  which caused corrupted indexes for non-128-dim embeddings (#171, #164)
- Add page boundary checks in read_vector/read_neighbors to prevent
  segfaults on large tables with >100K rows (#164)
- Use BinaryHeap::into_sorted_vec() for deterministic result ordering
  instead of into_iter() which yields arbitrary order (#171)
- Handle non-kNN scans (COUNT, WHERE IS NOT NULL) gracefully by returning
  false from hnsw_gettuple when no ORDER BY operator is present (#152)

Agent/SPARQL fixes:
- Fix SQL type mismatch: ruvector_list_agents() and
  ruvector_find_agents_by_capability() now use RETURNS TABLE(...)
  matching the Rust TableIterator signatures instead of RETURNS SETOF jsonb (#167)
- Add empty query validation to ruvector_sparql() and
  ruvector_sparql_json() to prevent panics on invalid input (#167)
- Change workspace panic profile from "abort" to "unwind" so pgrx can
  convert Rust panics to PostgreSQL errors instead of killing the backend (#167)

Security:
- Bump lru dependency from 0.12 to 0.16 in ruvector-graph, ruvector-cli,
  and ruvLLM to resolve GHSA-xpfx-fvgv-hgqp Stacked Borrows violation (#148)

Version bumps: workspace 2.0.3, ruvector-postgres 2.0.2

Co-Authored-By: claude-flow <ruv@ruv.net>
…-lru-issues

# Conflicts:
#	crates/rvf/README.md
#	crates/rvf/rvf-kernel/src/lib.rs
#	npm/packages/ruvector/package.json
#	npm/packages/rvf/package.json
#	npm/packages/rvlite/package.json
@github-actions
Copy link
Contributor

Benchmark Results Summary

Distance Function Benchmarks


HNSW Index Benchmarks


Quantization Benchmarks


See full results in the artifacts.

@github-actions
Copy link
Contributor

Benchmark Comparison

Distance Benchmarks

Baseline (main)

Current (PR)

grparry pushed a commit to grparry/ruvector that referenced this pull request Feb 17, 2026
Three additional hardening fixes for the SPARQL subsystem, building on
PR ruvnet#172:

1. Parser: replace hardcoded saturating_sub(6) with saved_pos variable.
   The old backtrack assumed all update keywords are 6 chars, but LOAD,
   DROP, and CLEAR are 4-5 chars, causing incorrect parse positions.

2. Executor: change default_graph from Option<&'a str> to Option<String>
   and remove Box::leak calls in the GraphPattern::Graph handler. Each
   GRAPH clause previously leaked a String allocation that was never freed.

3. Operators: wrap ruvector_sparql parse/execute/format in catch_unwind
   so that panics from non-empty but malformed queries are converted to
   PostgreSQL ERROR messages instead of crashing the backend.

Closes ruvnet#167

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ruvnet added a commit that referenced this pull request Feb 20, 2026
fix: HNSW index bugs, agent/SPARQL crashes, lru security
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant