Skip to content

YantrikDB

v0.7.17 Feature

This release adds 2 notable features for engineering teams evaluating rollout.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

agent-memory ai-agents anthropic claude-code cognitive-memory database
+12 more
embeddings hnsw knowledge-graph llm llm-memory mcp memory persistent-memory python rust semantic-memory vector-db

Summary

AI summary

db.reembed adds engine‑side embedder migration with atomic HNSW swap while queuing concurrent writes.

Changes in this release

Feature Low

`db.reembed(new_embedder_name, options)` enables engine-side embedder migration.

`db.reembed(new_embedder_name, options)` enables engine-side embedder migration.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Re-encode every memory under a new embedder and atomically swap the active HNSW index.

Re-encode every memory under a new embedder and atomically swap the active HNSW index.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Concurrent recalls continue serving; concurrent writes queue during cutover.

Concurrent recalls continue serving; concurrent writes queue during cutover.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

5-phase state machine: Probing → Encoding → Rebuilding → Swapping → Verifying → Completed.

5-phase state machine: Probing → Encoding → Rebuilding → Swapping → Verifying → Completed.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

`report.generation`, `report.encoded_count`, `report.build_hwm`, `report.duration` provide detailed reembed report.

`report.generation`, `report.encoded_count`, `report.build_hwm`, `report.duration` provide detailed reembed report.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Customizable options: namespace, progress callback, batch size, HNSW params, write policy.

Customizable options: namespace, progress callback, batch size, HNSW params, write policy.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Write policy `Queue` queues concurrent writers during cutover instead of blocking them.

Write policy `Queue` queues concurrent writers during cutover instead of blocking them.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Progress callback receives phase, processed count, total count during reembed.

Progress callback receives phase, processed count, total count during reembed.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

End-to-end correctness proof ensures post-swap recall returns rows under new embedder.

End-to-end correctness proof ensures post-swap recall returns rows under new embedder.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Compatibility: `db.reembed()` is additive; pre-v0.7.17 APIs unchanged; forward-only schema migration.

Compatibility: `db.reembed()` is additive; pre-v0.7.17 APIs unchanged; forward-only schema migration.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: high

Feature Low

Migration additive and idempotent; no data mutation on existing rows.

Migration additive and idempotent; no data mutation on existing rows.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: low

Feature Low

New columns `memories.embedding_generation`, `meta.active_generation`, `idx_memories_embedding_generation` introduced in v28 schema.

New columns `memories.embedding_generation`, `meta.active_generation`, `idx_memories_embedding_generation` introduced in v28 schema.

Source: granite4.1:8b-q6_K@2026-05-19

Confidence: low

Feature Low

Schema migration adds `memories.embedding_generation`, `meta.active_generation`, and index `idx_memories_embedding_generation` idempotently without mutating existing rows.

Schema migration adds `memories.embedding_generation`, `meta.active_generation`, and index `idx_memories_embedding_generation` idempotently without mutating existing rows.

Source: granite4.1:30b@2026-05-20-audit

Confidence: low

Full changelog

Headline

db.reembed(new_embedder_name, options) — engine-side embedder migration. Re-encode every memory under a new embedder + atomically swap the active HNSW index, while concurrent recalls continue serving and concurrent writes queue (rather than block).

Closes #41. Shipped as PR #42 — 22 commits across 12 substantive checkpoints, 1492 tests passing (default features) + 1481 slim + 1499 with embedder-download, 0 regressions.

What ships

A 5-phase state machine — Probing → Encoding → Rebuilding → Swapping → Verifying → Completed — invoked via:

let report = db.reembed("potion-base-32M", ReembedOptions::default())?;
// report.generation       — new active generation
// report.encoded_count    — rows re-encoded under the new embedder
// report.build_hwm        — covers_through_seq captured at the cutover barrier
// report.duration         — wall-clock runtime

Or with progress + custom HNSW params + namespace scope:

let opts = ReembedOptions {
    namespace: Some("default".to_string()),
    progress_cb: Some(Box::new(|p| println!("{:?} {}/{:?}", p.phase, p.processed, p.total))),
    batch_size: 512,
    hnsw_m: Some(32),
    write_policy: ReembedWritePolicy::Queue,  // default
    ..Default::default()
};
let report = db.reembed("potion-base-32M", opts)?;

