Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA 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.
Menu: Left/Backspace from a submenu always returns to the first row, discarding the parent selection (8 open PRs, no issue)
Reported by rkondratowicz · filed Sep 30, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 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. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.
Original report
System details
AMD Ryzen 9 7940HS (integrated Radeon 780M, no discrete GPU), Omarchy 4.0.4-1, kernel 7.2.5-3-omarchy, Hyprland, stable channel.
Reproduces on stock Omarchy with no custom plugins and an unmodified ~/.config/omarchy/extensions/omarchy-menu.jsonc. Not hardware- or theme-specific — the cause is a single unconditional assignment in Menu.qml, so it should affect every user on 4.0.x.
What's wrong?
In the menu, descending into a submenu with Right and then returning with Left (or Backspace on an empty filter) always places the cursor on the first row, discarding the parent row you entered from. The menu effectively forgets where you were.
Steps to reproduce
- Press
SUPER+SPACEto open the menu. - Scroll to a category that is not at the top — e.g.
Style. - Press
Rightto enter it. - Press
Leftto go back.
Actual: the cursor jumps to Apps (row 0).
Expected: the cursor is back on Style (row 3), the row you entered from.
Also affects the shipped direct-submenu bindings
The same reset happens when the menu is opened straight into a submenu, because openExistingMenu() starts with an empty navStack:
omarchy menu summon system, thenLeft→ lands onAppsinstead ofSystem.SUPER+ESCAPE(System) orSUPER+CTRL+C(Capture), thenLeft→ same reset.
And after a search result, where the saved row is not a direct child of the rebuilt parent:
- Type
positionat root, openStyle > Menu Bar > Position, thenLeft→ lands onApps, becauserootis rebuilt unfiltered and no row matches the saved id.
This is why I am reporting it as a bug rather than a feature request: Left/Backspace are implemented as navigation-back, and they do navigate back. What is broken is that they unconditionally discard the cursor position, including for the direct-submenu bindings Omarchy ships. There is no configuration to change this — I checked omarchy-menu.jsonc, shell.json, and shell.toml.
Root cause
shell/plugins/menu/Menu.qml, setActiveMenu():
function setActiveMenu(id, pushHistory, fromPointer) {
...
root.activeMenu = id
root.filterText = ""
root.selectedIndex = 0 // <-- unconditional
...
}goBack() calls setActiveMenu() on every path, so the cursor is always reset:
function goBack() {
if (root.activeMenu === "root") return false
if (root.navStack.length > 0) {
var previous = root.navStack[root.navStack.length - 1]
...
root.setActiveMenu(previous, false)
return true
}
var active = root.item(root.activeMenu)
root.setActiveMenu((active && active.parent) ? active.parent : "root", false)
return true
}The root problem is that navStack (property var navStack: []) stores only menu ids. It has no room to record which row was selected, so there is nothing to restore — hence the hardcoded reset.
Verified not fixed on the default branch either. On quattro (as of today) setActiveMenu() still contains root.selectedIndex = 0, so a fix is needed regardless of which release this lands in.
Related work — this is blocked behind duplication, not behind a decision
I want to be explicit that this issue already has implementations and no owner. There are currently eight open PRs for exactly this behaviour, and three more were auto-closed as duplicates. None have been merged. All touch only shell/plugins/menu/Menu.qml (plus MenuModel.js / test/shell.d/menu-test.sh):
| PR | Approach |
|---|---|
| #7074 | restore by numeric index |
| #7954 | store index alongside navStack history |
| #11577 | fix nav history resetting cursor index |
| #12098 | restore by stable item ID, index clamp fallback |
| #12644 | falls back to nearest visible ancestor; covers the direct-submenu paths |
| #12759 | also restores each level's filterText; makes Left always navigate back |
| #13012 | restore by item ID so the cursor follows reordering |
| #13225 | restore by item ID, skip non-selectable rows |
On 2026-09-21 an automated duplication check closed #7657, #7800 and #8322 as "similar to #7074", keeping #7074 open as the survivor. #7074 has not been merged since. For the record, #7657 was the most thoroughly validated of the three before closure: it was reviewed on a live VM (test/shell.d/menu-test.sh, 124 passed, plus five adjacent suites) and had the direct-submenu gap from #11409's reporter folded into it.
The approaches are not identical, which is likely why consolidation has stalled: restoring by numeric index (#7074) breaks when rows change or when a search result is not a direct child of the rebuilt parent, while restoring by item id (#12098, #13012, #13225) survives that but needs a fallback when the saved row is hidden or no longer selectable. #12644 additionally covers the direct-submenu and deep-search cases listed above. A single fix likely needs the item-id restore plus a nearest-visible-ancestor fallback.
What would help
- Pick a canonical PR (or say which approach should win) so the other seven can be closed in one go.
- The
enhancementlabel on most of these reads wrong to me — losing your place on Back is a navigation defect, and it affects shipped bindings. Relabelling asbugwould also match the behaviour being reported here. - Do not close the menu plugin's `appLibrary` wiring — I checked whether patching locally via
omarchy plugin clone omarchy.menuwas a viable workaround and it is not, on 4.0.4-1: cloned menu plugins get a null scopedappLibrary, which empties the Apps submenu (#12061, #12989, #12944, #12325). Mentioning it only so nobody spends time on that workaround while this is open.
Happy to test a consolidated fix on my machine and report back, and I can provide a screen recording of the A/B if that is useful.
View raw text
## System details
AMD Ryzen 9 7940HS (integrated Radeon 780M, no discrete GPU), Omarchy 4.0.4-1, kernel 7.2.5-3-omarchy, Hyprland, stable channel.
Reproduces on stock Omarchy with no custom plugins and an unmodified `~/.config/omarchy/extensions/omarchy-menu.jsonc`. Not hardware- or theme-specific — the cause is a single unconditional assignment in `Menu.qml`, so it should affect every user on 4.0.x.
## What's wrong?
In the menu, descending into a submenu with `Right` and then returning with `Left` (or `Backspace` on an empty filter) always places the cursor on the **first row**, discarding the parent row you entered from. The menu effectively forgets where you were.
### Steps to reproduce
1. Press `SUPER+SPACE` to open the menu.
2. Scroll to a category that is not at the top — e.g. `Style`.
3. Press `Right` to enter it.
4. Press `Left` to go back.
Actual: the cursor jumps to `Apps` (row 0).
Expected: the cursor is back on `Style` (row 3), the row you entered from.
### Also affects the shipped direct-submenu bindings
The same reset happens when the menu is opened straight into a submenu, because `openExistingMenu()` starts with an empty `navStack`:
- `omarchy menu summon system`, then `Left` → lands on `Apps` instead of `System`.
- `SUPER+ESCAPE` (System) or `SUPER+CTRL+C` (Capture), then `Left` → same reset.
And after a search result, where the saved row is not a direct child of the rebuilt parent:
- Type `position` at root, open `Style > Menu Bar > Position`, then `Left` → lands on `Apps`, because `root` is rebuilt unfiltered and no row matches the saved id.
This is why I am reporting it as a bug rather than a feature request: `Left`/`Backspace` *are* implemented as navigation-back, and they do navigate back. What is broken is that they unconditionally discard the cursor position, including for the direct-submenu bindings Omarchy ships. There is no configuration to change this — I checked `omarchy-menu.jsonc`, `shell.json`, and `shell.toml`.
## Root cause
`shell/plugins/menu/Menu.qml`, `setActiveMenu()`:
```qml
function setActiveMenu(id, pushHistory, fromPointer) {
...
root.activeMenu = id
root.filterText = ""
root.selectedIndex = 0 // <-- unconditional
...
}
```
`goBack()` calls `setActiveMenu()` on every path, so the cursor is always reset:
```qml
function goBack() {
if (root.activeMenu === "root") return false
if (root.navStack.length > 0) {
var previous = root.navStack[root.navStack.length - 1]
...
root.setActiveMenu(previous, false)
return true
}
var active = root.item(root.activeMenu)
root.setActiveMenu((active && active.parent) ? active.parent : "root", false)
return true
}
```
The root problem is that `navStack` (`property var navStack: []`) stores **only menu ids**. It has no room to record which row was selected, so there is nothing to restore — hence the hardcoded reset.
Verified not fixed on the default branch either. On `quattro` (as of today) `setActiveMenu()` still contains `root.selectedIndex = 0`, so a fix is needed regardless of which release this lands in.
## Related work — this is blocked behind duplication, not behind a decision
I want to be explicit that **this issue already has implementations and no owner**. There are currently **eight open PRs** for exactly this behaviour, and three more were auto-closed as duplicates. None have been merged. All touch only `shell/plugins/menu/Menu.qml` (plus `MenuModel.js` / `test/shell.d/menu-test.sh`):
| PR | Approach |
|---|---|
| [#7074](https://github.com/omacom/omarchy/pull/7074) | restore by numeric index |
| [#7954](https://github.com/omacom/omarchy/pull/7954) | store index alongside `navStack` history |
| [#11577](https://github.com/omacom/omarchy/pull/11577) | fix nav history resetting cursor index |
| [#12098](https://github.com/omacom/omarchy/pull/12098) | restore by stable item ID, index clamp fallback |
| [#12644](https://github.com/omacom/omarchy/pull/12644) | falls back to nearest visible ancestor; covers the direct-submenu paths |
| [#12759](https://github.com/omacom/omarchy/pull/12759) | also restores each level's `filterText`; makes `Left` always navigate back |
| [#13012](https://github.com/omacom/omarchy/pull/13012) | restore by item ID so the cursor follows reordering |
| [#13225](https://github.com/omacom/omarchy/pull/13225) | restore by item ID, skip non-selectable rows |
On 2026-09-21 an automated duplication check closed [#7657](https://github.com/omacom/omarchy/pull/7657), [#7800](https://github.com/omacom/omarchy/pull/7800) and [#8322](https://github.com/omacom/omarchy/pull/8322) as "similar to #7074", keeping #7074 open as the survivor. #7074 has not been merged since. For the record, #7657 was the most thoroughly validated of the three before closure: it was reviewed on a live VM (`test/shell.d/menu-test.sh`, 124 passed, plus five adjacent suites) and had the direct-submenu gap from #11409's reporter folded into it.
The approaches are not identical, which is likely why consolidation has stalled: restoring by **numeric index** (#7074) breaks when rows change or when a search result is not a direct child of the rebuilt parent, while restoring by **item id** (#12098, #13012, #13225) survives that but needs a fallback when the saved row is hidden or no longer selectable. #12644 additionally covers the direct-submenu and deep-search cases listed above. A single fix likely needs the item-id restore *plus* a nearest-visible-ancestor fallback.
## What would help
1. **Pick a canonical PR** (or say which approach should win) so the other seven can be closed in one go.
2. The `enhancement` label on most of these reads wrong to me — losing your place on Back is a navigation defect, and it affects shipped bindings. Relabelling as `bug` would also match the behaviour being reported here.
3. **Do not close the menu plugin's `appLibrary` wiring** — I checked whether patching locally via `omarchy plugin clone omarchy.menu` was a viable workaround and it is not, on 4.0.4-1: cloned menu plugins get a null scoped `appLibrary`, which empties the Apps submenu (#12061, #12989, #12944, #12325). Mentioning it only so nobody spends time on that workaround while this is open.
Happy to test a consolidated fix on my machine and report back, and I can provide a screen recording of the A/B if that is useful.Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
- Fixed bypr/11577· confirmed
- Fixed bypr/12644· confirmed
- Related PRpr/12759· confirmed
- Related PRpr/7954· confirmed
- Related PRpr/7074· confirmed
- Related PRpr/13012· confirmed
- Related PRpr/13225· 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)
The outcome (valid, duplicate, not a bug, …) is not decided yet.