ruvector/crates/ruvector-rulake/examples
ruvnet d60c802889 feat(rabitq,rulake): external_ids accessor + warm_restart example — close wave-5 gaps
=== Agent A: rabitq — non-dense ID preservation through persist ===
crates/ruvector-rabitq/src/{index,persist}.rs

Wave-5's warm_from_dir collapsed external u64 ids to (0..n) identity
because RabitqPlusIndex lacked an outer ids accessor. Surprise finding:
the persist LOAD path was already id-preserving — the pipeline reads
`id:u32` from disk and hands (id, v) into from_vectors_parallel, which
writes `id` into inner.ids. The only missing piece was the outer-layer
accessor so ruLake could read them back.

Added:
  - RabitqPlusIndex::external_ids(&self) -> &[u32]  (thin forward)
  - RabitqPlusIndex::ids_u64(&self)    -> Vec<u64>  (widening clone)

Regression test `persist_preserves_non_dense_ids` builds an index with
non-dense external ids (13*i + 7 for i in 0..50), save/load, asserts
byte-identical ids after round-trip. 37 → 38 rabitq tests.

=== rulake: drop the (0..n) workaround ===
crates/ruvector-rulake/src/lake.rs

warm_from_dir now calls `idx.ids_u64()` instead of synthesizing
(0..n). Non-dense external ids round-trip faithfully. The
~15-line inline comment documenting the old limitation is gone;
replaced with a 4-line pointer to the wave-6 close.

=== Agent B: warm_restart runnable example ===
crates/ruvector-rulake/examples/warm_restart.rs (new)

Runnable demo of the full save → ship → warm-restart cycle:
  - Phase 1: prime from backend, save to disk
  - Phase 2: spin up a FRESH RuLake with NO backend, warm_from_dir,
    query, assert warm_installs=1 / primes=0
  - Phase 3: cold-prime from backend for comparison
  - Final: report cold/warm speedup

Measured at n=5000 D=128 (agent's single-run numbers):
  Phase 1 prime:     5.03 ms
  save_cache_to_dir: 3.44 ms  (2.46 MiB rbpx)
  Phase 2 warm:      5.00 ms  (warm_installs=1, primes=0)
  Phase 3 cold:      3.60 ms
  Speedup cold/warm: 0.70×

Honest finding: at n=5k D=128, cold-prime is actually faster than
warm-load because our parallel prime is <5ms and parsing 2.5 MB of
rbpx is slower. The warm-restart win shows up at larger n where
compression dominates; documented in the example's closing block.

Steady-state QPS matches within 1.2% (same compressed index in both).

38 rabitq + 21 rulake lib + 22 rulake federation = 81 tests. Clippy
-D warnings clean across both crates.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-23 23:52:51 -04:00
..
sidecar_daemon.rs feat(rabitq,rulake): VectorKernel + memory_class + per-collection stats + sidecar example 2026-04-23 21:27:04 -04:00
warm_restart.rs feat(rabitq,rulake): external_ids accessor + warm_restart example — close wave-5 gaps 2026-04-23 23:52:51 -04:00