[CmdPal] Per-provider search weight (Lower/Normal/Higher) - #49191
[CmdPal] Per-provider search weight (Lower/Normal/Higher)#49191Michael Jolley (michaeljolley) wants to merge 3 commits into
Conversation
| <value>Search weight</value> | ||
| </data> | ||
| <data name="Settings_ExtensionPage_SearchWeight_SettingsCard.Description" xml:space="preserve"> | ||
| <value>Nudge this provider's results up or down among equally-relevant matches. It never overrides a stronger text match.</value> |
There was a problem hiding this comment.
I think we can probably drop "It never overrides a stronger text match.". that feels redundantly verbose
There was a problem hiding this comment.
Done. Dropped that sentence, so the description now just reads "Nudge this provider's results up or down among equally-relevant matches."
| // Per-provider weight is a within-tier nudge only. Resolving it here (rather than in | ||
| // the tier classifier) guarantees it can never promote an item across a tier boundary. | ||
| var providerWeight = providerWeightLookup?.Invoke(topLevelOrAppItem) ?? ProviderSearchWeight.Normal; | ||
| var providerBonus = MainListRanker.ProviderBonus(providerWeight); |
There was a problem hiding this comment.
Yea this is another case of what I mentioned over in #49189 - we're like, going into MainListRanker to get a value, then just passing it back into MainListRanker. Feels like it should all be in MainListRanker
There was a problem hiding this comment.
Same theme as the MainListRanker note on #49189. I'm keeping ProviderBonus as its own public method on the ranker because it's independently unit tested (ProviderWeightingTests and RelevanceHarnessTests assert the Lower < Normal < Higher mapping directly). Folding it into WithinTierScore would remove that tested seam, so I'd rather keep the map then combine split. Happy to revisit as part of the same "move it all into MainListRanker" cleanup.
68ac9ca to
a325c62
Compare
a325c62 to
b3c445a
Compare
…red ranker (#49189) >[!WARNING] > This PR is one in a series of PRs focused on rearchitecting the search/scoring logic of the `MainListPage`. An explanation of the entire search/scoring logic can be found below. > > **This PR should not be merged until PR #49190 is merged into it.** >[!NOTE] > To test the final result, run the branch associated with PR #49249. This stack rebuilds how Command Palette ranks and displays results on its main page. Strong text matches now consistently appear above weaker ones. Usage history and provider preferences can improve ordering between similarly relevant results, but they cannot push a poor match above an obvious one. The stack also makes search feel faster. Results appear without waiting for slower providers, app scoring runs more efficiently, and weak matches are hidden while the user has typed only one or two characters. Automated tests protect the new behavior, while privacy conscious telemetry measures performance and relevance without recording searches. ## Pull requests 1. [#49189](#49189) introduces the new ranking foundation. Results are grouped by match strength, ensuring exact names, prefixes, and acronyms rank above loose fuzzy matches. 2. [#49190](#49190) improves how Command Palette learns from command usage. Recent and frequently used commands receive a sensible boost, and that history now persists across restarts. 3. [#49191](#49191) lets users give each provider a Lower, Normal, or Higher search preference. This preference helps resolve close matches without overriding result relevance. 4. [#49194](#49194) makes the first set of results appear sooner. Commands and apps are shown immediately, while slower fallback results are added when they become available. 5. [#49195](#49195) adds a comprehensive relevance test suite. It verifies that common searches return the expected results and protects ranking quality from future regressions. 6. [#49197](#49197) adds privacy conscious search telemetry. It measures result counts, response time, and which result position was selected without recording search text, result names, paths, or other user content. 7. [#49246](#49246) adds a performance measurement suite. It identifies where search time is spent and provides a reliable way to evaluate performance improvements. 8. [#49247](#49247) delivers the main performance improvement. App results are scored in parallel and expensive work no longer blocks rendering, while the final result order remains unchanged. 9. [#49249](#49249) prevents misleading results from flashing when a search begins. For one or two character searches, weak fuzzy app matches remain hidden until the query is specific enough to produce useful results. > [!WARNING] > These PRs should be merged in LIFO order starting with #49249 with this PR being the last. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a per-provider SearchWeight (Lower/Normal/Higher, default Normal) that nudges main-page search results within their relevance tier only. The nudge is a small additive within-tier bonus (+/- 5 points, half a point of lexical quality) so it breaks near-ties but can never move an item across a tier boundary. Applies to installed apps too via the well-known AllApps provider. - ProviderSettings: new ProviderSearchWeight enum + SearchWeight property; legacy/missing JSON deserializes to Normal. - MainListRanker: ProviderWeightBonus constant + ProviderBonus() mapping. - MainListPage.ScoreTopLevelItem: resolves each item's provider weight and feeds it into the within-tier score. - ProviderSettingsViewModel + ExtensionPage.xaml: a Lower/Normal/Higher ComboBox per provider. - Tests: within-tier reorder, never crosses a tier boundary, Normal is a no-op, applies to app items, serialization round-trip + legacy default. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A per-provider SearchWeight change only affected new queries: scoring reads the weight live but scored results are cached, so an already-settled query kept its old order until the next keystroke. HotReloadSettings now detects a provider weight change and re-scores the active query in place. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5459b847-afeb-4163-a803-977759dd92df
Addresses review feedback: the 'It never overrides a stronger text match.' sentence was redundantly verbose next to the existing description. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 49185697-186e-406f-b081-8c985c134274
b3c445a to
82251d5
Compare
Warning
This PR is one in a series of PRs focused on rearchitecting the search/scoring logic of the
MainListPage. An explanation of the entire search/scoring logic can be found in the first PR of the change (#49189).This PR should not be merged until PR #49194 is merged into it.
Phase 3 of the stacked CmdPal search overhaul. Based on and targeting
dev/mjolley/frecency-redesign(phase 2), NOT main.What
Adds a per-provider Search weight (Lower / Normal / Higher, default Normal) that nudges main-page search results within their relevance tier only. Tier always dominates; the weight can reorder near-ties but can never move an item across a tier boundary.
Changes
ProviderSettings: newProviderSearchWeightenum (Lower = -1, Normal = 0, Higher = 1) +SearchWeightproperty. Missing/legacy JSON deserializes to Normal.MainListRanker:ProviderWeightBonus = 5.0constant andProviderBonus(weight)mapping (signed magnitude). Half a point of lexical quality (LexicalScale = 10), so it only breaks near-ties.MainListPage.ScoreTopLevelItem: resolves each item's provider weight (top-level commands by their provider id, installed apps by the well-knownAllAppsprovider) and feeds it into the within-tier score. Backward-compatible optional parameter.ProviderSettingsViewModel+ExtensionPage.xaml: a Lower/Normal/Higher ComboBox per provider (shown for built-ins and apps too). New resw strings. RanapplyXamlStyling.Design constant
Tests (all green, x64 host)
CommandPalette.slnfx64/Debug = exit 0. ViewModels 157/157. All other CmdPal unit suites pass (Registry + WindowWalker not run - known pre-existing non-green).Atomic to phase 3; host-side only, no extension SDK changes.