← Reports

Vault Architecture — Data Flow & Memory System

How Lucienne and Luci share knowledge, store data, and recall past work

Date: 2026-04-07  |  Implemented during MC-232 resolution

2
Databases
8
MCP Tools
403
Sessions Indexed
15 min
Git Sync Interval

Architecture Diagram

LOCAL (Lucienne's Mac) REMOTE (Luci, Hetzner) ┌─────────────────────────┐ ┌──────────────────────────┐ │ │ │ │ │ vault.db R/W───git push─────>vault.db READ ONLY │ │ ├─ files (90) │ │ pulled via git every 15m │ │ ├─ edges (42) │<──git pull──────│ │ │ ├─ tags (57) │ │ mc.db R/W │ │ ├─ sessions_index (25) │ │ ├─ tickets (242) │ │ ├─ activity_log │ │ ├─ task_runs (5,067) │ │ ├─ search_fts (FTS5) │ │ ├─ sessions_index (378) │ │ └─ vitals_log │ │ ├─ heartbeats (499) │ │ │ │ ├─ activity_log │ │ vault_mcp.py MCP │ │ └─ ticket_comments │ │ ├─ memory_search │ │ │ │ ├─ session_search ─────│───MC API────────>vault_mcp.py MCP │ │ ├─ activity_log ───────│───MC API────────>(same code, reads both │ │ ├─ luci_status ────────│───MC API────────> vault.db + mc.db) │ │ └─ graph_neighbors │ │ │ │ │ │ MC API :3001 │ │ dashboard.py :8787───MC API────────>│ ├─ /api/v1/tickets │ │ (reads local vault.db │ │ ├─ /api/v1/activity │ │ + MC API for tickets) │ │ └─ /api/v1/sessions/ │ │ │ │ search │ └─────────────────────────┘ └──────────────────────────┘

Two Databases, Clear Ownership

vault.db — Knowledge Graph

Lucienne OWNS   Luci READS via git

TablePurpose
filesIndex of all markdown files (PKA + personal vault)
edgesTyped relationships between files (belongs_to, references, assigned_to)
tags / tag_assignmentsTag taxonomy and file-tag mappings
sessions_index / sessions_ftsIndexed session transcripts with FTS5 search
activity_logLucienne's activity audit trail
search_ftsFull-text search across all indexed files

Rebuilt by: python index.py --rebuild
Sessions indexed by: python session_indexer.py
Location: PKA/Vault/vault.db

mc.db — Mission Control Ops

Luci OWNS   Lucienne READS via API

TablePurpose
ticketsMC ticket board (242 tickets)
ticket_comments / messagesTicket conversation history
task_runsScheduler execution log (5,067 runs)
sessions_index / sessions_ftsLuci's indexed session transcripts (378)
heartbeatsServer health checks every 15 min
activity_logLuci's activity audit trail

Written by: mc_pickup.py, scheduler.py, heartbeat.py
Sessions indexed by: python session_indexer.py
Location: ~/workspace/mission-control/mc.db

MCP Tools — Memory Recall for Any Session

The vault MCP server runs as a stdio process with each Claude Code session. Configured in .mcp.json on both local and Luci.

memory_search
FTS5 search across all indexed files — memories, tasks, projects, notes. Returns paths, titles, snippets.
memory_recall
Find related memories by topic using FTS + graph edges. Returns direct matches + connected files.
session_search
Search past session transcripts by keyword. Merges local + Luci results via API. Shows what was discussed and when.
activity_log
Recent activity from both sides — merges local vault.db + Luci mc.db entries. Filter by days, category.
graph_neighbors
Traverse the knowledge graph — find all files connected to a given file via typed edges.
file_lookup
Query files by type, status, project, assignee. "Show me all todo tasks assigned to Lucienne."
memory_health
Lifecycle tracking — which memories are stale, who owns them, when last reviewed.
luci_status
Live check on Luci — active tickets, inbox count, recent activity. Queries MC API.

Data Flow — How Information Moves

Lucienne writes → Luci reads (via git)

1
Lucienne creates/edits markdown files

Memory files, tasks, projects, notes in PKA/Vault/. Personal vault data in ~/.claude/vault/.

2
index.py scans and builds vault.db

Parses frontmatter, extracts wikilinks, creates typed edges, populates FTS5. Runs on each dashboard refresh.

3
Git push → Luci pulls every 15 minutes

Git-sync task on Luci pulls the repo. vault.db is included in git (Luci reads it). Luci never pushes vault.db changes back — .git/info/exclude prevents it.

4
Luci's MCP server reads the git-pulled vault.db

Any Luci session can search Lucienne's memories, files, edges, and sessions via the same MCP tools.

Luci writes → Lucienne reads (via MC API)

1
Luci processes tickets, runs tasks, logs activity

mc_pickup.py, scheduler.py, heartbeat.py all write to mc.db. Session transcripts accumulate in ~/.claude/projects/.

2
session_indexer.py mines transcripts into mc.db

378 sessions indexed with user requests, assistant summaries, tools used, files touched. Searchable via FTS5.

3
MC API serves the data at :3001

/api/v1/activity — Luci's activity log
/api/v1/sessions/search?q=... — search Luci's session transcripts
/api/v1/tickets — ticket board, comments, messages

4
Lucienne's MCP tools query the API transparently

session_search("telegram") returns 3 local + 3 Luci results merged. activity_log() merges both sides. luci_status() shows live Luci state.

Session Transcript Indexing

Claude Code stores every conversation as JSONL files. The session indexer parses these and extracts structured data into SQLite with FTS5 search — turning raw transcripts into searchable institutional memory.

FieldSourceExample
session_idJSONL filename789e09ec-f299-...
started_atFirst message timestamp2026-04-07T09:35:25Z
branchGit branch at session startmaster
user_requestsFirst line of each user message"have a look at MC232" | "set everything up"
summaryFirst lines of assistant responses"Let me boot up and pull that ticket..."
tools_usedAll tool_use blocksBash, Read, Edit, Agent, SSH
key_filesFile paths from Read/Edit/Writevault_mcp.py, schema.sql, mc_pickup.py

Run: python session_indexer.py (incremental) or python session_indexer.py --rebuild (full)
Local: indexes from ~/.claude/projects/-Users-elmar-PKA/ → vault.db
Luci: indexes from ~/.claude/projects/-home-lucienne-workspace/ → mc.db

Key Files

FileLocationPurpose
vault.dbPKA/Vault/vault.dbKnowledge graph + session index (Lucienne owns)
mc.dbLuci: ~/workspace/mission-control/mc.dbMC ops + session index (Luci owns)
vault_mcp.pyPKA/vault_mcp.py + Luci: ~/workspace/vault_mcp.pyMCP server — 8 tools for memory recall
session_indexer.pyPKA/session_indexer.py + Luci: ~/workspace/session_indexer.pyMines JSONL transcripts into DB
index.pyPKA/index.pyMarkdown file indexer — builds vault.db knowledge graph
schema.sqlPKA/Vault/schema.sqlCanonical vault.db schema (v2)
mc_pickup.pyLuci: ~/workspace/mc_pickup.pyMC ticket dispatcher — now uses mc.db
git-sync.mdLuci: ~/workspace/tasks/git-sync.mdEvery 15 min — pull/push PKA, excludes vault.db
.mcp.jsonPKA/.mcp.json + Luci: ~/.claude/.mcp.jsonMCP server configuration

Rules

RuleWhy
Lucienne NEVER writes to mc.dbmc.db is Luci's operational database — accessed via API only
Luci NEVER writes to vault.dbvault.db is in git — binary merge conflicts cause data loss (MC-232)
vault.db stays in gitLuci needs to read it (memories, knowledge graph) via git pull
vault.db excluded from Luci git staging.git/info/exclude prevents Luci from pushing vault.db changes
Git-sync excludes vault.db, mc.db, .bak filesPrevents binary file conflicts and backup file noise
MCP tools merge both sides transparentlysession_search, activity_log query local + Luci via API
Markdown is source of truth, DB is indexvault.db is rebuildable from files via index.py --rebuild
Historical note: ~2,083 local activity_log entries were lost on 2026-04-07 during the vault.db rebuild (disk I/O error mid-migration). The activity_log was mostly index rebuild noise. Real institutional memory lives in session transcripts (now indexed), MC tickets, and git history.
Session indexing is manual. Run python session_indexer.py periodically to index new sessions. Consider adding it as a scheduled task on Luci for automatic indexing.