Knowledge base
Project entities, decisions, and links live in .senkani/knowledge/*.md — markdown as source of truth. SQLite is a rebuilt index. KBLayer1Coordinator detects staleness and recovers from corruption.
Why markdown + rebuilt index
Markdown is diff-able, review-able, and human-editable. SQLite is fast. Senkani keeps the markdown as the source of truth and the SQLite index as a derivable artifact — if the index gets corrupt or stale, rebuild it from markdown. This is the inverse of the usual pattern ("DB is truth, exports are stale") and it prevents whole classes of data-loss bugs.
Entity → link → decision
- Entity — a named thing: a module, a class, a concept, a person, a library.
upsert_entitycreates or updates. - Link — a typed edge between two entities:
depends_on,replaced_by,authored_by, etc. - Decision — a dated note attached to one or more entities explaining why something was built that way.
FTS5 search
search_knowledge hits the FTS5-indexed body text. BM25 ranking. Queries are sanitized (FTS5 operator syntax stripped) before execution.
Enrichment + validation
High-mention entities (≥ 5× per session) get queued for Gemma enrichment via MLX. EnrichmentValidator flags information loss (enrichment shorter than original body), contradiction (enrichment contains negation of source claims), and excessive rewrite (low Jaccard similarity) before commit. The goal is strict drift detection — enrichment is additive, not editorial.
Rollback + timeline
Every enrichment commit creates an append-only history row. senkani kb rollback <id> reverts the latest enrichment; senkani kb history <id> lists prior versions; senkani kb timeline is a chronological view of all KB mutations across the project.
Layer 1 coordinator
KBLayer1Coordinator detects SQLite index staleness (markdown newer than indexed) and corruption (unreadable pragmas). In either case it rebuilds from markdown without stopping the MCP server. Hand-edits to .senkani/knowledge/*.md are safe — the index follows.
Portable vault (Phase V.7)
The markdown vault is project-local by default but relocatable. Set kb_vault_path in ~/.senkani/config.json (or pass senkani kb migrate --to <path> — the CLI persists the path for you) to keep the vault next to other Obsidian vaults instead of inside the project tree. The resolver appends <project-slug> per-project so multiple repos sharing one vault root never collide on entity name. senkani kb migrate and senkani kb unmigrate move files in either direction; both are content-hash idempotent (running twice is a no-op) and surface conflicts (dest content differs) as a non-zero exit instead of silently overwriting. WikiLinkResolver handles click-through resolution for [[Name]] with folder-hint disambiguation ([[skills/auth/Login]] vs [[skills/admin/Login]]).
Bridge to compound learning
See compound learning for the KB ↔ learning bridge: entity-mention counts boost proposal confidence; applied context docs seed entity stubs; rolling back an entity invalidates derived context docs.