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

omarchy-bluetooth-power off: type-wide rfkill block trips platform switches and removes the radio from the USB bus (ThinkPad/Dell)

Reported by DrakeMorrison · filed Aug 23, 2026 · open at source

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

omarchy-bluetooth-power off: type-wide rfkill block trips platform switches and removes the radio from the USB bus (ThinkPad/Dell)revision 1 · captured 2026-09-28 21:24 UTC via poll

Summary

omarchy-bluetooth-power off runs rfkill block bluetooth, a type-wide block. On laptops that expose a platform Bluetooth rfkill switch next to the adapter's own hci0 switch (ThinkPads via thinkpad_acpi, Dells via dell-laptop, …), that also blocks the platform switch — and the embedded controller answers by cutting USB power to the Bluetooth module. hci0 disappears from the kernel entirely rather than going Powered: no.

This is the root cause behind the "widget disappears" report in #6956 on this class of hardware, and it is what makes the panel-side fixes there (#7048, #7065) insufficient on it: keeping the toggle visible doesn't help when the radio is no longer on the bus.

Expected Behaviour

Turning Bluetooth off leaves the adapter present and soft-blocked (Powered: no), so BlueZ and the panel still see it and the toggle can turn it back on. The off state should still persist across reboots (the reason the block was chosen).

Actual Behaviour

On a ThinkPad E16 Gen 1, rfkill block bluetooth disconnects the module within 3–50 ms:

rfkill[343193]: block set for type bluetooth
kernel: usb 3-10: USB disconnect, device number 5
systemd[1]: Stopped target Bluetooth Support.

After that bluetoothctl list is empty, /sys/class/bluetooth/ is empty, the 8087:0026 device is gone from the USB bus, and the only rfkill left is the platform one:

$ rfkill list
0: tpacpi_bluetooth_sw: Bluetooth
        Soft blocked: yes
        Hard blocked: no

Here rfkill unblock bluetooth does re-enumerate the module (~0.5 s + ~2 s firmware load), so omarchy-bluetooth-power on recovers it from a terminal. The Dell Latitude 7440 report on #6956 shows hardware where even that fails and only a suspend/resume or reboot brings the radio back.

Steps to Reproduce

On a machine where rfkill list shows a platform switch alongside hci0:

  1. omarchy-bluetooth-power off (or the panel switch / right-click on the bar icon).
  2. journalctl -k -f shows usb N-M: USB disconnect immediately after the block.
  3. bluetoothctl list → no controllers; rfkill list → only the platform switch.
  4. The bar icon vanishes (Panel.qml: visible: adapter !== null), and toggleBluetooth() returns early on !adapter, so there is no UI way back.

Cause

omarchy-bluetooth-power:

off)
    rfkill block bluetooth

rfkill block <type> is RFKILL_OP_CHANGE_ALL: the kernel sets the global state for the type and blocks every rfkill of that type, including platform switches whose set_block callback talks to firmware. On thinkpad_acpi that is the SBDC ACPI method, and the EC then powers the CNVi Bluetooth side down.

Suggested Fix

Block only the adapter rfkills, not the platform switches:

# indexes of the hci* rfkills
rfkill -n -o ID,DEVICE | awk '$2 ~ /^hci/ {print $1}' | xargs -r -n1 rfkill block

hci0's soft block still drops the adapter to Powered: no, and systemd-rfkill persists it under the adapter's own ID (/var/lib/systemd/rfkill/pci-…-usb-…:bluetooth), so the off state survives a reboot the same way. on can stay rfkill unblock bluetooth since unblocking the platform switch is harmless.

Two caveats worth handling:

  • The hci rfkill is recreated if the adapter is re-enumerated (suspend/resume on some machines), and a new rfkill inherits the global type state — which a per-index block never sets. So after a resume the adapter may come back unblocked even though the user turned it off. omarchy-bluetooth-power (or a udev rule on the hci rfkill add) may need to re-apply the saved state; alternatively keep the type-wide block but immediately unblock platform switches by index.
  • is-on/powered should treat "no controller but a platform switch is soft-blocked" as off, not no hardware, so the panel can show "Turned Off" — which is what #7048 / #7065 do.

Workaround I'm running

A udev rule that fires on the platform switch's change event with soft=1, unblocks that switch by index, and (if the adapter did re-enumerate) re-blocks just hci0 for a few seconds so systemd-rfkill's restore doesn't power it back up:

ACTION=="change", SUBSYSTEM=="rfkill", ATTR{name}=="tpacpi_bluetooth_sw", ATTR{soft}=="1", \
  RUN+="/usr/bin/systemd-run --no-block --collect --unit=thinkpad-bluetooth-keep-adapter /usr/local/bin/thinkpad-bluetooth-keep-adapter $attr{index}"

In practice the rule runs within ~6 ms — before the EC cuts power — so the module never even disconnects and the toggle just works. Happy to turn the per-index approach into a PR against omarchy-bluetooth-power if that direction is welcome.

System Details

  • Lenovo ThinkPad E16 Gen 1 (21JN0040US), BIOS R2AET59W 1.34
  • CPU: Intel Core i5-1335U · GPU: Iris Xe
  • Bluetooth: Intel (8087:0026) on Raptor Lake CNVi, USB-attached; platform rfkill tpacpi_bluetooth_sw from thinkpad_acpi
  • Kernel 7.1.9-arch1-2 · bluez 5.87-2
  • Omarchy 4.0.0-1 (Quattro)
  • Debug log (expires in 24 h; journal section deduplicated, dmesg skipped, relevant rfkill/USB journal lines appended at the end): https://logs.omarchy.org/BXDjuk
