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

Audio panel opens the headset's microphone to drive a cosmetic level meter, crackling and pumping playback volume

Reported by eirikkva · filed Sep 8, 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

Audio panel opens the headset's microphone to drive a cosmetic level meter, crackling and pumping playback volumerevision 1 · captured 2026-09-28 21:23 UTC via poll

What happened

Opening the audio panel (Super + Ctrl + A) while listening through a USB headset makes the audio crackle and the playback volume pump up and down for several seconds before settling. Closing the panel and reopening it reproduces it every time.

The panel opens a PwNodePeakMonitor on the input node to drive the microphone level bar. When the selected input is the same physical device as the output — which is the normal case for any headset — opening the mic puts the headset into call mode: sidetone and the noise-reduction/AGC chain engage, which crackles and rides the playback gain until it settles. The meter is purely cosmetic, so the audio damage buys nothing.

Expected

Opening the audio panel should not alter or disturb playback.

Root cause

shell/plugins/panels/audio/Panel.qml:580-584

PwNodePeakMonitor {
  id: inputPeakMonitor
  node: root.source
  enabled: root.opened && !!root.source
}

enabled is gated only on the panel being open and an input existing — it never considers whether that input belongs to the same device currently being used for playback.

Reproduction

  1. Plug in a USB headset (mic + speakers on one device) and select it for both output and input.
  2. Play audio.
  3. Press Super + Ctrl + A.
  4. Audio crackles and the volume pumps for several seconds.

Objective evidence

Watching the headset's ALSA capture state while driving the panel over IPC (omarchy shell omarchy.audio open|close) and polling Capture: Status: in /proc/asound/card<n>/stream0:

PluginCapture state on panel openSink volume
stock omarchy.audioStop → `Running`dropped 0.70 → 0.35
patched (see below)stays Stopunchanged

So the panel demonstrably opens the microphone of the device being listened through, and the stock run reproduced the volume drop on its own.

Kernel/device context for the test machine: the headset is a Jabra Evolve2 30 SE (0b0e:0e36). Note this is not the same as the separate snd-usb-audio sticky-mixer issue on that device — the crackle reproduces independently of it, and the A/B above was run with that already resolved.

Scope

Not device-specific. Any single-device headset (USB or Bluetooth) where input and output are the same physical endpoint should be affected, since the trigger is simply opening the mic while playing audio through it.

Suggested fix

Skip the input meter when the input and output resolve to the same device. Patch below is against 4.0.2-1 and has been running here since applying it:

+  // Identify the physical device behind a node, ignoring direction and profile:
+  //   alsa_output.usb-...Jabra_Evolve2...-00.analog-stereo
+  //   alsa_input.usb-...Jabra_Evolve2...-00.mono-fallback
+  // both reduce to usb-...Jabra_Evolve2...-00.
+  function deviceKey(node) {
+    if (!node || !node.name) return ""
+    var n = String(node.name).replace(/^alsa_(output|input)\./, "")
+    var dot = n.lastIndexOf(".")
+    return dot > 0 ? n.substring(0, dot) : n
+  }
+
+  readonly property bool inputSharesOutputDevice: {
+    var inKey = deviceKey(root.source)
+    return inKey !== "" && inKey === deviceKey(root.volumeSink || root.sink)
+  }
+
   PwNodePeakMonitor {
     id: inputPeakMonitor
     node: root.source
-    enabled: root.opened && !!root.source
+    enabled: root.opened && !!root.source && !root.inputSharesOutputDevice
   }

