The four layers
- JSONL ground truth — every chat turn, every tool call, written to
~/pippa-db/sessions/{conversation_id}.jsonlbefore being shown to Dad. The system of record. Encrypted at rest with Fernet. - SQLite cache — fast index over conversations, brains, message ordering. Derived from JSONL — purgeable and rebuildable.
- ChromaDB embeddings — semantic search over the Obsidian vault and over conversation history. Embedded with BGE-M3 via Ollama (1024-dim, multilingual, local).
- Obsidian vault — Pippa's distilled long-term identity and lessons. Hand-curated by Pippa (with Dad's approval) when something is worth promoting from chat to permanent record.
Retrieval contract
When Pippa answers, the context engine assembles: vault entry point (instructions.md), then identity and core files, then index files on demand. Conversation memory and tool outputs come from JSONL via the SQLite index. Vector retrieval over the vault sits on top for the rare 'where did I write about X' queries.
Why two retrieval styles
Vault is loaded fully (with on-demand expansion for large index files); semantic similarity is unnecessary because Pippa already knows the structure. Conversation history is too big to load fully — that is where vector retrieval earns its keep.
What this teaches generally
- JSONL ground truth + derived index is the durability pattern that survives every database choice.
- Hand-curated semantic memory beats auto-distilled memory for identity-critical content.
- Two retrieval styles (full-load vs vector) coexist comfortably when each fits its data shape.