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
fieldofmemory_iddid 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
- Memory
Data - Memory
Patch - Sparse update: only the fields the writer actually touched are
Some. Presence is the “touched” signal — untouched fields areNoneand skipped on the wire. Enables field-level LWW merge (a whole-snapshot update cannot distinguish “cleared” from “carried a stale copy”).topic_keycannot be cleared via a patch (matchesApp::update);Somesets it, absent leaves it. - Relation
Edge - A projected relation edge (directed, from → to). Reconstructed from the log.
Enums§
- Core
Error - Decay
State - Whether a memory is due for human re-validation given its type and age.
- Event
Kind - Relation
- Scope
- Stale
Reason - 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.
NeedsReviewiff the type has a review window and at least that many whole months have elapsed sinceupdated_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).Noneif either timestamp is malformed — the caller treats that asFresh. - 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
RelationAssertedevents into the current relation graph. Deterministic: last-writer-by-(lamport, event_id)per ordered(from_id, to_id)pair. A winningNotConflictassertion 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"), orNonewhen 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.