Repository navigation
Merge quattro into upstream/convergence - #696
Open
scottjones wants to merge 73 commits into
Open
scottjones wants to merge 73 commits into
scottjones wants to merge 73 commits into
Conversation
…part aarch64 covers Apple Silicon Macs, Snapdragon laptops, Raspberry Pis and VMs, so the CPU architecture can't pick platform setup. omarchy-hw-platform prints apple-silicon, qualcomm, generic-aarch64 or generic from the vendor prefixes in the device tree's root compatible (/proc/device-tree, then /sys/firmware/devicetree/base) and the CPU, and fails when they contradict each other. Its qualcomm answer uses the same evidence as the dragon branch's omarchy-hw-qualcomm-soc, and the fixtures check the two agree. omarchy-hw-apple-silicon is the Apple predicate on top of it. An image built away from its hardware names its target in a root-owned manifest, /var/lib/omarchy/image/target (format=1, platform=). While the root is being built rather than booted, the detector answers from it and never reads the build host's device tree; a booted system always answers from its hardware. As root it restarts in an empty environment, so no variable picks the platform for privileged setup. Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com> Co-authored-by: Jimmy Van Veen <8206925+JimmayVV@users.noreply.github.com>
An architecture check is right for an ABI, a binary or a repository's $arch, not for picking a platform. The lint lists each shipped check after review and fails on a new one, so platform setup goes through omarchy-hw-platform.
omarchy-reinstall-pkgs installed the base list on every machine. A platform's default set is now the base list, then install/omarchy-aarch64.packages on aarch64, then the platform's own list when it has one (install/omarchy-qualcomm.packages adds linux-firmware-qcom). omarchy-pkg-defaults prints the set for the detected platform, or for the one named, and reinstall installs it. x86_64 still gets exactly the base list, and an image build gets its target's set.
linux-aarch64 has no thunderbolt module, and mkinitcpio fails the whole image over a MODULES entry it cannot find. The optional form, thunderbolt?, is not enough: a systemd initramfs copies MODULES as written into modules-load.d, where "thunderbolt?" names no module, and a kernel without the module would still list it there. thunderbolt_module.conf now adds plain thunderbolt only when modinfo finds it as a module for the kernel being built. Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
omarchy_hooks.conf assigned HOOKS outright, and mkinitcpio sources drop-ins in name order, so it ran after any numbered drop-in (90-*.conf) and threw its hooks away. HOOKS now comes from 00-omarchy-hooks.conf, which sorts first, and later drop-ins add to it. The NVIDIA kms filter and the vconsole handling stay in omarchy_hooks.conf. With the drop-ins Omarchy writes, machines keep the same HOOKS, MODULES and FILES; a user drop-in that sets HOOKS and sorts before omarchy_hooks.conf now takes effect instead of being overwritten. Migration 1786605598 now sources the baseline first, since without it the migration would read empty HOOKS and also rebuild hybrid systems. It skips a machine that lacks the baseline.
lsblk -s prints the ancestor tree with box-drawing prefixes ("└─/dev/nvme0n1p6"), so the crypto_LUKS parent came back as a path that does not exist and first-boot setup stopped with "Could not locate the LUKS device to re-key". -r prints raw names. Factory reset uses the same lookup.
cryptsetup open tries enrolled tokens before the key file, so a TPM2 or FIDO2 token could authorize the re-key with a wrong passphrase.
Exercise raw ancestry output without invoking provisioning or reset. Cover btrfs subvolume roots, absent encryption, failed probes, and explicit cryptdevice specifications.
A first boot killed after the staged install key's slot was retired left the key file behind, and every retry then stopped at "the staged LUKS key no longer unlocks". A lost key file with the boot-time auto-unlock still configured let setup finish with the disk unlocking unattended. The re-key now runs from install/provisioning/luks-rekey.sh and records its phase and slot numbers (never key material) in /var/lib/omarchy/provisioning/luks-rekey.state. It reuses the owner's slot instead of adding a duplicate, retires LUKS1 slots too, and destroys the staged key only after the volume proves it opens nothing. Setup refuses to finish while any part of the provisioning unlock remains. The journal ends at phase=done and leaves together with pending, so a retry after the staged key is retired must use the password the disk already holds. Key checks exclude LUKS2 tokens: cryptsetup open tries an enrolled token (say a TPM2 slot a previous owner left behind) before the key and reports its slot whatever key it was given. Slot listings read only the keyslot section, since a luks2-keyring token looks like a keyslot in luksDump.
Installation gives the login user, root and the disk holding / one password, but omarchy-drive-password changed only the LUKS key, so the three drifted apart. For the disk holding / it now checks the current password opens the disk, changes the LUKS key, confirms the new key opens the disk and the old one no longer does, and only then sets the login and root passwords. Any other encrypted drive changes its LUKS key alone. Every drive now asks for the current password with gum instead of cryptsetup's prompt. A journal in ~/.local/state/omarchy/drive-password.state (disk UUID, key slots and phase, never a password, written with the re-key journal helpers) lets the next run finish an interrupted change. The rerun accepts only the old key (removing the slot the interrupted change added) or the new one (retiring the old slot), so another key such as a recovery passphrase never becomes the login password. luksChangeKey is judged by whether the new key opens the disk, not by its exit status, and key checks exclude LUKS2 tokens, which cryptsetup open would otherwise accept in place of any password. Runs are serialised, cryptsetup calls hold a disk lock, a / whose LUKS partition cannot be resolved fails closed, and passwords are never traced. A new password equal to the current one is refused, and --pbkdf argon2id is passed only to LUKS2, so LUKS1 drives can change their password again.
Provisioning, factory reset and update call a fixed set of operations through it. A platform whose boot chain the generic Limine path can't drive registers a directory of root-owned entrypoints in the dispatcher; every other platform gets a no-op and keeps its generic path. Apple Silicon is registered to omarchy-mac-boot's /usr/lib/omarchy/mac-boot, with its required operations failing clearly when the package or an entrypoint is missing. docs/lifecycle-dispatch.md is the contract, including how a Qualcomm boot package would plug in.
… key slots Owner provisioning asks provision-prepare before the owner form, hands the staged unlock to provision-commit and provision-verify where the platform implements both, and records the kept LUKS slot through luks-slots before the staged key is destroyed; the disk password change records the owner's new slot the same way. On x86, Snapdragon and generic aarch64 every call is a no-op and first boot is unchanged.
Where a platform implements the reset operations, reset-prepare and reset-verify stage and prove the factory root's boot files, the throwaway slot is added only after that, and reset-commit gets the key on standard input once the factory root is active. A failure before the switch rolls the boot state back and revokes the slot. Elsewhere the Limine UKI path is unchanged.
omarchy-update-boot runs update-verify after AUR packages, the last sudo-capable step, so it also covers the initramfs rebuilds they trigger. It follows third-party build code, so like AUR it authenticates through the no-update wrapper. A failed verification finishes the update's remaining steps, then exits non-zero without offering the reboot. Where the platform does not implement it nothing runs and nothing asks for root.
migrations/1790347292.sh resolves the new optional migrate operation and, where the platform's boot package implements it, runs it as root. The entrypoint moves the machine onto the platform's official package set, idempotently and resumably; its failure leaves the migration pending. Once it succeeds, a root-owned marker spares other accounts the migration and its root prompt. Everywhere else, Macs without the boot package included, the migration is a no-op, and an undetermined platform keeps it pending.
A platform package names its platform with groups=('omarchy-platform-<name>'),
<name> being what omarchy-hw-platform prints. omarchy-settings ships a
pre-transaction hook, the guard it runs and a copy of the detector, so the
guard is resident before the runtime and any platform package. The guard
reads tags from the synced databases and refuses a transaction that installs
a package tagged for another platform; a transaction without a tagged
package passes without asking which machine this is. Image builds answer
from the image's root-owned target manifest, as the detector does.
The guard ships on aarch64 only: no platform package is built for x86_64,
so x86 transactions run no hook. Hardware setup starts by proving the guard
is resident and checking the packages an installer placed without it. On
generic aarch64, where no platform packages exist, a missing guard is
logged, not fatal, and on x86 it is expected.
docs/platform-guard.md is the contract.
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: Jimmy Van Veen <8206925+JimmayVV@users.noreply.github.com>
omarchy-hw-vulkan reports a Vulkan runtime, not whether this voxtype build has a Vulkan backend. The aarch64 voxtype-bin package ships only the CPU and ONNX binaries, so on any aarch64 machine with a Vulkan driver setup ran `voxtype setup gpu --enable` and printed "Vulkan backend not installed" in the middle of an otherwise working install. Require the backend binary too. x86_64 voxtype-bin always ships /usr/lib/voxtype/voxtype-vulkan, so x86 installs still switch to the GPU backend as before. Ported from #483. Co-authored-by: Oliver Lukschander <33756270+oliverlukschander@users.noreply.github.com>
The widevine package registers its CDM for Chromium and Firefox only. Brave looks for the CDM in its own install directory, finds nothing, and DRM sites (Netflix, Apple TV+, Spotify) fail with a blank player and no useful error. This hits machines where Widevine comes from that package, such as aarch64 ones, since no Widevine component is published for them. Link /opt/WidevineCdm/chromium into /opt/brave-bin and /opt/brave-origin-bin through as_root when Brave or Brave Origin is installed, and add a migration that repairs existing installs. Both do nothing when the widevine package is absent or the browser already has a CDM. A standard x86 install has no widevine package, so nothing changes there. Ported from #474, extended to Brave Origin. Co-authored-by: Caleb Marshall <68087341+cajomar@users.noreply.github.com>
With file logging, run_logged sends a failing leaf's output and its "Failed:" marker to the install log only, so the caller sees setup stop with an exit status and nothing else. A missing command (exit 127) was the case that made this hard to diagnose. Print the failed script, its exit status and the log path on stderr. Stdout logging mode already shows the failure marker and is unchanged, and successful steps stay quiet. Ported from #389 (the logging part). Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
A migration that exits 75 changed nothing and cannot finish yet: omarchy-migrate leaves it pending with its login notification, runs the migrations after it and exits 0, so omarchy update carries on. Any other failure still stops the queue. The platform migration passes a deferred refusal of its entrypoint through, and defers itself where the dispatcher can't resolve its entrypoint (the platform can't be told, or the entrypoint isn't trusted): nothing has run then, so the update goes on to its boot verification, which fails there, as documented.
00-omarchy-hooks.conf set the busybox line on every machine. On a Mac, omarchy-mac-boot's drop-ins then add the Asahi firmware hooks, but its encryption drop-in reads busybox encrypt as a Mac unlocked through cryptdevice= and leaves the line alone. The image came out as "... block encrypt asahi omarchy-vendorfw filesystems ...", with no systemd, sd-encrypt or omarchy-mac-encrypt, so an encrypted Mac could not unlock its disk. Reproduced against an M1 Pro's installed drop-ins. The baseline now asks omarchy-hw-platform. Apple Silicon starts from the systemd line its boot package builds on. A Mac whose own mkinitcpio.conf carries the asahi hook, or busybox encrypt, keeps that line, as a legacy install needs. x86, Snapdragon and generic aarch64 keep today's busybox line, as does a machine with no detector. The detector is the runtime's, or else the copy omarchy-settings ships for its platform guard, so a settings package newer than the runtime still places a Mac. A detector that cannot place the machine stops the build. The HOOKS test now composes the baseline on each platform and on legacy Mac lines. A new test composes it with omarchy-mac-boot 20260926-1.45's drop-ins, kept as fixtures, and checks the exact HOOKS the M1 Pro builds. The NVIDIA test pins its platform.
Not every optional install exists on every architecture: some vendors ship no aarch64 build, and some repositories don't carry a package at all. Each Install row now carries a `when:` guard naming every package its install command adds, checked with omarchy-pkg-available, so a row with nothing to install disappears instead of failing halfway through a pacman transaction. The rows that build from the AUR (Chrome, Edge, Brave, Brave Origin, Zen, NordVPN) are guarded on the CPU architectures their vendors publish for. omarchy-pkg-available asks the sync databases: one `pacman -Slq` per batch, and `pacman -Sp` for a name that list doesn't hold, so a provided name (libappindicator-gtk3) and a version constraint resolve the way `pacman -S` will. The menu's guard prelude sources the same function, so the whole batch still costs one fork. omarchy-reinstall-pkgs reports and skips a default that no configured repository offers instead of failing the transaction. On x86_64 every guarded row resolves against the stable and edge repositories, so the menu is unchanged there. Tests derive each row's packages from its install command on x86_64 and aarch64 and fail when the guard names different ones. Co-authored-by: Ryan Hughes <1630358+ryanrhughes@users.noreply.github.com>
Electron draws a blank window when the machine has no DRM render node: a VM, a headless or passthrough GPU, or a GPU whose driver isn't up yet (Apple M3 and later on Linux today). omarchy-hw-render-gpu tells whether a renderD node exists, and omarchy-cmd-electron-gl-args prints --ozone-platform=wayland --disable-gpu only when it doesn't. omarchy-cmd-electron-gl-wrap installs a marked PATH wrapper in /usr/local/bin that execs the real binary with those flags, so it follows the machine rather than the moment it was installed. It refuses to replace a launcher it didn't write, or to wrap a binary over itself, and stages the write so a failure leaves the old launcher in place. omarchy-cmd-desktop-exec-repair points the user's desktop entry at the wrapper by replacing only the executable token, keeping arguments, other actions and customizations, with a backup. The 1Password installer uses them when the machine has no render node. With one, which is every x86 machine with a working GPU, nothing changes. Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
gpu-screen-recorder knows NVIDIA, AMD, Intel and Broadcom GPUs and aborts during GL init on anything else, such as Apple Silicon's, before a recording starts. Screen recording now falls back to wf-recorder, when it is installed, if gpu-screen-recorder is missing or exits before the file appears. The picker, file naming, notifications and post-processing are shared. wf-recorder records one audio device, so desktop plus microphone go through a temporary null sink that stop unloads, and its track is pinned to 48 kHz. Portal capture and --resolution stay gpu-screen-recorder only. The finalize pass keeps 48 kHz too: loudnorm declares 192 kHz output, so without -ar the AAC encoder wrote 96 kHz from a 48 kHz recording, which many editors decode as silence, and which on Apple Silicon makes the speaker safety daemon lock the amps. omacom#11092 makes the same one-line change; whichever lands second drops it. Stop and status matched `pgrep -f ^gpu-screen-recorder`, which misses wf-recorder and matches any command line that starts with that path. The script now records the recorder's pid, and the new omarchy-capture-screenrecording-process checks or signals it by its executable, through a pidfd opened before the check so a reused pid can't be signalled. When that pid is no longer a recorder (a recording started before this change, or one that died), every recorder the user runs counts, as it does for the bar indicator and the Stop row, which use the same helper. Where gpu-screen-recorder works, which is every x86 GPU it supports today, it records as before. Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com> Co-authored-by: Issac Trotts <15530+ijt@users.noreply.github.com>
systemd-logind treats a closed lid as docked only when an external display is on a connector type it lists (HDMI, DisplayPort, DVI, VGA...). Displays on "USB" connectors, which Apple Silicon uses for USB-C displays, aren't on that list, and a missing comma fuses DVI-A and Composite into one entry. With such a display in use, closing the lid suspended a laptop that was still being used on it. omarchy-system-lid-inhibit holds a handle-lid-switch inhibitor while one of those connectors is connected and enabled in Hyprland, on a laptop where HandleLidSwitchDocked is ignore, which is exactly the case logind would have ignored had it counted the display. It releases the inhibitor when the display goes. A compositor or logind that doesn't answer changes nothing, since releasing then would suspend a closed lid. The inhibitor runs as a transient user unit bound to the monitor watcher's unit, so a watcher that dies can't leave the lid inhibited until logout. The monitor watcher runs it alongside the clamshell sync. On a machine whose external displays are all on connectors logind counts, it does nothing.
When a monitor is unplugged, or the lid turns off the laptop panel, Hyprland first warps focus to whichever monitor it lists first and only then moves the removed monitor's workspaces over. The workspace you were on lands hidden behind that monitor's own (Hyprland 0.56.2, CMonitor::onDisconnect). monitor.focused fires before Hyprland records the new focus, so the monitor still reported as active is the one being left: its workspace is remembered until the event loop next turns, and a monitor.removed in that window focuses it again once the removal has finished. An open special workspace already comes along, and any focus or workspace change made before the restore runs wins.
Laptops with an ambient light sensor and a keyboard backlight LED now light the keys in the dark and dim them as the room brightens, inverse to display auto-brightness. omarchy-brightness-keyboard-auto polls the sensor every five seconds (preferring an IIO device that names itself ALS, and converting a raw channel with its offset and scale) and maps lux onto the LED, with a deadband so it doesn't chase noise. It pauses while the screen is locked or the lid is closed. A level set with the keyboard-brightness keys wins until the light changes enough that it no longer fits. omarchy-brightness-keyboard records each level it sets in the session's runtime directory (a private state directory without one), so the loop can tell keys turned off on purpose from keys left off by the lock screen or a restored zero, which it lights again. The user unit runs it in the graphical session. Its ExecCondition asks --available, so it is a no-op on machines without both a sensor and a keyboard LED. First run enables it, and a migration enables it for existing installs, writing the enable symlink itself when there is no live user manager. Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com> Co-authored-by: Gabe Ohlson <3355909+6abe@users.noreply.github.com>
An image is built away from the machine it will run on, so its hardware leaves would probe the builder. While the image manifest the detector already reads (/var/lib/omarchy/image/target) exists, omarchy-apply-hardware queues every leaf of install/hardware/all.sh instead of running it and arms omarchy-provision-hardware.service. On the first boot, before owner setup and the login screen, omarchy-provision-hardware retires the manifest and runs the queue on the real hardware: a failed step stays queued for the next boot (exit 75), and the initramfs is rebuilt once after the last step when a step changed its inputs or asked for it. Bluetooth starts its service on that boot, whose target is already up. Root ignores any environment override of these paths. Without a manifest, as on every ISO install, hardware setup runs exactly as before. Nothing here fetches package databases: an image carries its sync databases and every package its steps install.
A root built from a distribution tarball instead of the ISO (Arch Linux ARM's ships LANG=C) never went through the ISO's locale step, so it ran non-UTF-8. The config phase now selects en_US.UTF-8, generating it if needed, but only when LANG is unset, C or POSIX: any named locale is somebody's choice and stays. The ISO writes the locale before this runs, so an ISO install is unchanged. Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
Quickshell types only exact media classes, so a virtual source (an Audio/Source/Virtual: EasyEffects' source, or the microphone mapping a platform package adds) has no PwNode.audio. With one as the default input the audio panel showed the input at 0% and its slider changed nothing, the peak meter stayed flat, the microphone widget read it as muted, and the panel could not list it unless it was already the default. Such an input now goes through wpctl for its volume and mute (UntypedInput in shell/Commons, one reader and one pactl subscribe for the whole shell), the panel meters it with the new omarchy-audio-source-level, and the input list takes an untyped node PulseAudio lists as a source. A platform whose audio runs through its own processing can also name nodes that are neither devices nor apps in /usr/share/omarchy-platform/audio.json, which Omarchy ships none of: the panel and the microphone widget leave them out, and a "replaced" node only while its replacement exists. Without the file nothing is hidden. On every machine: the input list leaves out a source whose ports are all unavailable (an empty headset jack) unless it is the default, as the output list does for sinks; choosing an input no longer moves a filter's own capture (a source output with node.link-group), which would feed the filter from the new input or from itself; the shell's own level meters no longer light the microphone widget; and omarchy-audio-sink-availability reads pactl in the C locale for sinks too, since "not available" is translated.
systemd-firstboot writes an XKB layout only for keymaps listed in kbd-model-map. Nine the setup form offers are not (Colemak, Azerbaijani, Bulgarian, Czech, Swiss German, Kyrgyz, Norwegian, Polish, Ukrainian), so it wrote KEYMAP= alone, the readback refused it, and owner setup could never get past the keyboard step for them. Setup now adds the XKB settings itself when firstboot left none, matching the console map so the shared password types the same on the desktop: kbd's cz is QWERTY, bg-cp1251 phonetic and azerty French AZERTY, and non-Latin layouts keep a US layout to switch to, as kbd-model-map's own rows do. A test checks every layout the form offers ends with an XKB layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
The ambient keyboard backlight treated any 0 the keyboard-brightness keys had not recorded as an accident and relit it within five seconds. Firmware Fn keys (Fn+Space on ThinkPads and Framework laptops, Fn+F10 on Dells) write the LED directly, so on those laptops turning the keys off never stuck. The lock screen's off now records a blank, and only that blank or a 1% leftover is taken back; any other off is a choice that pauses auto like the keys do. A wake clears the blank only once the restore succeeded, the command runs one at a time so a blank racing a wake can't leave the LED and record disagreeing, and the loop drops a blank once it has taken the keys back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
Each menu open checked every Install row against the sync databases, which costs most of a second of pacman work on every machine to hide rows only an ARM machine is missing. The fix for those is publishing the ARM packages, not hiding the rows, so this removes omarchy-pkg-available, the Install rows' availability and architecture guards, and reinstall's skipping of defaults no repository offers. The Windows VM row keeps its x86_64 guard, since no package fixes a guest that needs an x86_64 host, and reinstall keeps its aarch64 channel handling. This reverts commit aea001c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
Factory reset moved the running root aside, marked the reset committed, then renamed the staged factory root to @. If that second rename failed, cleanup saw a committed reset: it skipped the boot package's rollback and kept the throwaway LUKS slot, and since the swap had not happened it deleted the staged root as well, leaving nothing at @. The reset now commits only once the factory root is at @. A failed activation renames the old root back first, then cleanup rolls the platform's boot state back and revokes the throwaway slot. If that rename fails too, both roots are kept, cleanup still rolls back and revokes, and the error names the rename that recovers the machine. The generic Limine path has already rebuilt its boot files from the factory root by then, as it had before this change.
A saved pid that no longer named a recorder made status and stop select every gpu-screen-recorder and wf-recorder the user ran, so stopping could interrupt, and after five seconds kill, a recording started somewhere else. A stale pid now means no recording of ours is running: the toggle starts a new one, and --stop-recording finds nothing to stop. Stop acts on the recorder the status check selected rather than selecting again. Without a saved pid, as for a recording started before the pid was saved, every recorder the user runs still counts.
With desktop and microphone audio both requested, wf-recorder records a null sink fed by two loopbacks, and a loopback that failed to load was ignored: the recording went ahead without that source, or silent when both failed. A missing null sink or default device dropped audio just as quietly. A source that cannot be captured is now left out with a notification naming it, the loopbacks that did load are unloaded, and the recording carries the source that remains, or no audio track at all.
These vendors currently publish Linux builds for x86_64 alone (the AUR's
microsoft-edge-stable-bin and spotify are arch=('x86_64'), and Dropbox lists
no Linux ARM client), so no native aarch64 build is available and choosing
one on an ARM machine only fails. Like the Windows VM row they keep a uname
check, which the menu answers once per open without asking pacman. The other
Install rows are unchanged.
The generic Limine path added its throwaway LUKS slot without recording it, so a reset that failed before activation never revoked it. Once the factory root's UKI was on the ESP, a failed activation that put the old root back left a machine that booted the factory kernel and unlocked unattended with a key readable on the ESP, while the screen said the current root was back. The generic slot is now recorded like the platform's and revoked by cleanup whenever the reset fails before the factory root is active. A failed activation on that path says the boot files were already rebuilt from the factory system and to run limine-update before rebooting.
The recorder's pid is saved only once its file exists. Until then a pid left by a recording that ended without a stop still counted as stale, so pressing the toggle again while the new recorder started found nothing of ours and could start a second recording. Starting a recording now clears that pid, and during startup the toggle falls back to the user's recorders as before.
The notice said the dropped source "could not be captured", which was wrong when the null sink itself failed to load: the microphone was never tried, and desktop audio recorded alone as it always has. It now says the source could not be added to the recording, true for a missing device, a failed loopback and a failed null sink alike.
Heroic publishes Linux builds for x86_64 alone (its arm64 builds are for macOS and Windows), and Mojang's Linux launcher is a single x86_64 tarball. They join Edge, Spotify and Dropbox under the same uname check, so every row whose vendor ships no native Linux aarch64 build is treated alike.
The bar indicator and the menu's Stop Screenrecording row asked the process helper whether any recorder the user runs was alive, while the toggle's stop acts only on the recording it saved. With a stale saved pid alongside an unrelated recorder, both offered a stop that did nothing. omarchy-capture-screenrecording --status answers with the selection the stop uses, and both now ask it. Status needs no recordings directory and never notifies, so the recordings-directory check moved below argument parsing and skips it.
On aarch64 a channel change edited the machine's pacman.conf in place: an awk pass found the [omarchy] server and rewrote its channel, appended a section where there was none, checked the channel's omarchy.db first, and gated it all on a per-platform table of qualified channels. Install finalization appended Omarchy to a template, or on a Mac copied one bundled inside omarchy-mac. What a machine ended up with was never in the repository. Each platform now has a pacman.conf and mirrorlist per channel, copied whole: x86_64's stay in default/pacman, Snapdragon and other aarch64 machines use default/pacman/aarch64, and Apple Silicon default/pacman/apple-silicon, with Omarchy and Asahi ALARM ahead of Arch Linux ARM. Omarchy publishes aarch64 packages on edge alone so far, so every ARM channel points at edge for now and channel changes work there; moving a channel is a template edit. A channel without both files is refused before anything changes, including a dev checkout's own templates. Reinstall goes back to resetting to stable, and the update confirmation loses the missing-repository notice it no longer needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
…does" This reverts commit 9a07e13.
On aarch64 a channel change edited the machine's pacman.conf in place: an awk pass found the [omarchy] server and rewrote its channel, appended a section where there was none, checked the channel's omarchy.db first, and gated it all on a per-platform table of qualified channels. Install finalization appended Omarchy to a template, or on a Mac copied one bundled inside omarchy-mac. What a machine ended up with was never in the repository. Each platform now has a pacman.conf and mirrorlist per channel, copied whole: x86_64's stay in default/pacman, Snapdragon and other aarch64 machines use default/pacman/aarch64, and Apple Silicon default/pacman/apple-silicon, with Omarchy and Asahi ALARM ahead of Arch Linux ARM. Omarchy publishes aarch64 packages on edge alone so far, so every ARM channel points at edge for now and channel changes work there; moving a channel is a template edit. A channel without both files is refused before anything changes, including a dev checkout's own templates. Reinstall goes back to resetting to stable, and the update confirmation loses the missing-repository notice it no longer needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
Fresh installs mark every migration done, and every Apple Silicon machine is a fresh install, so the Mac handoff to omarchy-mac-boot (and the migrate operation it called), zram for aarch64 installs that predate the package list, the Brave Widevine link and the Broadcom migration's Apple Silicon guard never run anywhere. The exit-75 deferral in omarchy-migrate existed only for two of them. Keyboard backlight auto stays on new installs through first run rather than switching on for existing ones, and migration 1786605598 goes back to quattro: the mkinitcpio drop-ins arrive by package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pacman platform guard (and the detector copy omarchy-settings shipped for it, which the HOOKS baseline fell back to), the lint against uname gates, first run staying pending after a failed finalization, run_logged echoing failures to stderr, half-up battery rounding, hiding empty-jack inputs and leaving a filter's capture alone when choosing an input all rode along with the Mac work without serving it. Each goes back to quattro's behaviour and can come back on its own merits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A platform package could load its own Hyprland binds, settings and gestures: binds that replaced Omarchy's chords and decorated every later bind, settings ahead of the theme, and gestures after the user's files, which needed every hl.gesture call wrapped so a default could step aside. On a Mac those carried macOS habits (a three-finger workspace swipe, tap-to-click off, menus opening on the built-in screen, other screenshot and keyboard-backlight chords), not anything the hardware needs, and Omarchy should behave the same on every machine. The one bind a Mac does need, its lid switch under the SMC's name, joins Omarchy's own lid binds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts them Every aarch64 channel's template pointed at the edge repository, but a switch to stable or rc installs the release-named omarchy and omarchy-settings. On edge/aarch64 those are the 4.0.4 release line, which has no omarchy-hw-platform, lifecycle dispatch or omarchy-pkg-defaults, so `omarchy-channel-set stable` on a Mac replaced the quattro runtime it runs with one that cannot run it, and succeeded. aarch64 platforms now have edge templates alone, so a switch to stable or rc is refused before anything changes; adding those templates once a release supports aarch64 opens them. Refresh with no channel named, as reinstall runs it, and install finalization for a channel the platform has no templates for take the platform's default channel: stable on x86_64, edge on aarch64.
d0b94d9 returned omarchy-audio-input-set-default to moving every source output, as not serving Mac support. It does: asahi-audio's microphone DSP on Apple Silicon records the raw array through a filter-chain capture stream (audio_effect.jNNN-mic, node.link-group "filter-chain-..."). On an M1 Pro, choosing the Mac's microphone in the audio panel moved that stream onto the DSP's own output, and the microphone recorded digital silence (-91 dB, from -55 dB of room noise) until PipeWire restarted. With the skip it keeps recording (-54 dB). This restores the skip of source outputs carrying node.link-group, and its test, as they were before that commit.
The aarch64 edge templates, the template helper and the update-process docs still said every platform has a template per channel and every ARM channel installs from edge, which the previous commit made untrue.
omarchy-mac and omarchy-mac-boot now live in omacom/omarchy-mac-pkgs, with each package at the top level. The dispatcher, its documentation and the Apple Silicon package list name that repository, and the drop-in test's fixtures, byte for byte the same as omarchy-mac-boot/files/etc/mkinitcpio.conf.d at 4399105, cite it there.
The migrate operation went with the Mac migrations, and no caller hands a machine to a platform migration any more, so the header lists only the flows that still dispatch. The optional-operations comment is rewrapped.
A fresh install marks every migration done only for the user it creates, so an account added later runs them all on its first update. On an Apple Silicon Mac this one matches: an M1 Pro reports sys_vendor "Apple Inc." and a BCM4387 (14e4:4433), so it would append feature_disable=0x82000, which stops that chip scanning once brcmfmac reloads. Restore the guard and its test case.
Two conflicts, both from fixes made on each side: - omarchy-install-gaming-steam: quattro installs the lib32 drivers before Steam so pacman does not resolve lib32-vulkan-driver to the NVIDIA stack; this branch runs Steam's post-install hook after the package. Both kept: drivers, Steam, hook. platform-app-hooks-test expects that order. - omarchy-install-gaming-gpu-lib32: both turned the "&&" that failed with no GPU into an if; this branch's version, which also says it skipped, kept. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
maralcbr
force-pushed
the
upstream/convergence
branch
from
October 6, 2026 03:16
606e33d to
2827c5e
Compare
Collaborator
|
Thanks @scottjones, closing this one as superseded rather than merging it.
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings
quattro(65c0f33, 114 commits since this branch left it at 3faafba) intoupstream/convergence, which GitHub shows as conflicting. Two conflicts, both where each side fixed the same scripts:omarchy-install-gaming-gpu-lib32: both sides turned the&&that failed with no GPU into anif; this branch's version, which also says it skipped, kept.platform-app-hooks-test.sh: its Steam cases now expect drivers, Steam, hook.Evidence
Full shell suite on an M2 Max: 8 failing files on 606e33d, 5 after the merge.
kernel-headers-migration,network-captive-portal,omarchy-kernel-migrationandvideo-backgroundpass (quattro had fixed them). Of the rest,runtime-smokeis #695;elsewhen-migration,passwordless-grant-lifecycleandlaunch-browserfail on quattro itself;desktop-entry-launchfailed once in the full run but passes alone here, on 606e33d and on quattro.Merge Danger
Door: two-way
Blast Radius: whole branch
It's a merge of 114 upstream commits into the convergence branch, so everything quattro changed since Sep 27 lands with it. #694 and #695 don't depend on it.
🤖 Generated with Claude Code