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

omarchy-system-sleep-lock posts a new critical notification per failure, so a repeating fault leaves unbounded reboot-persistent toasts

Reported by Mahdi-Si · filed Sep 7, 2026 · open at source

Partly in the audited area (lock) — 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?
AreaPartly in the audited arealock· 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: partly in the audited area (lock) — 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

omarchy-system-sleep-lock posts a new critical notification per failure, so a repeating fault leaves unbounded reboot-persistent toastsrevision 1 · captured 2026-09-28 21:23 UTC via poll

What's wrong?

omarchy-system-sleep-lock is a first-party sender that can fire on a condition which repeats indefinitely, but it posts each failure as a brand-new critical notification instead of replacing the previous one. Because critical toasts are stored with expire_timeout: 0 and the live-popup directory is uncapped, a repeating fault accumulates permanent on-screen cards that are replayed on every shell start.

On this machine a 20-minute fault window left 38 never-expiring critical toasts that survived two reboots and were still on screen three days later.

report_unsecured() in bin/omarchy-system-sleep-lock:

omarchy-notification-send -u critical -g 󰌾 \
  "Screen did not lock before suspend" \
  "The session was left unlocked ($1)." >/dev/null 2>&1 || true

No -r/--replace-id, even though omarchy-notification-send supports -r/--replace-id and -p/--print-id.

