pub struct EpisodicStore<'a> { /* private fields */ }Expand description
Dedicated persistence view over the episodic-record LMDB database.
Implementations§
Source§impl<'a> EpisodicStore<'a>
impl<'a> EpisodicStore<'a>
Sourcepub fn with_adaptive_aliases(self, aliases: AdaptiveAliases) -> Self
pub fn with_adaptive_aliases(self, aliases: AdaptiveAliases) -> Self
Attach adaptive aliases for query and ingest-time key expansion.
Sourcepub fn with_enrichment(self, enrichment: VocabularyEnrichment) -> Self
pub fn with_enrichment(self, enrichment: VocabularyEnrichment) -> Self
Attach vocabulary enrichment for index-time term expansion.
Sourcepub fn with_embedder(self, embedder: Arc<dyn Embedder + Send + Sync>) -> Self
pub fn with_embedder(self, embedder: Arc<dyn Embedder + Send + Sync>) -> Self
Attach an embedder for vector reranking.
Sourcepub fn append(&self, record: &EpisodicRecord) -> Result<()>
pub fn append(&self, record: &EpisodicRecord) -> Result<()>
Append a source record without allowing an existing raw ID to be overwritten.
Sourcepub fn append_batch(&self, records: &[EpisodicRecord]) -> Result<()>
pub fn append_batch(&self, records: &[EpisodicRecord]) -> Result<()>
Append many source records, then project them into the sidecar in one term-index transaction.
Sourcepub fn rebuild_sidecar(&self) -> Result<usize>
pub fn rebuild_sidecar(&self) -> Result<usize>
Rebuild the DUP_SORT sidecar from the authoritative raw records.
Used when a store contains records but an empty v2 sidecar (legacy stores whose postings lived in the retired v1 database, or stores whose sidecar was lost). The raw lane is never touched; a failure leaves the sidecar empty and search falls back to the raw scan.
Sourcepub fn sidecar_is_empty(&self) -> Result<bool>
pub fn sidecar_is_empty(&self) -> Result<bool>
Number of (term, id) postings in the sidecar.
LMDB 0.8 exposes no per-database stat, so emptiness is checked by
peeking the first entry (cheap; whole-db counts are not needed).
iter() (not iter_start) is used because iter_start unwraps
MDB_FIRST, which fails NotFound on an empty database.
Sourcepub fn record_count(&self) -> Result<u64>
pub fn record_count(&self) -> Result<u64>
Number of raw records in the authoritative lane.
Sourcepub fn append_explicit(
&self,
record: &EpisodicRecord,
policy: EpisodicCapturePolicy,
) -> Result<bool>
pub fn append_explicit( &self, record: &EpisodicRecord, policy: EpisodicCapturePolicy, ) -> Result<bool>
Append an explicit record according to the capture policy.
Sourcepub fn append_explicit_batch(
&self,
records: &[EpisodicRecord],
policy: EpisodicCapturePolicy,
) -> Result<usize>
pub fn append_explicit_batch( &self, records: &[EpisodicRecord], policy: EpisodicCapturePolicy, ) -> Result<usize>
Append many explicit records according to the capture policy.
Sourcepub fn get(&self, id: EpisodicId) -> Result<Option<EpisodicRecord>>
pub fn get(&self, id: EpisodicId) -> Result<Option<EpisodicRecord>>
Read an episodic record by its canonical ID.
Sourcepub fn transition(
&self,
id: EpisodicId,
transition: MemoryTransition,
) -> Result<()>
pub fn transition( &self, id: EpisodicId, transition: MemoryTransition, ) -> Result<()>
Apply an explicit lifecycle transition to a persisted record.
Sourcepub fn scan(
&self,
session_id: Option<Uuid>,
limit: usize,
) -> Result<Vec<EpisodicRecord>>
pub fn scan( &self, session_id: Option<Uuid>, limit: usize, ) -> Result<Vec<EpisodicRecord>>
Return records in sequence order, optionally restricted to a session.
Sourcepub fn search(
&self,
query: &str,
limit: usize,
include_historical: bool,
) -> Result<Vec<EpisodicSearchResult>>
pub fn search( &self, query: &str, limit: usize, include_historical: bool, ) -> Result<Vec<EpisodicSearchResult>>
Search current episodic records using deterministic token overlap.
This is a v6 library path only. It does not alter the v5 MCP search route and keeps source records attached to every hit.
When the query asks for the current/latest value of something
(see is_current_query), the topic cluster is reordered by
deterministic chronology so the most recent statement outranks older
ones — post-retrieval temporal resolution, not a scoring change.
Sourcepub fn search_with_limits(
&self,
query: &str,
limit: usize,
candidate_limit: usize,
include_historical: bool,
) -> Result<Vec<EpisodicSearchResult>>
pub fn search_with_limits( &self, query: &str, limit: usize, candidate_limit: usize, include_historical: bool, ) -> Result<Vec<EpisodicSearchResult>>
Search with an explicit candidate budget before selective reranking.
Uses multi-query pool widening: the original query plus sub-queries focused on key content words generate candidate IDs. All candidates are then scored with the primary query’s deterministic scoring. This helps answer turns that match few original query terms but match the key entity strongly enter the candidate pool.
Sourcepub fn search_with_rerank(
&self,
query: &str,
limit: usize,
candidate_limit: usize,
include_historical: bool,
alpha: f32,
) -> Result<Vec<EpisodicSearchResult>>
pub fn search_with_rerank( &self, query: &str, limit: usize, candidate_limit: usize, include_historical: bool, alpha: f32, ) -> Result<Vec<EpisodicSearchResult>>
Search with vector reranking on top of deterministic scoring.
Pipeline: deterministic scoring → top-N candidates → embed query + candidates → reranking → top-K.
Modes by alpha:
alpha >= 2.0— protected top-K (ConvMemory v2 pattern): fully reorder only the deterministic top-limitset by cosine similarity. Membership is fixed, so recall@limit is preserved by construction; only ordering (R@1/MRR) can change.1.0 <= alpha < 2.0— tiebreaker mode: only reorder adjacent candidates whose deterministic scores are within δ=0.05, using cosine as the tiebreaker.alpha < 1.0— hybrid blending: score = α·det_norm + (1-α)·cosine.
Falls back to search_with_limits() when no embedder is attached.
Auto Trait Implementations§
impl<'a> !RefUnwindSafe for EpisodicStore<'a>
impl<'a> !UnwindSafe for EpisodicStore<'a>
impl<'a> Freeze for EpisodicStore<'a>
impl<'a> Send for EpisodicStore<'a>
impl<'a> Sync for EpisodicStore<'a>
impl<'a> Unpin for EpisodicStore<'a>
impl<'a> UnsafeUnpin for EpisodicStore<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> Fruit for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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