Part of #534 (Phase 3 EPIC). Builds on #535 (substrate).
Thesis
Treat memories as typed records, not lines in a file. Different kinds of memory have different lifecycles and different rules for promotion, decay, and recall. Recall scores candidates by recency + salience + access frequency + scope match, not raw text grep — and returns explanation strings so users can see why a memory was surfaced.
Memory types
Initial taxonomy (extensible):
| Type |
Example |
semantic |
"the API base URL is api.deepseek.com" |
episodic |
"user rejected the autoformat-on-save proposal in this session" |
procedural |
"to deploy: cargo build --release && scp …" |
reflective |
"last refactor of compaction.rs broke working_set tests — be cautious" |
intentional |
"next step: wire moontree-style memory" |
constitutional |
"this user prefers explicit error handling over unwrap" |
restriction |
"never run git push --force without confirming" |
Recall ranking
Score = w_text * fts5_rank + w_recency * recency_decay + w_salience * salience + w_frequency * log(access_count) + w_scope * scope_match.
Each hit returns a RecallHit { memory, score, explanation: "matched 'compaction' (FTS) + accessed 4× this session + recent" }. Users see why something was surfaced; this is also debuggable.
Concrete
- Memory record schema in
crates/tui/src/memory/model.rs.
- Recall function in
crates/tui/src/memory/recall.rs.
- Replace
tools/recall_archive.rs BM25 with the new ranker.
/memory UI surfaces type as a column.
- Existing flat-file content imports as
semantic by default.
- No embeddings in this issue — FTS5 + signals first. Reopen for vectors only if quality wall hit.
Open questions
- Which types does the model write directly (via a tool call) vs which are auto-classified by the extraction subagent (#E)?
- How aggressive is salience decay? Half-life of 30 days? 7? Per-type?
- Default weights for the recall scoring function.
Acceptance signals
recall(query, scope) returns ranked, typed results with explanations.
/memory UI surfaces type and recall score.
- Recall regression: a fixture set of memories + queries produces stable rankings across runs.
- Existing flat-file content survives migration as
semantic memories.
Part of #534 (Phase 3 EPIC). Builds on #535 (substrate).
Thesis
Treat memories as typed records, not lines in a file. Different kinds of memory have different lifecycles and different rules for promotion, decay, and recall. Recall scores candidates by recency + salience + access frequency + scope match, not raw text grep — and returns explanation strings so users can see why a memory was surfaced.
Memory types
Initial taxonomy (extensible):
semanticepisodicproceduralreflectiveintentionalconstitutionalrestrictiongit push --forcewithout confirming"Recall ranking
Score =
w_text * fts5_rank + w_recency * recency_decay + w_salience * salience + w_frequency * log(access_count) + w_scope * scope_match.Each hit returns a
RecallHit { memory, score, explanation: "matched 'compaction' (FTS) + accessed 4× this session + recent" }. Users see why something was surfaced; this is also debuggable.Concrete
crates/tui/src/memory/model.rs.crates/tui/src/memory/recall.rs.tools/recall_archive.rsBM25 with the new ranker./memoryUI surfaces type as a column.semanticby default.Open questions
Acceptance signals
recall(query, scope)returns ranked, typed results with explanations./memoryUI surfaces type and recall score.semanticmemories.