This repository was archived by the owner on Oct 20, 2026. It is now read-only.
Repository navigation
fix(search): stop a repeated URL from faking cross-engine agreement - #431
Merged
leookun merged 1 commit intoSep 15, 2026
Merged
Conversation
`WebSearch::search` fuses the engines with Reciprocal Rank Fusion, which
sums one term per ranked list. `merge` added a term for every result
instead, so an engine that listed the same canonical URL twice had both
of its ranks counted:
1/61 + 1/62 = 0.0325
That is what two independent engines agreeing at rank 1 are worth
(2/61 = 0.0328), produced from a single list. Agreement across engines is
the only ranking signal this federation has, and a repeat inside one
engine forges it.
The repeats come from the repository's own canonicalization, not from
exotic input. `canonicalize` in `search/engine.rs` drops the fragment,
the trailing slash and the `utm_*`, `gclid`, `fbclid` and `mc_*`
parameters, and `redirected_target` unwraps the Bing, DuckDuckGo and
Google redirector links, so rows that are visibly distinct on one result
page collapse onto one URL. Nothing dedupes an engine's own list before
`merge` sees it.
`merge` already knew the rule: the engine label was guarded with
`!existing.engines.contains(&engine)`. Put the score behind the same
guard, so each engine contributes its best rank once. Cross-engine
merging and the longest-snippet rule are untouched.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Problem
WebSearch::searchqueries the 23 engines incatalog.rsin parallel and fuses their result lists with Reciprocal Rank Fusion. RRF exists to reward a document that several independent lists agree on, so it adds one1 / (k + rank)term per list.merge(server/src/search/federation.rs:120) added a term per result instead:An engine that lists one canonical URL at ranks 1 and 2 therefore scores
1/61 + 1/62 = 0.03252, which is what two independent engines both ranking it first are worth (2/61 = 0.03279). Theenginesfield still correctly lists one engine, so the inflated score carries no sign of where it came from, and the score is whatresults.sort_byorders by atfederation.rs:102.Why an engine repeats a URL
The repeats come from this repository's own canonicalization rather than from odd input.
canonicalize(server/src/search/engine.rs:295) drops the fragment, the trailing slash and theutm_*,gclid,fbclid,mc_cidandmc_eidparameters, andredirected_target(engine.rs:318) unwraps the Bing/ck/a, DuckDuckGouddgand Google/urlredirector links. Any two rows on one result page whose links differ only in one of those ways collapse onto one string. Output ofcanonical_urlandresult_urlon currentmain:Nothing removes the duplicate before it is scored.
parsetakes the first ten hits and returns them as they came (engine.rs:118for HTML,:190for JSON), andsearchhands the whole list tomerge(federation.rs:83).Fix
Put the score behind the guard that was already there for the engine label, so each engine contributes its best rank once. Cross-engine merging is untouched, and a repeat can still upgrade the stored snippet, which is the one thing a second row genuinely adds.
I did not dedupe inside
parseinstead: that would need the same bookkeeping in the HTML and JSON parsers, and it would throw away the later row's longer snippet.mergeis where a URL becomes one entry, so it is where a list should count once.Verification
two_engines_that_agree_on_a_url_still_sum_both_rankspasses before and after; it is there to pin that a genuine two-engine merge still sums both ranks and keeps both labels.federation.rshad no tests before this, so the new module is at the end of the file.Gates, on the toolchain CI uses (
dtolnay/rust-toolchain@stable, here 1.98.0):