Merge remote-tracking branch 'origin/quattro' into fix-snapshot-locate-and-timeline-leak

# Conflicts:
#	docs/file-layout.md
This commit is contained in:
David Heinemeier Hansson
2026-07-26 19:14:09 -07:00
240 changed files with 6263 additions and 2472 deletions
+141
View File
@@ -0,0 +1,141 @@
# Speaker tunings
Laptop speakers ship voiced by the vendor's Windows DSP layer, which Linux does
not get. A tuning restores that as a PipeWire filter-chain in front of the
internal speaker sink: a declarative graph hosted by a small PipeWire client, with
no GUI app and no binary blob.
```
default/audio/tunings/<vendor>-<model>/
├── tuning.conf # description, match, provenance, measurements
└── filter-chain.conf # the graph, with @SPEAKER_SINK@ substituted on install
```
`on` renders the graph into `~/.config/pipewire/omarchy-speaker-tuning.conf.d/`
and runs it as its own PipeWire client via `omarchy-speaker-tuning.service`, rather than
loading it into the audio daemon. The daemon only reads its own config at startup,
so a daemon-loaded tuning could only be switched by restarting PipeWire — which
drops every PulseAudio client's connection, and applications that do not reconnect
(Spotify) then have to be restarted by hand. Hosting it separately makes switching
a start/stop of one small process, and contains failure: a malformed tuning breaks
only that service instead of stopping PipeWire from starting at all.
Tunings apply automatically: `install/hardware/speaker-tuning.sh` installs the
LV2 dependency and `install/user/first-run/audio-tuning.sh` applies the tuning,
both gated on the match. Machines without a matching tuning are untouched.
Switching it on happens at first-run, not at finalize-user time, because finalize-user
also runs in the ISO chroot where there is no audio server: the sink a tuning has
to target does not exist there, so nothing could be written — and nothing would
retry, since the finalizer marks all shipped migrations complete on a fresh
install. Matching itself deliberately does not consult the audio graph, so the
LV2 dependency is still installed in the chroot.
```bash
omarchy audio tuning on # install the matching tuning
omarchy audio tuning off # remove it, back to raw speakers
omarchy audio tuning status # installed? in use? what matches?
```
`match` and `fronted-sink` are also accepted; they exist for the install hooks
and the sink-listing scripts rather than for daily use.
## Adding a tuning
Add a directory with a `tuning.conf` and a `filter-chain.conf`. No new command is
needed: matching is data. A tuning declares how to recognise its hardware, plus the
`sink_pattern` its graph targets:
| Key | Matches on | Notes |
|---|---|---|
| `match_sku` | DMI product SKU, whole value | Most precise. Vendors key speaker firmware on it, so it identifies the hardware rather than a marketing name |
| `match_dmi` | DMI product name or family, substring | Convenient, but a short string widens fast — `product_family` here is `Dell Laptops` |
| `match_command` | Any predicate you name | For hardware needing a sharper test than either |
`match_sku` and `match_dmi` are lists, so one tuning can cover several models it has
been validated on:
```bash
match_sku=("0DB9" "0DBA") # XPS 14 and XPS 16
```
`sink_pattern` is required whichever method you use, since the graph's target sink
is substituted from it.
Gate narrowly and widen as models are validated; a tuning aimed at the wrong
drivers can sound worse than none and can stress them. When a tuning covers a model
it was not measured on, say so in `tuning.conf` — the provenance fields are there to
keep that distinction visible rather than implied.
Two hard requirements:
- **End in a limiter.** Peaks must stay under 0 dBFS with headroom.
- **Do not boost what the drivers cannot deliver.** The XPS 14 tuning
deliberately *cuts* 40 Hz by around 18 dB. Excursion down there buys nothing
and costs distortion.
## Building one
Measuring a laptop and fitting a filter-chain to it is a separate job with its own
tools, in [omarchy-audio-tuner](https://github.com/omacom-io/omarchy-audio-tuner).
It is not installed by default — almost nobody authoring a tuning, and it needs
python, ffmpeg and mpv.
```bash
omarchy pkg add omarchy-audio-tuner
```
Its README is the walkthrough, and covers both cases: copying a reference that
already sounds right (how the XPS 14 tuning was made, no microphone needed), and
designing from scratch, which needs a *calibrated* measurement mic and a target
curve that measurement alone cannot give you.
## What a tuning must report
A tuning is not reviewable on "sounds better to me". Record these, measured, in
`tuning.conf`:
| Field | What it is |
|---|---|
| `magnitude_rms_db` | Deviation from the reference or target it was fitted to |
| `bass_group_delay_swing_ms` | Max minus min group delay, 30300 Hz |
| `limiter_headroom_db` | Worst-case peak against the limiter threshold |
| `dynamic_range_delta_lu` | LRA change against the reference |
Measure electrically by capturing the physical speaker sink's monitor, which sits
upstream of the volume control, so results are independent of listening level.
## How this fits the audio graph
Two things about the surrounding system are worth knowing, because both caused
real bugs:
- **Volume lives downstream of the tuning.** A tuning is a virtual sink that
becomes the default output, and changing *its* volume would alter the level
going into the processing — moving the display while the speakers stay put, and
changing the tone of anything with a compressor or limiter in it.
`omarchy-audio-output-sink` is the single definition of "which sink does this
output's volume really use": it resolves a sink through any DSP sink to the
physical one, and with no argument resolves the current default output. The
volume keys, the output switcher's OSD and the audio panel all use it, so they
cannot disagree. Resolving the *current default* rather than "whatever a tuning
fronts" is what keeps it correct when headphones or HDMI are selected while a
tuning still exists.
- **The fronted sink is hidden.** The tuning and the physical speakers both exist
in the graph, and selecting the physical one would only bypass the tuning. So
`omarchy-audio-sink-availability` reports it unavailable and
`omarchy-audio-output-switch` skips it, leaving one speaker entry in the panel.
A WirePlumber smart filter would remove the need for both — it leaves the real
device as the default output — but on PipeWire 1.6.8 / WirePlumber 0.5.15 the
graph loads and links correctly as a smart filter and then passes audio through
unprocessed. Revisit when that is understood.
- **EasyEffects cannot coexist with a tuning.** It moves any stream that follows
the default sink to its own sink, so it would grab audio back from a
filter-chain. `on` refuses while it is running rather than installing a graph
that would be bypassed.
- **The tuning's own output must not be moved.** A filter-chain's output is a
playback stream like any other, so anything rerouting "all streams" to a newly
selected output would drag the processing with it — onto headphones, or into the
tuning's own sink, which is a cycle. The tuning sets `node.dont-move`, and
`omarchy-audio-output-set-default` moves only streams that carry an
`application.name`.
+22 -13
View File
@@ -97,6 +97,7 @@ default/** ──► omarchy-settings /usr/share/omarchy
│ → /etc/skel/.bashrc (post_install cp -f)
├─ hypr/toggles/flags.lua /etc/skel/.local/state/omarchy/toggles/hypr/
├─ nautilus-python/extensions/*.py /etc/skel/.local/share/nautilus-python/extensions/
├─ tensaku/state.toml /etc/skel/.local/state/tensaku/state.toml
├─ uwsm/env.d/10-omarchy /usr/share/uwsm/env.d/
├─ environment.d/*.conf /usr/lib/environment.d/
├─ fontconfig/conf.avail/50-omarchy.conf /usr/share/fontconfig/conf.avail/
@@ -105,6 +106,7 @@ default/** ──► omarchy-settings /usr/share/omarchy
├─ applications/mimeapps.list /usr/share/applications/mimeapps.list
├─ systemd/user/*.{service,path} /usr/lib/systemd/user/
├─ systemd/system-sleep/unmount-fuse /usr/lib/systemd/system-sleep/
├─ systemd/zram-generator.conf.d/90-omarchy.conf /usr/lib/systemd/zram-generator.conf.d/
├─ fonts/omarchy/omarchy.ttf /usr/share/fonts/omarchy/
├─ sddm/omarchy/ /usr/share/sddm/themes/omarchy/
├─ sddm/hyprland.lua /usr/share/sddm/hyprland.lua
@@ -195,13 +197,19 @@ migration. Migrations run as the user; privileged work should invoke the
appropriate helper or privilege prompt. Migrations must be idempotent;
machine-wide repairs should no-op when another user already applied them.
Each graphical user has `omarchy-update-user-notify.path` watching the packaged
migration directory for changes, and `omarchy-update-user-notify.service` is
also started once per login via its own `WantedBy=graphical-session.target`.
Either way the service runs `omarchy-migrate-notify` as that user. The notifier checks
`omarchy-migrate --pending`. If this user has missing migration state, it shows a
notification that opens a terminal for `omarchy-migrate`. The notifier never runs
migrations in the background.
Each graphical user has `omarchy-migrate-notify.service`, started once per login
through `WantedBy=graphical-session.target`. The package also ships
`omarchy-update-user-notify.service` as a symlink onto it, so users enabled
under the old unit name keep working before they reach migration `1785095882`.
It runs `omarchy-migrate-notify` as
that user, which checks `omarchy-migrate --pending`. If this user has missing
migration state, it shows a notification that opens a terminal for
`omarchy-migrate`. The notifier never runs migrations in the background.
Login is the only trigger. Nothing watches the packaged migration directory: a
watcher cannot tell a bypassed `pacman -Syu` from the package transaction inside
a normal `omarchy update`, so it notified about migrations that `omarchy-migrate`
was already applying in the visible update terminal.
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
pending migrations. It does not need `--force`; migrations happen when state
@@ -219,8 +227,8 @@ systemd instance:
Voxtype post-update hook.
- `install/user/first-run/enable-user-units.sh``systemctl --user enable`
the shipped user units (`bt-agent`, `omarchy-sleep-lock`,
`omarchy-recover-internal-monitor`, `omarchy-update-user-notify.path`,
`omarchy-update-user-notify.service`). Done here, not at finalize, because
`omarchy-recover-internal-monitor`, `omarchy-migrate-notify.service`).
Done here, not at finalize, because
the user manager isn't reachable from the ISO chroot; `ConditionPath*`
in the unit files keeps services inert when they don't apply.
- `install/user/first-run/gnome-theme.sh`,
@@ -247,14 +255,14 @@ the legacy finalization marker from `~/.local/state/omarchy/` into `done/`.
`omarchy-setup-system` (root, in chroot) runs target-side setup at ISO
finalization. It sources:
- `install/config/*.sh` — theme links, lockout limits, lockscreen PAM,
- `install/config/all.sh` — theme links, lockout limits, lockscreen PAM,
powerprofilesctl shebang fix, docker setup, Snapper retention, locate
index tuning, service enablement, firewall.
- `install/hardware/all.sh` via `omarchy-setup-hardware` — vendor- and
device-specific kernel modules, udev rules, microcode, wireless regdom,
ASUS / Framework / Intel / Apple / Lenovo quirks.
- `install/login/*.sh` — SDDM theme/session config.
- `install/post-install/*.sh` — final pacman/udev/localdb passes.
- `install/login/all.sh` — SDDM theme/session config.
- `install/post-install/all.sh` — final pacman/udev/localdb passes.
Logging goes to `/var/log/omarchy-install.log` via
`install/helpers/logging.sh`.
@@ -288,8 +296,9 @@ return to the packaged default.
| Package-owned system file (e.g. systemd user service/path in `/usr/lib`) | `default/`, document the mapping in `default/package-defaults.tsv`, then add the `install -Dm644` line in `omarchy-settings` PKGBUILD |
| Per-user file that's static but lives outside `~/.config` | `default/`, then add `install -Dm644 ... $pkgdir/etc/skel/...` in `omarchy-settings` PKGBUILD |
| Runtime tweak that needs `$HOME` or live system state | extend `omarchy-finalize-user`, or add a per-user leaf under `install/user/` and wire into `install/user/all.sh` |
| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `omarchy-setup-system` or `install/hardware/all.sh` |
| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `install/config/all.sh` or `install/hardware/all.sh` |
| One-time fix for existing installs | `migrations/<unix-timestamp>.sh` |
| Package-owned path something else may already write | Prefer a path nothing else writes, such as a vendor drop-in under `/usr/lib`. Otherwise the `--overwrite` entry in `bin/omarchy-update-system-pkgs` has to ship a release before the file |
| User-facing `omarchy-*` command | `bin/omarchy-<group>-<verb>` — see `GROUP_DESCRIPTIONS` in `bin/omarchy` |
| New stock theme | `themes/<name>/` (+ matching templates under `default/themed/` if they need theme colors) |
| User-installed theme | `~/.config/omarchy/themes/<name>/` |
+11 -9
View File
@@ -43,16 +43,9 @@ omarchy-hook post-update
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
all pending migrations for the current user in the visible update terminal.
### During direct pacman updates
### At login
Raw `sudo pacman -Syu` is guarded. Users should normally run:
```bash
omarchy update
```
If a user explicitly bypasses the guard, user sessions watch the packaged
migration directory and run a notifier. The notifier checks:
Every graphical login starts `omarchy-migrate-notify.service`, which checks:
```bash
omarchy-migrate --pending
@@ -67,6 +60,15 @@ omarchy-migrate
The notifier never runs migrations silently in the background.
This is what covers users who did not run the update themselves: someone who
bypassed the pacman guard with `sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman
-Syu`, and any second user on the machine, whose migration markers are per-user
and therefore still missing after another user updated.
Login is the only trigger on purpose. Watching the packaged migration directory
also fires during a normal `omarchy update`, which prompts for migrations that
`omarchy-migrate` is about to run in the visible update terminal.
### Manually
Users can safely run:
+36 -9
View File
@@ -118,6 +118,7 @@ omarchy-update
├─ create snapper snapshot, if snapper is installed
└─ run update pipeline
├─ block system sleep and temporarily enable shell stay-awake mode
├─ omarchy-update-dev
├─ omarchy-update-keyring
├─ omarchy-update-system-pkgs
├─ omarchy-migrate
@@ -133,6 +134,8 @@ omarchy-update
Important behavior:
- In dev-link mode, `omarchy update` fast-forwards the active checkout from its
configured upstream before changing system packages or running migrations.
- `omarchy update` checks/runs migrations in the same visible terminal via
`omarchy-migrate` after pacman finishes.
- A failure should leave enough output in `/tmp/omarchy-update.log` and the
@@ -146,20 +149,37 @@ High-level flow:
sudo pacman -Syu
├─ pre-transaction guard aborts and tells the user to run omarchy update
└─ if explicitly bypassed, upgrades omarchy and related packages
└─ user session notices migration directory changes
├─ omarchy-update-user-notify.path triggers, if enabled
└─ at that user's next login
├─ omarchy-migrate-notify.service starts with graphical-session.target
├─ omarchy-migrate-notify checks omarchy-migrate --pending
├─ if this user has missing migration state, show notification
└─ click opens terminal: omarchy-migrate
```
Login is deliberately the only trigger. A watcher on the packaged migration
directory cannot distinguish a bypassed `pacman -Syu` from the package
transaction inside a normal `omarchy update`, so it fired notifications for
migrations that `omarchy-migrate` was about to apply in the visible update
terminal. The retired unit was `omarchy-update-user-notify.path`.
Fallbacks:
- `omarchy-first-run` enables the user notification path unit.
- `omarchy-first-run` also invokes `omarchy-migrate-notify` on graphical
startup, so users who updated before the path unit existed still get prompted
if they have missing migration state.
- `omarchy-first-run` enables `omarchy-migrate-notify.service`, which also
covers users created after install: their per-user migration markers are
missing, so their first login prompts them to run every shipped migration.
- The package ships `omarchy-update-user-notify.service` as a symlink onto
`omarchy-migrate-notify.service`. Users set up before the rename hold an
absolute `graphical-session.target.wants` symlink to the old path, and the
migration that repoints it only runs for users who run an update — the
opposite of who the notifier is for. The alias can be dropped once installs
have run migration `1785095882`.
- The notifier waits for a live notification server before sending, because
`graphical-session.target` can be reached before the shell claims
`org.freedesktop.Notifications`.
- The notifier is only a prompt. It does not run migrations in the background.
- A session that is already open when another user updates is not re-checked;
it picks the migrations up at its next login, or whenever that user runs
`omarchy-migrate` or `omarchy update`.
- Direct pacman updates do not run `omarchy-hook post-update` unless the user
explicitly runs that hook; without a package-update marker, the only pending
state we can derive is missing per-user migration markers.
@@ -172,11 +192,16 @@ The bar widget `omarchy.system-update` runs:
omarchy-update-available
```
`omarchy-update-available` checks the installed Omarchy package for updates:
`omarchy-update-available` checks the active Omarchy sources for updates:
- new upstream commits for the active dev-linked checkout
- `omarchy-dev`, when installed
- otherwise `omarchy`, when installed
The dev check fetches the checkout's configured upstream before comparing it
with `HEAD`. A failed fetch is quiet and falls back to the existing remote-
tracking state.
Exit codes:
- `0` — Omarchy updates are available; stdout is the update list.
@@ -196,11 +221,12 @@ scripts.
| `omarchy-update` | Public user command. Adds transcript logging, lock, confirmation, snapshot, sleep/idle inhibitors, package updates, migrations, hooks, update-state refresh, and restart checks. | **Keep.** This is the blessed entry point and owns the update pipeline. |
| `omarchy-update-perform` | Hidden compatibility wrapper for `omarchy-update -y`. | **Temporary.** Keep only for old callers; new code should call `omarchy-update` directly. |
| `omarchy-update-confirm` | Gum confirmation copy for `omarchy update`. | **Question.** Could be inlined into `omarchy-update`; separate file only helps keep copy isolated. |
| `omarchy-update-dev` | Fast-forwards the active dev-linked checkout from its configured upstream; no-ops for package-backed installs. | **Keep.** Runs before package updates so a checkout conflict stops the update before system mutation. |
| `omarchy-update-keyring` | Ensures Omarchy keyring and Arch keyring are current before the main transaction. | **Keep, but review.** It uses targeted `pacman -Sy` for keyring bootstrapping; acceptable for this special case but should remain tightly scoped. |
| `omarchy-update-system-pkgs` | Runs `sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm` with targeted transition `--overwrite` entries so the ALPM guard allows the transaction and early package-layout conflicts are handled. | **Keep for now.** Small leaf command, clear/testable. |
| `omarchy-migrate` | Public migration command. Waits for pacman, then runs all pending migrations for the current user. Supports `--pending`. | **Keep.** This replaces the discarded `omarchy-update-user-finalize` name and no longer needs `--force`. |
| `omarchy-update-pacman-guard` | ALPM pre-transaction guard that aborts direct `pacman -Syu` style upgrades unless Omarchy set `OMARCHY_UPDATE_PACMAN=1` or the user explicitly set `OMARCHY_ALLOW_DIRECT_PACMAN=1`. | **Keep internal/hidden.** This is what nudges users back to `omarchy update`. |
| `omarchy-migrate-notify` | Internal notification helper for direct pacman updates. Uses `omarchy-migrate --pending` and shows notification only when this user has pending migrations. | **Keep internal/hidden.** Clear name now that the public command is `omarchy-migrate`. |
| `omarchy-migrate-notify` | Internal login-time notification helper. Uses `omarchy-migrate --pending` and shows a notification only when this user has pending migrations. | **Keep internal/hidden.** Clear name now that the public command is `omarchy-migrate`. |
| `omarchy-update-user-notify` | Hidden compatibility wrapper for `omarchy-migrate-notify`. | **Temporary.** Keep only for old callers. |
| `omarchy-update-available` | Update checker for shell widget and post-update refresh. | **Keep.** Could eventually be renamed `omarchy-update-check`, but current name matches widget semantics. |
| `omarchy-update-aur-pkgs` | Updates AUR packages with `yay -Sua` if foreign packages exist and AUR is reachable. | **Question.** Omarchy is package-backed now, but users may still install AUR packages. Keep for now. |
@@ -220,7 +246,8 @@ scripts.
idempotent when they repair machine-wide state.
2. **Migration notification naming**
- The real helper is `omarchy-migrate-notify`.
- The real helper is `omarchy-migrate-notify`, started by
`omarchy-migrate-notify.service`.
- `omarchy-update-user-notify` remains only as a hidden compatibility wrapper.
3. **Update pipeline ownership**