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-1703GitHub issuePublicDecided· Out of scope

Internal monitor position cannot be made to stick: clamshell watcher and Display panel scaling both re-apply position = "auto"

Reported by skoom21 · filed Aug 17, 2026 · open at source

Decided: Out of scope — decided by agents · verified 4 days ago.

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?
AreaOutside the audited area· 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?
Decided by agents and verified by a second, independent agent — see the decision.

Original report

Internal monitor position cannot be made to stick: clamshell watcher and Display panel scaling both re-apply position = "auto"revision 1 · captured 2026-09-28 21:29 UTC via poll

System details

Dell Latitude E5470 · Intel Core i5-6440HQ · Omarchy 4.0.0-1 · Hyprland 0.56.2 · internal eDP-1 1366x768 + external HDMI-A-1 1920x1080

What's wrong?

On a laptop with an external monitor, an explicit position for the internal panel cannot be made to stick. Two separate code paths re-apply the internal monitor with position = "auto", so any manual arrangement is discarded within about a second — and with the stock monitors.lua, this happens to everyone, not just users with an unusual config.

The Display panel offers brightness, text size, scale and enable/disable, but no way to arrange monitors, so laying them out at all means editing config or reaching for a third-party tool — which then loses the race described below.

This is adjacent to #7084 and #6673 but is a distinct defect: those concern scale (desc:-keyed rules, and global-vs-per-monitor persistence). This one is about position, and it reproduces with connector-name rules and the shipped defaults. Happy to have it folded into #7084 if maintainers see them as one bug in omarchy-hyprland-monitor-clamshell.

Root cause 1 — the default config guarantees the fallback

bin/omarchy-hyprland-monitor-clamshell:

read_monitor_position() {
  local position
  position=$(configured_internal_monitor_value position)
  if [[ $position =~ ^[-[:alnum:]_.+]+$ ]]; then
    echo "$position"
    return
  fi

  echo auto
}

enable_internal_output() {
  ...
  position=$(read_monitor_position)
  hyprctl eval "hl.monitor({ output = \"$INTERNAL\", mode = \"preferred\", position = \"$position\", scale = $scale })" ...
}

configured_internal_monitor_value matches only a rule keyed by the internal connector name:

printf '^[[:space:]]*hl\\.monitor\\(\\{.*output[[:space:]]*=[[:space:]]*"%s"' "$1"

But the monitors.lua Omarchy ships contains no such rule — only the generic catch-all:

hl.monitor({ output = "", mode = "preferred", position = "auto", scale = omarchy_monitor_scale })

So on a stock install the lookup finds nothing, read_monitor_position returns auto, and the watcher re-asserts the internal panel auto-placed. Unlike the scale path — which has a documented fallback chain ending at omarchy_monitor_scale — position has no equivalent: it does not consult the catch-all's position, it just goes to auto.

omarchy-hyprland-monitor-watch calls this on every monitor event (and on a timer while docked), so the override is effectively immediate and repeating.

Root cause 2 — the Display panel's scale buttons discard position

bin/omarchy-hyprland-monitor-scaling:

hyprctl eval "hl.monitor({ output = \"$active_monitor\", mode = \"${width}x${height}@${refresh_rate}\", position = \"auto\", scale = $new_scale })" >/dev/null

position = "auto" is hardcoded, so changing scale from the Display panel re-places that monitor regardless of any configured position. This one affects external monitors too, not just the internal panel.

Steps to reproduce

  1. Laptop with an external monitor connected, stock ~/.config/hypr/monitors.lua.
  2. Give the two monitors a deliberate layout — e.g. centre the internal panel vertically against the external one:
   hyprctl keyword monitor "eDP-1,1366x768@60,1920x156,1"
  1. hyprctl monitors | grep -A2 eDP-1 → position is correct for about a second.
  2. Trigger any monitor event, or just wait while docked.

Expected: the layout holds.
Actual: eDP-1 snaps back to an auto-assigned position (here 1920x0), losing the vertical offset. Pressing any scale button in the Display panel does the same thing immediately, and to whichever monitor is focused.

Workaround

Add an explicit connector-name rule for the internal panel to monitors.lua, so the clamshell lookup finds a position instead of falling back to auto:

hl.monitor({ output = "HDMI-A-1", mode = "preferred", position = "0x0",    scale = omarchy_monitor_scale })
hl.monitor({ output = "eDP-1",    mode = "preferred", position = "1920x156", scale = omarchy_monitor_scale })

Keeping scale = omarchy_monitor_scale rather than a literal preserves the Display panel's scale persistence, which rewrites the local omarchy_monitor_scale line.

This holds across monitor events, but is still undone for the focused monitor whenever a Display-panel scale button is pressed (root cause 2).

