/** * Embedding reconciliation (FOUNDATION-PLAN W2.3 phase 2): converge the * embeddings table to the record tables after ingest changes them. * * The live write path embeds each record as it is created; ingest bypasses * that path, so pulled or branch-switched records arrive with no vectors * (search degrades to per-record keyword fallback until fixed). This module * closes the gap as a full converge pass rather than a per-ingest delta — * it is idempotent, self-healing (records posted while the model was * unavailable get embedded on a later pass), and needs no change-tracking * plumbing through the ingest code. * * Per (index, record) the rules are, in order: * - record gone → delete the embedding row (orphan cleanup) * - no embedding row → embed and insert (with content hash) * - hash NULL, vector kept → backfill the hash from current text, no model * call. NULL means "written before hashes existed" (pre-v2 rows, or the * soak's bare addEntry) and record embed text is immutable in practice, * so the existing vector is trusted. A record whose text was rewritten by * ingest inside that window keeps a stale vector until its next change — * accepted: the window is one startup, and hash comparison catches every * change after backfill. * - hash differs → re-embed (the only model calls a pulled * status-change costs are zero: status edits leave embed text unchanged) * * Concurrency: model inference never runs inside a transaction; every write * is a single upsert/delete statement, so concurrent reconcilers duplicate * at most some work, never corrupt state. Fallback mode (no model) still * performs cleanup and backfill — only embedding work is skipped. */ import type { Embedder } from "../../embeddings/embedder.js"; import { type SqliteDatabase } from "../sqlite/db.js"; export interface ReconcileStats { embedded: number; backfilled: number; deleted: number; /** Records left without a vector (model unavailable or embed failed). */ pending: number; } /** Converge the embeddings table to the record tables. Never throws. */ export declare function reconcileEmbeddings(db: SqliteDatabase, embedder: Embedder): Promise; //# sourceMappingURL=embedding-reconcile.d.ts.map