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

Speed test panel reads 0 on both dials: 5s phase timer starts at process launch, ahead of the helper's ~3-4.7s warm-up

Reported by mdsilvers · filed Sep 22, 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

Speed test panel reads 0 on both dials: 5s phase timer starts at process launch, ahead of the helper's ~3-4.7s warm-uprevision 1 · captured 2026-09-28 21:23 UTC via poll

What happened

Opening the internet speed test (network panel -> speed test, omarchy.speedtest)
regularly shows 0 on both the download and upload dials. No error is
displayed — the dials simply never move off zero.

Expected

Each dial shows the measured throughput, as omarchy-network-speedtest reports
it on stdout.

Root cause

shell/plugins/panels/speedtest/Panel.qml gives each direction a fixed 5-second
window that starts when the process is launched:

function startPhase(nextPhase) {
  ...
  speedTestProc.running = true
  phaseTimer.restart()        // 5000 ms, measured from launch
}

But bin/omarchy-network-speedtest cannot emit its first sample until it has:

  1. fetched the Netflix OCA endpoint list from api.fast.com,
  2. spawned its 8 traffic workers, and
  3. completed one sleep 1 sampling interval.

That warm-up is most of the budget, so phaseTimer fires and SIGTERMs the
script after only a fraction of a second of real measurement — and when the
api.fast.com call is slow, before the script has printed anything at all.
With no line parsed, downloadMbps/uploadMbps stay "" and toMbps()
returns 0.

Steps to reproduce

Time how long the helper takes to produce its first line:

time omarchy-network-speedtest down | head -1
time omarchy-network-speedtest up   | head -1

Then open the speed test panel and compare against the 5s phase timer.

Measurements from this machine

Time to first sample (6 runs):

directionruns
down3.13s, 2.95s, 2.98s
up2.96s, 4.49s, 2.98s

The dominant and most variable term is the endpoint fetch. Five consecutive
calls to api.fast.com:

1.01s  1.38s  0.89s  4.71s  1.77s

So a typical run leaves ~2s of measuring inside the 5s window, and a slow
endpoint fetch leaves none — which is when both dials read 0. The link itself
is healthy (~220 Mbit/s down, ~66 Mbit/s up), and running the helper directly
from a shell produces correct values throughout.

Suggested fix

Start the measurement window on the first sample rather than at process
launch, and keep a longer guard so a genuinely wedged run still gives up:

+  property bool sampleSeen: false
+
   function updateSpeedTestLine(line) {
     var value = parseFloat(line)
     if (!isFinite(value) || value < 0) return
 
+    if (!sampleSeen) {
+      sampleSeen = true
+      warmupTimer.stop()
+      phaseTimer.restart()
+    }
+
     if (phase === "down") downloadMbps = String(value)
     else if (phase === "up") uploadMbps = String(value)
   }
 
   function startPhase(nextPhase) {
     ...
     speedTestProc.running = true
-    phaseTimer.restart()
+    sampleSeen = false
+    warmupTimer.restart()
   }
+
+  Timer {
+    id: warmupTimer
+    interval: 20000
+    repeat: false
+    onTriggered: root.stopPhase()
+  }

warmupTimer also needs stopping alongside phaseTimer in close(),
stopPhase() and onExited.

Running this locally, each direction now gets a full 5 seconds of actual
traffic and both dials populate reliably:

startPhase down
first-sample phase=down val=224     (4.0s after launch)
stopPhase   phase=down              (5.0s of measurement)
startPhase up
first-sample phase=up   val=66      (3.6s after launch)
stopPhase   phase=up                (5.0s of measurement)

An alternative worth considering is having omarchy-network-speedtest print a
0 sample (or a ready marker) as soon as its workers are up, so the panel can
distinguish "warming up" from "no data" without a timer change.

System details

  • Omarchy 4.0.4-1
  • Kernel 7.2.5-3-omarchy, Hyprland v0.56.2
  • AMD Ryzen 7 7735HS / Radeon 680M (Rembrandt)
  • Wi-Fi (wlp2s0), connection healthy and not rate-limited
