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.
Launching… OSD can remain indefinitely due to unordered show/close IPC calls
Reported by brianmsm · filed Aug 25, 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
System details
- AMD Ryzen AI 9 365 / Radeon 880M
- Omarchy 4.0.1-1
- Hyprland 0.56.2
- Quickshell 0.3.1-1
What's wrong?
The Launching … OSD can remain visible indefinitely after the launched application has already mapped and become active. I have seen this twice; the latest occurrence was launching TIDAL Hi-Fi from the Omarchy app menu.
Expected: the OSD closes when the app maps, or at worst after the 15-second launch timeout.
Actual: the app launches successfully, but the OSD remains until manually closed with:
omarchy-shell osd closeA privacy-cropped screenshot is available if needed. The full omarchy-debug output is intentionally not attached because it contains unrelated local identifiers and network logs; the system details above and deterministic reproduction contain the relevant evidence.
Probable root cause: unordered detached show / close IPC calls
In shell/services/AppLibrary.qml, launchDelay waits 2 seconds, sets launchOsdOpen = true, and dispatches this asynchronously:
Quickshell.execDetached(["omarchy-shell", "osd", "show", JSON.stringify({
icon: "",
message: root.launchOsdMessage,
duration: 0
})])If the app maps at approximately the same time, onValuesChanged() or onActiveToplevelChanged() calls closeLaunchFeedback(). That stops launchTimeout, dispatches a separate detached osd close process, and sets launchOsdOpen = false.
The two detached IPC client processes are not ordered. The close request can reach Quickshell first, followed by the delayed show. In that ordering:
closecloses an OSD that is not open yet.- AppLibrary marks the OSD closed and stops the 15-second timeout.
showarrives afterward withduration: 0.- Nothing remains that can close it, so it stays indefinitely.
This timing explains why the problem is intermittent and more likely for apps that map around the 2-second launch-feedback threshold.
Deterministic IPC-level reproduction
Running the same show and close commands concurrently reproduces the unordered final state:
payload='{"icon":"","message":"Race test","duration":0}'
open=0
closed=0
for i in $(seq 1 100); do
omarchy-shell osd show "$payload" >/dev/null &
omarchy-shell osd close >/dev/null &
wait
state=$(omarchy-shell osd state)
if [[ $state == open ]]; then
((open+=1))
omarchy-shell osd close >/dev/null
else
((closed+=1))
fi
done
printf 'open=%d closed=%d\n' "$open" "$closed"Observed:
open=53 closed=47A finite OSD duration provides a reliable backstop. Repeating 100 iterations with duration: 20 and checking after 30 ms resulted in:
open=0 closed=100Possible fixes
- Minimal/defensive: give the launch OSD a finite duration (for example 13,000 ms, the time remaining between the 2-second display delay and the existing 15-second overall timeout). Normal app mapping can still close it early, but an inverted IPC ordering can no longer strand it forever.
- Stronger: serialize/acknowledge the
showbefore allowingclose, or pass a launch generation/token to the OSD so a close can cancel a not-yet-processed show for that generation.
This appears related in symptom, but not identical in cause, to PR #6413 (Stop stranding the Launching… OSD when a second app is launched). That fix preserved launchOsdOpen across a second launch; this is another path where the QML-side flag and actual OSD state diverge.
View raw text
## System details
- AMD Ryzen AI 9 365 / Radeon 880M
- Omarchy 4.0.1-1
- Hyprland 0.56.2
- Quickshell 0.3.1-1
## What's wrong?
The `Launching …` OSD can remain visible indefinitely after the launched application has already mapped and become active. I have seen this twice; the latest occurrence was launching TIDAL Hi-Fi from the Omarchy app menu.
Expected: the OSD closes when the app maps, or at worst after the 15-second launch timeout.
Actual: the app launches successfully, but the OSD remains until manually closed with:
```bash
omarchy-shell osd close
```
A privacy-cropped screenshot is available if needed. The full `omarchy-debug` output is intentionally not attached because it contains unrelated local identifiers and network logs; the system details above and deterministic reproduction contain the relevant evidence.
## Probable root cause: unordered detached `show` / `close` IPC calls
In `shell/services/AppLibrary.qml`, `launchDelay` waits 2 seconds, sets `launchOsdOpen = true`, and dispatches this asynchronously:
```qml
Quickshell.execDetached(["omarchy-shell", "osd", "show", JSON.stringify({
icon: "",
message: root.launchOsdMessage,
duration: 0
})])
```
If the app maps at approximately the same time, `onValuesChanged()` or `onActiveToplevelChanged()` calls `closeLaunchFeedback()`. That stops `launchTimeout`, dispatches a separate detached `osd close` process, and sets `launchOsdOpen = false`.
The two detached IPC client processes are not ordered. The `close` request can reach Quickshell first, followed by the delayed `show`. In that ordering:
1. `close` closes an OSD that is not open yet.
2. AppLibrary marks the OSD closed and stops the 15-second timeout.
3. `show` arrives afterward with `duration: 0`.
4. Nothing remains that can close it, so it stays indefinitely.
This timing explains why the problem is intermittent and more likely for apps that map around the 2-second launch-feedback threshold.
## Deterministic IPC-level reproduction
Running the same `show` and `close` commands concurrently reproduces the unordered final state:
```bash
payload='{"icon":"","message":"Race test","duration":0}'
open=0
closed=0
for i in $(seq 1 100); do
omarchy-shell osd show "$payload" >/dev/null &
omarchy-shell osd close >/dev/null &
wait
state=$(omarchy-shell osd state)
if [[ $state == open ]]; then
((open+=1))
omarchy-shell osd close >/dev/null
else
((closed+=1))
fi
done
printf 'open=%d closed=%d\n' "$open" "$closed"
```
Observed:
```text
open=53 closed=47
```
A finite OSD duration provides a reliable backstop. Repeating 100 iterations with `duration: 20` and checking after 30 ms resulted in:
```text
open=0 closed=100
```
## Possible fixes
- Minimal/defensive: give the launch OSD a finite duration (for example 13,000 ms, the time remaining between the 2-second display delay and the existing 15-second overall timeout). Normal app mapping can still close it early, but an inverted IPC ordering can no longer strand it forever.
- Stronger: serialize/acknowledge the `show` before allowing `close`, or pass a launch generation/token to the OSD so a close can cancel a not-yet-processed show for that generation.
This appears related in symptom, but not identical in cause, to PR #6413 (`Stop stranding the Launching… OSD when a second app is launched`). That fix preserved `launchOsdOpen` across a second launch; this is another path where the QML-side flag and actual OSD state diverge.
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
Not linked to any known issue, other report or change yet.
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 09:05 UTC