pub struct App { /* private fields */ }Expand description
An open Memnite instance: the event log + its SQLite projection.
Implementations§
Source§impl App
impl App
Sourcepub fn open(data_dir: impl AsRef<Path>) -> Result<Self, CliError>
pub fn open(data_dir: impl AsRef<Path>) -> Result<Self, CliError>
Open (creating if needed) a Memnite data dir: <dir>/log/ + <dir>/memnite.db.
Sourcepub fn add(
&self,
spec: AddSpec,
root: &Path,
ctx: &EventCtx,
) -> Result<MemoryRow, CliError>
pub fn add( &self, spec: AddSpec, root: &Path, ctx: &EventCtx, ) -> Result<MemoryRow, CliError>
Create a memory: stamp anchor hashes from root, append a MemoryAdded
event to the log, and project it. Returns the projected MemoryRow.
Sourcepub fn session_summary(
&self,
summary: String,
project: String,
scope: Scope,
ctx: &EventCtx,
) -> Result<MemoryRow, CliError>
pub fn session_summary( &self, summary: String, project: String, scope: Scope, ctx: &EventCtx, ) -> Result<MemoryRow, CliError>
Persist a session summary as a memory (mem_type = "session_summary").
Model-driven: the caller passes the distilled text. Plain add — summaries
accumulate as history (no topic_key upsert).
Sourcepub fn get(&self, memory_id: &str) -> Result<Option<MemoryRow>, CliError>
pub fn get(&self, memory_id: &str) -> Result<Option<MemoryRow>, CliError>
Fetch one memory by id.
Sourcepub fn rebuild(&self) -> Result<usize, CliError>
pub fn rebuild(&self) -> Result<usize, CliError>
Rebuild the projection from the full log. Returns the event count folded.
Sourcepub fn search(
&self,
query: impl Into<SearchQuery>,
) -> Result<Vec<MemoryRow>, CliError>
pub fn search( &self, query: impl Into<SearchQuery>, ) -> Result<Vec<MemoryRow>, CliError>
Full-text search over memories, narrowed by optional filters. User text
is sanitized into FTS5 syntax; a blank query returns no results. Accepts
anything convertible into SearchQuery (e.g. a plain &str).
Sourcepub fn list_stale(&self) -> Result<Vec<MemoryRow>, CliError>
pub fn list_stale(&self) -> Result<Vec<MemoryRow>, CliError>
All memories currently marked stale.
Sourcepub fn delete(&self, memory_id: &str, ctx: &EventCtx) -> Result<(), CliError>
pub fn delete(&self, memory_id: &str, ctx: &EventCtx) -> Result<(), CliError>
Tombstone a memory (append a MemoryDeleted event). Errors if the id is
unknown. Re-deleting an already-deleted memory is a no-op (delete is
terminal in the fold), so no duplicate event is appended.
Sourcepub fn mark(&self, memory_id: &str, ctx: &EventCtx) -> Result<(), CliError>
pub fn mark(&self, memory_id: &str, ctx: &EventCtx) -> Result<(), CliError>
Mark a memory as reviewed: append a MemoryReviewed event, resetting its
decay clock (updated_ts) without changing its status. Errors NotFound if
the id is unknown or already deleted (a tombstone cannot be reviewed).
Sourcepub fn review_list(
&self,
now: &str,
project: Option<&str>,
mem_type: Option<&str>,
) -> Result<Vec<MemoryRow>, CliError>
pub fn review_list( &self, now: &str, project: Option<&str>, mem_type: Option<&str>, ) -> Result<Vec<MemoryRow>, CliError>
Live memories whose decay verdict (given now, an RFC3339 timestamp) is
NeedsReview, optionally narrowed by exact project / mem_type. Read-time
only — nothing is written and the log is untouched.
Sourcepub fn relate(
&self,
from_id: &str,
to_id: &str,
spec: RelationSpec,
ctx: &EventCtx,
) -> Result<(), CliError>
pub fn relate( &self, from_id: &str, to_id: &str, spec: RelationSpec, ctx: &EventCtx, ) -> Result<(), CliError>
Assert a relation from_id → to_id. Appends a RelationAsserted event and
projects it. Both memories must exist, be live (not deleted), and differ.
spec.judged_by records who classified it (“agent” for interactive/manual,
an engine name for the judge).
Sourcepub fn relations_for(
&self,
memory_id: &str,
) -> Result<Vec<RelationRow>, CliError>
pub fn relations_for( &self, memory_id: &str, ) -> Result<Vec<RelationRow>, CliError>
Relation edges touching a memory (as source or target).
Sourcepub fn list_relations(&self) -> Result<Vec<RelationRow>, CliError>
pub fn list_relations(&self) -> Result<Vec<RelationRow>, CliError>
Every relation edge.
Sourcepub fn find_candidates(
&self,
memory_id: &str,
limit: u32,
) -> Result<Vec<MemoryRow>, CliError>
pub fn find_candidates( &self, memory_id: &str, limit: u32, ) -> Result<Vec<MemoryRow>, CliError>
Candidate memories worth relating to memory_id: FTS over its title within
the same project + scope, excluding self / deleted / already-related pairs.
Uses OR-match (broad recall). Returns up to limit rows. Callers treat a
failure as “no candidates” (non-blocking) at the surface layer.
Sourcepub fn conflicts_scan(
&self,
judge: impl Fn(&MemoryView, &MemoryView) -> Result<Verdict, JudgeError>,
judged_by: &str,
since: Option<String>,
limit: u32,
ctx: &EventCtx,
) -> Result<ScanSummary, CliError>
pub fn conflicts_scan( &self, judge: impl Fn(&MemoryView, &MemoryView) -> Result<Verdict, JudgeError>, judged_by: &str, since: Option<String>, limit: u32, ctx: &EventCtx, ) -> Result<ScanSummary, CliError>
Batch scan: for each live memory, find candidates and ask the injected
judge to classify each pair. Non-not_conflict verdicts are asserted as
RelationAsserted events stamped with judged_by (provenance is the
caller’s, never a hardcoded literal — keeps the audit trail honest under a
swapped judge). Judge errors are swallowed per pair (never abort); the first
one is sampled into ScanSummary::first_error.
since limits the scan to memories updated at/after it. It must be the same
RFC3339 form as the stored updated_ts — the comparison is lexical, so a
differently-formatted timestamp will filter incorrectly.
Sourcepub fn check(
&self,
root: &Path,
ctx: &EventCtx,
) -> Result<CheckSummary, CliError>
pub fn check( &self, root: &Path, ctx: &EventCtx, ) -> Result<CheckSummary, CliError>
Run the staleness checker over every anchored, non-deleted memory. When a memory’s verdict changes its status, append the verdict event and project it. Memories without anchors (nothing to verify) are skipped.
Sourcepub fn context(
&self,
project: &str,
limit: u32,
) -> Result<Vec<MemoryRow>, CliError>
pub fn context( &self, project: &str, limit: u32, ) -> Result<Vec<MemoryRow>, CliError>
Recent memories for a project (newest-updated first, deleted excluded).
Sourcepub fn timeline(&self, memory_id: &str) -> Result<Vec<EventMetaRow>, CliError>
pub fn timeline(&self, memory_id: &str) -> Result<Vec<EventMetaRow>, CliError>
Event history of one memory, oldest first.
Sourcepub fn doctor(&self) -> Result<DoctorReport, CliError>
pub fn doctor(&self) -> Result<DoctorReport, CliError>
Compare the log fold against the projection and report divergences. A
clean projection (after any normal op, since each op projects incrementally)
returns zero mismatches and cursor_ok == true.
Sourcepub fn update(
&self,
memory_id: &str,
patch: UpdatePatch,
root: &Path,
ctx: &EventCtx,
) -> Result<MemoryRow, CliError>
pub fn update( &self, memory_id: &str, patch: UpdatePatch, root: &Path, ctx: &EventCtx, ) -> Result<MemoryRow, CliError>
Update a memory by patch: emits a sparse MemoryPatched delta containing
only the fields patch provides — untouched fields are left None and
carry no value over the wire, enabling field-level LWW merge downstream
(see memnite_core::replay). The LOG FOLD (not the projection) is only
consulted to validate the memory exists and is not deleted; it is not used
to fill in omitted fields. Anchors in the patch are re-hashed from root;
omitted anchors are left untouched. Errors if the id is unknown. Returns
the new projected row.
Sourcepub fn import(&self, reader: impl BufRead) -> Result<ImportSummary, CliError>
pub fn import(&self, reader: impl BufRead) -> Result<ImportSummary, CliError>
Import an NDJSON event bundle: append only events whose event_id is not
already in the local log (dedup), then rebuild the projection from the
full log. Rebuild — not incremental apply — because imported events may
carry a lamport below the local max and must be re-folded in
(lamport, event_id) order. Corrupt lines are skipped and counted.
Sourcepub fn export(
&self,
since: Option<u64>,
writer: impl Write,
) -> Result<usize, CliError>
pub fn export( &self, since: Option<u64>, writer: impl Write, ) -> Result<usize, CliError>
Write the event log as an NDJSON bundle (one event per line), sorted by
(lamport, event_id) for deterministic, diff-friendly bundles. With
since, only events whose lamport >= since are written. Returns the
number of events written.
Sourcepub fn ingest(
&self,
source: &dyn IngestSource,
root: &Path,
project: &str,
ctx: &EventCtx,
) -> Result<IngestSummary, CliError>
pub fn ingest( &self, source: &dyn IngestSource, root: &Path, project: &str, ctx: &EventCtx, ) -> Result<IngestSummary, CliError>
Ingest memories from any IngestSource (source-agnostic). Each item gets a
deterministic memory_id (mem_ing_<source>_<key-slug>); a new id is
added, a changed one (by projected title/body/type/topic) is updated, an
unchanged one is skipped. Idempotent.