Skip to content

search overhaul stage 1: SQLite FTS query parser, bm25 weights, diacritics, pagination - #29

Merged
andrei-hasna merged 1 commit into
mainfrom
feat/search-stage-1-sqlite-fts
Jul 24, 2026
Merged

search overhaul stage 1: SQLite FTS query parser, bm25 weights, diacritics, pagination#29
andrei-hasna merged 1 commit into
mainfrom
feat/search-stage-1-sqlite-fts

Conversation

@andrei-hasna

Copy link
Copy Markdown
Contributor

Stage 1 of the staged search overhaul. Stacked on #28 (review/merge that first).

What

  • Real query parser (src/search.ts): AND by default, "quoted phrases", prefix*, explicit OR, NOT / leading-- negation — replaces terms.map(t=>+"${t}*"+).join(' OR ').
  • AND-first / OR-fallback: precise multi-term queries stay precise; when no doc matches all terms (e.g. natural-language ask() / context.pack() questions) the query degrades to OR recall instead of returning nothing.
  • bm25 column weights so title/source_uri outrank body.
  • Schema v9 migration (src/knowledge-db.ts): rebuild chunks_fts with the diacritic-folding tokenizer (porter unicode61 remove_diacritics 2), backfilled losslessly from the existing stored FTS rows. Idempotent, guarded by live-tokenizer inspection.
  • Offset pagination on hybridSearch with a widened fetch window (stable, non-overlapping pages). Malformed MATCH degrades to zero keyword hits instead of throwing.

Tests

tests/search-parity.test.ts flips the Stage 0 characterization assertions to AND / phrase / NOT / prefix / bm25 / diacritic / pagination — these fail on the old builder and pass now. Schema-version expectations bumped 8 -> 9 across affected suites.

Risk / compatibility

  • Losing OR-recall for NL questions is mitigated by the OR fallback (regression caught + covered by sdk.test.ts).
  • The v9 rebuild is a no-op cost on already-migrated DBs (tokenizer check) and lossless (copies stored FTS rows; no re-ingest).

🤖 Generated with Claude Code

…nation

Replace the OR-of-prefixes FTS builder with a real query parser: AND by
default, "quoted phrases", prefix*, explicit OR, and NOT/leading-dash
negation. AND-first / OR-fallback keeps precise multi-term queries precise
while natural-language questions (ask/context.pack) retain recall instead
of returning nothing. Malformed MATCH expressions degrade to zero keyword
hits rather than throwing.

Weight bm25 columns so title/source_uri outrank body. Rebuild chunks_fts
under a new schema v9 migration with the diacritic-folding tokenizer
(porter unicode61 remove_diacritics 2), backfilled losslessly from the
existing stored FTS rows; the rebuild runs in a transaction so a crash
mid-migration rolls back to the old index instead of leaving an empty one.
Add offset pagination to hybridSearch/hybridSearchItems with a widened
fetch window for stable, non-overlapping pages.

Includes the shared parity fixtures corpus and flips the search-parity
suite to assert AND/phrase/NOT/prefix/bm25/diacritic/pagination behavior
(fails on the old builder, passes now); schema-version expectations bumped
8 -> 9 across affected suites; regenerated bin/dist artifacts.
@andrei-hasna
andrei-hasna force-pushed the feat/search-stage-1-sqlite-fts branch from 1f357e3 to 2ced352 Compare July 24, 2026 15:10
@andrei-hasna
andrei-hasna changed the base branch from feat/search-stage-0-parity-scaffolding to main July 24, 2026 15:11
@andrei-hasna
andrei-hasna merged commit 1a2c2a6 into main Jul 24, 2026
@andrei-hasna
andrei-hasna deleted the feat/search-stage-1-sqlite-fts branch July 24, 2026 15:11
andrei-hasna added a commit that referenced this pull request Jul 24, 2026
Bring in #22/#26/#27/#29/#3 (hosted-url scrub, --json error contract,
reject unknown top-level commands, FTS query parser, public-package
docs hardening). Renumber this change to 0.2.90 (main consumed 0.2.88
and 0.2.89); rebuild bin/ and dist/ from merged sources.
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