message_fts and agent_session_message_fts keyed their FTS5 external-content index on SQLite's implicit rowid. A drizzle table rebuild (INSERT...SELECT drops the rowid) or VACUUM reshuffles it, silently desyncing the index (wrong/missing hits, no error; the default integrity-check does not detect it).
Add a real fts_rowid integer-unique column to each table, set content_rowid to it, and assign it in the AFTER INSERT trigger (MAX+1, O(log N) via the unique index, race-free under withWriteTx). A real column is carried verbatim through rebuilds and untouched by VACUUM, so the index stays aligned by construction. Update both search joins to base.fts_rowid = fts.rowid, convert the agent-session triggers to DROP+CREATE, and add a regression test reproducing a rowid-reshuffling rebuild that asserts integrity-check,1 stays clean (with a NULL fts_rowid negative control). Note the same latent hazard on knowledge search_text_fts (deferred; no rebuild/VACUUM path today).