A few choices that have shaped every other choice:
The store has one user (you). There are no multi-tenant primitives to design around. When the design has to choose between flexibility and simplicity, it picks simplicity.
Vendor coupling lives in two pluggable seams, configured separately:
EmbeddingProvider (always used) and the optional
GenerativeProvider. A generative LLM may be used for
background / maintenance work through that second seam, but
never on the synchronous recall/remember path — a normal read or
write never depends on a generative model being up. With no generative
provider configured the server runs fully on embeddings plus
deterministic heuristics. MCP tool descriptions stay generic: they say
“the calling LLM,” not “Claude.” Adding a provider is one class plus
an application.ini switch.
The auto-migration framework will refuse to drop, rename, or rewrite existing data. Schema changes add columns or indexes. Destructive operations (column resizes for an embedding dim change, for example) are deliberate, narrow exceptions covered in Embedding Migration.
A WAR swap can be rolled back in seconds. Restoring a database from backup costs you every memory written between the backup and the rollback. Every operational procedure in this manual is built around that asymmetry: take the backup first, change the data carefully, keep the rollback path short.
The MCP tools any LLM can call are deliberately read/write-of-facts only. Migration triggers, re-embedding, log inspection, schema fiddling — all of those are operator actions, performed by editing application.ini and restarting, or by running SQL directly. This makes it impossible for an LLM with a leaked access token to cause structural damage to the store.