Documentation

Core Concepts

Learn the state, consistency, security, and retrieval concepts that define KuraDB behavior.

Read-only service boundary

KuraDB is read-only from the consumer's perspective. The HTTP API accepts health, list, and search requests, but never content mutations. Filesystem ingestion is the only content-write path:

watched inbox → parser → databaseHandler.Upsert → SQLite

This boundary prevents API clients from modifying the retrieval corpus outside the watcher-controlled pipeline.

Registry versus loaded databases

The registry in db.json records desired databases. The daemon opens those entries only during startup. Therefore:

SQLite as source of truth

Each database stores parsed chunks and embeddings in {db}/data.db. SQLite controls whether a row is active, pending embedding, or dismissed. In-memory caches improve query speed but are disposable:

State Durable source Rebuild behavior
Chunk content file_data.content Never sourced from vector cache
Embedding file_data.embedding Loaded into vector buckets at startup
Query embedding query_cache.embedding Preloaded into openai.Cache
Source vectors Derived in memory Rebuilt by averaging and normalizing chunk vectors
Watch snapshot record.json Loaded before the next directory comparison

Chunk lifecycle

A parsed file produces numbered chunks. Upsert first marks existing active rows for the source as dismissed, then inserts or updates current chunks in one transaction. If a chunk's content is unchanged, its embedding is retained; changed content clears the embedding and resets is_embed to FALSE.

Deleted files are not physically removed. The watcher calls Dismiss, which marks matching rows with dismiss = TRUE. Every active query path filters those rows.

Embedding consistency

The OpenAI client requests text-embedding-3-small vectors with 512 dimensions. Encoded vectors use little-endian float32, so one valid blob is 2,048 bytes. KuraDB enforces consistency at several points:

Dual retrieval

A search can execute keyword retrieval, semantic retrieval, or both.

Strategy Query preparation Retrieval Ranking
Keyword gse tokenization, trimming, lowercase, deduplication SQLite LIKE across active content Number of matched tokens, then row ID
Semantic Query embedding from cache or OpenAI Two-stage in-memory cosine search, then SQLite hydration Cosine score, with a 0.3 minimum

When both branches run, they execute concurrently and remain separate in the response. KuraDB does not merge their rankings into a single score.

Source-level vector filtering

Semantic search derives one normalized vector per source from its chunk vectors. It first ranks all source vectors, keeps approximately 5% with a minimum of 20 candidates, then calculates chunk-level cosine similarity only within those sources. If source vectors are unavailable, it falls back to searching all chunk vectors.

Query cache

openai.Cache maps the exact query string to an embedding. On a miss, semantic search calls OpenAI and stores the vector in memory. An OnSet callback asynchronously persists the encoded vector to global.db with a five-second timeout. Startup preloads valid entries without re-triggering persistence.

API response contract

Search results are grouped by source and expose only:

{
  "source": "/path/to/file.md",
  "matches": [
    {"chunk": 1, "content": "..."}
  ]
}

Internal fields such as row ID, semantic score, keyword hit count, chunk total, and cache state remain implementation details.

Platform assumptions

The watcher compares direct directory entries using size and modification time. KuraDB supports local macOS and Linux filesystems with reliable POSIX semantics. It does not claim correctness on Windows, SMB, NFS, or FUSE mounts where those assumptions can fail.

中文