The Queue write policy means concurrent writers during the cutover don't block — they're queued to oplog (as TEXT) and the post-swap materializer re-encodes them under the new embedder.

Correctness invariants locked

4 brainstorm sessions with gpt-5.5 caught 10+ critical correctness bugs in the design space before any shipped:

  • No read-side dim split-brain — SearchState is the single atomic publication unit (provenance + embedder + dim + generation + covers_through_seq + HNSW params + vec_index). ArcSwap-wrapped.
  • No stale-writer commitrecord_text runs the writer-revalidation loop: embed outside the WriteRouter guard, acquire guard, re-check (generation, digest), retry if a reembed swap completed under the embed step.
  • No compactor generation rollbacktry_publish_search_state is the only SearchState mutator; rejects strictly-lesser-generation publishes via ArcSwap::compare_and_swap.
  • Durable crash recoverymeta.active_generation + memories.embedding_generation form the single durable linearization point. open() reads them and rebuilds SearchState; staging columns from a crashed mid-reembed are discarded if SQL didn't commit, or carried forward if it did.
  • SQL embedding boundaryDurableEmbeddingStore module is the only sanctioned path through which engine code reads memories.embedding. A compile-test (recall_rs_has_no_raw_sql_embedding_reads) fails the build if a future refactor reintroduces raw SQL access in the hot recall path.

All 8 brainstorm-4 §10 invariants have regression tests. End-to-end correctness proof: reembed_post_swap_recall_returns_rows_under_new_embedder plants rows under E0 (sentinel 0.42), reembeds to E1 (sentinel 0.99), recalls under E1 vector space, all rows return.

v28 schema migration

Two new surfaces:

  • memories.embedding_generation INTEGER — per-row stamp of which SearchState generation the row was encoded under. NULL on pre-v28 rows (treated as generation 0). Reembed Phase-2's swap transaction writes the new generation atomically with promoting embedding_new into embedding.
  • meta.active_generation row — durable record of the current active SearchState generation. Read by open() and used to rebuild the SearchState across restarts.
  • idx_memories_embedding_generation — supports the post-swap materializer's "scan rows under stale generation" query.

Migration is additive + idempotent. No data mutation on existing rows.

Limitations / deferred (documented)

  • Cross-dim reembed is not supported in v1. The engine's standalone embedding_dim field still gates ~7 sites (engine/conflict.rs, engine/indices.rs, engine/record.rs, distributed/replication.rs); retiring it is a separate structural increment. Cross-dim returns a typed error pointing at the escape hatch ("open new DB at new dim, copy memories"). Same-dim covers the primary upgrade use case (model version bump within vector space).
  • HTTP backend — this release is the engine primitive. The corresponding yantrikdb-server REST endpoint + cluster-mode reembed (openraft applier semantics) is a downstream PR. yantrikdb-hermes-plugin embedded mode is unblocked now; HTTP-mode plugin users wait for the server PR.

Test counts

| Build | Tests passing |
|---|---|
| cargo test --lib --release (default features) | 1492 |
| cargo test --lib --no-default-features --release (slim) | 1481 |
| cargo test --lib --features embedder-download --release | 1499 |
| cargo fmt --check --all | ✅ clean |
| cargo clippy | ✅ clean |

Compatibility

db.reembed() is purely additive. All pre-v0.7.17 APIs work unchanged. The v27 schema (shipped in v0.7.16) and the new v28 schema are both forward-only — opening a v0.7.16 DB with v0.7.17 binary triggers idempotent additive migration; opening a v0.7.17 DB with v0.7.16 binary stays at v27 and ignores the new columns.

Acknowledgements

Designed in 4 brainstorm rounds with gpt-5.5; each round caught real correctness bugs (not gold-plating). hermes-agent shaped the ergonomics asks (implicit auto-load, Probing-emits-total). The substrate-paper experiment (agent-in-loop catching design-level + structural-fit bugs before they ship) continues to validate.

— closes #41

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track YantrikDB

Get notified when new releases ship.

Sign up free

About YantrikDB

All releases →

Related context

Earlier breaking changes

  • v0.7.20 `correct()` now mutates in place, preserving rid and adding revision history (BREAKING CHANGE).
  • v0.7.9 Pure-additive; existing engines keep English models on v0.1.0.

Beta — feedback welcome: [email protected]