plus hiding the now-inert bar rather than leaving it at zero:

   Rectangle {
+    visible: !root.inputSharesOutputDevice
     width: parent.width
     height: Math.max(Style.space(5), Style.spacing.xs)

Trade-off: no mic level bar while on a headset. Any other input still meters normally. If the meter is considered worth keeping, the alternative would be sourcing the level from a stream that doesn't require opening the capture device.

I'm happy to open a PR with this if the approach looks right.

System details

Omarchy4.0.2-1
Kernel7.1.9-arch1-2
CPUIntel Core Ultra 5 228V
GPUIntel Arc Graphics 130V/140V
Quickshell0.3.1 (Arch)
HeadsetJabra Evolve2 30 SE (0b0e:0e36)

Related but distinct (both are crashes in this panel, not this behaviour): #10371, #10432.

View raw text
## What happened

Opening the audio panel (`Super + Ctrl + A`) while listening through a USB headset makes the audio crackle and the playback volume pump up and down for several seconds before settling. Closing the panel and reopening it reproduces it every time.

The panel opens a `PwNodePeakMonitor` on the **input** node to drive the microphone level bar. When the selected input is the *same physical device* as the output — which is the normal case for any headset — opening the mic puts the headset into call mode: sidetone and the noise-reduction/AGC chain engage, which crackles and rides the playback gain until it settles. The meter is purely cosmetic, so the audio damage buys nothing.

## Expected

Opening the audio panel should not alter or disturb playback.

## Root cause

`shell/plugins/panels/audio/Panel.qml:580-584`

```qml
PwNodePeakMonitor {
  id: inputPeakMonitor
  node: root.source
  enabled: root.opened && !!root.source
}
```

`enabled` is gated only on the panel being open and an input existing — it never considers whether that input belongs to the same device currently being used for playback.

## Reproduction

1. Plug in a USB headset (mic + speakers on one device) and select it for both output and input.
2. Play audio.
3. Press `Super + Ctrl + A`.
4. Audio crackles and the volume pumps for several seconds.

## Objective evidence

Watching the headset's ALSA capture state while driving the panel over IPC (`omarchy shell omarchy.audio open|close`) and polling `Capture: Status:` in `/proc/asound/card<n>/stream0`:

| Plugin | Capture state on panel open | Sink volume |
|---|---|---|
| stock `omarchy.audio` | `Stop` → **`Running`** | dropped 0.70 → 0.35 |
| patched (see below) | stays `Stop` | unchanged |

So the panel demonstrably opens the microphone of the device being listened through, and the stock run reproduced the volume drop on its own.

Kernel/device context for the test machine: the headset is a Jabra Evolve2 30 SE (`0b0e:0e36`). Note this is **not** the same as the separate `snd-usb-audio` sticky-mixer issue on that device — the crackle reproduces independently of it, and the A/B above was run with that already resolved.

## Scope

Not device-specific. Any single-device headset (USB or Bluetooth) where input and output are the same physical endpoint should be affected, since the trigger is simply opening the mic while playing audio through it.

## Suggested fix

Skip the input meter when the input and output resolve to the same device. Patch below is against `4.0.2-1` and has been running here since applying it:

```diff
+  // Identify the physical device behind a node, ignoring direction and profile:
+  //   alsa_output.usb-...Jabra_Evolve2...-00.analog-stereo
+  //   alsa_input.usb-...Jabra_Evolve2...-00.mono-fallback
+  // both reduce to usb-...Jabra_Evolve2...-00.
+  function deviceKey(node) {
+    if (!node || !node.name) return ""
+    var n = String(node.name).replace(/^alsa_(output|input)\./, "")
+    var dot = n.lastIndexOf(".")
+    return dot > 0 ? n.substring(0, dot) : n
+  }
+
+  readonly property bool inputSharesOutputDevice: {
+    var inKey = deviceKey(root.source)
+    return inKey !== "" && inKey === deviceKey(root.volumeSink || root.sink)
+  }
+
   PwNodePeakMonitor {
     id: inputPeakMonitor
     node: root.source
-    enabled: root.opened && !!root.source
+    enabled: root.opened && !!root.source && !root.inputSharesOutputDevice
   }
```

plus hiding the now-inert bar rather than leaving it at zero:

```diff
   Rectangle {
+    visible: !root.inputSharesOutputDevice
     width: parent.width
     height: Math.max(Style.space(5), Style.spacing.xs)
```

Trade-off: no mic level bar while on a headset. Any other input still meters normally. If the meter is considered worth keeping, the alternative would be sourcing the level from a stream that doesn't require opening the capture device.

I'm happy to open a PR with this if the approach looks right.

## System details

| | |
|---|---|
| Omarchy | 4.0.2-1 |
| Kernel | 7.1.9-arch1-2 |
| CPU | Intel Core Ultra 5 228V |
| GPU | Intel Arc Graphics 130V/140V |
| Quickshell | 0.3.1 (Arch) |
| Headset | Jabra Evolve2 30 SE (`0b0e:0e36`) |

Related but distinct (both are crashes in this panel, not this behaviour): #10371, #10432.

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:09 UTC