Architecture and security boundaries

CLI and MCP delegate to shared deterministic services; optional AI remains outside that path.

flowchart TB
    subgraph hosts["Agent hosts"]
        H1["Codex"]
        H2["Claude Code"]
        H3["Cursor"]
        H4["Gemini CLI / Claude Desktop"]
    end

    subgraph adapters["Protocol adapters"]
        CLI["CLI · knowl …"]
        MCP["MCP · knowl serve"]
        HOOK["Short-lived lifecycle hooks"]
        VIEW["GET-only local viewer"]
    end

    subgraph core["Deterministic core services"]
        GOV["Validation · reconciliation · history"]
        RET["Vector-primary retrieval · BM25 fallback · context"]
        LIFE["Tasks · sessions · handoffs"]
        EVID["Evidence · drift · code index"]
        WS["Workspace federation"]
        SYN["Skills · tag synthesis"]
    end

    subgraph local["Local project state"]
        DB[(" .knowl/knowl.db ")]
        SK[".knowl/skills/"]
        MAN["Machine-local workspace manifest"]
        PEER[("Promoted peer atoms · read-only")]
    end

    AI["Optional configured AI<br/>ask · raw ingest · assisted comparison/derivation"]

    hosts --> CLI
    hosts --> MCP
    hosts --> HOOK
    CLI --> GOV
    CLI --> RET
    CLI --> LIFE
    CLI --> EVID
    CLI --> WS
    CLI --> SYN
    MCP --> GOV
    MCP --> RET
    MCP --> LIFE
    MCP --> EVID
    MCP --> WS
    MCP --> SYN
    HOOK --> LIFE
    VIEW --> DB
    GOV --> DB
    RET --> DB
    LIFE --> DB
    EVID --> DB
    WS --> DB
    SYN --> DB
    SYN --> SK
    WS --> MAN
    WS --> PEER
    CLI -. configured only .-> AI
    MCP -. configured ingest/derivation .-> AI
    AI --> GOV
Layer Source Responsibility
Protocol and commands src/mcp, src/cli MCP registration, CLI parsing, host setup, lifecycle envelopes
Core contracts src/core Types, validation boundaries, formatting, configuration, token budgets
Store and retrieval src/store SQLite schema, assertions, evidence, ranking, sessions, portability, maintenance
Workspace federation src/workspace External manifests, membership, ownership, promotion, peer resolution
Code intelligence src/code Tree-sitter indexing and symbol:// resolution
Learned skills src/skills File-backed package validation, registry, entrypoint execution
Viewer src/viewer Loopback-only graph and inspection APIs
Optional AI src/pipeline, src/ai Filter → extract → verify → merge pipeline, question answering, assisted derivation

Storage, retrieval, governance, lifecycle, skills, and synthesis need no provider. Writes always pass size validation and, by default, secret and sensitive-path checks. The database and skills are local; workspace manifests hold external machine paths; the unauthenticated viewer is loopback-only.

Write durability

All three SQLite databases — the knowledge store, the transcript index, and the resume store — run in WAL with synchronous = NORMAL.

NORMAL does not fsync on every commit. An application crash, a killed knowl serve, Ctrl-C, or a closed laptop lid still lose nothing: SQLite's documentation is explicit that "transactions are durable across application crashes regardless of the synchronous setting or journal mode", and that "WAL mode is safe from corruption with synchronous=NORMAL". Only a power cut or an OS crash can drop the last seconds of writes, and the file still opens cleanly afterwards. Measured against FULL on this schema, NORMAL is 4.19× on un-batched writes — the common shape here, since one knowl_store or one hook capture is a single write — and better under contention.

Variable Default Meaning
KNOWL_SQLITE_SYNCHRONOUS NORMAL NORMAL or FULL. Set FULL to fsync every commit, buying durability across power loss at roughly 4× the per-write cost. OFF is refused: it can corrupt the database on power loss and measured no faster than NORMAL. An unrecognised value stops the command rather than silently falling back.