Skip to main content

MemoryStore

Struct MemoryStore 

Source
pub struct MemoryStore { /* private fields */ }
Expand description

The LMDB environment containing all 14 galaxy sub-databases plus 4 index DBs.

Implementations§

Source§

impl MemoryStore

Source

pub fn open(path: impl AsRef<Path>, map_size: usize) -> Result<Self>

Open or create an LMDB store at the given path.

On Unix, the store directory is created with mode 0o700 (owner-only access) if it does not already exist. Existing directories are left untouched.

Source

pub fn open_default(path: impl AsRef<Path>) -> Result<Self>

Open with the default map size.

4 GB on Unix: LMDB truncates the data file sparsely (ftruncate), so reservation costs nothing until pages are written. On Windows NTFS materializes the file at full map size immediately — a 4 GB default would allocate 4 GB on disk per store the moment it opens — so the Windows default is smaller; pass an explicit size to open() for large stores. (Auto-grow on MapFull is a planned follow-up.)

Source

pub fn open_readonly(path: impl AsRef<Path>) -> Result<Self>

Open an existing LMDB store without creating a directory, database, or writable LMDB environment. This is the preservation boundary used by read-only evaluator servers: an incomplete or incompatible store must fail closed for the caller to investigate, never be initialized or repaired in place.

Source

pub fn ensure_schema(path: impl AsRef<Path>) -> Result<Vec<String>>

Complete a store’s schema in place: create any galaxy, index, or named database this build expects but an older store lacks, then let the caller reopen normally. Returns the database names that were missing.

Restores from older builds can be byte-exact yet not openable (found 2026-09-14: a 9.0.0 backup lacked cold_storage). This is the only in-place repair path; open_readonly deliberately stays strict so preservation callers see an incomplete store instead of a silent fix.

Source

pub const fn with_entry_limit(self, limit: usize) -> Self

Set a per-galaxy entry limit for DoS prevention.

When set, put will reject writes that would exceed the limit. This prevents a single galaxy from exhausting the LMDB map.

Source

pub fn path(&self) -> &Path

Path to the LMDB file.

Source

pub const fn env(&self) -> &Environment

Get the LMDB environment handle.

Source

pub fn mutation_count(&self) -> u64

Monotonic counter of successful mutations since this handle was opened (puts, deletes, clears, raw writes). Used by the dispatch pipeline’s write-audit journal to detect actual store writes.

Source

pub const fn index_dbs(&self) -> &IndexDbs

Get the cached index database handles.

Source

pub const fn semantic_encoder(&self) -> &SemanticEncoder

Get the semantic encoder.

Source

pub fn episodic(&self) -> EpisodicStore<'_>

Open the v6 lossless episodic record view.

Source

pub fn set_episodic_embedder(&self, embedder: Arc<dyn Embedder + Send + Sync>)

Attach an embedder for episodic vector reranking.

Source

pub fn set_episodic_aliases(&self, aliases: AdaptiveAliases)

Attach adaptive aliases for episodic key expansion.

Source

pub fn set_episodic_enrichment(&self, enrichment: VocabularyEnrichment)

Attach vocabulary enrichment for episodic index-time term expansion.

Source

pub fn galaxy_db(&self, galaxy: Galaxy) -> Result<Database>

Get a named database handle for a galaxy.

Source

pub fn put(&self, galaxy: Galaxy, memory: &Memory) -> Result<()>

Store a memory in the given galaxy. Keyed by memory.metadata.id. Also updates all secondary indexes.

Returns a clear error if the per-galaxy entry limit is exceeded or if the LMDB map is full.

Source

pub fn get(&self, galaxy: Galaxy, id: Uuid) -> Result<Option<Memory>>

Retrieve a memory by ID from the given galaxy.

Source

pub fn find_across_galaxies(&self, id: Uuid) -> Result<Option<(Galaxy, Memory)>>

Retrieve a memory by ID searching across all memory galaxies (S9 cross-galaxy traversal).

