# 資料一致性

了解 KuraDB 每一種狀態以哪個儲存為權威來源，以及 chunk 與 embedding 如何與它保持一致。

## SQLite 作為 source of truth

每個資料庫都將解析後的 chunk 與 embedding 儲存在 `{db}/data.db`。SQLite 決定 row 處於 active、pending embedding 或 dismissed 狀態。記憶體快取只用來提升查詢速度，隨時可捨棄：

| 狀態 | 持久來源 | 重建行為 |
|---|---|---|
| Chunk content | `file_data.content` | 絕不從 vector cache 取得 |
| Embedding | `file_data.embedding` | 啟動時載入 vector bucket |
| Query embedding | `global.db` 的 `query_cache.embedding` | 預載至 `openai.Cache` |
| Source vector | 在記憶體衍生 | 由 chunk vector 加總並正規化後重建 |
| Watch snapshot | `record.json` | 下次比較目錄前載入 |

搜尋結果一律以 `dismiss = FALSE` 從 SQLite hydrate，因此仍留在記憶體中的 vector 無法回傳 SQLite 已不視為 active 的內容。

## Chunk 生命週期

解析後的檔案會產生以 `(source, chunk)` 為 key 的編號 chunk。`Upsert` 會先將來源既有的 active row 標記為 dismissed，再於同一 transaction 中插入或更新目前 chunk。若 chunk content 未變，其 embedding 會保留；若 content 已變，則清除 embedding 並將 `is_embed` 重設為 `FALSE`。

刪除的檔案不會被實體移除。Watcher 會呼叫 `Dismiss`，將相符 row 標記為 `dismiss = TRUE`。每條 active query path 都會過濾這些 row。寫入路徑的逐步說明見 [儲存寫入](/indexing-pipeline-storage)。

## Embedding 一致性

OpenAI client 會要求 `text-embedding-3-small` 的 512 維向量。編碼格式使用 little-endian `float32`，因此有效 blob 為 2,048 bytes。KuraDB 在多個位置維持一致性：

- OpenAI response 必須包含要求數量的向量。
- 每個回傳向量都必須正好有 512 個元素。
- Query-cache preload 會略過 byte length 不等於 `openai.Dim() * 4` 的 blob。
- Vector search 與 source vector 重建會忽略維度與 query 或該 source 不同的向量。
- Embedding update 的 SQL predicate 會包含原始 content，避免檔案變更後套用過期結果。
