Skip to content

[CmdPal] Replace main-page magic-number scoring with a principled tiered ranker#49189

Draft
michaeljolley wants to merge 1 commit into
mainfrom
dev/mjolley/cmdpal-search-overhaul
Draft

[CmdPal] Replace main-page magic-number scoring with a principled tiered ranker#49189
michaeljolley wants to merge 1 commit into
mainfrom
dev/mjolley/cmdpal-search-overhaul

Conversation

@michaeljolley

Copy link
Copy Markdown
Contributor

Summary

Users report Command Palette main/root page results are wrongly ranked: the thing they want exists but is buried below junk. Today's ordering is a flat weighted sum of hand-tuned magic numbers in MainListPage.ScoreTopLevelItem (alias +9001, match x10, subtitle -4/2, extension /1.5, fallback x0.5) plus an additive frecency weight, which makes obvious matches lose to noise and is effectively untestable.

This PR re-architects the main-page scoring into a principled, testable, multi-signal ranker. It is the first atomic step of a larger search-quality effort (see follow-ups below).

What changed

  • New MainListRanker (Microsoft.CmdPal.UI.ViewModels/Commands/MainListRanker.cs):
    • A hard tier ladder decides ordering: alias-exact > exact-title > prefix > acronym/word-boundary > fuzzy > fallback floor.
    • A normalized within-tier score (lexical quality + frecency + alias-substring nudge + provider bonus) only reorders items that already share a tier, so a weak signal can never jump an item over a better lexical match.
    • Tier + within-tier score are packed into a single sortable int, so the existing score-descending sort (InternalListHelpers.FilterListWithScores) is unchanged.
    • Defines IRankSignal / IRerankStage seam interfaces so a future on-device semantic or small-LLM reranker can slot in later as a post-first-paint pass. No model ships here.
  • ScoreTopLevelItem refactor: the magic-number tail is replaced by tier classification + the within-tier score. The within-tier math deliberately mirrors the old balance, so items that share a tier keep their long-standing relative order; only cross-tier behavior changes.
  • Tests: updated the ranking invariants to assert the new contract - heavy usage reorders within a tier but never crosses a tier boundary.

Scope / safety

  • Host-side only. The extension SDK toolkit (ListHelpers / FuzzyStringMatcher) and extension-owned list pages are untouched, keeping this atomic and free of ABI/extension-compat risk.
  • Deterministic; no new dependencies; no settings schema or IPC changes.

Validation

  • Build CommandPalette.slnf (x64 / Debug): exit 0.
  • All 146 Microsoft.CmdPal.UI.ViewModels.UnitTests pass.

Follow-ups (separate PRs)

These were intentionally deferred to keep this PR atomic and to give privacy/schema-sensitive work its own review:

  1. frecency-redesign - timestamped, time-decayed frecency (exp decay + log(uses)), larger store, migration of persisted history; feeds the within-tier signal.
  2. provider-weighting - per-provider Lower/Normal/Higher control in Settings (schema + XAML), applied as a within-tier bonus.
  3. fast-first-paint - render deterministic command/app results instantly and slot slow out-of-proc fallback results in asynchronously.
  4. relevance-harness - golden-set MSTest harness asserting expected top-N ordering.
  5. search-telemetry - opt-in, privacy-tagged search telemetry (never logs raw query text).

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

Rework the main/root page relevance scoring into a principled, testable
multi-signal ranker. Ordering is now decided by a hard tier ladder
(alias-exact > exact-title > prefix > acronym/word-boundary > fuzzy >
fallback floor); frecency and other within-tier signals only reorder items
that already share a tier, so an obvious match can no longer be buried under
junk.

- Add MainListRanker: RankTier ladder, tier classifier, normalized
  within-tier score, and a packed sortable int so the existing
  score-descending sort is unchanged.
- Add IRankSignal / IRerankStage seam interfaces so a future on-device
  semantic or small-LLM reranker can slot in later. No model ships today.
- Replace the hand-tuned constants in ScoreTopLevelItem with tier
  classification plus the within-tier score. Within-tier math mirrors the
  old balance so shared-tier ordering is preserved; only cross-tier
  behavior changes.
- Update ranking tests to assert the new tier invariant: heavy usage
  reorders within a tier but never crosses a tier boundary.

Host-side only; the extension SDK toolkit and extension-owned pages are
untouched.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the Product-Command Palette Refers to the Command Palette utility label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant