Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.

Inbox
ReportR-1616GitHub issuePublicFixed

Search ranks `Remove › Development › Rust` above the RustDesk app — Enter runs the removal

Reported by RodriMora · filed Aug 20, 2026 · open at source

Validation verdict: Reproduced. An engine-executed run exited 1 and showed the defect signal. Awaiting a human decision.

At a glance

1 · What is claimed?
  • ConfirmedReproducible: searching 'rust' with ~/.rustup present and RustDesk installed makes Remove > Development > Rust row 1, the Enter target
  • Not confirmedAffects the menu component
3 · Is it reproducible?
An engine-executed run exited 1 and showed the defect signal. See reproducer
4 · What remains unclear?
  • Open question for maintainers: Open decision: may a search result that runs a destructive action (remove, uninstall) be the default Enter target? Options: (A) keep the current ranking (SW-REQ-260922-SJ7P); (B) rank destructive rows below other matches unless the query names the action (PR #7661); (C) keep install/remove rows out of global search (#6376's ask); (D) ask for confirmation before a destructive row runs from search, as SW-REQ-260922-8CQ4 does for uninstalling an app.
  • Open question for maintainers: The decision is the Omarchy maintainers'; a draft requirement listing these options sits on this report's branch (report/cmulrfoje01ui18w4w89862tn), and approving one option = merging that draft into the baseline with the chosen text.
  • Affects the menu component — no requirement of the menu component is confirmed as violated
5 · What happens next?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. So far: in the audited area (menu) — decided by agents · verified; not a duplicate of another report — decided by agents · verified; intended behaviour — a design question, not a defect — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Open question — draft spec awaiting a decision

Draft — awaiting a decisionSW-REQ-261005-ZEQ3component menurefines A filter query narrows to visible, selectable rows whose… SYS-REQ-260922-V7W6

May a search result that runs a destructive action (remove, uninstall) be the default Enter target?

What the code does today

(upstream quattro 035ce29f) searchScore (MenuModel.js:341-363) puts an exact label match in the best tier, so with ~/.rustup present and RustDesk installed, 'rust' ranks Remove > Development > Rust first; the menu selects row 0 on a query change (Menu.qml:722-726) and Enter activates it (Menu.qml:1153-1157), which runs omarchy-remove-dev-env rust (default/omarchy/omarchy-menu.jsonc:343) and rustup self uninstall -y with no confirmation (bin/omarchy-remove-dev-env:111-114).

Options (listed neutrally — the choice is the maintainers')
  1. AKeep the current ranking (SW-REQ-260922-SJ7P)
  2. BA destructive row shall rank below the other matches unless the query names the action
  3. CInstall/remove rows shall not appear in global search
  4. DA destructive row activated from search shall ask for confirmation, as SW-REQ-260922-8CQ4 does for uninstalling an app

Approving this draft means choosing one option; its text then replaces this description.

Why this is an open question

Raised by omacom/omarchy#7630 (proof inbox R-1616). The validation (report/cmulrfoje01ui18w4w89862tn, rval-6102a632d0b497ca1436a3f8476bcf72) reproduced the order with MenuModel.js on the shipped menu. The order conforms to SW-REQ-260922-SJ7P; SYS-REQ-260922-V7W6's rationale says ranking decides which row Enter activates; no requirement says whether a destructive action may be that row. Open upstream PR #7661 implements option B; #6376 asked for option C.

Raised inomacom/omarchy#7630 (upstream) R-1616 (this report)

Proposed on this report's branch @ 135fe5b6af · specs/software/requirements/SW-REQ-261005-ZEQ3.req.yaml · not part of the audited spec until approved and merged

Written after the validation was sealed at 923b93ce72: the seal covers the reproducer and the observed behaviour, not this proposed text.

Original report

Search ranks `Remove › Development › Rust` above the RustDesk app — Enter runs the removalrevision 1 · captured 2026-09-28 21:29 UTC via poll

Summary

Typing rust in the Omarchy menu (Super+Alt+Space) surfaces Remove › Development › Rust as the top result, above the RustDesk app. Since Enter runs whatever is highlighted and it's easy to press Enter before reading the row, the toolchain gets wiped instead of launching RustDesk.

Related: #6376 (same class of problem, marked fixed). This is a case that fix doesn't cover.

Reproduction

Omarchy 4.0 (Quattro), stock menu. Conditions:
- ~/.rustup exists → remove.development.rust is visible and matches rust exactly
- RustDesk is an installed app (label "RustDesk")

  1. Open the menu, type rust
  2. First result is Rust (path Remove › Development), not RustDesk
  3. Enter executes omarchy-remove-dev-env rust

Root cause

searchScore in shell/plugins/menu/MenuModel.js ties the top tier to exact label matches regardless of subtree:

  • remove.development.rust → label Rust == query → tier 0 (action row)
  • RustDesk app row → rustdesk only prefix-matches → tier 10, then −5 for being an app → 5000
  • Result: the removal ranks ~4700 points first.

It only didn't bite in the #6376 "steam" case because the Steam app also exact-matches and its −5 app bonus edges out the Remove row. Any app whose name merely starts with the query loses to a same-named install/remove entry ("rust", "go", "zen" while installed, etc.).

Expected behavior / solution options

  1. Don't let destructive rows trump apps — remove.*/install.* rows should not outrank the app the user is actually after unless the query is verb-specific ("remove rust").
  2. #6376's original ask — keep install.*/remove.* out of global search entirely; only searchable inside their own submenu.
  3. Removal/install rows must be unmistakable — show the parent path (Remove › Development) as the primary title, not a subtitle, and/or require a second keypress (Enter → confirm) for destructive rows.
  4. Remember what I actually pick (frecency) — record successful searches locally and use them to boost ranking on later runs:
  • When a row is activated from a search, save {query, itemId/menuId, timestamp} to a local state file (e.g. ~/.local/state/omarchy/menu-search-history.json), hooked into activateIndex/runAction in shell/plugins/menu/Menu.qml.
  • In searchScore/sorting, add a recency+frequency boost for rows previously opened from the same query: first time rust → RustDesk, from then on RustDesk leads and the muscle-memory Enter is safe.
  • Local-only, cheap to store, resettable (delete the file), and helps generally — not just for this bug.
  • Gives the best long-term behavior for a keyboard-first workflow: the menu learns instead of hardcoding which subtree wins.

Notes

Any of 1–3 alone fixes the immediate hazard; 4 in combination makes the menu safe by default and predictable over time. Suggested combined ask: 1 or 2 for the safety floor, plus 4 for personal ranking.

View raw text
### Summary

Typing `rust` in the Omarchy menu (Super+Alt+Space) surfaces `Remove › Development › Rust` as the top result, above the RustDesk app. Since Enter runs whatever is highlighted and it's easy to press Enter before reading the row, the toolchain gets wiped instead of launching RustDesk.

Related: #6376 (same class of problem, marked fixed). This is a case that fix doesn't cover.

### Reproduction

Omarchy 4.0 (Quattro), stock menu. Conditions:
- `~/.rustup` exists → `remove.development.rust` is visible and matches `rust` exactly
- RustDesk is an installed app (label "RustDesk")

1. Open the menu, type `rust`
2. First result is `Rust` (path `Remove › Development`), not RustDesk
3. Enter executes `omarchy-remove-dev-env rust`

### Root cause

`searchScore` in `shell/plugins/menu/MenuModel.js` ties the top tier to exact label matches regardless of subtree:

- `remove.development.rust` → label `Rust` == query → tier **0** (action row)
- RustDesk app row → `rustdesk` only prefix-matches → tier 10, then −5 for being an app → **5000**
- Result: the removal ranks ~4700 points first.

It only didn't bite in the #6376 "steam" case because the Steam app also exact-matches and its −5 app bonus edges out the Remove row. Any app whose name merely starts with the query loses to a same-named install/remove entry ("rust", "go", "zen" while installed, etc.).

### Expected behavior / solution options

1. **Don't let destructive rows trump apps** — `remove.*`/`install.*` rows should not outrank the app the user is actually after unless the query is verb-specific ("remove rust").
2. **#6376's original ask** — keep `install.*`/`remove.*` out of global search entirely; only searchable inside their own submenu.
3. **Removal/install rows must be unmistakable** — show the parent path (`Remove › Development`) as the primary title, not a subtitle, and/or require a second keypress (Enter → confirm) for destructive rows.
4. **Remember what I actually pick (frecency)** — record successful searches locally and use them to boost ranking on later runs:
   - When a row is activated from a search, save `{query, itemId/menuId, timestamp}` to a local state file (e.g. `~/.local/state/omarchy/menu-search-history.json`), hooked into `activateIndex`/`runAction` in `shell/plugins/menu/Menu.qml`.
   - In `searchScore`/sorting, add a recency+frequency boost for rows previously opened from the same query: first time `rust` → RustDesk, from then on RustDesk leads and the muscle-memory Enter is safe.
   - Local-only, cheap to store, resettable (delete the file), and helps generally — not just for this bug.
   - Gives the best long-term behavior for a keyboard-first workflow: the menu learns instead of hardcoding which subtree wins.

### Notes

Any of 1–3 alone fixes the immediate hazard; 4 in combination makes the menu safe by default *and* predictable over time. Suggested combined ask: 1 or 2 for the safety floor, plus 4 for personal ranking.

Validation

AI validator claude-code (claude-opus-5.5) · evaluated revision 1 at product commit 1e43373287af · sealed 2026-10-05T14:29:56Z

Validator's summary (commentary, not evidence)

Validation of omacom/omarchy#7630 on quattro-proof 1e433732 (upstream quattro 035ce29f product code plus the proof layer). The reported ranking reproduces with the shipped menu and MenuModel.js: on a system with ~/.rustup present and RustDesk installed, searching 'rust' from the root menu ranks Remove > Development > Rust first (exact label, best tier; searchScore, MenuModel.js:341-363 upstream) and the RustDesk app second (label prefix, minus the app shift). Install > Development > Rust is disabled by its ~/.rustup guard and search skips disabled rows. The menu selects row 0 when the query changes (Menu.qml:722-726) and Enter activates the selected row (Menu.qml:1153-1157), so Enter runs omarchy-remove-dev-env rust (default/omarchy/omarchy-menu.jsonc:343), which calls rustup self uninstall -y with no confirmation (bin/omarchy-remove-dev-env:111-114). This order conforms to SW-REQ-260922-SJ7P (score tiers); SYS-REQ-260922-V7W6's rationale says ranking decides which row Enter activates, and SW-REQ-260922-8CQ4 asks for a confirmation only when an app is uninstalled with Delete. No requirement says whether a destructive action may be the default Enter target, so this is an open specification question for the maintainers. KI-MENU-SEARCH-SCORE-RANKING (root exact labels vs nested twins, cross-field terms) was examined: a different ranking defect. Open upstream PR #7661 proposes one of the options; #6376 is the earlier, related report.

  • ConfirmedReproducible

    Reproducible: searching 'rust' with ~/.rustup present and RustDesk installed makes Remove > Development > Rust row 1, the Enter target

    Engine: engine-executed run exited 1 and showed the defect signal

    Evidence: file test/reports/report-cmulrfoje01ui18w4w89862tn.sh

    Validator's rationale (commentary): Observed with MenuModel.js on the shipped menu: Remove > Development > Rust score 356, RustDesk score 5372. The order follows SW-REQ-260922-SJ7P; whether a destructive row may be the Enter target is the open question below.

  • Not confirmedAffects a componentmenu

    Affects the menu component

    Engine: no requirement of the menu component is confirmed as violated

Engine reference checks at 923b93ce72af (11/11 ok)
  • okcommit923b93ce72af9b445616721fabde7eb822a21635
  • okbase commit1e43373287afbd6dca4674ad463d5b5db7812358
  • okbase ancestry1e43373287afbd6dca4674ad463d5b5db7812358
  • okproduct code untouchedthis report's reproducer branch
  • okbranchthis report's reproducer branch
  • okfiletest/reports/report-cmulrfoje01ui18w4w89862tn.sh
  • okrequirementSW-REQ-260922-8CQ4
  • okrequirementSW-REQ-260922-SJ7P
  • okrequirementSYS-REQ-260922-V7W6
  • okcomponentmenu
  • okknown issueKI-MENU-SEARCH-SCORE-RANKING

The engine's own check, at validation time, that the commits, the reproducer branch (touching only reproducer files), the reproducer files and every mapped requirement / component / known issue really exist.

Validator-authored hypothesis. Each claim's verification is engine-computed: confirmed only from an engine-executed reproducer run recorded in this record, refuted when recorded evidence contradicts it. Prose is commentary. The disposition of the report is a human decision.

Reproducer

engine-runexit 1 · expected exit 0 · defect exit 1 · 35 ms · 2026-10-05T14:29:55Z→ showed the defect
test/reports/report-cmulrfoje01ui18w4w89862tn.shon this report's reproducer branch @ 923b93ce72
sh test/reports/report-cmulrfoje01ui18w4w89862tn.sh

Setup failure: exit 2 means the reproducer could not set up (e.g. the product did not build) — such a run decides nothing.

Defect signal: output contains AS-REPORTED:

Matched lines (engine, over the full output)
AS-REPORTED: row 1 (the Enter target) is the destructive row [action] Remove › Development › Rust (omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-dev-env rust'); the RustDesk app is row 2
Observed output · 468 bytes
search 'rust' from the root menu, top rows (row 1 is the Enter target):
  1. [action] Remove › Development › Rust (score 356) -> omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-dev-env rust'
  2. [app] Apps › RustDesk (score 5372)
AS-REPORTED: row 1 (the Enter target) is the destructive row [action] Remove › Development › Rust (omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-dev-env rust'); the RustDesk app is row 2

Needs: linux · node >= 18 on PATH (the script exits 2 with SETUP: otherwise); nothing to build: MenuModel.js is plain JavaScript loaded straight from the worktree · ran on linux/amd64

Linked

  • Fixed bypr/7661· confirmed
  • Related PRpr/10457· confirmed
  • Fixed bypr/12223· confirmed

Decision

Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.

  • Decided by agents · verified: in the audited area (menu)
  • Decided by agents · verified: not a duplicate of another report
  • Decided by agents · verified: intended behaviour — a design question, not a defect

The outcome (valid, duplicate, not a bug, …) is not decided yet.