From 3859ed5926ee84ff1dafb68dd72accd8a130ba69 Mon Sep 17 00:00:00 2001 From: Dmitry Teryaev Date: Sat, 11 Jul 2026 23:22:34 +0300 Subject: [PATCH] fix(search): lexical BM25 review follow-up (camelCase query + fallback + tests + docs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #432 (BM25 lexical fallback via LadybugDB FTS), applying the /requesting-code-review findings that came in after #432 merged. Reviewers found no Critical issues; the one real bug now fixed: - B1 (recall regression, now in master via #432): pasted camelCase queries (e.g. "DistributionChunkService") returned [] — LadybugDB FTS's tokenizer does not split camelCase, and the raw query was passed to QUERY_FTS_INDEX while Symbol.search_text is built from _split_identifier tokens. The heuristic fallback didn't save it (it also doesn't split camelCase). Fixed via a shared build_fts_query (search_scoring) that pre-splits the query the same way search_text is indexed; added a regression test. - B2/B3: degenerate queries and empty BM25 results now fall back to the heuristic scan (preserves the role-ranked listing for degenerate queries; defensive against stemming / selective-filter-thinning cases). - C1: test_cap_advisory_silent_below_cap now forces the heuristic path so it isn't passed vacuously on the BM25 default. - C2: added a Symbol.search_text schema-anchor test (guards against a silently empty search_text column breaking all searches with zero test signal). - Docs: swept 6 stale ontology-18 references (AGENT-GUIDE, ARCHITECTURE x2, DESIGN, CONFIGURATION x2) to 19; fixed the re-rank module attribution (search_lexical, not search_scoring) and added `package` to the search_text composition. Review push-back: one reviewer claimed the LadybugDB constraints behind the defensive build-side code (DROP TABLE refused while an FTS index references it; DELETE needs LOAD EXTENSION FTS) "don't reproduce" on the shipped version. Both were re-proved empirically (the DROP refusal reproduced in a fresh probe; the DELETE-needs-LOAD was the exact failure behind 22 incremental-test fixes in #432) — the defensive code stays. Bench (~/jrag-bench/shopizer): query mean ~26ms post-fix (the pre-split adds ~2ms; still ~3.3x faster than the heuristic-only baseline of 82.8ms); build phases unchanged. 21 lexical tests green. Co-Authored-By: Claude --- docs/AGENT-GUIDE.md | 2 +- docs/ARCHITECTURE.md | 6 +-- docs/CONFIGURATION.md | 6 +-- docs/DESIGN.md | 2 +- .../search/search_lexical.py | 28 ++++++++--- .../search/search_scoring.py | 26 ++++++++++ tests/search/test_search_lexical.py | 49 ++++++++++++++++++- 7 files changed, 101 insertions(+), 18 deletions(-) diff --git a/docs/AGENT-GUIDE.md b/docs/AGENT-GUIDE.md index 860b1be..934bbf2 100644 --- a/docs/AGENT-GUIDE.md +++ b/docs/AGENT-GUIDE.md @@ -14,7 +14,7 @@ Copy the block between `