View raw text
## What happened

Opening the internet speed test (network panel -> speed test, `omarchy.speedtest`)
regularly shows **0 on both the download and upload dials**. No error is
displayed — the dials simply never move off zero.

## Expected

Each dial shows the measured throughput, as `omarchy-network-speedtest` reports
it on stdout.

## Root cause

`shell/plugins/panels/speedtest/Panel.qml` gives each direction a fixed 5-second
window that starts **when the process is launched**:

```qml
function startPhase(nextPhase) {
  ...
  speedTestProc.running = true
  phaseTimer.restart()        // 5000 ms, measured from launch
}
```

But `bin/omarchy-network-speedtest` cannot emit its first sample until it has:

1. fetched the Netflix OCA endpoint list from `api.fast.com`,
2. spawned its 8 traffic workers, and
3. completed one `sleep 1` sampling interval.

That warm-up is most of the budget, so `phaseTimer` fires and SIGTERMs the
script after only a fraction of a second of real measurement — and when the
`api.fast.com` call is slow, before the script has printed anything at all.
With no line parsed, `downloadMbps`/`uploadMbps` stay `""` and `toMbps()`
returns 0.

## Steps to reproduce

Time how long the helper takes to produce its first line:

```bash
time omarchy-network-speedtest down | head -1
time omarchy-network-speedtest up   | head -1
```

Then open the speed test panel and compare against the 5s phase timer.

## Measurements from this machine

Time to first sample (6 runs):

| direction | runs |
|---|---|
| down | 3.13s, 2.95s, 2.98s |
| up   | 2.96s, 4.49s, 2.98s |

The dominant and most variable term is the endpoint fetch. Five consecutive
calls to `api.fast.com`:

```
1.01s  1.38s  0.89s  4.71s  1.77s
```

So a typical run leaves ~2s of measuring inside the 5s window, and a slow
endpoint fetch leaves none — which is when both dials read 0. The link itself
is healthy (~220 Mbit/s down, ~66 Mbit/s up), and running the helper directly
from a shell produces correct values throughout.

## Suggested fix

Start the measurement window on the **first sample** rather than at process
launch, and keep a longer guard so a genuinely wedged run still gives up:

```diff
+  property bool sampleSeen: false
+
   function updateSpeedTestLine(line) {
     var value = parseFloat(line)
     if (!isFinite(value) || value < 0) return
 
+    if (!sampleSeen) {
+      sampleSeen = true
+      warmupTimer.stop()
+      phaseTimer.restart()
+    }
+
     if (phase === "down") downloadMbps = String(value)
     else if (phase === "up") uploadMbps = String(value)
   }
 
   function startPhase(nextPhase) {
     ...
     speedTestProc.running = true
-    phaseTimer.restart()
+    sampleSeen = false
+    warmupTimer.restart()
   }
+
+  Timer {
+    id: warmupTimer
+    interval: 20000
+    repeat: false
+    onTriggered: root.stopPhase()
+  }
```

`warmupTimer` also needs stopping alongside `phaseTimer` in `close()`,
`stopPhase()` and `onExited`.

Running this locally, each direction now gets a full 5 seconds of actual
traffic and both dials populate reliably:

```
startPhase down
first-sample phase=down val=224     (4.0s after launch)
stopPhase   phase=down              (5.0s of measurement)
startPhase up
first-sample phase=up   val=66      (3.6s after launch)
stopPhase   phase=up                (5.0s of measurement)
```

An alternative worth considering is having `omarchy-network-speedtest` print a
`0` sample (or a ready marker) as soon as its workers are up, so the panel can
distinguish "warming up" from "no data" without a timer change.

## System details

- Omarchy `4.0.4-1`
- Kernel `7.2.5-3-omarchy`, Hyprland `v0.56.2`
- AMD Ryzen 7 7735HS / Radeon 680M (Rembrandt)
- Wi-Fi (`wlp2s0`), connection healthy and not rate-limited

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 17:03 UTC