The architecture that ends mid-conversation amnesia — Canon · Recall · Spine · Auto-recall. v3 · spine-first
Write paths feed the indexer → ChromaDB & Canon. A query embeds once; that single embedding drives both the spine match and the vector recall (the RECALL↔SPINE coupling), and the spine's required obligations are placed above the similarity hits — spine-first.
| Layer | Question it answers | Mechanism | Live |
|---|---|---|---|
| Canon | "What is the verified, deterministic fact?" | Gitea reference cards (/opt/gaios/canon), edited only via canon_set | — cards |
| Recall | "What is similar to what I'm doing?" | ChromaDB vector search (nomic-embed-text 768-dim) over 4 collections | — docs |
| Spine | "What is required but dissimilar?" | Per-project dependency-validity DAG, hint-scoped | — spines · — gaps |
| Auto-recall | "How do I never forget to look?" | Per-turn enrichment + get_context bootstrap (spine-first) | always-on |
Dense ≤8 KB markdown reference cards (/opt/gaios/canon/*.md, Gitea branch main), one per fact/domain/incident — the single source of truth for anything deterministic (ports, IPs, paths, rules, incidents). — cards today. Edited only via canon_set (commit + push); searchable in Recall within ~60 s. The forcing function: pull the card and cite it inline before stating an infra fact.
ChromaDB on 127.0.0.1:8000, four collections, all embedded by nomic-embed-text (768-dim) served VPS-local at 127.0.0.1:11434 (one embedder for index and query). Queried via the recall MCP tool — embed → search each collection → merge, sort L2 ascending.
| Collection | Source | Live docs | Holds |
|---|---|---|---|
| canon | /opt/gaios/canon/*.md | — | verified reference cards |
| sessions-v2 | memory/conversation_sync/*.json | — | synced session summaries / decisions |
| projects-v2 | memory/projects/*.json | — | project state + next steps |
| ideas | memory/idea_pipeline/*.json | — | idea backlog |
Distance scale (probe-derived): ≤300 good · 300–400 loose · >400 noise (a random query scores ~443).
gaios_indexer.py (gaios-indexer.service) polls every 60 s: hash-change → re-embed + upsert; deleted → remove; failure → log + skip. Live: — documents tracked, status —. Every durable write becomes searchable within ~60 s automatically.
Vector recall returns what is similar, never what is required. The Project Spine closes that gap: a curated, machine-verified, per-project dependency-validity DAG (/home/ubuntu/api/spines/<project>.json, engine spine.py). A node = a validity-critical obligation whose absence invalidates downstream output; status is computed by running the node's typed checks — no passing verifier, never "done". Hint-scoped (semantic, bind threshold 0.6); >1 match → MULTIPLE SPINES MATCHED — confirm rather than guess. Live: — spines (—) with — open gaps.
Recall is the workhorse (hundreds/day) and used to be spine-blind. Now recall starts from the spine — and the two are coupled through a single embedding:
Conservative by design — false authority (a wrong spine injected as "required") is worse than a missing one, so binding needs a margin and never silently picks on a tie. Single-embed; cached profile embeddings + TTL gaps cache → warm cost is a few cosines. Fail-safe: if the spine engine is down, recall still returns its hits. Per-token auto-recall stays spine-blind by design (spine injection at machine speed would bloat and stall). Engine: /home/ubuntu/api/recall_spine.py.
inference_proxy is hard-injected with a <gaios_recall_context> block (embed user text → top-K → prepend) before the model sees the prompt.hint it assembles (now spine-first): SPINE gaps, recall hits, identity profile, active projects, pending tasks, recent sessions/ideas. One call and the agent is grounded.canon_set→canon · sync_conversation→sessions · save_task/project→projects/tasks · log_idea→ideas. All re-embed ~60s.
Cowork-Claude · 5 Pantheon ministers · HESTIA · HQ workers — all bound by recall-before-action + spine-first.
JSON under /home/ubuntu/memory/{projects,conversation_sync,idea_pipeline,task_queue} — durable truth the index mirrors. Tasks: —.
recall-before-action · spine-first · precommit before any state change · recall before declaring a limitation.
| Component | Where | Service / tool |
|---|---|---|
| Canon store | /opt/gaios/canon (Gitea) | canon_set / canon_get |
| ChromaDB | 127.0.0.1:8000 | chromadb.service |
| Embedder | 127.0.0.1:11434 (nomic-embed-text, keep-alive) | Ollama (VPS-local) |
| Indexer | /home/ubuntu/api/gaios_indexer.py | gaios-indexer.service (60s) |
| Recall library | /home/ubuntu/api/recall_lib.py | recall MCP tool (gaios-ext) |
| Spine engine | /home/ubuntu/api/spine.py + spines/*.json | spine.py · gaps-json |
| Spine-first layer | /home/ubuntu/api/recall_spine.py | recall (Cowork + ministers + HESTIA) |
| Auto-recall / bootstrap | inference_proxy.py · gaios_mcp.py get_context | per-turn + session-start |
| Live stats feed | memory_stats.py → /data/memory-stats.json | memory-stats.timer (2 min) |