Cross-galaxy associations and edges reference galaxy-blind UUIDs. This searches through all memory galaxies in canonical order and returns the first matching (Galaxy, Memory) pair, or None if not found.

Source

pub fn delete(&self, galaxy: Galaxy, id: Uuid) -> Result<bool>

Delete a memory by ID from the given galaxy. Returns true if a key was removed. Also removes all secondary index entries for the memory.

Source

pub fn scan(&self, galaxy: Galaxy, limit: usize) -> Result<Vec<Memory>>

Scan up to limit memories from the given galaxy (unordered by LMDB page layout).

Source

pub fn scan_all(&self, galaxy: Galaxy) -> Result<Vec<Memory>>

Scan every memory in the galaxy (unordered by LMDB page layout).

Used by maintenance tooling (e.g. index rebuild). The full galaxy is materialized in memory — prefer Self::scan for bounded reads.

Source

pub fn scan_all_strict(&self, galaxy: Galaxy) -> Result<Vec<Memory>>

Maintenance scan that refuses to omit an undecodable source record. Use before replacing derived indexes; a tolerant scan is not a complete authoritative snapshot when any record fails decoding.

Source

pub fn count(&self, galaxy: Galaxy) -> Result<usize>

Count entries in a galaxy.

Source

pub fn clear_galaxy(&self, galaxy: Galaxy) -> Result<usize>

Clear all memories from a galaxy in a single transaction. Returns the number of entries cleared. Also removes all secondary index entries.

Source

pub fn batch_put(&self, galaxy: Galaxy, memories: &[Memory]) -> Result<usize>

Put multiple memories into a galaxy in a single transaction. Returns the number of memories written.

Source

pub fn get_raw(&self, galaxy: Galaxy, key: &[u8]) -> Result<Option<Vec<u8>>>

Get raw key-value bytes (for advanced use cases).

Source

pub fn put_raw(&self, galaxy: Galaxy, key: &[u8], val: &[u8]) -> Result<()>

Put raw key-value bytes (for advanced use cases).

Source

pub fn delete_raw(&self, galaxy: Galaxy, key: &[u8]) -> Result<bool>

Delete raw key-value bytes (for advanced use cases). Returns true if a key was removed.

Source

pub fn put_raw_batch( &self, galaxy: Galaxy, entries: &[(&[u8], &[u8])], ) -> Result<()>

Batch multiple raw key-value writes in a single LMDB transaction. All writes succeed or fail atomically.

Source

pub fn put_raw_batch_untracked( &self, galaxy: Galaxy, entries: &[(&[u8], &[u8])], ) -> Result<()>

Batch multiple raw key-value writes without advancing the mutation counter.

For governance bookkeeping (karma chain, write-audit journal): these writes are metadata about dispatches, not memory mutations. Letting them tick the counter attributes a whole batch flush to whichever dispatch happens to be in flight when the threshold trips — the 2026-08-28 restore-drill false-positive class (“read-only” tools flagged with the previous batch’s size as their write delta).

Source

pub fn find_by_content_hash( &self, galaxy: Galaxy, hash: &str, ) -> Result<Option<Uuid>>

Check if a memory with the same content hash already exists in the galaxy. Uses the content_hash index for O(1) lookup. Returns the existing memory’s ID if found.

Source

pub fn find_by_content_hash_scan( &self, galaxy: Galaxy, hash: &str, ) -> Result<Option<Uuid>>

Scan-based content hash lookup (O(n) fallback, used for testing index correctness).

Source

pub fn put_dedup(&self, galaxy: Galaxy, memory: &Memory) -> Result<Uuid>

Store a memory with content-hash deduplication. If a memory with the same content already exists in the galaxy, returns the existing memory’s ID without creating a duplicate.

Source

pub fn put_batch(&self, galaxy: Galaxy, memories: &[Memory]) -> Result<()>

Store multiple memories in a single LMDB transaction (batch write). All writes and index updates succeed or fail atomically.

Source

