Part of #534 (Phase 3 EPIC). Builds on #535 (substrate) and #536 (engine).
Thesis
Memories don't live alone — they cause, supersede, contradict, support each other. Storing edges turns "recall" into "navigate from this fact to its consequences" and lets the system flag when a new memory contradicts an old one instead of silently piling up conflicts. Silent conflict accumulation is the #1 source of "memory feels wrong" failures in long-lived stores.
Edge kinds
| Kind |
Meaning |
causes |
A led to B happening |
supersedes |
B replaces A; A should not surface in recall unless asked |
contradicts |
A and B make incompatible claims; needs resolution |
supports |
B is evidence for A |
promoted_from |
B graduated from A (episodic → procedural, etc., for #F lifecycle) |
Concrete
- Edge table in the SQLite store (
memory_edges with from_id, to_id, kind, created_at).
- Recall returns related memories with their relationship (1-hop traversal default, configurable depth).
- Contradiction detection: when a new
semantic or constitutional memory is written, run a gated LLM check against existing memories tagged with overlapping keys. If a conflict is detected, surface to the user via /memory UI: "this fact contradicts X — supersede, keep both, or drop new?"
- Contradiction LLM check is opt-in (cost) and uses the cheapest available model.
Open questions
- How wide should the contradiction-check candidate set be? FTS5-overlap top-N? Same-type same-scope?
- Should contradiction checks run inline (block the write) or async (write first, surface conflict next session)?
- UI: how to render an edge graph in a TUI without becoming visual noise — list view of related memories per hit, or actual graph rendering?
Acceptance signals
- Edges queryable from recall results.
- Contradictions prompt the user, never auto-resolve.
- Edge graph survives session and migration.
supersedes edges suppress superseded memories from default recall (visible only with --include-superseded).
Part of #534 (Phase 3 EPIC). Builds on #535 (substrate) and #536 (engine).
Thesis
Memories don't live alone — they cause, supersede, contradict, support each other. Storing edges turns "recall" into "navigate from this fact to its consequences" and lets the system flag when a new memory contradicts an old one instead of silently piling up conflicts. Silent conflict accumulation is the #1 source of "memory feels wrong" failures in long-lived stores.
Edge kinds
causessupersedescontradictssupportspromoted_fromConcrete
memory_edgeswithfrom_id,to_id,kind,created_at).semanticorconstitutionalmemory is written, run a gated LLM check against existing memories tagged with overlapping keys. If a conflict is detected, surface to the user via/memoryUI: "this fact contradicts X — supersede, keep both, or drop new?"Open questions
Acceptance signals
supersedesedges suppress superseded memories from default recall (visible only with--include-superseded).