fix(augment): gate the rescue's FTS fallback on query-token coverage (#2092) - #2214
Conversation
|
Checked both bot items:
|
The coverage gate pushed _rescue near 80 lines. Pull the FTS-fallback leg into its own helper, mirroring _rescue_wide_text, which is the same extraction for the widened leg. Pure function of (pattern, rows); the page-type check becomes a guard clause instead of a nested branch. No behaviour change.
… change ruff format swept rewraps of untouched code into the PR (main is not format-clean and CI only runs ruff check) — that is what tripped the bot's 'signature changed: _log_search_firing' and 'introduced complex method: _handle_search_post' warnings; both functions are semantically untouched. Restore main's formatting on every line this PR does not own.
|
Both warnings were artifacts of a whole-file |
RaghavChamadiya
left a comment
There was a problem hiding this comment.
Thanks @punk-dev-robot. The rescue fallback now requires meaningful query-token coverage against the candidate title, target, or snippet instead of applying a backend-specific absolute score. The tests cover the acceptance and rejection boundaries. Approved.
What
Fixes #2092. The zero-result grep rescue's FTS fallback (
_rescueincli/commands/augment_cmd/search.py) returned the first FTS row pointing at a code page with no quality check, so a multi-token pattern where only one common token matched produced a confidentWiki suggests ...line for an unrelated file (repro in the issue:bluetooth codec negotiation fallbackriding on "fallback").Shape
Token coverage, per @RaghavChamadiya's spec in #2092 (comment) (first comment) — not the BM25 floor I originally proposed: SQLite BM25 is unbounded while PostgreSQL
ts_rankis ~0–1, so any constant floor silently kills the fallback on one dialect, and SQLite scores are clamp-postprocessed besides._RESCUE_FTS_MIN_TERMS = 2, documented next to the other rescue tunables._rescue's FTS loop:needed = min(_RESCUE_FTS_MIN_TERMS, len(_pattern_terms(pattern)))distinct query tokens must appear in the row'stitle + target_path + snippet(lowered). Reuses_pattern_terms, the same guard family as the widened path's single-token check.needed= 1): the zero-result rescue deliberately allows generic names, and the gate must not mute that.continue(a later row may cover) and logged at debug level — visible underaugment --verbose— so we can watch what the gate is eating, as requested.Measurements
From my local before/after run on the dotfiles repo (the table in #2092): the weak query covers 1/4 terms → now silent;
btrfs space monitoring,containerd image cleanup,hyprland monitor workspaceall cover ≥2 terms in the suggested row → still rescue. The unit tests encode the weak repro verbatim.Tests
TestRescueFtsCoverageGateintests/unit/cli/test_augment_search.py: weak single-token ride silent, covered row fires, gate scans past a weak first row, single-token pattern still fires, non-code page still skipped. Sabotage-verified: with the gate neutralized (needed = 0), the silent-ride and scan-past tests fail.