Editors want to pin a few pages, such as a getting-started guide, to the top of a query’s results, in the order they pinned them, whichever ranking the reader picked. Below the pins, the reader’s ranking still applies. The ranker’s rules still hold: deprecated pages sink and ties settle by ID.
Pinned pages are the ones editors most want readers to find. A pin that works under one ranking only, or that moves when the editor’s list is edited later, undermines the search readers rely on.
Reproduce
Pin guide and rank api, release and guide by Recent. It should give guide, release, api. Today pinnedFirst ignores the pins and gives release, api, guide.
Acceptance criteria
- Pinned results come first, in the order they were pinned, above every base ranking, including one added later.
- Below the pins, the base ranking applies unchanged; a pin that matches no result is ignored.
- A policy keeps the pins it was built with: editing the caller’s list afterwards changes nothing.
- The ranker’s rules still hold: a deprecated page sinks even when it is pinned, and ties settle by ID. An unknown mode is rejected.
Notes
- The checker builds pinnedFirst(pins, choosePolicy(mode)) (PinnedFirst and ChoosePolicy in Go, pinned_first and choose_policy in Rust), ranks the case’s results with rankResults, and prints their IDs, or rejected.
- In TypeScript and Go, one case wraps the teammate’s oldest-first policy, which the checker supplies.
- Keep rankResults as it is: pinning is a policy, and the ranker should not learn about it.
- Rust: a fn pointer cannot carry the pins. Change RankingPolicy to a type that can, and keep its name; the checker uses it.