View raw text
### Summary

`omarchy-bluetooth-power off` runs `rfkill block bluetooth`, a **type-wide** block. On laptops that expose a *platform* Bluetooth rfkill switch next to the adapter's own `hci0` switch (ThinkPads via `thinkpad_acpi`, Dells via `dell-laptop`, …), that also blocks the platform switch — and the embedded controller answers by **cutting USB power to the Bluetooth module**. `hci0` disappears from the kernel entirely rather than going `Powered: no`.

This is the root cause behind the "widget disappears" report in #6956 on this class of hardware, and it is what makes the panel-side fixes there (#7048, #7065) insufficient on it: keeping the toggle visible doesn't help when the radio is no longer on the bus.

### Expected Behaviour

Turning Bluetooth off leaves the adapter present and soft-blocked (`Powered: no`), so BlueZ and the panel still see it and the toggle can turn it back on. The off state should still persist across reboots (the reason the block was chosen).

### Actual Behaviour

On a ThinkPad E16 Gen 1, `rfkill block bluetooth` disconnects the module within 3–50 ms:

```
rfkill[343193]: block set for type bluetooth
kernel: usb 3-10: USB disconnect, device number 5
systemd[1]: Stopped target Bluetooth Support.
```

After that `bluetoothctl list` is empty, `/sys/class/bluetooth/` is empty, the `8087:0026` device is gone from the USB bus, and the only rfkill left is the platform one:

```
$ rfkill list
0: tpacpi_bluetooth_sw: Bluetooth
        Soft blocked: yes
        Hard blocked: no
```

Here `rfkill unblock bluetooth` does re-enumerate the module (~0.5 s + ~2 s firmware load), so `omarchy-bluetooth-power on` recovers it *from a terminal*. The Dell Latitude 7440 report on #6956 shows hardware where even that fails and only a suspend/resume or reboot brings the radio back.

### Steps to Reproduce

On a machine where `rfkill list` shows a platform switch alongside `hci0`:

1. `omarchy-bluetooth-power off` (or the panel switch / right-click on the bar icon).
2. `journalctl -k -f` shows `usb N-M: USB disconnect` immediately after the block.
3. `bluetoothctl list` → no controllers; `rfkill list` → only the platform switch.
4. The bar icon vanishes (`Panel.qml`: `visible: adapter !== null`), and `toggleBluetooth()` returns early on `!adapter`, so there is no UI way back.

### Cause

`omarchy-bluetooth-power`:

```sh
off)
    rfkill block bluetooth
```

`rfkill block <type>` is `RFKILL_OP_CHANGE_ALL`: the kernel sets the global state for the type and blocks every rfkill of that type, including platform switches whose `set_block` callback talks to firmware. On `thinkpad_acpi` that is the `SBDC` ACPI method, and the EC then powers the CNVi Bluetooth side down.

### Suggested Fix

Block only the adapter rfkills, not the platform switches:

```sh
# indexes of the hci* rfkills
rfkill -n -o ID,DEVICE | awk '$2 ~ /^hci/ {print $1}' | xargs -r -n1 rfkill block
```

`hci0`'s soft block still drops the adapter to `Powered: no`, and systemd-rfkill persists it under the adapter's own ID (`/var/lib/systemd/rfkill/pci-…-usb-…:bluetooth`), so the off state survives a reboot the same way. `on` can stay `rfkill unblock bluetooth` since unblocking the platform switch is harmless.

Two caveats worth handling:

- The hci rfkill is recreated if the adapter is re-enumerated (suspend/resume on some machines), and a new rfkill inherits the *global* type state — which a per-index block never sets. So after a resume the adapter may come back unblocked even though the user turned it off. `omarchy-bluetooth-power` (or a udev rule on the hci rfkill `add`) may need to re-apply the saved state; alternatively keep the type-wide block but immediately unblock platform switches by index.
- `is-on`/`powered` should treat "no controller but a platform switch is soft-blocked" as *off*, not *no hardware*, so the panel can show "Turned Off" — which is what #7048 / #7065 do.

### Workaround I'm running

A udev rule that fires on the platform switch's `change` event with `soft=1`, unblocks that switch by index, and (if the adapter did re-enumerate) re-blocks just `hci0` for a few seconds so systemd-rfkill's restore doesn't power it back up:

```
ACTION=="change", SUBSYSTEM=="rfkill", ATTR{name}=="tpacpi_bluetooth_sw", ATTR{soft}=="1", \
  RUN+="/usr/bin/systemd-run --no-block --collect --unit=thinkpad-bluetooth-keep-adapter /usr/local/bin/thinkpad-bluetooth-keep-adapter $attr{index}"
```

In practice the rule runs within ~6 ms — before the EC cuts power — so the module never even disconnects and the toggle just works. Happy to turn the per-index approach into a PR against `omarchy-bluetooth-power` if that direction is welcome.

### System Details

- Lenovo ThinkPad E16 Gen 1 (21JN0040US), BIOS R2AET59W 1.34
- CPU: Intel Core i5-1335U · GPU: Iris Xe
- Bluetooth: Intel (8087:0026) on Raptor Lake CNVi, USB-attached; platform rfkill `tpacpi_bluetooth_sw` from `thinkpad_acpi`
- Kernel 7.1.9-arch1-2 · bluez 5.87-2
- Omarchy 4.0.0-1 (Quattro)
- Debug log (expires in 24 h; journal section deduplicated, `dmesg` skipped, relevant rfkill/USB journal lines appended at the end): https://logs.omarchy.org/BXDjuk

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 08:32 UTC