pub fn query(&self, galaxy: Galaxy, query: &MemoryQuery) -> Result<Vec<Memory>>

Query memories in a galaxy with filtering. Uses secondary indexes when the query is a pure single-dimension filter (single tag, importance range, or time range with no other filters). Falls back to scan for complex multi-dimensional queries.

Source

pub fn put_semantic(&self, galaxy: Galaxy, memory: &mut Memory) -> Result<()>

Store a memory with semantically-derived 5D coordinates.

Replaces the SHA-256 hash-based Coordinate5D::encode() with anchor-based TF projection. The memory’s coord5d field is updated with semantically meaningful x/y/z values before storage.

Source

pub fn find_similar( &self, galaxy: Galaxy, query_text: &str, limit: usize, ) -> Result<Vec<(Memory, f32)>>

Find memories in a galaxy with content semantically similar to the query text.

Encodes the query text into a 5D coordinate and scans the galaxy, returning memories sorted by semantic distance (nearest first).

Source

pub fn put_embedding(&self, memory_id: Uuid, embedding: &[f32]) -> Result<()>

Store an embedding vector for a memory in the Embeddings galaxy. Keyed by the memory’s UUID.

Source

pub fn get_embedding(&self, memory_id: Uuid) -> Result<Option<Vec<f32>>>

Retrieve an embedding vector for a memory from the Embeddings galaxy.

Source

pub fn delete_embedding(&self, memory_id: Uuid) -> Result<bool>

Delete an embedding vector from the Embeddings galaxy.

Source

pub fn put_embedding_cache( &self, cache_key: &str, embedding: &[f32], ) -> Result<()>

Store a cached embedding under a caller-computed cache key (embedder namespace + content hash). Vectors for the same content differ across models, so the key must carry the namespace.

Source

pub fn put_embedding_cache_batch( &self, entries: &[(String, Vec<f32>)], ) -> Result<()>

Batched cache write: one transaction for the whole ingest chunk.

Source

pub fn get_embedding_cache(&self, cache_key: &str) -> Result<Option<Vec<f32>>>

Look up a cached embedding. Ok(None) = miss; the caller embeds.

Source

pub fn get_embedding_cache_batch( &self, keys: &[String], ) -> Result<Vec<Option<Vec<f32>>>>

Batched lookup: one read transaction for the whole ingest chunk. Result aligns 1:1 with keys.

Source

pub fn embedding_cache_count(&self) -> Result<u64>

Number of cached vectors (doctor / honesty surfaces).

Source

pub fn record_revision( &self, galaxy: Galaxy, id: MemoryId, old_hash: &str, new_hash: &str, actor: RevisionActor, ) -> Result<MemoryRevision>

Append one content revision to a memory’s chain. Seq is derived from the current chain tail (append-only by convention); the write bumps the store mutation counter so dispatch windows attribute it.

Source

pub fn revisions( &self, galaxy: Galaxy, id: MemoryId, ) -> Result<Vec<MemoryRevision>>

Full revision chain for a memory, ordered by seq. Empty for memories never content-updated (or pre-S11c).

Source

pub fn verify_revision_chain( &self, galaxy: Galaxy, id: MemoryId, current_hash: &str, ) -> Result<RevisionChainReport>

Walk one memory’s revision chain and grade it against the memory’s current content hash (seq continuity, hash linkage, head match).

Source

pub fn record_attestation( &self, galaxy: Galaxy, id: MemoryId, entry: &RecordAttestation, ) -> Result<()>

Record one creation attestation for a memory. Upsert by key (att:{galaxy}:{memory_id}): re-attestation overwrites, which is safe because attestation covers the creation event and memory ids are unique per create. The write bumps the mutation counter like every other store mutation.

Source

pub fn attestation( &self, galaxy: Galaxy, id: MemoryId, ) -> Result<Option<RecordAttestation>>

This memory’s creation attestation, if the creating dispatch signed one (key-available creates only — absence is honest, not an error).

Source