Two shell-side properties turn that from noisy into permanent:

  1. Critical notifications carry expireTimeout: 0, so they never auto-dismiss and never leave popupStateDir on their own.
  2. shell/plugins/notifications/Service.qml caps historyDir at historyLimit: 10, but `popupStateDir` has no equivalent cap. Live toasts are mirrored to ~/.local/state/omarchy/notifications/*.json and replayed on every shell start.

Net effect: any repeating critical-urgency source grows the live-popup set without bound, and every card persists across reboots until dismissed by hand.

replaces_id does work — verified

Since #7834 concerns replacement hints being ignored, I verified the portable path actually functions in the shipped 4.0.2 shell before proposing it:

id=$(omarchy-notification-send -u critical -p "REPLACE-TEST" "first")   # -> 4
omarchy-notification-send -u critical -r "$id" "REPLACE-TEST" "second"
omarchy-notification-send -u critical -r "$id" "REPLACE-TEST" "third"

Result: exactly one file in popupStateDir, id 4, body third. replaces_id collapses correctly. The fix below is therefore verified rather than assumed.

Steps to reproduce

Any condition that makes the lock miss its budget repeatedly reproduces this. In my case:

  1. Laptop reaches critical battery with the lid closed.
  2. Machine enters a suspend/wake loop — suspend, spurious wake ~8s later, logind re-suspends ~24s later (45s period).
  3. Each cycle, the just-resumed Quickshell cannot reach secure within budget_cap_ms=12000 while amdgpu/xHCI are still re-initialising, so report_unsecured fires.
  4. 28 cycles produced 28 identical critical toasts; 38 total with earlier ones.
  5. Reboot twice — every non-expiring critical is restored to the screen.

A synthetic repro needs no battery fault: call omarchy-notification-send -u critical in a loop and observe that nothing ever caps or coalesces the result.

Expected

A repeating identical failure collapses into one card (optionally with a count), and the persisted live-popup set is bounded the way history already is.

Actual

38 separate critical toasts, unbounded, restored across reboots, each requiring manual dismissal.

Suggested fix

In report_unsecured, persist the id from omarchy-notification-send -p (e.g. under ~/.local/state/omarchy/) and pass it back via -r on later failures, so repeats replace instead of accumulating. Verified working above.

Separately, consider bounding popupStateDir the way historyDir is bounded, so no repeating critical sender can grow it without limit.

Scope — what is not being claimed

  • The trigger here was a dying battery. That is not Omarchy's fault, and the warning was correct: the session genuinely did suspend unlocked 28 times. I am not asking for the warning to be suppressed.
  • The lock path on this machine is otherwise healthy — running omarchy-system-sleep-lock directly returns secure: true, exit 0, in 0.65s against the 12000ms budget.
  • The report is only about the unbounded, non-coalescing, reboot-persistent notification behaviour for a repeating condition.

Related

  • #7834 — replacement hints ignored by the 4.0 shell. That issue notes replaces_id is the portable mechanism; this is a first-party sender not using it. Complementary, not duplicate.
  • #10145 — identical notifications no longer grouped since Quickshell replaced mako. Adjacent: daemon-side grouping would mask this symptom. Filed separately because the call-site fix is one line and independent of it, and because the uncapped popupStateDir is its own failure mode.
  • #7280 — omarchy-sleep-lock.service restart thrash while logind's sleep is in flight. I also observed this (restart counter reached 83, Failed to inhibit: ... already running), and am not re-reporting it; noting only that it co-occurs in the same fault window.
  • #10299 — stalled lock latches lockRequested. Different failure, not what happened here: lock status showed lastEvent: "init" with no latch.

System details

Omarchy4.0.2-1 (stable)
Kernel7.1.9-arch1-2
CPUAMD Ryzen 7 4800HS with Radeon Graphics
GPUAMD Renoir (Radeon Vega) + NVIDIA GTX 1660 Ti Mobile
Quickshell0.3.1-1
Hyprland0.56.2
systemd261.2-1-arch

report_unsecured on current quattro is byte-identical to the shipped 4.0.2 copy, so this is present on the default branch.

View raw text
### What's wrong?

`omarchy-system-sleep-lock` is a first-party sender that can fire on a condition which repeats indefinitely, but it posts each failure as a brand-new critical notification instead of replacing the previous one. Because critical toasts are stored with `expire_timeout: 0` and the live-popup directory is uncapped, a repeating fault accumulates permanent on-screen cards that are replayed on every shell start.

On this machine a 20-minute fault window left **38 never-expiring critical toasts** that survived two reboots and were still on screen three days later.

`report_unsecured()` in `bin/omarchy-system-sleep-lock`:

```bash
omarchy-notification-send -u critical -g 󰌾 \
  "Screen did not lock before suspend" \
  "The session was left unlocked ($1)." >/dev/null 2>&1 || true
```

No `-r`/`--replace-id`, even though `omarchy-notification-send` supports `-r/--replace-id` and `-p/--print-id`.

Two shell-side properties turn that from noisy into permanent:

1. Critical notifications carry `expireTimeout: 0`, so they never auto-dismiss and never leave `popupStateDir` on their own.
2. `shell/plugins/notifications/Service.qml` caps `historyDir` at `historyLimit: 10`, but **`popupStateDir` has no equivalent cap**. Live toasts are mirrored to `~/.local/state/omarchy/notifications/*.json` and replayed on every shell start.

Net effect: any repeating critical-urgency source grows the live-popup set without bound, and every card persists across reboots until dismissed by hand.

### `replaces_id` does work — verified

Since #7834 concerns replacement hints being ignored, I verified the portable path actually functions in the shipped 4.0.2 shell before proposing it:

```bash
id=$(omarchy-notification-send -u critical -p "REPLACE-TEST" "first")   # -> 4
omarchy-notification-send -u critical -r "$id" "REPLACE-TEST" "second"
omarchy-notification-send -u critical -r "$id" "REPLACE-TEST" "third"
```

Result: exactly one file in `popupStateDir`, id `4`, body `third`. `replaces_id` collapses correctly. The fix below is therefore verified rather than assumed.

### Steps to reproduce

Any condition that makes the lock miss its budget repeatedly reproduces this. In my case:

1. Laptop reaches critical battery with the lid closed.
2. Machine enters a suspend/wake loop — suspend, spurious wake ~8s later, logind re-suspends ~24s later (45s period).
3. Each cycle, the just-resumed Quickshell cannot reach `secure` within `budget_cap_ms=12000` while amdgpu/xHCI are still re-initialising, so `report_unsecured` fires.
4. 28 cycles produced 28 identical critical toasts; 38 total with earlier ones.
5. Reboot twice — every non-expiring critical is restored to the screen.

A synthetic repro needs no battery fault: call `omarchy-notification-send -u critical` in a loop and observe that nothing ever caps or coalesces the result.

### Expected

A repeating identical failure collapses into one card (optionally with a count), and the persisted live-popup set is bounded the way history already is.

### Actual

38 separate critical toasts, unbounded, restored across reboots, each requiring manual dismissal.

### Suggested fix

In `report_unsecured`, persist the id from `omarchy-notification-send -p` (e.g. under `~/.local/state/omarchy/`) and pass it back via `-r` on later failures, so repeats replace instead of accumulating. Verified working above.

Separately, consider bounding `popupStateDir` the way `historyDir` is bounded, so no repeating critical sender can grow it without limit.

### Scope — what is *not* being claimed

- The **trigger** here was a dying battery. That is not Omarchy's fault, and the warning was **correct**: the session genuinely did suspend unlocked 28 times. I am not asking for the warning to be suppressed.
- The lock path on this machine is otherwise healthy — running `omarchy-system-sleep-lock` directly returns `secure: true`, exit `0`, in **0.65s** against the 12000ms budget.
- The report is only about the **unbounded, non-coalescing, reboot-persistent notification behaviour** for a repeating condition.

### Related

- **#7834** — replacement *hints* ignored by the 4.0 shell. That issue notes `replaces_id` is the portable mechanism; this is a first-party sender not using it. Complementary, not duplicate.
- **#10145** — identical notifications no longer grouped since Quickshell replaced mako. Adjacent: daemon-side grouping would mask this symptom. Filed separately because the call-site fix is one line and independent of it, and because the uncapped `popupStateDir` is its own failure mode.
- **#7280** — `omarchy-sleep-lock.service` restart thrash while logind's sleep is in flight. I also observed this (restart counter reached 83, `Failed to inhibit: ... already running`), and am **not** re-reporting it; noting only that it co-occurs in the same fault window.
- **#10299** — stalled lock latches `lockRequested`. Different failure, not what happened here: `lock status` showed `lastEvent: "init"` with no latch.

### System details

| | |
|---|---|
| Omarchy | 4.0.2-1 (stable) |
| Kernel | 7.1.9-arch1-2 |
| CPU | AMD Ryzen 7 4800HS with Radeon Graphics |
| GPU | AMD Renoir (Radeon Vega) + NVIDIA GTX 1660 Ti Mobile |
| Quickshell | 0.3.1-1 |
| Hyprland | 0.56.2 |
| systemd | 261.2-1-arch |

`report_unsecured` on current `quattro` is byte-identical to the shipped 4.0.2 copy, so this is present on the default branch.

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/9790· confirmed
  • Fixed bypr/10686· 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: partly in the audited area (lock)
  • Decided by agents · verified: matches no known issue

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