Add chunks_fts virtual table and three sync triggers via migration V002__fts.sql. Backfill existing chunks if any.
Why now / why this size
chunks_fts is the lexical index for kebab-search. Splitting it from p1-6 keeps P1 focused on relational data; bringing it as V002 lets users upgrade an existing P1 DB without re-ingesting.
(Used by kebab index --rebuild-fts. Re-runs INSERT INTO chunks_fts SELECT ... FROM chunks after DELETE FROM chunks_fts;.)
Behavior contract
Migration file migrations/V002__fts.sql ships exactly the SQL in design §5.5 (FTS5 virtual table with unicode61 remove_diacritics 2 tokenizer + chunks_ai / chunks_ad / chunks_au triggers).
On migration apply, backfill: INSERT INTO chunks_fts(chunk_id, doc_id, heading_path, text) SELECT chunk_id, doc_id, heading_path_json, text FROM chunks;.
rebuild_chunks_fts is idempotent: full delete then re-insert from chunks.
Triggers ensure that every future INSERT/UPDATE/DELETE on chunks keeps chunks_fts in sync within the same transaction.
chunks_fts row count must equal chunks row count after any successful migration / rebuild.
Korean morphological tokenizer (kept as P+ note; default unicode61 remove_diacritics 2).
Risks / notes
FTS5 triggers run inside the same transaction as their host chunks mutation; bulk ingest performance may need batching considerations later.
chunks_fts is a content-less FTS5 table per §5.5 (with UNINDEXED chunk_id/doc_id). Tests should rely on bm25(chunks_fts) ranking only — not on raw scoring values.