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.
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
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
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:
- fetched the Netflix OCA endpoint list from
api.fast.com, - spawned its 8 traffic workers, and
- completed one
sleep 1sampling 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 theapi.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 -1Then 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.77sSo 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 a0 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, Hyprlandv0.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