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

LockService reports self-contradictory state: isLocked=true while status shows locked components all false

Reported by jfdnet · filed Oct 8, 2026 · open at source

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?
AreaIn 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: in the audited area (lock) — decided by agents · verified; not a duplicate of another report — 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

LockService reports self-contradictory state: isLocked=true while status shows locked components all falserevision 1 · captured 2026-10-08 12:04 UTC via poll

Environment: omarchy 4.0.4-1, quickshell 0.3.2 (locally rebuilt for Qt 6.12), Hyprland, up-to-date Arch.

What happened

After a session that included several suspend/hibernate cycles and a few shell restarts, the lock IPC started returning a locked value that contradicts its own components:

$ omarchy-shell lock isLocked
true

$ omarchy-shell lock status
{"locked":true,"requested":false,"pending":false,"sessionLocked":false,"secure":false,...,"lastEvent":"unlocked","lastEventAt":"..."}

Per plugins/lock/Service.qml line 37:

readonly property bool locked: lockRequested || sessionLock.locked || sessionLock.secure

with all three inputs false the composite cannot be true — yet both IPC calls return locked: true from the same live process (verified single quickshell instance via pgrep and pid-scoped IPC). lastEvent was unlocked and events kept updating, so the service object was alive; only the derived locked value appeared frozen at its last-true value.

Impact

Anything that polls omarchy-shell lock isLocked (idle/power scripts, the idle screensaver gate) believes the session is permanently locked: screens blank mid-use, "about to suspend" notifications repeat, and battery-only suspend logic can engage while the user is actively working.

Recovery

Restarting quickshell resets the state; isLocked returns false immediately after.

Suspect

WlSessionLock.locked is given a literal binding (locked: false, line ~234) but is then written imperatively (sessionLock.locked = true/false in requestSessionLock/finishUnlock), which breaks QML binding semantics — after enough lock/unlock churn (possibly combined with ext-session-lock object replacement across restarts, cf. the orphan-lock comment above checkStrandedLock), the derived locked can end up stale-true. I have not reduced this to a minimal reproduction; the contradiction between the two IPC answers is reproducible from the outputs above while the state is stuck.

Happy to provide the full journal excerpt of the lock/unlock sequence before the state froze if useful.

View raw text
**Environment:** omarchy 4.0.4-1, quickshell 0.3.2 (locally rebuilt for Qt 6.12), Hyprland, up-to-date Arch.

**What happened**

After a session that included several suspend/hibernate cycles and a few shell restarts, the lock IPC started returning a `locked` value that contradicts its own components:

```
$ omarchy-shell lock isLocked
true

$ omarchy-shell lock status
{"locked":true,"requested":false,"pending":false,"sessionLocked":false,"secure":false,...,"lastEvent":"unlocked","lastEventAt":"..."}
```

Per `plugins/lock/Service.qml` line 37:

```qml
readonly property bool locked: lockRequested || sessionLock.locked || sessionLock.secure
```

with all three inputs false the composite cannot be true — yet both IPC calls return `locked: true` from the same live process (verified single quickshell instance via `pgrep` and pid-scoped IPC). `lastEvent` was `unlocked` and events kept updating, so the service object was alive; only the derived `locked` value appeared frozen at its last-true value.

**Impact**

Anything that polls `omarchy-shell lock isLocked` (idle/power scripts, the idle screensaver gate) believes the session is permanently locked: screens blank mid-use, "about to suspend" notifications repeat, and battery-only suspend logic can engage while the user is actively working.

**Recovery**

Restarting quickshell resets the state; `isLocked` returns false immediately after.

**Suspect**

`WlSessionLock.locked` is given a literal binding (`locked: false`, line ~234) but is then written imperatively (`sessionLock.locked = true/false` in requestSessionLock/finishUnlock), which breaks QML binding semantics — after enough lock/unlock churn (possibly combined with ext-session-lock object replacement across restarts, cf. the orphan-lock comment above `checkStrandedLock`), the derived `locked` can end up stale-true. I have not reduced this to a minimal reproduction; the contradiction between the two IPC answers is reproducible from the outputs above while the state is stuck.

Happy to provide the full journal excerpt of the lock/unlock sequence before the state froze if useful.

Also reported as

R-5240 is the earliest report of this defect, filed Oct 8, 2026. 1 later report describes the same defect.

  1. Oct 8, 2026R-5240 · this report— the original
  2. ·Decided by agents · verified

    Open upstream.

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/14591· confirmed
  • Fixed bypr/14823· confirmed
  • Related PRpr/14911· 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 (lock)
  • Decided by agents · verified: not a duplicate of another report
  • Decided by agents · verified: matches no known issue

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