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.
omarchy-theme-set-browser hangs when brave-origin is running but Brave is not (pgrep -x brave false-positive)
Reported by patterninterrupt · filed Aug 25, 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
System details
AMD Ryzen 9 5950X, AMD Radeon RX 9070 XT (Navi 48), Omarchy 4.0.0.r1827.gb86d450-1, kernel 7.1.8-arch1-3.
Both brave-bin 1:1.93.137-1 and brave-origin-bin 1:1.93.137-1 installed; only brave-origin is ever run.
What's wrong?
omarchy update hangs indefinitely inside a migration. The migration never returns, so omarchy-migrate never writes its marker file, and that migration plus every migration after it stays pending forever — each subsequent omarchy update re-runs it and hangs again.
In my case migration 1787481315 ("Re-stage the current theme so an installed theme's code is dropped") hung. It calls omarchy-theme-refresh → omarchy-theme-set, which blocks on run_parallel's wait in the post-theme command list. But the migration is incidental — anything that reaches omarchy-theme-set-browser hangs the same way.
The culprit is the last-but-one line of bin/omarchy-theme-set-browser:
refresh_running_browser brave brave # guard: pgrep -x braverefresh_running_browser guards on pgrep -x brave. brave-origin's processes are all named plain `brave` — that is exactly the collision the very next line already documents:
# Match on the binary path: the running process is named plain "brave", and a
# bare -f brave-origin pattern would also match the installer's own terminal.
refresh_running_browser /opt/brave-origin-bin/ brave-origin -fSo with brave-origin running and Brave not running, pgrep -x brave matches (27 processes here, all children of /opt/brave-origin-bin/brave), the guard passes, and the script then launches the other binary, /usr/bin/brave (from brave-bin, /opt/brave-bin/). With --no-startup-window that new instance has no window to close, never exits, and run_parallel's wait blocks on it forever.
This is the same failure mode as #4772, which was fixed by adding the pgrep guard. This case slips past that fix because the guard produces a false positive across two different browsers that share a process name.
Steps to reproduce
- Install both
brave-binandbrave-origin-bin. - Launch brave-origin. Do not launch Brave.
- Run
omarchy theme set <any-theme>(oromarchy updatewith a pending migration that re-stages the theme). - It hangs.
psshows a stray/usr/bin/brave --refresh-platform-policy --no-startup-window. Killing it lets the update continue.
Diagnostics
Timing each of the 14 post_theme_commands individually, stdin from /dev/null:
| command | result |
|---|---|
omarchy-theme-set-browser | timeout at 25s |
| all 13 others | ≤ 3s, rc=0 |
Narrowing to the two Brave branches:
$ timeout 10 brave --refresh-platform-policy --no-startup-window # rc=124 (hang)
$ timeout 10 brave-origin --refresh-platform-policy --no-startup-window # rc=0 (0s)Confirming the false positive:
$ pgrep -xc brave
27
$ pgrep -af brave | grep -v origin # is real Brave running?
(nothing)
$ readlink -f /usr/bin/brave /usr/bin/brave-origin
/usr/bin/brave
/usr/bin/brave-originAfter quitting brave-origin, omarchy-migrate ran straight through with no hang.
Note: contributing.md points at omarchy debug --no-sudo --print for diagnostics, but that command does not exist on 4.0.0 (Unknown Omarchy command: omarchy debug), so the details above are gathered by hand.
Suggested fix
Match the plain-Brave branch on its binary path, the way the brave-origin branch already does, so the two cannot alias each other:
refresh_running_browser /opt/brave-bin/ brave -fA timeout around the "$command" --refresh-platform-policy call would also cap the damage generally — the policy is picked up on next launch anyway, so there is nothing to lose by giving up on it.
View raw text
### System details
AMD Ryzen 9 5950X, AMD Radeon RX 9070 XT (Navi 48), Omarchy 4.0.0.r1827.gb86d450-1, kernel 7.1.8-arch1-3.
Both `brave-bin 1:1.93.137-1` and `brave-origin-bin 1:1.93.137-1` installed; only brave-origin is ever run.
### What's wrong?
`omarchy update` hangs indefinitely inside a migration. The migration never returns, so `omarchy-migrate` never writes its marker file, and that migration plus every migration after it stays pending forever — each subsequent `omarchy update` re-runs it and hangs again.
In my case migration `1787481315` ("Re-stage the current theme so an installed theme's code is dropped") hung. It calls `omarchy-theme-refresh` → `omarchy-theme-set`, which blocks on `run_parallel`'s `wait` in the post-theme command list. But the migration is incidental — anything that reaches `omarchy-theme-set-browser` hangs the same way.
The culprit is the last-but-one line of `bin/omarchy-theme-set-browser`:
```bash
refresh_running_browser brave brave # guard: pgrep -x brave
```
`refresh_running_browser` guards on `pgrep -x brave`. **brave-origin's processes are all named plain `brave`** — that is exactly the collision the very next line already documents:
```bash
# Match on the binary path: the running process is named plain "brave", and a
# bare -f brave-origin pattern would also match the installer's own terminal.
refresh_running_browser /opt/brave-origin-bin/ brave-origin -f
```
So with brave-origin running and Brave not running, `pgrep -x brave` matches (27 processes here, all children of `/opt/brave-origin-bin/brave`), the guard passes, and the script then launches **the other binary**, `/usr/bin/brave` (from `brave-bin`, `/opt/brave-bin/`). With `--no-startup-window` that new instance has no window to close, never exits, and `run_parallel`'s `wait` blocks on it forever.
This is the same failure mode as #4772, which was fixed by adding the `pgrep` guard. This case slips past that fix because the guard produces a false positive across two different browsers that share a process name.
### Steps to reproduce
1. Install both `brave-bin` and `brave-origin-bin`.
2. Launch brave-origin. Do not launch Brave.
3. Run `omarchy theme set <any-theme>` (or `omarchy update` with a pending migration that re-stages the theme).
4. It hangs. `ps` shows a stray `/usr/bin/brave --refresh-platform-policy --no-startup-window`. Killing it lets the update continue.
### Diagnostics
Timing each of the 14 `post_theme_commands` individually, stdin from `/dev/null`:
| command | result |
|---|---|
| `omarchy-theme-set-browser` | **timeout at 25s** |
| all 13 others | ≤ 3s, rc=0 |
Narrowing to the two Brave branches:
```
$ timeout 10 brave --refresh-platform-policy --no-startup-window # rc=124 (hang)
$ timeout 10 brave-origin --refresh-platform-policy --no-startup-window # rc=0 (0s)
```
Confirming the false positive:
```
$ pgrep -xc brave
27
$ pgrep -af brave | grep -v origin # is real Brave running?
(nothing)
$ readlink -f /usr/bin/brave /usr/bin/brave-origin
/usr/bin/brave
/usr/bin/brave-origin
```
After quitting brave-origin, `omarchy-migrate` ran straight through with no hang.
Note: `contributing.md` points at `omarchy debug --no-sudo --print` for diagnostics, but that command does not exist on 4.0.0 (`Unknown Omarchy command: omarchy debug`), so the details above are gathered by hand.
### Suggested fix
Match the plain-Brave branch on its binary path, the way the brave-origin branch already does, so the two cannot alias each other:
```bash
refresh_running_browser /opt/brave-bin/ brave -f
```
A `timeout` around the `"$command" --refresh-platform-policy` call would also cap the damage generally — the policy is picked up on next launch anyway, so there is nothing to lose by giving up on it.
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
- Related PRpr/9423· confirmed
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:42 UTC