Skip to content

fix(search): lexical BM25 review follow-up — camelCase query + fallback + docs#433

Merged
HumanBean17 merged 1 commit into
masterfrom
fix/lexical-bm25-review-fixes
Jul 11, 2026
Merged

fix(search): lexical BM25 review follow-up — camelCase query + fallback + docs#433
HumanBean17 merged 1 commit into
masterfrom
fix/lexical-bm25-review-fixes

Conversation

@HumanBean17

Copy link
Copy Markdown
Owner

Summary

Follow-up to #432 (BM25 lexical fallback via LadybugDB FTS), applying the /requesting-code-review findings 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_text is built from _split_identifier tokens, but the raw query was passed straight to QUERY_FTS_INDEX and LadybugDB FTS's tokenizer does not split camelCase — so search DistributionChunkService matched 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 way search_text is indexed, so index/query tokenization finally agree. Regression test added.

Other fixes

  • B2/B3: degenerate queries ("", 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.
  • C1: test_cap_advisory_silent_below_cap now forces the heuristic path (it was passing vacuously on the BM25 default).
  • C2: added a Symbol.search_text schema-anchor test (guards against a silently empty search_text breaking all searches with zero test signal).
  • Docs: swept 6 stale ontology 18 references (AGENT-GUIDE, ARCHITECTURE×2, DESIGN, CONFIGURATION×2) to 19; fixed the re-rank module attribution (search_lexical, not search_scoring); added package to the search_text composition.

Review push-back (for the record)

One reviewer asserted the LadybugDB constraints behind #432's defensive build-side code (DROP TABLE refused while an FTS index references it; Symbol DML 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.

Verification

  • 21 lexical tests green (incl. the new camelCase regression + search_text anchor).
  • Bench (~/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.
  • Diff is a focused +101/−18 across 7 files (branched from current master, so no unrelated revert noise).

🤖 Generated with Claude Code

…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>
@HumanBean17 HumanBean17 merged commit 051390b into master Jul 11, 2026
4 checks passed
@HumanBean17 HumanBean17 deleted the fix/lexical-bm25-review-fixes branch July 11, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant