add support for fts in mm grep using bm25 - #180
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces FTS5 full-text search capabilities over the chunks table using a trigram tokenizer and BM25 ranking, including automatic trigger-based synchronization and idempotent backfilling of legacy data. The reviewer feedback highlights two key improvements: first, avoiding a redundant and expensive fallback to a LIKE scan when FTS5 is available but returns no results; second, using the more robust pragma module_list instead of pragma compile_options to detect FTS5 support and prevent false negatives on certain SQLite builds.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…ed DB + pragmas Stacked on the bm25/FTS work (#180); the range predicate lands inside _chunk_filter_sql so both the bm25 path and the LIKE fallback become index-selective per directory instead of post-filtering the global table. - Context.filter and find --sort/--depth via vectorized pyarrow.compute instead of an in-memory SQLite round-trip (62µs vs 6.8ms per filter at 500 files; Arrow schema/types now preserved). - uri LIKE 'prefix%' → index-backed range predicates (plan flips full-table SCAN → index SEARCH, asserted in tests) across the chunk filter, mm sql, semantic search, and prune_missing; mm sql reuses fetched rows instead of a third table scan. - New chunks(content_hash, mode, extraction_id, chunk_idx) and extractions(content_hash) indexes: the per-file has_text_chunks probe was scanning every orphan chunk in the global DB. - shared_db() at every call site (one schema bootstrap per process, was 4-6 per grep -s); busy_timeout/cache_size/mmap_size/temp_store pragmas; chunks_vec existence probe memoized per connection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GnYsrLTmdJphKkm7yjWDV
Summary
BM25 (Best Match 25) is the standard ranking function used by full-text search (fts) engines to score and rank documents by relevance to a query. This PR allows using fts with bm25 when
--semantic/-sflag is specified and falls back to a%LIKE%query.flowchart LR A["search_chunks_fts()"] --> B{"FTS5?"} B -- yes --> C["search_chunks_bm25"] B -- no --> F["LIKE fallback"] C --> D{"query ≥ 3 chars?"} D -- no --> E["return []"] D -- yes --> G["build filters + phrase"] G --> I["FTS5 MATCH + bm25()<br/>ORDER BY bm25 LIMIT ?"] I --> J{"non-empty?"} J -- yes --> L["return BM25 rows"] J -- no --> F F --> N["LIKE %q% scan<br/>→ return rows"]