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.
Laptop display never re-enabled after unplugging an external monitor: Hyprland's FALLBACK output is counted as an external display
Reported by HritwikSinghal · filed Aug 24, 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?
- 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
What happens
- Dock a laptop to an external monitor.
- Turn the laptop panel off (
SUPER + CTRL + Delete, or Hardware -> Laptop Display). - Unplug the external monitor.
The laptop panel is never re-enabled. The machine is left with no display at all until the next login, where omarchy-recover-internal-monitor.service clears the toggle.
This appears to be what #7228 and #7209 are reporting. #7380 is the same virtual output crashing omarchy-shell.
Root cause
omarchy-hyprland-monitor-external-active decides "is an external monitor active?" purely from output names:
hyprctl monitors all -j | jq -e '.[] | select(.name | test("^(eDP|LVDS|DSI)-") | not) | select(.disabled == false)'But Hyprland runs outputs that have no display behind them. Its FallbackStateKeeper (src/state/FallbackState.cpp, added in 0.56.0) creates one named literally FALLBACK, through the headless backend, the moment the set of enabled monitors becomes empty:
m_listeners.monitorRemoved = Event::bus()->m_events.monitor.removed.listen([this](PHLMONITOR removed) {
if (State::monitorState()->monitors().size() > 1)
return;
...
Log::logger->log(Log::DEBUG, "[FallbackStateKeeper] Monitor {} removed, entering fallback", removed->m_name);
setFallbackActive(true);
});monitors() is m_monitors (enabled only), distinct from allMonitors()/m_realMonitors (which includes disabled ones). That is the crux: an internal panel sitting at disabled = true does not count, so unplugging the external display in step 3 empties the enabled set and the fallback fires.
FALLBACK then reports disabled: false and matches none of the internal-panel prefixes, so the helper answers "an external monitor is active" -- and every caller that uses it to decide whether re-enabling the internal panel is safe backs off:
# bin/omarchy-hyprland-monitor-internal
recover() {
omarchy-hyprland-monitor-external-active && return 0 # <-- bails here
omarchy-hyprland-toggle-enabled $TOGGLE || return 0
omarchy-hyprland-toggle $TOGGLE off # never reached
wake
}Same guard in omarchy-hyprland-monitor-clamshell's enable_internal(), and in the watcher's sync_poll_state(). omarchy-hyprland-monitor-watch fires correctly on monitorremoved and retries at 1s, 3s and 7s -- every attempt bails at the same line, so the toggle flag is never cleared.
Only the next login recovers, because omarchy-recover-internal-monitor.service asks omarchy-hw-external-monitors instead, which reads DRM state and cannot be fooled this way.
Reproducing the false positive without unplugging anything
hyprctl output create headless makes a virtual output through the same headless backend:
$ hyprctl output create headless
$ hyprctl monitors all -j | jq -r '.[] | "\(.name) disabled=\(.disabled)"'
eDP-1 disabled=false
HEADLESS-1 disabled=false
$ omarchy-hw-external-monitors; echo "DRM check -> $?" # 1 = nothing connected, correct
DRM check -> 1
$ omarchy-hyprland-monitor-external-active; echo "name check -> $?" # 0 = "external active", wrong
name check -> 0This is a regression
omarchy 3.8.5 guarded recovery on the hardware check, so it was immune:
# omarchy 3.8.5, bin/omarchy-hyprland-monitor-internal
recover() {
if ! omarchy-hw-external-monitors && omarchy-hyprland-toggle-enabled $TOGGLE; then
omarchy-hyprland-toggle $TOGGLE off
fi
}omarchy-hyprland-monitor-external-active did not exist in 3.8.5; neither did omarchy-hyprland-monitor-clamshell. off() regressed the same way -- 3.8.5 guarded "Can't disable the only active display" with ! omarchy-hw-external-monitors too.
Worth noting that 96afc684 (2026-04-23) moved this guard onto the hardware check deliberately, titled "Move to a hardware check for external monitors instead to deal with recover timing". The quattro rewrite moved it back onto the name check.
Two things I checked and ruled out, in case they come up:
- Hyprland 0.55 -> 0.56 is not the trigger. 0.55.4 also entered an unsafe state and enabled a
HEADLESS-1output when the last enabled monitor went away (prepareFallbackOutput/enterUnsafeStateinsrc/Compositor.cpp), so a name test would have been fooled there too. 0.56 only renamed it toFALLBACKand made it on-demand rather than created at startup. - f4b832eb (`hyprctl monitors` -> `hyprctl monitors all`) is not the trigger. I ran the helper's exact jq both ways against a live virtual output; both report "external active". No difference for this bug.
Suggested fix
A real display has a DRM connector; a virtual output has none. Cross-check candidates against sysfs, which restores the hardware truth recover() used to have while keeping the monitors all behaviour f4b832eb needed for mirrors (a mirrored external has a connected connector, so it keeps counting).
PR: fixes the helper in one place, so recover(), off(), clamshell's enable_internal()/disable_internal() and the watcher's poll are all corrected at once. Includes a test that fails on the current helper at its first assertion.
Environment
omarchy-dev4.0.0.r1816.g43bfe9b-1- Hyprland 0.56.2
- Dell XPS,
eDP-1internal panel + DP-1 external
View raw text
### What happens
1. Dock a laptop to an external monitor.
2. Turn the laptop panel off (`SUPER + CTRL + Delete`, or Hardware -> Laptop Display).
3. Unplug the external monitor.
The laptop panel is never re-enabled. The machine is left with **no display at all** until the next login, where `omarchy-recover-internal-monitor.service` clears the toggle.
This appears to be what #7228 and #7209 are reporting. #7380 is the same virtual output crashing `omarchy-shell`.
### Root cause
`omarchy-hyprland-monitor-external-active` decides "is an external monitor active?" purely from output *names*:
```bash
hyprctl monitors all -j | jq -e '.[] | select(.name | test("^(eDP|LVDS|DSI)-") | not) | select(.disabled == false)'
```
But Hyprland runs outputs that have no display behind them. Its `FallbackStateKeeper` (`src/state/FallbackState.cpp`, added in 0.56.0) creates one named literally `FALLBACK`, through the headless backend, the moment the set of **enabled** monitors becomes empty:
```cpp
m_listeners.monitorRemoved = Event::bus()->m_events.monitor.removed.listen([this](PHLMONITOR removed) {
if (State::monitorState()->monitors().size() > 1)
return;
...
Log::logger->log(Log::DEBUG, "[FallbackStateKeeper] Monitor {} removed, entering fallback", removed->m_name);
setFallbackActive(true);
});
```
`monitors()` is `m_monitors` (enabled only), distinct from `allMonitors()`/`m_realMonitors` (which includes disabled ones). **That is the crux:** an internal panel sitting at `disabled = true` does not count, so unplugging the external display in step 3 empties the enabled set and the fallback fires.
`FALLBACK` then reports `disabled: false` and matches none of the internal-panel prefixes, so the helper answers "an external monitor is active" -- and every caller that uses it to decide whether re-enabling the internal panel is safe backs off:
```bash
# bin/omarchy-hyprland-monitor-internal
recover() {
omarchy-hyprland-monitor-external-active && return 0 # <-- bails here
omarchy-hyprland-toggle-enabled $TOGGLE || return 0
omarchy-hyprland-toggle $TOGGLE off # never reached
wake
}
```
Same guard in `omarchy-hyprland-monitor-clamshell`'s `enable_internal()`, and in the watcher's `sync_poll_state()`. `omarchy-hyprland-monitor-watch` fires correctly on `monitorremoved` and retries at 1s, 3s and 7s -- every attempt bails at the same line, so the toggle flag is never cleared.
Only the next login recovers, because `omarchy-recover-internal-monitor.service` asks `omarchy-hw-external-monitors` instead, which reads DRM state and cannot be fooled this way.
### Reproducing the false positive without unplugging anything
`hyprctl output create headless` makes a virtual output through the same headless backend:
```console
$ hyprctl output create headless
$ hyprctl monitors all -j | jq -r '.[] | "\(.name) disabled=\(.disabled)"'
eDP-1 disabled=false
HEADLESS-1 disabled=false
$ omarchy-hw-external-monitors; echo "DRM check -> $?" # 1 = nothing connected, correct
DRM check -> 1
$ omarchy-hyprland-monitor-external-active; echo "name check -> $?" # 0 = "external active", wrong
name check -> 0
```
### This is a regression
omarchy 3.8.5 guarded recovery on the hardware check, so it was immune:
```bash
# omarchy 3.8.5, bin/omarchy-hyprland-monitor-internal
recover() {
if ! omarchy-hw-external-monitors && omarchy-hyprland-toggle-enabled $TOGGLE; then
omarchy-hyprland-toggle $TOGGLE off
fi
}
```
`omarchy-hyprland-monitor-external-active` did not exist in 3.8.5; neither did `omarchy-hyprland-monitor-clamshell`. `off()` regressed the same way -- 3.8.5 guarded "Can't disable the only active display" with `! omarchy-hw-external-monitors` too.
Worth noting that 96afc684 (2026-04-23) moved this guard onto the hardware check *deliberately*, titled "Move to a hardware check for external monitors instead to deal with recover timing". The quattro rewrite moved it back onto the name check.
Two things I checked and ruled out, in case they come up:
- **Hyprland 0.55 -> 0.56 is not the trigger.** 0.55.4 also entered an unsafe state and enabled a `HEADLESS-1` output when the last enabled monitor went away (`prepareFallbackOutput`/`enterUnsafeState` in `src/Compositor.cpp`), so a name test would have been fooled there too. 0.56 only renamed it to `FALLBACK` and made it on-demand rather than created at startup.
- **f4b832eb (`hyprctl monitors` -> `hyprctl monitors all`) is not the trigger.** I ran the helper's exact jq both ways against a live virtual output; both report "external active". No difference for this bug.
### Suggested fix
A real display has a DRM connector; a virtual output has none. Cross-check candidates against sysfs, which restores the hardware truth `recover()` used to have while keeping the `monitors all` behaviour f4b832eb needed for mirrors (a mirrored external has a connected connector, so it keeps counting).
PR: fixes the helper in one place, so `recover()`, `off()`, `clamshell`'s `enable_internal()`/`disable_internal()` and the watcher's poll are all corrected at once. Includes a test that fails on the current helper at its first assertion.
### Environment
- `omarchy-dev` 4.0.0.r1816.g43bfe9b-1
- Hyprland 0.56.2
- Dell XPS, `eDP-1` internal panel + DP-1 external
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/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 08:39 UTC