Skip to main content

Crate memnite_core

Crate memnite_core 

Source
Expand description

memnite-core: event-sourced foundation (event log + replay).

Structs§

Anchor
Conflict
A cross-writer lost-field conflict: a value some writer set for field of memory_id did not survive into the projected winner (it lost to a different writer). Heuristic — lamport is a total order, not causal — so this can over-report a deliberately-superseded edit. Advisory; never blocks.
Event
Log
Append-only NDJSON event log. The single source of truth.
Memory
MemoryData
MemoryPatch
Sparse update: only the fields the writer actually touched are Some. Presence is the “touched” signal — untouched fields are None and skipped on the wire. Enables field-level LWW merge (a whole-snapshot update cannot distinguish “cleared” from “carried a stale copy”). topic_key cannot be cleared via a patch (matches App::update); Some sets it, absent leaves it.
RelationEdge
A projected relation edge (directed, from → to). Reconstructed from the log.

Enums§

CoreError
DecayState
Whether a memory is due for human re-validation given its type and age.
EventKind
Relation
Scope
StaleReason
Status

Functions§

apply
Apply a single event to a state map, in place. This is the per-event fold step used by replay; exposed so an incremental projection (e.g. a SQLite store) shares the exact same semantics as a full rebuild.
decay_state
Decay verdict. NeedsReview iff the type has a review window and at least that many whole months have elapsed since updated_ts. Unknown type or unparseable timestamp → Fresh (fail-open: an advisory nudge must never block or misfire).
detect_conflicts
Detect cross-writer lost-field conflicts across the event log. Pure, total, deterministic (memory_ids sorted; fields in fixed order). Skips memories with a terminal MemoryDeleted.
months_elapsed
Whole months elapsed between two RFC3339 timestamps, comparing only the fixed “YYYY-MM-DD” date prefix (std only, no chrono): (y2-y1)*12 + (m2-m1), minus 1 if the day-of-month has not yet been reached (a partial month doesn’t count). Never negative (clamped to 0). None if either timestamp is malformed — the caller treats that as Fresh.
new_event_id
Generate a fresh, monotonic, sortable event id (ULID, 26 chars). This is the only non-deterministic call in the crate; keep it out of fold.
next_lamport
Next logical-clock value: one past the highest lamport seen. Empty stream starts at 1.
normalize_project
Canonical form of a project name: trimmed, lowercased, with every maximal run of separators (-, _, or whitespace) collapsed into a single -, and no leading or trailing -. Idempotent: normalize_project(&normalize_project(s)) == normalize_project(s).
replay
Fold an event stream into current memory state. Deterministic: events are sorted by (lamport, event_id) before applying.
replay_relations
Fold RelationAsserted events into the current relation graph. Deterministic: last-writer-by-(lamport, event_id) per ordered (from_id, to_id) pair. A winning NotConflict assertion removes the edge (retraction) — it is absent from the map. Non-relation events are ignored.
review_marker
Inline recall marker, e.g. Some("needs_review: decision, 7mo"), or None when the memory is fresh. Shared by every recall surface (CLI + MCP) so the annotation is byte-identical everywhere.
threshold_months
Review window per memory type, in months. None = the type never decays. Policy lives in code by design (no config file); changing it = edit this table.