lorekeeper-devlisted
Install: claude install-skill Jessinra/Lorekeeper
# Lorekeeper Dev
Practices and conventions for developing the Lorekeeper MCP server.
## Architecture
Two vector store backends (switch via `LORE_VECTOR_STORE`):
- **LanceDB** (default) — concurrent multi-process, no lock files. `LanceDBEngine` in `lancedb_engine.py`. Uses sentence-transformers directly, no Mem0 for vectors.
- **Chroma** (fallback, `LORE_VECTOR_STORE=chroma`) — Mem0-backed `ChromaDBEngine` in `chromadb_engine.py`. Single-process only.
- **SQLite sidecar** — memory metadata (`score`, `confidence`, `soft_deleted`, `usage_count`), all `MemoryLink` rows, BM25 index source. Shared by both backends.
Engine factory: `engine_factory.py` → `build_engine()`. Orchestrator: `MemoryService` in `orchestrator.py` (was `Orchestrator` in earlier versions).
Canonical identity: `lore_id` UUID lives in the vector store's metadata. All app logic uses `lore_id`.
## Hybrid Scoring Formula
```
combined = 0.45·semantic + 0.30·keyword + 0.15·(score/10) + 0.10·log_usage_norm
```
Weights are env-configurable (`LORE_W_*`). Dedup threshold: `0.6·semantic + 0.4·keyword >= 0.85`.
## Known Quirks
**Chroma distance vs. similarity (critical):**
Mem0 v2 `score_and_rank` receives Chroma cosine _distances_ but treats them as similarities — items with distance ~0.0 get filtered out; unrelated items (distance ~1.0) score 1.0 and block all inserts.
**Fix**: bypass mem0 pipeline — embed directly with `SentenceTransformer`, query the collection directly, return `score = 1.0 - distance`.