Rank installed apps above equally matching menu entries

Searching the menu for an installed app buried it: "brave" listed Setup >
Defaults > Browser, Install > Browser and Remove > Browser ahead of the
Brave app itself. All four are exact label matches scoring 0, so the
tiebreak falls to declaration order, and mergeAppRows appends app rows
after every static item.

Bias app rows ahead of menu entries that match equally well. The bias is
smaller than the gap between match tiers, so a menu entry that matches the
query better still sorts first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Jones
2026-07-26 14:25:31 -04:00
co-authored by Claude Opus 5
parent a8977c4433
commit ab798d80b2
2 changed files with 26 additions and 0 deletions
+20
View File
@@ -109,6 +109,26 @@ assertDeepEqual(
const defaultItems = menu.parseMenuJsonc(defaultMenuJsonc)
const defaultById = Object.fromEntries(defaultItems.map(item => [item.id, item]))
// App rows land after every static item, so ranking has to survive the real
// menu's item count: with hundreds of entries ahead of them, the order
// tiebreak alone buries an installed app under Install and Remove.
const rankBase = menu.mergeMenuSources(defaultItems, [])
const ranked = menu.mergeAppRows(rankBase.items, rankBase.itemOrder, [
{ id: 'apps.brave', parent: 'apps', kind: 'app', label: 'Brave', description: '', aliases: [] },
{ id: 'apps.fontforge', parent: 'apps', kind: 'app', label: 'FontForge', description: '', aliases: [] }
])
const rankScore = (id, query) => menu.searchScore(ranked.items, ranked.items[id], query)
assert(
['install.browser.brave', 'remove.browser.brave', 'setup.default.browser.brave'].every(
id => rankScore('apps.brave', 'brave') < rankScore(id, 'brave')
),
'menu ranks an installed app above menu entries matching the query equally well'
)
assert(
rankScore('style.font', 'font') < rankScore('apps.fontforge', 'font'),
'menu keeps a better-matching menu entry above a weaker app match'
)
const triggerItems = defaultItems.filter(item => item.parent === 'trigger')
assertEqual(
triggerItems[0].id,