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-2226GitHub issuePublicFixed

Menu: first item is clipped/scrolled off on initial display in scrollable lists (omarchy-menu-select / SUPER+K)

Reported by b-lov · filed Oct 3, 2026 · open at source

In the audited area (menu) — decided by agents · verified. Not validated yet.

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?
AreaIn the audited areamenu· Decided by agents · verified
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; matches no known issue — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Original report

Menu: first item is clipped/scrolled off on initial display in scrollable lists (omarchy-menu-select / SUPER+K)revision 1 · captured 2026-10-03 21:59 UTC via poll

System details

AMD Ryzen 7 8845HS w/ Radeon 780M Graphics, Omarchy 4.0.0.r6713.ga85e29a-1 (Hyprland / Quickshell)

What's wrong?

When opening any list with more items than fit inside the initial view height (e.g. SUPER + K for omarchy-menu-keybindings, or any invocation of omarchy-menu-select with >8 items), the very first item (index 0) is scrolled up into negative space and clipped/obscured.

Steps to reproduce

  1. Press SUPER + K to open the keybindings menu.
  2. Notice the top of the list: the topmost entry (SUPER + K → Keybindings, priority 0) has scrolled up above the top border of the ListView and is clipped. Visually, the list appears to start with the second entry (SUPER + SPACE → Omarchy menu).
  3. Alternatively, run:
   omarchy-menu-select "Test" $(for i in {1..15}; do echo "Option $i"; done)

Notice "Option 1" has its top half cut off.

Root cause

In shell/plugins/menu/Menu.qml inside revealCursor():

function revealCursor() {
  if (displayModel.count === 0) return
  resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)

  var item = resultList.itemAtIndex(root.selectedIndex)
  if (!item) return

  var reach = root.rowPeek + root.rowSpacing
  if (root.selectedIndex < displayModel.count - 1) {
    var maxY = Math.max(resultList.originY, resultList.originY + resultList.contentHeight - resultList.height)
    var overhang = item.y + item.height + reach - (resultList.contentY + resultList.height)
    if (overhang > 0) resultList.contentY = Math.min(resultList.contentY + overhang, maxY)
  }
  if (root.selectedIndex > 0) {
    var underhang = resultList.contentY - (item.y - reach)
    if (underhang > 0) resultList.contentY = Math.max(resultList.contentY - underhang, resultList.originY)
  }
}
  1. On initial open, revealCursor() is invoked via Qt.callLater when displayModel loads.
  2. At this moment, before resultList.height has settled to the final mapped window height, overhang evaluates to > 0 because item.y + item.height + reach exceeds the initial list height.
  3. This sets resultList.contentY = overhang (typically ~30–40px), scrolling item 0 partially out of view.
  4. Because root.selectedIndex === 0, the underhang logic (if (root.selectedIndex > 0)) never resets `contentY` back to `originY`.
  5. As a result, item 0 remains permanently scrolled up and clipped.

Fix

When selectedIndex === 0, contentY should always remain flush at resultList.originY (0):

--- a/shell/plugins/menu/Menu.qml
+++ b/shell/plugins/menu/Menu.qml
@@ -690,6 +690,10 @@
   function revealCursor() {
     if (displayModel.count === 0) return
+    if (root.selectedIndex === 0) {
+      resultList.contentY = resultList.originY
+      return
+    }
     resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)
 
     var item = resultList.itemAtIndex(root.selectedIndex)
View raw text
### System details

AMD Ryzen 7 8845HS w/ Radeon 780M Graphics, Omarchy 4.0.0.r6713.ga85e29a-1 (Hyprland / Quickshell)

### What's wrong?

When opening any list with more items than fit inside the initial view height (e.g. `SUPER + K` for `omarchy-menu-keybindings`, or any invocation of `omarchy-menu-select` with >8 items), the **very first item (index 0) is scrolled up into negative space and clipped/obscured**.

#### Steps to reproduce
1. Press `SUPER + K` to open the keybindings menu.
2. Notice the top of the list: the topmost entry (`SUPER + K → Keybindings`, priority 0) has scrolled up above the top border of the ListView and is clipped. Visually, the list appears to start with the second entry (`SUPER + SPACE → Omarchy menu`).
3. Alternatively, run:
   ```bash
   omarchy-menu-select "Test" $(for i in {1..15}; do echo "Option $i"; done)
   ```
   Notice "Option 1" has its top half cut off.

#### Root cause
In `shell/plugins/menu/Menu.qml` inside `revealCursor()`:
```javascript
function revealCursor() {
  if (displayModel.count === 0) return
  resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)

  var item = resultList.itemAtIndex(root.selectedIndex)
  if (!item) return

  var reach = root.rowPeek + root.rowSpacing
  if (root.selectedIndex < displayModel.count - 1) {
    var maxY = Math.max(resultList.originY, resultList.originY + resultList.contentHeight - resultList.height)
    var overhang = item.y + item.height + reach - (resultList.contentY + resultList.height)
    if (overhang > 0) resultList.contentY = Math.min(resultList.contentY + overhang, maxY)
  }
  if (root.selectedIndex > 0) {
    var underhang = resultList.contentY - (item.y - reach)
    if (underhang > 0) resultList.contentY = Math.max(resultList.contentY - underhang, resultList.originY)
  }
}
```

1. On initial open, `revealCursor()` is invoked via `Qt.callLater` when `displayModel` loads.
2. At this moment, before `resultList.height` has settled to the final mapped window height, `overhang` evaluates to `> 0` because `item.y + item.height + reach` exceeds the initial list height.
3. This sets `resultList.contentY = overhang` (typically ~30–40px), scrolling item 0 partially out of view.
4. Because `root.selectedIndex === 0`, the underhang logic (`if (root.selectedIndex > 0)`) **never resets `contentY` back to `originY`**.
5. As a result, item 0 remains permanently scrolled up and clipped.

#### Fix
When `selectedIndex === 0`, `contentY` should always remain flush at `resultList.originY` (0):
```diff
--- a/shell/plugins/menu/Menu.qml
+++ b/shell/plugins/menu/Menu.qml
@@ -690,6 +690,10 @@
   function revealCursor() {
     if (displayModel.count === 0) return
+    if (root.selectedIndex === 0) {
+      resultList.contentY = resultList.originY
+      return
+    }
     resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)
 
     var item = resultList.itemAtIndex(root.selectedIndex)
```

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/14190· confirmed
  • Fixed bypr/14393· 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: matches no known issue

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