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

Low-battery warning never fires while docked: onBattery guard suppresses it when a dock supplies power but the battery still drains

Reported by zorzysty · filed Sep 9, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 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

Low-battery warning never fires while docked: onBattery guard suppresses it when a dock supplies power but the battery still drainsrevision 1 · captured 2026-09-28 21:23 UTC via poll

What happened

My laptop drained from 20% to 2% over ~22 minutes and was force-suspended by upowerd's critical-power action. I never got the "Time to recharge!" warning at any point.

The cause is the onBattery term in the low-battery guard, in shell/plugins/services/battery/BatteryModel.js:

function isDischarging(device, onBattery, dischargingState) {
  return !!(device && device.isPresent && onBattery && device.state === dischargingState)
}

UPower.onBattery reflects the daemon's OnBattery property, which is false whenever any power-supply line-power device is online — regardless of whether the battery is actually draining. So on a dock or charger that supplies power but less than the machine is drawing, device.state is Discharging and the percentage falls to zero while onBattery stays false, and the warning is suppressed for the entire discharge.

This silences the warning in the case where it is arguably most valuable: the user believes they are plugged in, so they have no reason to check the battery themselves.

Expected

A low-battery warning whenever the battery is actually discharging past the threshold, whether or not a line-power supply happens to be online.

Steps to reproduce

  1. Dock a laptop whose draw exceeds what the dock delivers (mine: ThinkPad P16s Gen 4 AMD driving two external 1080p displays over USB-C DP-MST, performance power profile).
  2. Confirm the mismatch: upower -i /org/freedesktop/UPower/devices/battery_BAT0 shows state: discharging while /sys/class/power_supply/AC/online is 1.
  3. Verify busctl get-property org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower OnBattery returns b false.
  4. Let the battery drain past 10%.

No notification is sent. It drains to the upowerd critical action.

Evidence from my system

UPower's own charge history for the affected window, /var/lib/upower/history-charge-*.dat:

07:52 20.000 discharging   <- boot, docked
07:59 10.000 discharging   <- threshold crossed
08:00  8.000 discharging
08:14  2.000 discharging   <- upowerd critical suspend

journalctl -b:

08:14:37 systemd-logind: suspend requested from client PID ... ('upowerd') (unit upower.service)

Notification history under ~/.local/state/omarchy/notifications/history/ has gapless sequence ids across that whole window with no battery entry, so omarchy-battery-low was never invoked. Line-power state was online throughout (/sys/class/power_supply/ucsi-source-psy-USBC000:001/online = 1, AC/online = 1).

I ruled out the obvious alternatives: the service does load and tick every 30s with correct UPower values (verified by instrumenting a clone and restarting the shell), omarchy-battery-low is on the shell's PATH and works when invoked manually, and DND was off.

Suggested fix

Drop the onBattery term — device.state === dischargingState already answers the question, and it is the only one of the two that is true in this scenario:

function isDischarging(device, onBattery, dischargingState) {
  return !!(device && device.isPresent && device.state === dischargingState)
}

I've been running this locally as a cloned plugin. Happy to send it as a PR if you'd like, including a case in the model's unit coverage for docked-but-draining.

Note that Service.qml's applyPowerProfile() is a separate, legitimate use of UPower.onBattery and should keep it.

System

  • Omarchy 4.0.2-1 (bug also present on quattro as of today)
  • ThinkPad P16s Gen 4 AMD, Ryzen AI 9 HX PRO 370, Radeon 890M
  • Kernel 7.1.9-arch1-2, quickshell 0.3.1-1

(omarchy debug isn't a command in 4.0.2, so the above is gathered manually. No screenshot: the bug is the absence of a notification.)

View raw text
## What happened

My laptop drained from 20% to 2% over ~22 minutes and was force-suspended by `upowerd`'s critical-power action. I never got the "Time to recharge!" warning at any point.

The cause is the `onBattery` term in the low-battery guard, in `shell/plugins/services/battery/BatteryModel.js`:

```js
function isDischarging(device, onBattery, dischargingState) {
  return !!(device && device.isPresent && onBattery && device.state === dischargingState)
}
```

`UPower.onBattery` reflects the daemon's `OnBattery` property, which is false whenever any power-supply line-power device is online — regardless of whether the battery is actually draining. So on a dock or charger that supplies power but **less than the machine is drawing**, `device.state` is `Discharging` and the percentage falls to zero while `onBattery` stays `false`, and the warning is suppressed for the entire discharge.

This silences the warning in the case where it is arguably most valuable: the user believes they are plugged in, so they have no reason to check the battery themselves.

## Expected

A low-battery warning whenever the battery is actually discharging past the threshold, whether or not a line-power supply happens to be online.

## Steps to reproduce

1. Dock a laptop whose draw exceeds what the dock delivers (mine: ThinkPad P16s Gen 4 AMD driving two external 1080p displays over USB-C DP-MST, `performance` power profile).
2. Confirm the mismatch: `upower -i /org/freedesktop/UPower/devices/battery_BAT0` shows `state: discharging` while `/sys/class/power_supply/AC/online` is `1`.
3. Verify `busctl get-property org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower OnBattery` returns `b false`.
4. Let the battery drain past 10%.

No notification is sent. It drains to the `upowerd` critical action.

## Evidence from my system

UPower's own charge history for the affected window, `/var/lib/upower/history-charge-*.dat`:

```
07:52 20.000 discharging   <- boot, docked
07:59 10.000 discharging   <- threshold crossed
08:00  8.000 discharging
08:14  2.000 discharging   <- upowerd critical suspend
```

`journalctl -b`:

```
08:14:37 systemd-logind: suspend requested from client PID ... ('upowerd') (unit upower.service)
```

Notification history under `~/.local/state/omarchy/notifications/history/` has gapless sequence ids across that whole window with no battery entry, so `omarchy-battery-low` was never invoked. Line-power state was online throughout (`/sys/class/power_supply/ucsi-source-psy-USBC000:001/online` = `1`, `AC/online` = `1`).

I ruled out the obvious alternatives: the service does load and tick every 30s with correct UPower values (verified by instrumenting a clone and restarting the shell), `omarchy-battery-low` is on the shell's PATH and works when invoked manually, and DND was off.

## Suggested fix

Drop the `onBattery` term — `device.state === dischargingState` already answers the question, and it is the only one of the two that is true in this scenario:

```js
function isDischarging(device, onBattery, dischargingState) {
  return !!(device && device.isPresent && device.state === dischargingState)
}
```

I've been running this locally as a cloned plugin. Happy to send it as a PR if you'd like, including a case in the model's unit coverage for docked-but-draining.

Note that `Service.qml`'s `applyPowerProfile()` is a separate, legitimate use of `UPower.onBattery` and should keep it.

## System

- Omarchy 4.0.2-1 (bug also present on `quattro` as of today)
- ThinkPad P16s Gen 4 AMD, Ryzen AI 9 HX PRO 370, Radeon 890M
- Kernel 7.1.9-arch1-2, quickshell 0.3.1-1

(`omarchy debug` isn't a command in 4.0.2, so the above is gathered manually. No screenshot: the bug is the absence of a notification.)

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 11:16 UTC