Summary
Adds Lakebase-backed persistent memory to CODA. Migrating from datasciencemonkey PR #145.
At session end, a Stop hook extracts 3–8 structured memories from the Claude transcript via the Databricks Claude Haiku serving endpoint, persists them to a coda_memories Postgres table, and regenerates coda_memory.md so the next session opens with the accumulated context already loaded.
Components
memory/extractor.py — Stop hook: parses the JSONL transcript, calls Haiku, writes to Lakebase, regenerates the local memory file.
memory/store.py — psycopg 3 + psycopg_pool with an OAuthConnection subclass that mints a fresh Lakebase OAuth credential on every pool recycle (45 min, ahead of the 1h token expiry). Follows the canonical Databricks Apps + Lakebase Autoscaling pattern.
memory/injector.py — Regenerates ~/.claude/memory/coda_memory.md (or project-scoped variant) from Lakebase.
memory/searcher.py — FTS-ranked search CLI used by the memory-recall subagent.
memory/hooks/user_prompt_submit.py — Zero-cost nudge so Claude knows to invoke the subagent when historical context would help.
setup_memory.py — Per-session schema init, memory-file warm-up, idempotent hook registration.
Schema
coda_memories: content_hash UNIQUE for dedup, content_tsv generated column + GIN index for FTS, nullable vector(1536) + HNSW (kept off by default — semantic search comes later).
Branch
feat/lakebase-memory — about to be pushed.
Diff scope
+6581 / -10, 36 files. Tests in tests/test_memory_*.py.
Follow-ups
- Embedding ingestion + MMR retrieval (vector column is in place, query side isn't yet).
- Memory decay / TTL.
- Multi-tenant scoping (currently single-user).
Summary
Adds Lakebase-backed persistent memory to CODA. Migrating from datasciencemonkey PR #145.
At session end, a Stop hook extracts 3–8 structured memories from the Claude transcript via the Databricks Claude Haiku serving endpoint, persists them to a
coda_memoriesPostgres table, and regeneratescoda_memory.mdso the next session opens with the accumulated context already loaded.Components
memory/extractor.py— Stop hook: parses the JSONL transcript, calls Haiku, writes to Lakebase, regenerates the local memory file.memory/store.py—psycopg 3+psycopg_poolwith anOAuthConnectionsubclass that mints a fresh Lakebase OAuth credential on every pool recycle (45 min, ahead of the 1h token expiry). Follows the canonical Databricks Apps + Lakebase Autoscaling pattern.memory/injector.py— Regenerates~/.claude/memory/coda_memory.md(or project-scoped variant) from Lakebase.memory/searcher.py— FTS-ranked search CLI used by thememory-recallsubagent.memory/hooks/user_prompt_submit.py— Zero-cost nudge so Claude knows to invoke the subagent when historical context would help.setup_memory.py— Per-session schema init, memory-file warm-up, idempotent hook registration.Schema
coda_memories:content_hashUNIQUE for dedup,content_tsvgenerated column + GIN index for FTS, nullablevector(1536)+ HNSW (kept off by default — semantic search comes later).Branch
feat/lakebase-memory— about to be pushed.Diff scope
+6581 / -10, 36 files. Tests in
tests/test_memory_*.py.Follow-ups