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

Bluetooth panel latches "Turned Off" when the adapter powers up after quickshell, disabling GUI pairing and the toggle

Reported by martin-irwin · filed Aug 20, 2026 · open at source

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

Bluetooth panel latches "Turned Off" when the adapter powers up after quickshell, disabling GUI pairing and the togglerevision 1 · captured 2026-09-28 21:29 UTC via poll

Summary

On a machine whose Bluetooth controller takes a moment to load firmware, the Bluetooth panel latches adapter.enabled = false at startup and never re-reads it. The panel shows "Turned Off" while the adapter is powered and fully working, discovery never starts, and the on/off switch cannot recover the state.

This is not #5868 (adapter genuinely off / AutoEnable). Here the adapter is on the whole time — rfkill is unblocked, bluetoothctl reports Powered: yes, omarchy-bluetooth-power is-on returns true, and a CLI scan finds devices normally. Only the panel is wrong.

Expected Behaviour

The panel reflects the adapter's real power state once BlueZ has finished bringing the adapter up.

Actual Behaviour

The panel shows "Turned Off" for the entire session. Because Panel.qml gates its discovery timer on adapter.enabled:

// plugins/panels/bluetooth/Panel.qml:512
running: root.opened && root.adapter !== null && root.adapter.enabled && !root.adapter.discovering

discovery never starts, so the AVAILABLE list stays empty and no new device can be paired from the GUI. That was the user-visible symptom that led me here — a Bluetooth mouse could not be paired from the panel, while bluetoothctl scan on saw it immediately at -35 dBm.

The switch cannot fix it either. toggleBluetooth() sends a direction based on the stale value:

// plugins/panels/bluetooth/Panel.qml:635-637
function toggleBluetooth() {
  if (!adapter) return
  Quickshell.execDetached(["omarchy-bluetooth-power", adapter.enabled ? "off" : "on"])
}

Since the panel believes it is off, clicking sends on. omarchy-bluetooth-power on runs rfkill unblock bluetooth (already unblocked) and wait_powered succeeds immediately (already powered). Nothing changes, no property is emitted, and the panel keeps its stale value. The switch is a silent no-op in precisely the state where the user needs it.

Root Cause

quickshell starts in the same second as bluetoothd, but slightly before it, and the adapter is not powered until firmware finishes loading:

PID  989  quickshell   Thu Aug 20 06:38:48
PID 1151  bluetoothd   Thu Aug 20 06:38:48

Aug 20 06:38:49 kernel: Bluetooth: hci0: Found device firmware: intel/ibt-12-16.sfi
Aug 20 06:38:50 kernel: Bluetooth: hci0: Firmware loaded in 1440955 usecs   <-- 1.44s
Aug 20 06:38:50 kernel: Bluetooth: hci0: Device booted in 12654 usecs

The panel binds the adapter inside that ~1.4s window, while Powered is still false, and does not pick up the later transition to true. Anything that slows firmware load (this Intel 8087:0a2b, a cold boot, a USB dongle) widens the window.

Note this is a distinct state from the one in #6956. An rfkill soft block removes the adapter object entirely and the panel renders "No adapter" (and the bar widget hides, per visible: adapter !== null). What is described here is adapter present, enabled == false, rendering "Turned Off" — reachable only via this race, since the toggle path always goes through rfkill.

Steps to Reproduce

  1. Use a machine whose controller needs ~1s+ of firmware load (Intel 8087:0a2b here), or otherwise delay the adapter becoming Powered past quickshell startup.
  2. Boot into the desktop.
  3. Open the Bluetooth panel. It reads "Turned Off".
  4. Verify the adapter is actually up: bluetoothctl show reports Powered: yes, rfkill list bluetooth shows no block, omarchy-bluetooth-power is-on succeeds.
  5. Click the switch. Nothing happens, and it keeps reading "Turned Off".
  6. Try to pair a new device from the panel. The AVAILABLE list never populates, while bluetoothctl scan on finds devices immediately.

omarchy restart shell fixes it for the session.

Suggested Fix

Re-read adapter.enabled when the adapter's Powered property changes rather than only at bind time. Two things would each independently reduce the damage:

  • Don't gate the discovery timer purely on the cached enabled, so a stale value can't silently disable pairing.
  • Have toggleBluetooth() ask omarchy-bluetooth-power for the current state instead of deriving the direction from a cached value, so the switch can always recover.

System Details

Omarchy4.0.0-1
Kernel7.1.8-arch1-3
MachineThinkPad T480s (20L8SCX800)
CPUIntel i5-8350U
ControllerIntel 8087:0a2b (hci0)
bluez5.87-2
quickshellquickshell-git 0.3.0.r20.g28771c7-1
View raw text
### Summary

On a machine whose Bluetooth controller takes a moment to load firmware, the Bluetooth panel latches `adapter.enabled = false` at startup and never re-reads it. The panel shows **"Turned Off"** while the adapter is powered and fully working, discovery never starts, and the on/off switch cannot recover the state.

This is not #5868 (adapter genuinely off / `AutoEnable`). Here the adapter is on the whole time — `rfkill` is unblocked, `bluetoothctl` reports `Powered: yes`, `omarchy-bluetooth-power is-on` returns true, and a CLI scan finds devices normally. Only the panel is wrong.

### Expected Behaviour

The panel reflects the adapter's real power state once BlueZ has finished bringing the adapter up.

### Actual Behaviour

The panel shows "Turned Off" for the entire session. Because `Panel.qml` gates its discovery timer on `adapter.enabled`:

```qml
// plugins/panels/bluetooth/Panel.qml:512
running: root.opened && root.adapter !== null && root.adapter.enabled && !root.adapter.discovering
```

discovery never starts, so the **AVAILABLE list stays empty and no new device can be paired from the GUI**. That was the user-visible symptom that led me here — a Bluetooth mouse could not be paired from the panel, while `bluetoothctl scan on` saw it immediately at -35 dBm.

The switch cannot fix it either. `toggleBluetooth()` sends a *direction* based on the stale value:

```qml
// plugins/panels/bluetooth/Panel.qml:635-637
function toggleBluetooth() {
  if (!adapter) return
  Quickshell.execDetached(["omarchy-bluetooth-power", adapter.enabled ? "off" : "on"])
}
```

Since the panel believes it is off, clicking sends `on`. `omarchy-bluetooth-power on` runs `rfkill unblock bluetooth` (already unblocked) and `wait_powered` succeeds immediately (already powered). Nothing changes, no property is emitted, and the panel keeps its stale value. **The switch is a silent no-op in precisely the state where the user needs it.**

### Root Cause

quickshell starts in the same second as `bluetoothd`, but slightly before it, and the adapter is not powered until firmware finishes loading:

```
PID  989  quickshell   Thu Aug 20 06:38:48
PID 1151  bluetoothd   Thu Aug 20 06:38:48

Aug 20 06:38:49 kernel: Bluetooth: hci0: Found device firmware: intel/ibt-12-16.sfi
Aug 20 06:38:50 kernel: Bluetooth: hci0: Firmware loaded in 1440955 usecs   <-- 1.44s
Aug 20 06:38:50 kernel: Bluetooth: hci0: Device booted in 12654 usecs
```

The panel binds the adapter inside that ~1.4s window, while `Powered` is still false, and does not pick up the later transition to true. Anything that slows firmware load (this Intel 8087:0a2b, a cold boot, a USB dongle) widens the window.

Note this is a distinct state from the one in #6956. An rfkill soft block removes the adapter object entirely and the panel renders **"No adapter"** (and the bar widget hides, per `visible: adapter !== null`). What is described here is adapter present, `enabled == false`, rendering **"Turned Off"** — reachable only via this race, since the toggle path always goes through rfkill.

### Steps to Reproduce

1. Use a machine whose controller needs ~1s+ of firmware load (Intel 8087:0a2b here), or otherwise delay the adapter becoming `Powered` past quickshell startup.
2. Boot into the desktop.
3. Open the Bluetooth panel. It reads "Turned Off".
4. Verify the adapter is actually up: `bluetoothctl show` reports `Powered: yes`, `rfkill list bluetooth` shows no block, `omarchy-bluetooth-power is-on` succeeds.
5. Click the switch. Nothing happens, and it keeps reading "Turned Off".
6. Try to pair a new device from the panel. The AVAILABLE list never populates, while `bluetoothctl scan on` finds devices immediately.

`omarchy restart shell` fixes it for the session.

### Suggested Fix

Re-read `adapter.enabled` when the adapter's `Powered` property changes rather than only at bind time. Two things would each independently reduce the damage:

- Don't gate the discovery timer purely on the cached `enabled`, so a stale value can't silently disable pairing.
- Have `toggleBluetooth()` ask `omarchy-bluetooth-power` for the current state instead of deriving the direction from a cached value, so the switch can always recover.

### System Details

| | |
|---|---|
| Omarchy | 4.0.0-1 |
| Kernel | 7.1.8-arch1-3 |
| Machine | ThinkPad T480s (20L8SCX800) |
| CPU | Intel i5-8350U |
| Controller | Intel 8087:0a2b (hci0) |
| bluez | 5.87-2 |
| quickshell | quickshell-git 0.3.0.r20.g28771c7-1 |

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 04:51 UTC