pub fn scan_attestations(&self) -> Result<Vec<RecordAttestation>>

Every attestation in the store (for wm anchor). Bounded walk — corrupt data can never spin this loop.

Source

pub fn verify_attestation( &self, galaxy: Galaxy, id: MemoryId, ) -> Result<AttestationReport>

Grade one memory’s attestation: presence, signature validity, and whether the attested hash still matches the live content hash. A content update after creation flips matches_head to false by design — updates are covered by the revisions chain, not by re-attestation.

Source

pub fn attestation_sweep( &self, ) -> Result<Vec<(RecordAttestation, AttestationReport)>>

Grade every attestation in the store (for wm anchor). Entries whose galaxy/id no longer parse are reported as broken — never skipped silently.

Source

pub fn put_cold_record(&self, record: &ColdRecord) -> Result<()>

Store a compressed cold record in the cold_storage DBI.

Source

pub fn get_cold_record(&self, id: MemoryId) -> Result<Option<ColdRecord>>

Retrieve a compressed cold record by memory id.

Source

pub fn delete_cold_record(&self, id: MemoryId) -> Result<bool>

Delete a cold record from the cold storage DBI (used when thawing back to hot).

Source

pub fn count_cold(&self, galaxy: Option<Galaxy>) -> Result<usize>

Count cold records in the cold storage database, optionally filtered by galaxy.

Source

pub fn list_cold_records( &self, galaxy: Option<Galaxy>, limit: usize, ) -> Result<Vec<ColdRecordSummary>>

List cold records (summaries) with optional galaxy filter and limit.

Source

pub fn query_cold_records( &self, query: &ColdQuery, ) -> Result<Vec<ColdRecordSummary>>

Query cold records matching a ColdQuery filter.

Source

pub fn find_cold_matching( &self, terms: &[String], galaxy: Option<Galaxy>, limit: usize, max_scan: usize, ) -> Result<ColdDiscoveryOutcome>

Bounded, identity-bound cold discovery.

Scans at most max_scan cold records (LMDB cold_storage DBI), filters by galaxy when given, decompresses each candidate, verifies the id/galaxy/content-hash chain, applies visibility (private never surfaces; superseded/non-current records are skipped), and returns up to limit full cold records whose content or tags contain every query term (case-insensitive). Nothing is thawed or mutated.

Source

pub fn find_cold_matching_eligible( &self, terms: &[String], galaxy: Option<Galaxy>, limit: usize, max_scan: usize, eligible: impl Fn(&Memory) -> bool, ) -> Result<ColdDiscoveryOutcome>

Apply caller eligibility to verified payloads before consuming result capacity. Rejected matches still consume the bounded scan budget.

Source

pub fn freeze_to_cold( &self, search: Option<&SearchEngine>, memory_id: MemoryId, distance: f32, factors: OuterRimFactors, digest_id: Option<MemoryId>, notes: Option<String>, codec: CompressionCodec, ) -> Result<ColdRecord>

Freeze an active hot memory into the compressed cold archive.

Non-destructive: preserves complete metadata, vector clocks, content, embeddings, and provenance. The memory transitions to Tier::Archival, is stored in cold_storage_db, is deindexed from Tantivy (if search provided), and is removed from the active hot galaxy.

Source

pub fn thaw_from_cold( &self, search: Option<&SearchEngine>, memory_id: MemoryId, ) -> Result<Memory>

Thaw a memory from compressed cold storage back into the hot active tier.

Zero data loss: restores the original memory with all fields, transitions tier back to Tier::Episodic, bumps access/recall count, updates accessed_at, stores into the hot galaxy, and reindexes into Tantivy search (if provided).

Source

pub fn find_anywhere( &self, id: MemoryId, ) -> Result<Option<(Galaxy, Memory, bool)>>

Find a memory anywhere: in the active hot galaxies, or decompressed from cold storage.

Returns (galaxy, memory, is_cold).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Fruit for T
where T: Send + Downcast,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more