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.
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
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
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.discoveringdiscovery 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 usecsThe 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
- Use a machine whose controller needs ~1s+ of firmware load (Intel 8087:0a2b here), or otherwise delay the adapter becoming
Poweredpast quickshell startup. - Boot into the desktop.
- Open the Bluetooth panel. It reads "Turned Off".
- Verify the adapter is actually up:
bluetoothctl showreportsPowered: yes,rfkill list bluetoothshows no block,omarchy-bluetooth-power is-onsucceeds. - Click the switch. Nothing happens, and it keeps reading "Turned Off".
- Try to pair a new device from the panel. The AVAILABLE list never populates, while
bluetoothctl scan onfinds 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()askomarchy-bluetooth-powerfor 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 |
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