Skip to content

EPIC: v0.9.0 Phase 3 — graduate memory from flat markdown to a typed, graph-structured store #534

@Hmbown

Description

@Hmbown

Thesis

Phase 1/2 (#489) borrowed Claude Code's memory integration shape — hierarchy, /memory, @import, quick-add. The substrate is still flat markdown (~/.deepseek/memory.md + anchors.md + JSONL cycle archive). Phase 3 graduates the substrate: typed memory classes, salience-weighted recall, graph edges between related memories, first-class contradiction tracking, and a hygiene loop that keeps the store from becoming stagnant.

Built natively in Rust under crates/tui/src/memory/. No new runtime dependencies. SQLite (already in the workspace via rusqlite in deepseek-state) with FTS5 for the substrate; vectors deferred until proven necessary.

Why now

Phase 1/2 needs to settle in production first. Users need to be living with /memory and @import before we know what the typed model should actually carve at, and what the auto-extraction signal looks like in the wild. This EPIC is soft-blocked on #491, #492, #493, #494, #495, #496, #497 shipping and getting at least one release of soak time.

Why not an external dependency

Considered wiring an external memory service (own MCP server). Rejected: adds a Node runtime requirement, splits the storage story across two systems, and the sophisticated parts of those designs (typed records, multi-signal recall, graph topology, contradiction tracking) are concepts we can implement natively in Rust without taking on a runtime dependency.

Why SQLite + FTS5

  • OLTP shape matches the access pattern (frequent small reads/writes, point lookups by id, status updates).
  • FTS5 ships built into SQLite — text search without a separate index.
  • Recursive CTEs cover graph traversal until proven insufficient.
  • sqlite-vec exists if/when vector recall becomes necessary.
  • Single-file backup, debuggable from any machine with sqlite3.

DuckDB rejected: analytical/OLAP shape, wrong fit for frequent small writes. LanceDB rejected for now: vector-first, columnar, versioning-on-every-write would create write amplification on status updates; revisit specifically if embedding-based recall becomes core. SurrealDB rejected: too young, recursive CTEs cover the graph case.

Sub-issues (all v0.9.0)

Out of scope

  • Replacing session_manager.rs / runtime_threads.rs / task_manager.rs — those persist execution state, not memory. They keep their own SQLite stores.
  • Vector embeddings (deferred; revisit only if FTS5 + signals proves insufficient).
  • Multimodal memory blobs.
  • Team / shared memory across users.

Acceptance signals

  • User-facing surface (/memory editor, # add, @import) unchanged from Phase 1/2.
  • Existing ~/.deepseek/memory.md and anchors.md migrate cleanly on first run; originals preserved as .bak.
  • Recall is typed and ranked, not BM25-over-flat-files.
  • Contradictions surfaced to the user, never silently auto-resolved.
  • Memory store gets less annoying over time, not more — measured by user-initiated drops trending down.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    Status
    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions