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

4.0.3 bar-widget sandbox omits slot geometry from PluginBarApi, silently breaking width-aware widgets

Reported by nathankramm · filed Sep 10, 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

4.0.3 bar-widget sandbox omits slot geometry from PluginBarApi, silently breaking width-aware widgetsrevision 1 · captured 2026-09-28 21:23 UTC via poll

Summary

The bar-widget sandbox added in the 4.0.2 → 4.0.3 window gives a third-party bar widget
PluginBarApi instead of the host Bar. That facade forwards no slot geometry, so a widget
that sizes itself against the space actually available to it can no longer compute a width
budget, and silently collapses to its smallest form on every monitor.

This is a sibling of #10888, #10929, #10937, #11063 and #10999 — same injectProps() change,
different missing surface. As in those, I am not arguing the sandbox is wrong; it is a clear
improvement. This is about a capability that had no sandboxed replacement, and about the
failure being completely silent.

Unlike the drag and registry cases, the information withheld here is purely presentational:
the widths of sibling widgets on a bar the user configured themselves. layoutConfig — which
tells a plugin which widgets are on the bar — is already forwarded. Only the widths are not.

The change

shell/plugins/bar/Bar.qml, injectProps() (Bar.qml:2002-2003):

if ("bar" in target) target.bar = firstParty
  ? root : root.pluginBarApiFor(pluginApiId, moduleName, registered)

firstParty is registryMetadata.firstParty === true (Bar.qml:1782), which comes from
manifest.__isFirstParty (shell.qml:1412) and is true only for plugins under
firstPartyPluginsDir = /usr/share/omarchy/shell/plugins (shell.qml:30). Anything installed
to ~/.config/omarchy/plugins therefore always receives the facade.

The real Bar root declares the geometry surface a width-aware widget needs:

memberBar.qml
moduleSlots:111
slotWindow(slot):388
sameWindow(left, right):393
layoutEntries(region):618
entryId(entry):767
entryIndex(entries, name):775
centerAnchor:52

shell/Ui/PluginBarApi.qml forwards none of them — `grep -cE
'slotWindow|sameWindow|moduleSlots|layoutEntries|entryId|entryIndex|centerAnchor'` returns
0. It declares foreground, barForeground, background, urgent, fontFamily,
position, vertical, barSize, transparent, foregroundAnimationEnabled,
centerSectionRevealHeld, activePopout, clickTargets, layoutConfig, plus the
tooltip/click-target/popout hooks.

Note barSize (the bar's thickness) and layoutConfig (the configured widget list) are both
forwarded. It is specifically the per-slot widths that are not, and those are the one input a
width computation cannot be done without.

Why it fails silently

A widget cannot ask "how much room do I have?" any other way. The window's own width is
reachable independently, via Quickshell's QsWindow.window.width attached property — so the
widget knows the bar is 1280px wide but has no way to learn that its neighbours have already
consumed 700 of it.

A plugin written defensively degrades to "no room". From costafot.markets
(BarWidget.qml:135):

readonly property real stripMaxWidth: {
  if (!root.bar || root.vertical) return -1
  var win = root.QsWindow.window
  if (!win || !(win.width > 0)) return -1
  var barHost = root.bar
  if (typeof barHost.slotWindow !== "function" || typeof barHost.sameWindow !== "function") return -1
  ...

That guard now returns -1 on every evaluation, so the widget's width-driven degradation
resolves to "zero room" unconditionally and it paints a single glyph — on a 1280px laptop
panel and a 3440px ultrawide alike, docked or undocked. Nothing is logged.

The alternative a plugin author reaches for is worse: skipping the guard and painting the full
strip regardless, which draws over the neighbouring section because the widget has no way to
know it has overflowed. So the sandbox leaves two options, silently-too-small and
silently-overlapping, with no way to choose correctly at runtime.

Steps to reproduce

  1. Install any third-party bar widget that sizes itself against available width, to

~/.config/omarchy/plugins/ (e.g. omarchy-markets).
2. Put it in a bar section with room to spare — a wide monitor, few neighbours.
3. Observe it renders in its collapsed/minimal form regardless of available width, with no
warning on stderr.
4. In the widget, log typeof bar.slotWindow in onBarChanged: undefined.

Suggestion

Forward a scoped, read-only width budget rather than the host Bar. Either would be enough:

  • readonly property real availableWidth on PluginBarApi, computed host-side for the

calling widget's own slot and window — the smallest possible surface, and it exposes nothing
about other plugins.
- or a slotWidths(region) accessor returning widths for the calling widget's own window,
keyed by module name, consistent with how _moduleWidgets is already scoped to the caller
(Bar.qml:263-266).

The first is preferable; it is the only number a widget actually needs, and it keeps the
facade's isolation intact.

System

  • omarchy 4.0.3-1 (Arch package), pacman -Qkk omarchy → 1727 files, 0 altered.
  • Reproduces with any third-party bar widget that reads slot geometry.

Two caveats, so nothing here is over-claimed:

  • I have not verified the before-state myself: only 4.0.3 is in my pacman cache, so I could

not extract an r2044 package to diff. #10929 reports that r2044's injectProps() assigned
target.bar = root unconditionally and that shell/Ui/PluginBarApi.qml does not exist in
that package at all. I am relying on that report for the "this changed" claim; everything
above about 4.0.3 itself is read directly from the installed tree.
- Unrelated but worth a line for anyone reproducing: /usr/share/omarchy/version in the
4.0.3-1 package contains 4.0.0.alpha. The file is unmodified (0 altered files), so the
package ships it stale; omarchy-version reports 4.0.3-1 correctly because it queries
pacman instead.

View raw text
## Summary

The bar-widget sandbox added in the 4.0.2 → 4.0.3 window gives a third-party bar widget
`PluginBarApi` instead of the host `Bar`. That facade forwards no slot geometry, so a widget
that sizes itself against the space actually available to it can no longer compute a width
budget, and silently collapses to its smallest form on every monitor.

This is a sibling of #10888, #10929, #10937, #11063 and #10999 — same `injectProps()` change,
different missing surface. As in those, I am not arguing the sandbox is wrong; it is a clear
improvement. This is about a capability that had no sandboxed replacement, and about the
failure being completely silent.

Unlike the drag and registry cases, the information withheld here is purely presentational:
the widths of sibling widgets on a bar the user configured themselves. `layoutConfig` — which
tells a plugin *which* widgets are on the bar — is already forwarded. Only the widths are not.

## The change

`shell/plugins/bar/Bar.qml`, `injectProps()` (Bar.qml:2002-2003):

```qml
if ("bar" in target) target.bar = firstParty
  ? root : root.pluginBarApiFor(pluginApiId, moduleName, registered)
```

`firstParty` is `registryMetadata.firstParty === true` (Bar.qml:1782), which comes from
`manifest.__isFirstParty` (shell.qml:1412) and is true only for plugins under
`firstPartyPluginsDir` = `/usr/share/omarchy/shell/plugins` (shell.qml:30). Anything installed
to `~/.config/omarchy/plugins` therefore always receives the facade.

The real `Bar` root declares the geometry surface a width-aware widget needs:

| member | Bar.qml |
|---|---|
| `moduleSlots` | :111 |
| `slotWindow(slot)` | :388 |
| `sameWindow(left, right)` | :393 |
| `layoutEntries(region)` | :618 |
| `entryId(entry)` | :767 |
| `entryIndex(entries, name)` | :775 |
| `centerAnchor` | :52 |

`shell/Ui/PluginBarApi.qml` forwards none of them — `grep -cE
'slotWindow|sameWindow|moduleSlots|layoutEntries|entryId|entryIndex|centerAnchor'` returns
**0**. It declares `foreground`, `barForeground`, `background`, `urgent`, `fontFamily`,
`position`, `vertical`, `barSize`, `transparent`, `foregroundAnimationEnabled`,
`centerSectionRevealHeld`, `activePopout`, `clickTargets`, `layoutConfig`, plus the
tooltip/click-target/popout hooks.

Note `barSize` (the bar's thickness) and `layoutConfig` (the configured widget list) are both
forwarded. It is specifically the per-slot widths that are not, and those are the one input a
width computation cannot be done without.

## Why it fails silently

A widget cannot ask "how much room do I have?" any other way. The window's own width *is*
reachable independently, via Quickshell's `QsWindow.window.width` attached property — so the
widget knows the bar is 1280px wide but has no way to learn that its neighbours have already
consumed 700 of it.

A plugin written defensively degrades to "no room". From `costafot.markets`
(`BarWidget.qml:135`):

```qml
readonly property real stripMaxWidth: {
  if (!root.bar || root.vertical) return -1
  var win = root.QsWindow.window
  if (!win || !(win.width > 0)) return -1
  var barHost = root.bar
  if (typeof barHost.slotWindow !== "function" || typeof barHost.sameWindow !== "function") return -1
  ...
```

That guard now returns `-1` on every evaluation, so the widget's width-driven degradation
resolves to "zero room" unconditionally and it paints a single glyph — on a 1280px laptop
panel and a 3440px ultrawide alike, docked or undocked. Nothing is logged.

The alternative a plugin author reaches for is worse: skipping the guard and painting the full
strip regardless, which draws over the neighbouring section because the widget has no way to
know it has overflowed. So the sandbox leaves two options, silently-too-small and
silently-overlapping, with no way to choose correctly at runtime.

## Steps to reproduce

1. Install any third-party bar widget that sizes itself against available width, to
   `~/.config/omarchy/plugins/` (e.g. [omarchy-markets](https://github.com/CostaFot/omarchy-markets)).
2. Put it in a bar section with room to spare — a wide monitor, few neighbours.
3. Observe it renders in its collapsed/minimal form regardless of available width, with no
   warning on stderr.
4. In the widget, log `typeof bar.slotWindow` in `onBarChanged`: `undefined`.

## Suggestion

Forward a scoped, read-only width budget rather than the host `Bar`. Either would be enough:

- `readonly property real availableWidth` on `PluginBarApi`, computed host-side for the
  calling widget's own slot and window — the smallest possible surface, and it exposes nothing
  about other plugins.
- or a `slotWidths(region)` accessor returning widths for the calling widget's own window,
  keyed by module name, consistent with how `_moduleWidgets` is already scoped to the caller
  (Bar.qml:263-266).

The first is preferable; it is the only number a widget actually needs, and it keeps the
facade's isolation intact.

## System

- `omarchy 4.0.3-1` (Arch package), `pacman -Qkk omarchy` → 1727 files, 0 altered.
- Reproduces with any third-party bar widget that reads slot geometry.

Two caveats, so nothing here is over-claimed:

- I have not verified the before-state myself: only 4.0.3 is in my pacman cache, so I could
  not extract an r2044 package to diff. #10929 reports that r2044's `injectProps()` assigned
  `target.bar = root` unconditionally and that `shell/Ui/PluginBarApi.qml` does not exist in
  that package at all. I am relying on that report for the "this changed" claim; everything
  above about 4.0.3 itself is read directly from the installed tree.
- Unrelated but worth a line for anyone reproducing: `/usr/share/omarchy/version` in the
  4.0.3-1 package contains `4.0.0.alpha`. The file is unmodified (0 altered files), so the
  package ships it stale; `omarchy-version` reports `4.0.3-1` correctly because it queries
  pacman instead.

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