fix(search): lexical BM25 review follow-up — camelCase query + fallback + docs#433
Merged
Merged
Conversation
…k + tests + docs) 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 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #432 (BM25 lexical fallback via LadybugDB FTS), applying the
/requesting-code-reviewfindings that came in after #432 merged. The review found no Critical issues; this PR fixes the one real bug that slipped into master, plus the test/doc gaps.The bug now in master (B1 — recall regression)
Pasted camelCase queries return
[].Symbol.search_textis built from_split_identifiertokens, but the raw query was passed straight toQUERY_FTS_INDEXand LadybugDB FTS's tokenizer does not split camelCase — sosearch DistributionChunkServicematched nothing. The heuristic fallback didn't save it (it also doesn't split camelCase). Verified empirically during review. This is the most common code-search query pattern (pasting a class name).Fix: a shared
build_fts_query(search_scoring) pre-splits the query the same waysearch_textis indexed, so index/query tokenization finally agree. Regression test added.Other fixes
"", stopword-only) and empty BM25 results now fall back to the heuristic scan — preserves the role-ranked listing for degenerate queries and is defensive against stemming / selective-filter-thinning cases.test_cap_advisory_silent_below_capnow forces the heuristic path (it was passing vacuously on the BM25 default).Symbol.search_textschema-anchor test (guards against a silently emptysearch_textbreaking all searches with zero test signal).ontology 18references (AGENT-GUIDE, ARCHITECTURE×2, DESIGN, CONFIGURATION×2) to 19; fixed the re-rank module attribution (search_lexical, notsearch_scoring); addedpackageto thesearch_textcomposition.Review push-back (for the record)
One reviewer asserted the LadybugDB constraints behind #432's defensive build-side code (
DROP TABLErefused while an FTS index references it; Symbol DML needsLOAD 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.Verification
search_textanchor).~/jrag-bench/shopizer): query mean ~26ms post-fix (pre-split adds ~2ms; still ~3.3× faster than the heuristic-only baseline of 82.8ms); build phases unchanged.🤖 Generated with Claude Code