Suggested fix

  • Give read_monitor_position a fallback chain mirroring configured_monitor_scale: internal rule → catch-all rule → auto. That alone would make an explicitly positioned catch-all survive.
  • Better, have enable_internal_output omit position entirely when the config does not specify one, instead of asserting auto. Re-asserting auto actively destroys a layout the user may have set through any other route; saying nothing leaves the current placement intact.
  • In omarchy-hyprland-monitor-scaling, preserve the monitor's current position instead of hardcoding position = "auto" — it can be read from hyprctl monitors -j before the change.
  • Longer term, the Display panel having any monitor-arrangement affordance would remove the need for users to hand-edit or use external tools here (cf. the closed #2858).
View raw text
### System details

Dell Latitude E5470 · Intel Core i5-6440HQ · Omarchy 4.0.0-1 · Hyprland 0.56.2 · internal `eDP-1` 1366x768 + external `HDMI-A-1` 1920x1080

### What's wrong?

On a laptop with an external monitor, an explicit `position` for the internal panel cannot be made to stick. Two separate code paths re-apply the internal monitor with `position = "auto"`, so any manual arrangement is discarded within about a second — and with the **stock** `monitors.lua`, this happens to everyone, not just users with an unusual config.

The Display panel offers brightness, text size, scale and enable/disable, but no way to arrange monitors, so laying them out at all means editing config or reaching for a third-party tool — which then loses the race described below.

This is adjacent to #7084 and #6673 but is a distinct defect: those concern **scale** (`desc:`-keyed rules, and global-vs-per-monitor persistence). This one is about **position**, and it reproduces with connector-name rules and the shipped defaults. Happy to have it folded into #7084 if maintainers see them as one bug in `omarchy-hyprland-monitor-clamshell`.

### Root cause 1 — the default config guarantees the fallback

`bin/omarchy-hyprland-monitor-clamshell`:

```bash
read_monitor_position() {
  local position
  position=$(configured_internal_monitor_value position)
  if [[ $position =~ ^[-[:alnum:]_.+]+$ ]]; then
    echo "$position"
    return
  fi

  echo auto
}

enable_internal_output() {
  ...
  position=$(read_monitor_position)
  hyprctl eval "hl.monitor({ output = \"$INTERNAL\", mode = \"preferred\", position = \"$position\", scale = $scale })" ...
}
```

`configured_internal_monitor_value` matches only a rule keyed by the internal connector name:

```bash
printf '^[[:space:]]*hl\\.monitor\\(\\{.*output[[:space:]]*=[[:space:]]*"%s"' "$1"
```

But the `monitors.lua` Omarchy ships contains no such rule — only the generic catch-all:

```lua
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = omarchy_monitor_scale })
```

So on a stock install the lookup finds nothing, `read_monitor_position` returns `auto`, and the watcher re-asserts the internal panel auto-placed. Unlike the `scale` path — which has a documented fallback chain ending at `omarchy_monitor_scale` — `position` has no equivalent: it does not consult the catch-all's `position`, it just goes to `auto`.

`omarchy-hyprland-monitor-watch` calls this on every monitor event (and on a timer while docked), so the override is effectively immediate and repeating.

### Root cause 2 — the Display panel's scale buttons discard position

`bin/omarchy-hyprland-monitor-scaling`:

```bash
hyprctl eval "hl.monitor({ output = \"$active_monitor\", mode = \"${width}x${height}@${refresh_rate}\", position = \"auto\", scale = $new_scale })" >/dev/null
```

`position = "auto"` is hardcoded, so changing scale from the Display panel re-places that monitor regardless of any configured position. This one affects external monitors too, not just the internal panel.

### Steps to reproduce

1. Laptop with an external monitor connected, stock `~/.config/hypr/monitors.lua`.
2. Give the two monitors a deliberate layout — e.g. centre the internal panel vertically against the external one:
   ```bash
   hyprctl keyword monitor "eDP-1,1366x768@60,1920x156,1"
   ```
3. `hyprctl monitors | grep -A2 eDP-1` → position is correct for about a second.
4. Trigger any monitor event, or just wait while docked.

**Expected:** the layout holds.
**Actual:** `eDP-1` snaps back to an auto-assigned position (here `1920x0`), losing the vertical offset. Pressing any scale button in the Display panel does the same thing immediately, and to whichever monitor is focused.

### Workaround

Add an explicit connector-name rule for the internal panel to `monitors.lua`, so the clamshell lookup finds a position instead of falling back to `auto`:

```lua
hl.monitor({ output = "HDMI-A-1", mode = "preferred", position = "0x0",    scale = omarchy_monitor_scale })
hl.monitor({ output = "eDP-1",    mode = "preferred", position = "1920x156", scale = omarchy_monitor_scale })
```

Keeping `scale = omarchy_monitor_scale` rather than a literal preserves the Display panel's scale persistence, which rewrites the `local omarchy_monitor_scale` line.

This holds across monitor events, but is still undone for the focused monitor whenever a Display-panel scale button is pressed (root cause 2).

### Suggested fix

- Give `read_monitor_position` a fallback chain mirroring `configured_monitor_scale`: internal rule → catch-all rule → `auto`. That alone would make an explicitly positioned catch-all survive.
- Better, have `enable_internal_output` omit `position` entirely when the config does not specify one, instead of asserting `auto`. Re-asserting `auto` actively destroys a layout the user may have set through any other route; saying nothing leaves the current placement intact.
- In `omarchy-hyprland-monitor-scaling`, preserve the monitor's current position instead of hardcoding `position = "auto"` — it can be read from `hyprctl monitors -j` before the change.
- Longer term, the Display panel having any monitor-arrangement affordance would remove the need for users to hand-edit or use external tools here (cf. the closed #2858).

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

  • Related PRpr/7146· 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.

  • Out of scopeDecided by agents · verified · 2026-10-09 04:38 UTC