141 lines
5.4 KiB
Markdown
141 lines
5.4 KiB
Markdown
# Memory Architecture
|
||
|
||
> How Timmy remembers, recalls, and learns — without hallucinating.
|
||
|
||
Refs: Epic #367 | Sub-issues #368, #369, #370, #371, #372
|
||
|
||
## Overview
|
||
|
||
Timmy's memory system uses a **Memory Palace** architecture — a structured, file-backed knowledge store organized into rooms and drawers. When faced with a recall question, the agent checks its palace *before* generating from scratch.
|
||
|
||
This document defines the retrieval order, storage layers, and data flow that make this work.
|
||
|
||
## Retrieval Order (L0–L5)
|
||
|
||
When the agent receives a prompt that looks like a recall question ("what did we do?", "what's the status of X?"), the retrieval enforcer intercepts it and walks through layers in order:
|
||
|
||
| Layer | Source | Question Answered | Short-circuits? |
|
||
|-------|--------|-------------------|------------------|
|
||
| L0 | `identity.txt` | Who am I? What are my mandates? | No (always loaded) |
|
||
| L1 | Palace rooms/drawers | What do I know about this topic? | Yes, if hit |
|
||
| L2 | Session scratchpad | What have I learned this session? | Yes, if hit |
|
||
| L3 | Artifact retrieval (Gitea API) | Can I fetch the actual issue/file/log? | Yes, if hit |
|
||
| L4 | Procedures/playbooks | Is there a documented way to do this? | Yes, if hit |
|
||
| L5 | Free generation | (Only when L0–L4 are exhausted) | N/A |
|
||
|
||
**Key principle:** The agent never reaches L5 (free generation) if any prior layer has relevant data. This eliminates hallucination for recall-style queries.
|
||
|
||
## Storage Layout
|
||
|
||
```
|
||
~/.mempalace/
|
||
identity.txt # L0: Who I am, mandates, personality
|
||
rooms/
|
||
projects/
|
||
timmy-config.md # What I know about timmy-config
|
||
hermes-agent.md # What I know about hermes-agent
|
||
people/
|
||
alexander.md # Working relationship context
|
||
architecture/
|
||
fleet.md # Fleet system knowledge
|
||
mempalace.md # Self-knowledge about this system
|
||
config/
|
||
mempalace.yaml # Palace configuration
|
||
|
||
~/.hermes/
|
||
scratchpad/
|
||
{session_id}.json # L2: Ephemeral session context
|
||
```
|
||
|
||
## Components
|
||
|
||
### 1. Memory Palace Skill (`mempalace.py`) — #368
|
||
|
||
Core data structures:
|
||
- `PalaceRoom`: A named collection of drawers (topics)
|
||
- `Mempalace`: The top-level palace with room management
|
||
- Factory constructors: `for_issue_analysis()`, `for_health_check()`, `for_code_review()`
|
||
|
||
### 2. Retrieval Enforcer (`retrieval_enforcer.py`) — #369
|
||
|
||
Middleware that intercepts recall-style prompts:
|
||
1. Detects recall patterns ("what did", "status of", "last time we")
|
||
2. Walks L0→L4 in order, short-circuiting on first hit
|
||
3. Only allows free generation (L5) when all layers return empty
|
||
4. Produces an honest fallback: "I don't have this in my memory palace."
|
||
|
||
### 3. Session Scratchpad (`scratchpad.py`) — #370
|
||
|
||
Ephemeral, session-scoped working memory:
|
||
- Write-append only during a session
|
||
- Entries have TTL (default: 1 hour)
|
||
- Queried at L2 in retrieval chain
|
||
- Never auto-promoted to palace
|
||
|
||
### 4. Memory Promotion — #371
|
||
|
||
Explicit promotion from scratchpad to palace:
|
||
- Agent must call `promote_to_palace()` with a reason
|
||
- Dedup check against target drawer
|
||
- Summary required (raw tool output never stored)
|
||
- Conflict detection when new memory contradicts existing
|
||
|
||
### 5. Wake-Up Protocol (`wakeup.py`) — #372
|
||
|
||
Boot sequence for new sessions:
|
||
```
|
||
Session Start
|
||
│
|
||
├─ L0: Load identity.txt
|
||
├─ L1: Scan palace rooms for active context
|
||
├─ L1.5: Surface promoted memories from last session
|
||
├─ L2: Load surviving scratchpad entries
|
||
│
|
||
└─ Ready: agent knows who it is, what it was doing, what it learned
|
||
```
|
||
|
||
## Data Flow
|
||
|
||
```
|
||
┌──────────────────┐
|
||
│ User Prompt │
|
||
└────────┬─────────┘
|
||
│
|
||
┌────────┴─────────┐
|
||
│ Recall Detector │
|
||
└────┬───────┬─────┘
|
||
│ │
|
||
[recall] [not recall]
|
||
│ │
|
||
┌───────┴────┐ ┌──┬─┴───────┐
|
||
│ Retrieval │ │ Normal Flow │
|
||
│ Enforcer │ └─────────────┘
|
||
│ L0→L1→L2 │
|
||
│ →L3→L4→L5│
|
||
└──────┬─────┘
|
||
│
|
||
┌──────┴─────┐
|
||
│ Response │
|
||
│ (grounded) │
|
||
└────────────┘
|
||
```
|
||
|
||
## Anti-Patterns
|
||
|
||
| Don't | Do Instead |
|
||
|-------|------------|
|
||
| Generate from vibes when palace has data | Check palace first (L1) |
|
||
| Auto-promote everything to palace | Require explicit `promote_to_palace()` with reason |
|
||
| Store raw API responses as memories | Summarize before storing |
|
||
| Hallucinate when palace is empty | Say "I don't have this in my memory palace" |
|
||
| Dump entire palace on wake-up | Selective loading based on session context |
|
||
|
||
## Status
|
||
|
||
| Component | Issue | PR | Status |
|
||
|-----------|-------|----|--------|
|
||
| Skill port | #368 | #374 | In Review |
|
||
| Retrieval enforcer | #369 | #374 | In Review |
|
||
| Session scratchpad | #370 | #374 | In Review |
|
||
| Memory promotion | #371 | — | Open |
|
||
| Wake-up protocol | #372 | #374 | In Review | |