From d783f46f5d41c61f17f8c79c2415490e96321da7 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 14 Sep 2026 21:55:22 -0400 Subject: [PATCH 001/121] Build Grok Bot 0.47.0 for aarch64 and fix packaged desktop integration --- pkgbuilds/grok-bot/PKGBUILD | 56 ++++++++++++++++------------- pkgbuilds/grok-bot/grok-bot.desktop | 2 +- pkgbuilds/grok-bot/grok-bot.install | 41 +++++++++++++++++++++ 3 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 pkgbuilds/grok-bot/grok-bot.install diff --git a/pkgbuilds/grok-bot/PKGBUILD b/pkgbuilds/grok-bot/PKGBUILD index 1109333..bcc5797 100644 --- a/pkgbuilds/grok-bot/PKGBUILD +++ b/pkgbuilds/grok-bot/PKGBUILD @@ -2,14 +2,15 @@ # Contributor: Omarchy pkgname=grok-bot -pkgver=0.29.0 +pkgver=0.47.0 pkgrel=1 -_commit=f0e5bfcee649ea84c0c61369cf896cd146d72136 +_commit=c1e7d7a46549956d25f53e9c0b9f59666e03aa3a pkgdesc='Grok Bot desktop agent' -arch=('x86_64') +arch=('x86_64' 'aarch64') url='https://x.ai/bot' license=('custom') depends=( + 'alsa-lib' 'at-spi2-core' 'gtk3' 'hicolor-icon-theme' @@ -25,32 +26,36 @@ optdepends=('libappindicator-gtk3: tray support') provides=('sand') conflicts=('sand') options=('!strip' '!debug') +install=grok-bot.install + +_deb_x86_64="grok-bot_${pkgver}_amd64.deb" +_deb_aarch64="grok-bot_${pkgver}_arm64.deb" source=( - "${pkgname}_${pkgver}.deb::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/x64/Grok_Bot_${pkgver}.deb" 'grok-bot.sh' 'grok-bot.desktop' ) -sha256sums=('d223b5830282aef11d5c46d8f4d1edd239bf992e336405cbd288d4476b9233d4' - '6dfa6c305941afa6cbaefbeaae06d05ab5a88f31630005d25a819a160c20c7a3' - '856056c9ca63dda5d01158ce8fb6a9a7cbb3f67c13a92b573cd196d3e50f26e7') -noextract=("${pkgname}_${pkgver}.deb") +source_x86_64=( + "${_deb_x86_64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/x64/${_deb_x86_64}" +) +source_aarch64=( + "${_deb_aarch64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/arm64/${_deb_aarch64}" +) +sha256sums=('6dfa6c305941afa6cbaefbeaae06d05ab5a88f31630005d25a819a160c20c7a3' + '3e2a2461ea58d17ac1777616be9ba660f7cb9ceefa9292016e36c55758bf78dd') +sha256sums_x86_64=('11ca0f51a535b97af51a352adf9c0f9ecd2e1b0430a69ae9451b688a7a065808') +sha256sums_aarch64=('836f8d19d3826c6573c31ac45c7a9b797abc73381ae0d2b1e7a8dae5410e7e46') +noextract=("${_deb_x86_64}" "${_deb_aarch64}") package() { - bsdtar -xOf "${srcdir}/${pkgname}_${pkgver}.deb" data.tar.xz | + local deb_var="_deb_${CARCH}" + local deb="${!deb_var}" + + bsdtar -xOf "${srcdir}/${deb}" data.tar.xz | bsdtar -x -C "${pkgdir}" -f - rm -rf "${pkgdir}/usr/share/doc" \ - "${pkgdir}/usr/share/applications/sand.desktop" - - local icon1024="${pkgdir}/usr/share/icons/hicolor/1024x1024/apps" - if [[ -f "${icon1024}/sand.png" && ! -f "${icon1024}/grok-bot.png" ]]; then - install -Dm644 "${icon1024}/sand.png" "${icon1024}/grok-bot.png" - fi - rm -f "${icon1024}/sand.png" - if [[ -f "${icon1024}/grok-bot.png" ]]; then - install -Dm644 "${icon1024}/grok-bot.png" \ - "${pkgdir}/usr/share/icons/hicolor/512x512/apps/grok-bot.png" - fi + "${pkgdir}/usr/share/applications/sand.desktop" \ + "${pkgdir}/usr/share/applications/grok-bot.desktop" # Always install our Wayland wrapper; do not keep any /usr/bin from the .deb. rm -f "${pkgdir}/usr/bin/grok-bot" "${pkgdir}/usr/bin/sand" @@ -64,9 +69,10 @@ package() { install -Dm644 "${pkgdir}/opt/Grok Bot/LICENSES.chromium.html" \ "${pkgdir}/usr/share/licenses/${pkgname}/LICENSES.chromium.html" - if ! { [[ -L /proc/self/ns/user ]] && unshare --user true; }; then - chmod 4755 "${pkgdir}/opt/Grok Bot/chrome-sandbox" - else - chmod 0755 "${pkgdir}/opt/Grok Bot/chrome-sandbox" - fi + # Ship chrome-sandbox without setuid. Upstream's build-time userns probe + # would measure the CI container, not the user's machine, and a setuid + # helper could not exec from "/opt/Grok Bot/" anyway (electron#44414). + # grok-bot.install tells users on kernels without unprivileged user + # namespaces how to run without the sandbox. + chmod 0755 "${pkgdir}/opt/Grok Bot/chrome-sandbox" } diff --git a/pkgbuilds/grok-bot/grok-bot.desktop b/pkgbuilds/grok-bot/grok-bot.desktop index 992c36c..ddda47a 100644 --- a/pkgbuilds/grok-bot/grok-bot.desktop +++ b/pkgbuilds/grok-bot/grok-bot.desktop @@ -8,6 +8,6 @@ Terminal=false Type=Application Categories=Development; MimeType=x-scheme-handler/grokbot;x-scheme-handler/sand; -StartupWMClass=Grok Bot +StartupWMClass=grok-bot StartupNotify=true Keywords=Grok;AI;Agent; diff --git a/pkgbuilds/grok-bot/grok-bot.install b/pkgbuilds/grok-bot/grok-bot.install new file mode 100644 index 0000000..11a7683 --- /dev/null +++ b/pkgbuilds/grok-bot/grok-bot.install @@ -0,0 +1,41 @@ +# Electron's renderer sandbox needs unprivileged user namespaces, or else a +# setuid-root chrome-sandbox. Upstream omarchy-pkgs probes for user namespaces +# inside package() and sets 4755 when they are missing. That is wrong twice +# for this repo: the build runs in a CI container where the probe fails, so +# every user would get the setuid helper; and the helper lives under +# "/opt/Grok Bot/", and Electron cannot exec a setuid chrome-sandbox from a +# path with a space (electron/electron#44414), so 4755 would not even work. +# +# The package therefore always ships chrome-sandbox as 0755. This hook only +# tells the user what to do on a host that lacks unprivileged user namespaces. +# The probe drops to nobody first: pacman runs hooks as root, and root can +# unshare a user namespace even where unprivileged users cannot. +_userns_available() { + [[ -L /proc/self/ns/user ]] || return 1 + if (( EUID == 0 )) && command -v setpriv >/dev/null; then + setpriv --reuid=65534 --regid=65534 --clear-groups -- unshare --user true 2>/dev/null + else + # Already unprivileged (or no setpriv): the direct probe is the real answer. + unshare --user true 2>/dev/null + fi +} + +_advise() { + _userns_available && return 0 + cat <<'MSG' +==> Unprivileged user namespaces are unavailable on this kernel, so Grok Bot's + renderer sandbox cannot start. A setuid chrome-sandbox is not an option + here: Electron cannot exec it from "/opt/Grok Bot/" (electron#44414). + To run without the sandbox, add this line to ~/.config/grok-bot-flags.conf: + + --no-sandbox +MSG +} + +post_install() { + _advise +} + +post_upgrade() { + _advise +} From 60cb8ea9f9cccc592400117c4fceb9d218b3d575 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 14 Sep 2026 21:57:39 -0400 Subject: [PATCH 002/121] Add an aarch64 OBS Studio build without the CEF browser plugin --- pkgbuilds/obs-studio/.omarchy/package.json | 9 ++ pkgbuilds/obs-studio/PKGBUILD | 107 +++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 pkgbuilds/obs-studio/.omarchy/package.json create mode 100644 pkgbuilds/obs-studio/PKGBUILD diff --git a/pkgbuilds/obs-studio/.omarchy/package.json b/pkgbuilds/obs-studio/.omarchy/package.json new file mode 100644 index 0000000..2a67d7e --- /dev/null +++ b/pkgbuilds/obs-studio/.omarchy/package.json @@ -0,0 +1,9 @@ +{ + "source": "local", + "upstream": { + "watch": { + "github": "obsproject/obs-studio", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + } +} diff --git a/pkgbuilds/obs-studio/PKGBUILD b/pkgbuilds/obs-studio/PKGBUILD new file mode 100644 index 0000000..f3f1693 --- /dev/null +++ b/pkgbuilds/obs-studio/PKGBUILD @@ -0,0 +1,107 @@ +# ARM build from the upstream release source bundle. The vendor CEF bundle +# is x86-only, so this build omits browser sources/docks. AJA is unavailable +# in Arch Linux ARM. Other plugins use upstream architecture detection. + +pkgname=obs-studio +pkgver=32.2.2 +pkgrel=1 +pkgdesc="Free and open source software for video recording and live streaming (without the x86-only CEF browser source)" +arch=('aarch64') +url="https://obsproject.com" +license=('GPL-2.0-or-later') +depends=( + 'alsa-lib' + 'curl' + 'ffmpeg>=8' + 'fontconfig' + 'freetype2' + 'gcc-libs' + 'glib2' + 'glibc' + 'jack' + 'jansson' + 'libdatachannel>=0.24.3' # WebRTC/WHIP output + 'libfdk-aac' + 'libgl' + 'libjuice' + 'libpipewire' + 'libpulse' + 'librist' # MPEGTS output + 'libva' + 'libx11' + 'libxcb' + 'libxcomposite' + 'libxkbcommon' + 'luajit' # Lua scripting + 'mbedtls3>=3.6.1' + 'pciutils' + 'python>=3.14' # Python scripting + 'qrcodegencpp-cmake' # obs-websocket connect QR code + 'qt6-base>=6.8' + 'qt6-svg' + 'qt6-wayland' + 'rnnoise' + 'sndio' + 'speexdsp' + 'srt' # MPEGTS output + 'systemd-libs' + 'util-linux-libs' + 'v4l-utils' + 'wayland' + 'x264' + 'zlib' +) +makedepends=( + 'asio' # header-only, obs-websocket + 'cmake' + 'extra-cmake-modules' + 'nlohmann-json' # header-only, obs-websocket and plugin manager + 'simde' # header-only, SIMD portability layer libobs uses on ARM + 'swig' # scripting bindings + 'uthash' # header-only, libobs + 'vlc' # VLC source plugin builds against libvlc headers, dlopens at runtime + 'websocketpp' # header-only, obs-websocket +) +optdepends=( + 'vlc: VLC media source' + 'v4l2loopback-dkms: V4L2 virtual camera output' +) +source=("https://github.com/obsproject/obs-studio/releases/download/$pkgver/OBS-Studio-$pkgver-Sources.tar.gz") +sha512sums=('6346b5bff255c9178ef57296489af11bc6949076b4084d3dff8d3da923c8b0d2ab64edb312629c54b8d4be1510bb4166b92838a8c6c2db55a7ee9e08108166de') + +build() { + local cmake_options=( + -S "obs-studio-$pkgver-sources" + -B build + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX=/usr + -DCMAKE_INSTALL_LIBDIR=lib + -DENABLE_BROWSER=OFF # no linux-aarch64 CEF exists + -DENABLE_AJA=OFF # libajantv2 is not in ALARM + -DENABLE_LIBFDK=ON + -DENABLE_JACK=ON + -DENABLE_SNDIO=ON + -DENABLE_VLC=ON + -DENABLE_WAYLAND=ON + + # The tarball has no .git for the version machinery to read. + -DOBS_VERSION_OVERRIDE="$pkgver" + -DOBS_COMPILE_DEPRECATION_AS_WARNING=ON + + # Arch ships mbedtls 3 side-by-side under /usr/lib/mbedtls3, and OBS's + # finder needs to be pointed at it (same paths the AUR pkgbases use). + -DMbedTLS_DIR=/usr/lib/mbedtls3/cmake/MbedTLS + -DMbedTLS_INCLUDE_DIR=/usr/include/mbedtls3 + -DMbedtls_LIBRARY=/usr/lib/mbedtls3/libmbedtls.so + -DMbedcrypto_LIBRARY=/usr/lib/mbedtls3/libmbedcrypto.so + -DMbedx509_LIBRARY=/usr/lib/mbedtls3/libmbedx509.so + + -Wno-dev + ) + cmake "${cmake_options[@]}" + cmake --build build +} + +package() { + DESTDIR="$pkgdir" cmake --install build +} From 97d2e864e3d485cd53f99695e6f75c668206656c Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 14 Sep 2026 21:57:39 -0400 Subject: [PATCH 003/121] Build stable Ghostty and its split packages for aarch64 --- pkgbuilds/ghostty/.omarchy/package.json | 9 ++ pkgbuilds/ghostty/PKGBUILD | 114 ++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 pkgbuilds/ghostty/.omarchy/package.json create mode 100644 pkgbuilds/ghostty/PKGBUILD diff --git a/pkgbuilds/ghostty/.omarchy/package.json b/pkgbuilds/ghostty/.omarchy/package.json new file mode 100644 index 0000000..088e385 --- /dev/null +++ b/pkgbuilds/ghostty/.omarchy/package.json @@ -0,0 +1,9 @@ +{ + "source": "local", + "upstream": { + "watch": { + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)", + "git_tags": "https://github.com/ghostty-org/ghostty.git" + } + } +} diff --git a/pkgbuilds/ghostty/PKGBUILD b/pkgbuilds/ghostty/PKGBUILD new file mode 100644 index 0000000..23166e5 --- /dev/null +++ b/pkgbuilds/ghostty/PKGBUILD @@ -0,0 +1,114 @@ +# Ghostty for aarch64, built from the upstream release source tarball. +# +# Ghostty 1.3.x requires Zig 0.15.2 exactly. Arch Linux ARM currently ships +# newer Zig releases, so use the verified upstream aarch64 toolchain only at +# package-build time rather than publishing a second Zig package. + +pkgbase=ghostty +pkgname=(ghostty ghostty-shell-integration ghostty-terminfo ghostty-nautilus) +pkgver=1.3.1 +pkgrel=1 +pkgdesc='Fast, native, feature-rich terminal emulator pushing modern features' +arch=(aarch64) +url='https://github.com/ghostty-org/ghostty' +license=(MIT) +depends=( + bzip2 + fontconfig + freetype2 + glib2 + glibc + gtk4 + gtk4-layer-shell + harfbuzz + libadwaita + libpng + oniguruma + pixman + wayland + zlib +) +makedepends=( + blueprint-compiler + curl + gettext + pkgconf +) +_zigver=0.15.2 +_archive="$pkgbase-$pkgver" +source=( + "https://release.files.ghostty.org/$pkgver/$_archive.tar.gz" + "https://ziglang.org/download/$_zigver/zig-aarch64-linux-$_zigver.tar.xz" +) +sha256sums=( + '3349d25600ffbda281197a18314f7d18791969cffe9474f0ff16a45a9ebfccdb' + '958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f' +) + +prepare() { + cd "$_archive" + PATH="$srcdir/zig-aarch64-linux-$_zigver:$PATH" \ + ZIG_GLOBAL_CACHE_DIR="$srcdir/zig-global-cache" \ + ./nix/build-support/fetch-zig-cache.sh +} + +build() { + cd "$_archive" + # A '-' suffix is a SemVer prerelease and selects Ghostty's tip channel. + # Keep the package revision as build metadata on the stable release. + PATH="$srcdir/zig-aarch64-linux-$_zigver:$PATH" \ + DESTDIR=build \ + zig build \ + --prefix /usr \ + --system "$srcdir/zig-global-cache/p" \ + -Doptimize=ReleaseFast \ + -Dgtk-x11=true \ + -Dcpu=baseline \ + -Dpie=true \ + -Demit-docs=false \ + -Dversion-string="$pkgver+omarchy.$pkgrel" \ + --build-id=sha1 +} + +package_ghostty() { + depends+=(ghostty-shell-integration ghostty-terminfo) + optdepends=('ghostty-nautilus: Open in Ghostty context menu in GNOME Files') + + cd "$_archive" + cp -a build/* "$pkgdir/" + install -Dm0644 LICENSE "$pkgdir/usr/share/licenses/ghostty/LICENSE" + rm -r "$pkgdir/usr/share/terminfo" \ + "$pkgdir/usr/share/ghostty/shell-integration" \ + "$pkgdir/usr/share/nautilus-python" +} + +package_ghostty-shell-integration() { + pkgdesc='Shell integration scripts for Ghostty' + depends=() + + cd "$_archive" + install -d "$pkgdir/usr/share/ghostty/shell-integration" + cp -a build/usr/share/ghostty/shell-integration/. \ + "$pkgdir/usr/share/ghostty/shell-integration/" + install -Dm0644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} + +package_ghostty-terminfo() { + pkgdesc='Terminfo for Ghostty' + depends=() + + cd "$_archive" + install -d "$pkgdir/usr/share/terminfo" + cp -a build/usr/share/terminfo/x "$pkgdir/usr/share/terminfo/" + install -Dm0644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} + +package_ghostty-nautilus() { + pkgdesc='Open in Ghostty for GNOME Files' + depends=(ghostty nautilus-python) + license=(GPL-2.0-or-later) + + cd "$_archive" + install -d "$pkgdir/usr/share/nautilus-python" + cp -a build/usr/share/nautilus-python/. "$pkgdir/usr/share/nautilus-python/" +} From afd8bcd7541d49e24b54a8fd56b653b5ae8cc1c0 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 14 Sep 2026 21:57:39 -0400 Subject: [PATCH 004/121] Add Pinta and its .NET 10 package dependencies for aarch64 --- .../dotnet-core-bin/.omarchy/package.json | 19 +++ pkgbuilds/dotnet-core-bin/PKGBUILD | 131 ++++++++++++++++++ pkgbuilds/dotnet-core-bin/dotnet.sh | 19 +++ pkgbuilds/pinta/.omarchy/package.json | 9 ++ pkgbuilds/pinta/PKGBUILD | 63 +++++++++ 5 files changed, 241 insertions(+) create mode 100644 pkgbuilds/dotnet-core-bin/.omarchy/package.json create mode 100644 pkgbuilds/dotnet-core-bin/PKGBUILD create mode 100755 pkgbuilds/dotnet-core-bin/dotnet.sh create mode 100644 pkgbuilds/pinta/.omarchy/package.json create mode 100644 pkgbuilds/pinta/PKGBUILD diff --git a/pkgbuilds/dotnet-core-bin/.omarchy/package.json b/pkgbuilds/dotnet-core-bin/.omarchy/package.json new file mode 100644 index 0000000..db663bc --- /dev/null +++ b/pkgbuilds/dotnet-core-bin/.omarchy/package.json @@ -0,0 +1,19 @@ +{ + "source": "local", + "origin": { + "aur": "dotnet-core-bin", + "commit": "2c499d7ce634efb8e93eee4c4239490b02e98e09" + }, + "upstream": { + "watch": { + "json": "https://builds.dotnet.microsoft.com/dotnet/release-metadata/10.0/releases.json", + "path": "latest-sdk", + "fields": { + "runtime": "latest-runtime" + }, + "variables": { + "_runtimever": "{runtime}" + } + } + } +} diff --git a/pkgbuilds/dotnet-core-bin/PKGBUILD b/pkgbuilds/dotnet-core-bin/PKGBUILD new file mode 100644 index 0000000..040344b --- /dev/null +++ b/pkgbuilds/dotnet-core-bin/PKGBUILD @@ -0,0 +1,131 @@ +# Maintainer: Attila Greguss +# Co-Maintainer: Nate Plumm + +pkgbase=dotnet-core-bin +pkgname=( + 'dotnet-host-bin' + 'aspnet-runtime-bin' + 'dotnet-runtime-bin' + 'dotnet-sdk-bin' + 'dotnet-targeting-pack-bin' + 'aspnet-targeting-pack-bin' + ) +# Version the split family by SDK release; dependencies expose runtime versions. +pkgver=10.0.401 +_runtimever=10.0.12 +_sdkver=$pkgver +_short_ver=10.0 +pkgrel=1 +arch=('x86_64' 'armv7h' 'aarch64') +url='https://www.microsoft.com/net/core' +license=('MIT') +options=('staticlibs') +source=('dotnet.sh') +source_armv7h=("https://builds.dotnet.microsoft.com/dotnet/Sdk/${_sdkver}/dotnet-sdk-${_sdkver}-linux-arm.tar.gz") +source_aarch64=("https://builds.dotnet.microsoft.com/dotnet/Sdk/${_sdkver}/dotnet-sdk-${_sdkver}-linux-arm64.tar.gz") +source_x86_64=("https://builds.dotnet.microsoft.com/dotnet/Sdk/${_sdkver}/dotnet-sdk-${_sdkver}-linux-x64.tar.gz") +sha512sums=('768151c7179fb6a126b3de9cae01e363e8894f6fab384b1e2c5066c2adca4578638983b1b62aea10dd18045e6d6e8f8ea13280481134de94f004a118919b2c06') +sha512sums_armv7h=('94a8a52862ca9f0de1075a468d6e4e307a1d4463098a9e8266e66939709a812b0126e212cce7e8c6feae6b078d86c8b77e088814a0e32531edb0da0a1ce90c11') +sha512sums_aarch64=('58ace73ced6b4360754689a686bdfb8a317f4da6cb8bb416dbc7d0ba9f47e43e3c09f5eb1f1a1cfaacbd10df9558da4882bf2a5e195d6ab56a02c1f9f76102ed') +sha512sums_x86_64=('51c8b999af9e8dd9998c9edc5944e19a90788862068acd38694e098889054ce8c23d4f0c5cccfa16bf187d044562359e5ee69a9f8ad0bbe913ba90311fbce25b') + +# Keep each split package's notices usable when installed independently. +_install_license() { + install -Dm644 LICENSE.txt "$pkgdir/usr/share/licenses/$pkgname/LICENSE.txt" + install -Dm644 ThirdPartyNotices.txt "$pkgdir/usr/share/licenses/$pkgname/ThirdPartyNotices.txt" +} + +package_dotnet-host-bin() { + pkgdesc='A generic driver for the .NET Core Command Line Interface (binary)' + provides=("dotnet-host" "dotnet-host=${_runtimever}") + conflicts=('dotnet-host') + depends=( + 'libgcc' + 'libstdc++' + 'glibc' + ) + + install -dm 755 "${pkgdir}"/usr/{bin,lib,share/{dotnet,dnx}} + cp -dr --no-preserve='ownership' dotnet host dnx "${pkgdir}"/usr/share/dotnet/ + _install_license + ln -sf /usr/share/dotnet/dotnet "${pkgdir}"/usr/bin/dotnet + ln -sf /usr/share/dotnet/dnx "${pkgdir}"/usr/bin/dnx + ln -sf /usr/share/dotnet/host/fxr/"${_runtimever}"/libhostfxr.so "${pkgdir}"/usr/lib/libhostfxr.so + install -Dm 644 "${srcdir}"/dotnet.sh -t "${pkgdir}"/etc/profile.d/ +} + +package_dotnet-runtime-bin() { + pkgdesc='The .NET Core runtime (binary)' + depends=( + "dotnet-host>=${_runtimever}" + 'libgcc' + 'libstdc++' + 'glibc' + 'icu' + 'libunwind' + 'zlib' + 'openssl' + ) + optdepends=('lttng-ust2.12: CoreCLR tracing') + provides=("dotnet-runtime=${_runtimever}" "dotnet-runtime-${_short_ver}") + conflicts=("dotnet-runtime=${_runtimever}" "dotnet-runtime-${_short_ver}") + + install -dm 755 "${pkgdir}"/usr/share/{dotnet/shared,licenses} + cp -dr --no-preserve='ownership' shared/Microsoft.NETCore.App "${pkgdir}"/usr/share/dotnet/shared/ + _install_license +} + +package_aspnet-runtime-bin() { + pkgdesc='The ASP.NET Core runtime (binary)' + depends=('dotnet-runtime-bin') + provides=("aspnet-runtime=${_runtimever}" "aspnet-runtime-${_short_ver}") + conflicts=("aspnet-runtime=${_runtimever}" "aspnet-runtime-${_short_ver}") + + install -dm 755 "${pkgdir}"/usr/share/{dotnet/shared,licenses} + cp -dr --no-preserve='ownership' shared/Microsoft.AspNetCore.App "${pkgdir}"/usr/share/dotnet/shared/ + _install_license +} + +package_dotnet-sdk-bin() { + pkgdesc='The .NET Core SDK (binary)' + depends=( + 'glibc' + 'libgcc' + 'libstdc++' + 'dotnet-runtime-bin' + 'dotnet-targeting-pack-bin' + 'aspnet-runtime-bin' + 'aspnet-targeting-pack-bin' + ) + provides=("dotnet-sdk-bin" "dotnet-sdk=${pkgver}" "dotnet-sdk-${_short_ver}=${pkgver}") + conflicts=("dotnet-sdk-bin" "dotnet-sdk=${pkgver}" "dotnet-sdk-${_short_ver}") + + install -dm 755 "${pkgdir}"/usr/share/{dotnet,licenses} + cp -dr --no-preserve='ownership' sdk sdk-manifests templates "${pkgdir}"/usr/share/dotnet/ + _install_license +} + +package_dotnet-targeting-pack-bin() { + pkgdesc='The .NET Core targeting pack (binary)' + provides=(dotnet-targeting-pack=${_runtimever} dotnet-targeting-pack-${_short_ver}) + conflicts=(dotnet-targeting-pack=${_runtimever} dotnet-targeting-pack-${_short_ver}) + + if [ $CARCH = 'x86_64' ]; then msarch=x64; + elif [ $CARCH = 'armv7h' ]; then msarch=arm; + elif [ $CARCH = 'aarch64' ]; then msarch=arm64; fi + + install -dm 755 "${pkgdir}"/usr/share/{dotnet,dotnet/packs,licenses} + cp -dr --no-preserve='ownership' packs/Microsoft.NETCore.App.{Host.linux-${msarch},Ref} "${pkgdir}"/usr/share/dotnet/packs/ + _install_license +} + +package_aspnet-targeting-pack-bin() { + pkgdesc='The ASP.NET Core targeting pack (binary)' + depends=(dotnet-targeting-pack-bin) + provides=(aspnet-targeting-pack=${_runtimever} aspnet-targeting-pack-${_short_ver}) + conflicts=(aspnet-targeting-pack=${_runtimever} aspnet-targeting-pack-${_short_ver}) + + install -dm 755 "${pkgdir}"/usr/share/{dotnet,dotnet/packs,licenses} + cp -dr --no-preserve='ownership' packs/Microsoft.AspNetCore.App.Ref "${pkgdir}"/usr/share/dotnet/packs/ + _install_license +} diff --git a/pkgbuilds/dotnet-core-bin/dotnet.sh b/pkgbuilds/dotnet-core-bin/dotnet.sh new file mode 100755 index 0000000..48b6ee6 --- /dev/null +++ b/pkgbuilds/dotnet-core-bin/dotnet.sh @@ -0,0 +1,19 @@ +# Set location for AppHost lookup +[ -z "$DOTNET_ROOT" ] && export DOTNET_ROOT=/usr/share/dotnet + +# Add dotnet directory to PATH, according to docs it must be added, plus VSCode C# Dev Kit doesn't work without this. +# See https://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#set-environment-variables-system-wide +case "$PATH" in + *"$DOTNET_ROOT"* ) true ;; + * ) PATH="$PATH:$DOTNET_ROOT" ;; +esac + +# Add dotnet tools directory to PATH +[ -z "$DOTNET_TOOLS_PATH" ] && export DOTNET_TOOLS_PATH="$HOME/.dotnet/tools" +case "$PATH" in + *"$DOTNET_TOOLS_PATH"* ) true ;; + * ) PATH="$PATH:$DOTNET_TOOLS_PATH" ;; +esac + +# Extract self-contained executables under HOME to avoid multi-user issues from using the default '/var/tmp' +[ -z "$DOTNET_BUNDLE_EXTRACT_BASE_DIR" ] && export DOTNET_BUNDLE_EXTRACT_BASE_DIR="${XDG_CACHE_HOME:-"$HOME"/.cache}/dotnet_bundle_extract" diff --git a/pkgbuilds/pinta/.omarchy/package.json b/pkgbuilds/pinta/.omarchy/package.json new file mode 100644 index 0000000..aad5b86 --- /dev/null +++ b/pkgbuilds/pinta/.omarchy/package.json @@ -0,0 +1,9 @@ +{ + "source": "local", + "upstream": { + "watch": { + "github": "PintaProject/Pinta", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + } +} diff --git a/pkgbuilds/pinta/PKGBUILD b/pkgbuilds/pinta/PKGBUILD new file mode 100644 index 0000000..1f46e28 --- /dev/null +++ b/pkgbuilds/pinta/PKGBUILD @@ -0,0 +1,63 @@ +# Pinta for Arch Linux ARM. The official repositories do not supply its +# .NET dependencies on ARM; use the dotnet-core-bin split package family. + +pkgname=pinta. +# +# This is the AUR 3.1.2-1 recipe with two substitutions: arch=('aarch64') +# and RuntimeIdentifier=linux-arm64. Makedepends/depends use this repo's +# dotnet-*-bin packages from AUR dotnet-core-bin; Arch extra's unversioned +# dotnet-sdk / dotnet-runtime / dotnet-host / dotnet-targeting-pack names +# are not in ALARM extra, and must not resolve to the leftover 2.1 packages. +# +# Version bumps are edits to this file: update pkgver and sha256sums. + +pkgname=pinta +pkgver=3.1.2 +pkgrel=1 +pkgdesc="Drawing/editing program modeled after Paint.NET. It's goal is to provide a simplified alternative to GIMP for casual users" + +arch=('aarch64') +license=('MIT') +url="https://pinta-project.com" + +makedepends=('pkgconf' 'autoconf-archive' 'intltool' 'dotnet-sdk-bin' 'dotnet-runtime-bin' 'dotnet-host-bin' 'dotnet-targeting-pack-bin' 'gtk4' 'perl') +depends=('dotnet-runtime-bin' 'dotnet-host-bin' 'libadwaita' 'hicolor-icon-theme' 'webp-pixbuf-loader') + +provides=($pkgname) +conflicts=($pkgname-git) + +source=("Pinta-${pkgver}.tar.gz::https://github.com/PintaProject/Pinta/archive/refs/tags/${pkgver}.tar.gz") +sha256sums=('98ed517b33f0e40fd1e3915ea5146355845ac12efd3bb07812c68a52c714cac6') + +prepare() { + cd "${srcdir}/Pinta-${pkgver}" + + for file in *.md *.txt; do + basename=$(tr '[:lower:]' '[:upper:]' <<< "${file%.*}") + newname="$basename.${file#*.}" + [ ! "$file" == "$newname" ] && mv "$file" "$newname" + done + + sed -i 's/net8.0/net10.0/g' Directory.Build.props + + ./autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var +} + +build() { + cd "${srcdir}/Pinta-${pkgver}" + + sed -i -r 's|^(PINTA_BUILD_OPTS\s=\s.*)|\1 -p:RuntimeIdentifier=linux-arm64|g' Makefile + + make +} + +package() { + cd "${srcdir}/Pinta-${pkgver}" + + make DESTDIR="${pkgdir}" install + + chmod -v 755 "${pkgdir}/usr/lib/pinta/"*.dll + + install -Dm644 -t "${pkgdir}/usr/share/doc/${pkgname}/" *.md + install -Dm644 -t "${pkgdir}/usr/share/licenses/${pkgname}/" LICENSE*.txt +} From 6064a14d4702d12fda4e879db697f51e86d0e783 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 00:06:41 -0400 Subject: [PATCH 005/121] Use Omarchy headers for IPU7 and MacBook SPI DKMS packages --- pkgbuilds/intel-ipu7-camera/PKGBUILD | 4 ++-- pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgbuilds/intel-ipu7-camera/PKGBUILD b/pkgbuilds/intel-ipu7-camera/PKGBUILD index c2770fd..a87e861 100644 --- a/pkgbuilds/intel-ipu7-camera/PKGBUILD +++ b/pkgbuilds/intel-ipu7-camera/PKGBUILD @@ -2,14 +2,14 @@ pkgname=intel-ipu7-camera pkgver=1.0.6 -pkgrel=1 +pkgrel=2 pkgdesc="Intel IPU7 MIPI camera stack for Hurrican/Performance (OV08X40 + hardware ISP)" arch=('x86_64') url="https://github.com/TsaiGaggery/hurrican_omarchy_enabling" license=('GPL-2.0-or-later') depends=( 'dkms' - 'linux-headers' + 'linux-omarchy-headers' 'v4l2loopback-dkms' 'v4l2-relayd' 'gstreamer' diff --git a/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD b/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD index eb7975a..47b69ab 100644 --- a/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD +++ b/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD @@ -2,12 +2,12 @@ _pkgbase=spi-pxa2xx-pci-nodma pkgname=macbook8-spi-pxa2xx-nodma-dkms pkgver=1.0 -pkgrel=1 +pkgrel=2 pkgdesc="Patched SPI PXA2xx PCI driver forcing PIO mode for MacBook8,1 Wildcat Point GSPI (8086:9ce6)" arch=('x86_64') url="https://github.com/basecamp/omarchy" license=('GPL-2.0-only') -depends=('dkms' 'linux-headers') +depends=('dkms' 'linux-omarchy-headers') makedepends=() conflicts=('spi_pxa2xx_pci' 'macbook12-spi-driver-dkms') provides=('spi_pxa2xx_pci_nodma') @@ -31,4 +31,4 @@ package() { # Modprobe blacklist: prevent the in-tree spi_pxa2xx_pci from claiming this device install -Dm644 "${srcdir}/macbook8-spi-nodma.conf" "${pkgdir}/usr/lib/modprobe.d/macbook8-spi-nodma.conf" -} \ No newline at end of file +} From 9d5c3eea19a566bf26716e702a20dd151e98dedc Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 00:13:57 -0400 Subject: [PATCH 006/121] Skip retained published archives when planning builds --- .github/workflows/test.yml | 1 + bin/check-versions | 4 +- build/build.sh | 12 +++++- helpers/package-metadata.sh | 12 ++++++ tests/published-build-plan.sh | 71 +++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100755 tests/published-build-plan.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b64690..6e48346 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,4 +46,5 @@ jobs: ./bin/omarchy-pkgs self-test ./bin/omarchy-release self-test ./tests/partial-release.sh + ./tests/published-build-plan.sh ' diff --git a/bin/check-versions b/bin/check-versions index 925570f..6f0558f 100755 --- a/bin/check-versions +++ b/bin/check-versions @@ -172,8 +172,8 @@ check_package() { # it because that exact filename is already published with different bytes. # If the artifact for this version already exists in the channel, there is # nothing to build regardless of which direction the versions differ. - if compgen -G "$REPO_ROOT/$mirror/$ARCH/${pkg}-${pkgbuild_version}-*.pkg.tar."[!s]* >/dev/null 2>&1; then - print_warning "$pkg $pkgbuild_version is already published — this checkout is behind the channel; not queueing" + if package_version_is_published "$REPO_ROOT/$mirror/$ARCH" "$pkg" "$pkgbuild_version" "$ARCH"; then + print_warning "$pkg $pkgbuild_version is already published; not queueing" return 1 fi diff --git a/build/build.sh b/build/build.sh index 96500e7..4c39147 100755 --- a/build/build.sh +++ b/build/build.sh @@ -531,9 +531,17 @@ check_needs_build() { if [[ "$local_version" == "$pkgbuild_version" ]]; then return 1 # Already up to date - else - return 0 # Needs building fi + + # Match check-versions: a retained archive is already published even when + # the DB now indexes a newer release (for example, 4.0.4rc1 vs 4.0.3). + # Rebuilding it would produce different bytes under an immutable filename. + if package_version_is_published "$FINAL_OUTPUT_DIR" "$pkg" "$pkgbuild_version" "$ARCH"; then + echo " + $pkg $pkgbuild_version - archive already published; skipping rebuild" + return 1 + fi + + return 0 # Needs building } # Collect packages that should be built for the selected mirror diff --git a/helpers/package-metadata.sh b/helpers/package-metadata.sh index a3ad047..ce46e92 100644 --- a/helpers/package-metadata.sh +++ b/helpers/package-metadata.sh @@ -191,6 +191,18 @@ package_supports_arch() { esac } +# The channel DB indexes only its newest version, but older published archives +# remain immutable. Both the scheduler and build planner must skip an existing +# filename even when the checkout differs from the version currently indexed. +package_version_is_published() { + local repo_dir="$1" package="$2" version="$3" target="$4" path + for path in "$repo_dir/$package-$version-$target.pkg.tar."* \ + "$repo_dir/$package-$version-any.pkg.tar."*; do + [[ -f "$path" && "$path" != *.sig ]] && return 0 + done + return 1 +} + # Channel membership: where a package may be published. Packages without a # `channels` key are members of every channel (they flow edge -> rc -> stable). package_has_channels() { diff --git a/tests/published-build-plan.sh b/tests/published-build-plan.sh new file mode 100755 index 0000000..538eff7 --- /dev/null +++ b/tests/published-build-plan.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# The timer and builder must agree when an older archive remains published. +set -euo pipefail +BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +TEST_ROOT=$(mktemp -d) +trap 'rm -rf "$TEST_ROOT"' EXIT +mkdir -p "$TEST_ROOT/bin" "$TEST_ROOT/pkgbuilds" "$TEST_ROOT/state" +cp "$BUILD_ROOT/bin/check-versions" "$TEST_ROOT/bin/" +cp -r "$BUILD_ROOT/helpers" "$BUILD_ROOT/build" "$TEST_ROOT/" +export OMARCHY_STATE_DIR="$TEST_ROOT/state" +unset OMARCHY_REPO_ROOT OMARCHY_RC_PINS OMARCHY_DEFER_RUNTIME_DEPS + +fixture() { + local name=$1 version=$2 release=$3 + mkdir -p "$TEST_ROOT/pkgbuilds/$name/.omarchy" + printf '{"source":"local","channels":["edge"]}\n' > "$TEST_ROOT/pkgbuilds/$name/.omarchy/package.json" + cat > "$TEST_ROOT/pkgbuilds/$name/PKGBUILD" < "$TEST_ROOT/db/$name-$version/desc" +} +db_entry omarchy 4.0.4rc1-1 +db_entry omarchy-settings 4.0.4rc1-1 +for package in current update rebuild; do db_entry "$package" 1-1; done +printf '%s\n' new-package other-arch rebuild signature-only update | sort > "$TEST_ROOT/expected" + +for arch in x86_64 aarch64; do + repo="$TEST_ROOT/pkgs.omarchy.org/edge/$arch" + mkdir -p "$repo" + tar --zstd -cf "$repo/omarchy.db.tar.zst" -C "$TEST_ROOT/db" . + touch "$repo/omarchy-4.0.3-1-$arch.pkg.tar.zst" + touch "$repo/omarchy-settings-4.0.3-1-any.pkg.tar.xz" + touch "$repo/unindexed-1-1-$arch.pkg.tar.zst" + touch "$repo/rebuild-1-1-$arch.pkg.tar.zst" + touch "$repo/signature-only-1-1-$arch.pkg.tar.zst.sig" + other=x86_64 + [[ "$arch" == x86_64 ]] && other=aarch64 + touch "$repo/other-arch-1-1-$other.pkg.tar.zst" + + "$TEST_ROOT/bin/check-versions" --arch "$arch" > "$TEST_ROOT/check.log" 2>&1 + sort "$TEST_ROOT/state/.sync-needed-edge-$arch" > "$TEST_ROOT/queue" + diff -u "$TEST_ROOT/expected" "$TEST_ROOT/queue" + + for selection in '' 'omarchy omarchy-settings current update rebuild unindexed signature-only other-arch new-package'; do + ARCH="$arch" MIRROR=edge DRY_RUN=true PACKAGES="$selection" \ + PKGBUILDS_DIR="$TEST_ROOT/pkgbuilds" HELPERS_DIR="$TEST_ROOT/helpers" \ + FINAL_OUTPUT_DIR="$repo" BUILD_PLAN_DIR="$TEST_ROOT/plan" \ + "$TEST_ROOT/build/build.sh" > "$TEST_ROOT/plan.log" 2>&1 + sort "$TEST_ROOT/plan/packages" > "$TEST_ROOT/planned" + diff -u "$TEST_ROOT/queue" "$TEST_ROOT/planned" + grep -q 'omarchy 4.0.3-1 - archive already published' "$TEST_ROOT/plan.log" + done + printf 'PASS: %s scheduler and explicit/unscoped plans skip retained archives, allow new versions and releases\n' "$arch" +done From 113ff6245908ae7399f7e3fb772cc0af7f0f8b44 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 00:18:51 -0400 Subject: [PATCH 007/121] Allow absent X11 session files in Yaru split packaging --- pkgbuilds/yaru-icon-theme/PKGBUILD | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/yaru-icon-theme/PKGBUILD b/pkgbuilds/yaru-icon-theme/PKGBUILD index 03a6710..e421772 100644 --- a/pkgbuilds/yaru-icon-theme/PKGBUILD +++ b/pkgbuilds/yaru-icon-theme/PKGBUILD @@ -11,7 +11,7 @@ pkgname=('yaru-sound-theme' 'yaru-icon-theme' 'yaru-session') pkgver=26.10.3 -pkgrel=1 +pkgrel=2 pkgdesc="Yaru default ubuntu theme" arch=(any) url="https://github.com/ubuntu/yaru" @@ -56,7 +56,8 @@ _delete_all_from_pkgdir_except() { rm -r "${pkgdir}"/usr/share/icons fi if [[ "$1" != "session" ]]; then - rm -r "${pkgdir}"/usr/share/{glib-2.0,xsessions,wayland-sessions} + # Newer Yaru releases no longer install the X11 session directory. + rm -rf "${pkgdir}"/usr/share/{glib-2.0,xsessions,wayland-sessions} rm -r "${pkgdir}"/usr/share/gnome-shell/{extensions,modes} fi # Delete remaining empty directories: From dee4caf7bcc3fdea467d277814c1aba31edd598b Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 00:46:31 -0400 Subject: [PATCH 008/121] Let DKMS packages rely on headers supplied by the base install --- pkgbuilds/intel-ipu7-camera/PKGBUILD | 1 - pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgbuilds/intel-ipu7-camera/PKGBUILD b/pkgbuilds/intel-ipu7-camera/PKGBUILD index a87e861..6683be9 100644 --- a/pkgbuilds/intel-ipu7-camera/PKGBUILD +++ b/pkgbuilds/intel-ipu7-camera/PKGBUILD @@ -9,7 +9,6 @@ url="https://github.com/TsaiGaggery/hurrican_omarchy_enabling" license=('GPL-2.0-or-later') depends=( 'dkms' - 'linux-omarchy-headers' 'v4l2loopback-dkms' 'v4l2-relayd' 'gstreamer' diff --git a/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD b/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD index 47b69ab..aa9b7b8 100644 --- a/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD +++ b/pkgbuilds/macbook8-spi-pxa2xx-nodma-dkms/PKGBUILD @@ -7,7 +7,7 @@ pkgdesc="Patched SPI PXA2xx PCI driver forcing PIO mode for MacBook8,1 Wildcat P arch=('x86_64') url="https://github.com/basecamp/omarchy" license=('GPL-2.0-only') -depends=('dkms' 'linux-omarchy-headers') +depends=('dkms') makedepends=() conflicts=('spi_pxa2xx_pci' 'macbook12-spi-driver-dkms') provides=('spi_pxa2xx_pci_nodma') From 5371afbbb397115a19f3ab2fd4973bc575c7e450 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 15 Sep 2026 08:16:34 -0400 Subject: [PATCH 009/121] Simplify Pinta packaging with the upstream release tarball --- pkgbuilds/pinta/PKGBUILD | 47 ++++++++-------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/pkgbuilds/pinta/PKGBUILD b/pkgbuilds/pinta/PKGBUILD index 1f46e28..5f1475f 100644 --- a/pkgbuilds/pinta/PKGBUILD +++ b/pkgbuilds/pinta/PKGBUILD @@ -1,16 +1,6 @@ # Pinta for Arch Linux ARM. The official repositories do not supply its # .NET dependencies on ARM; use the dotnet-core-bin split package family. -pkgname=pinta. -# -# This is the AUR 3.1.2-1 recipe with two substitutions: arch=('aarch64') -# and RuntimeIdentifier=linux-arm64. Makedepends/depends use this repo's -# dotnet-*-bin packages from AUR dotnet-core-bin; Arch extra's unversioned -# dotnet-sdk / dotnet-runtime / dotnet-host / dotnet-targeting-pack names -# are not in ALARM extra, and must not resolve to the leftover 2.1 packages. -# -# Version bumps are edits to this file: update pkgver and sha256sums. - pkgname=pinta pkgver=3.1.2 pkgrel=1 @@ -20,44 +10,25 @@ arch=('aarch64') license=('MIT') url="https://pinta-project.com" -makedepends=('pkgconf' 'autoconf-archive' 'intltool' 'dotnet-sdk-bin' 'dotnet-runtime-bin' 'dotnet-host-bin' 'dotnet-targeting-pack-bin' 'gtk4' 'perl') +makedepends=('pkgconf' 'intltool' 'dotnet-sdk-bin') depends=('dotnet-runtime-bin' 'dotnet-host-bin' 'libadwaita' 'hicolor-icon-theme' 'webp-pixbuf-loader') -provides=($pkgname) conflicts=($pkgname-git) -source=("Pinta-${pkgver}.tar.gz::https://github.com/PintaProject/Pinta/archive/refs/tags/${pkgver}.tar.gz") -sha256sums=('98ed517b33f0e40fd1e3915ea5146355845ac12efd3bb07812c68a52c714cac6') - -prepare() { - cd "${srcdir}/Pinta-${pkgver}" - - for file in *.md *.txt; do - basename=$(tr '[:lower:]' '[:upper:]' <<< "${file%.*}") - newname="$basename.${file#*.}" - [ ! "$file" == "$newname" ] && mv "$file" "$newname" - done - - sed -i 's/net8.0/net10.0/g' Directory.Build.props - - ./autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var -} +source=("https://github.com/PintaProject/Pinta/releases/download/${pkgver}/pinta-${pkgver}.tar.gz") +sha256sums=('27f55a026b51f6f18197e6bcfdd7c79544e41529d166daf6c93a1117e9ed45f0') build() { - cd "${srcdir}/Pinta-${pkgver}" - - sed -i -r 's|^(PINTA_BUILD_OPTS\s=\s.*)|\1 -p:RuntimeIdentifier=linux-arm64|g' Makefile - - make + cd "${srcdir}/pinta-${pkgver}" + ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var + make PINTA_BUILD_OPTS='--configuration Release -p:BuildTranslations=true -p:RuntimeIdentifier=linux-arm64' } package() { - cd "${srcdir}/Pinta-${pkgver}" + cd "${srcdir}/pinta-${pkgver}" make DESTDIR="${pkgdir}" install - chmod -v 755 "${pkgdir}/usr/lib/pinta/"*.dll - - install -Dm644 -t "${pkgdir}/usr/share/doc/${pkgname}/" *.md - install -Dm644 -t "${pkgdir}/usr/share/licenses/${pkgname}/" LICENSE*.txt + install -Dm644 -t "${pkgdir}/usr/share/doc/${pkgname}/" readme.md + install -Dm644 -t "${pkgdir}/usr/share/licenses/${pkgname}/" license-*.txt } From c17a46e40409a6ef023dd0876c8ecd398dc29356 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 15 Sep 2026 08:16:34 -0400 Subject: [PATCH 010/121] Use the MbedTLS CMake configuration for OBS --- pkgbuilds/obs-studio/PKGBUILD | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pkgbuilds/obs-studio/PKGBUILD b/pkgbuilds/obs-studio/PKGBUILD index f3f1693..688e890 100644 --- a/pkgbuilds/obs-studio/PKGBUILD +++ b/pkgbuilds/obs-studio/PKGBUILD @@ -88,13 +88,8 @@ build() { -DOBS_VERSION_OVERRIDE="$pkgver" -DOBS_COMPILE_DEPRECATION_AS_WARNING=ON - # Arch ships mbedtls 3 side-by-side under /usr/lib/mbedtls3, and OBS's - # finder needs to be pointed at it (same paths the AUR pkgbases use). + # Use Arch's side-by-side MbedTLS 3 CMake configuration. -DMbedTLS_DIR=/usr/lib/mbedtls3/cmake/MbedTLS - -DMbedTLS_INCLUDE_DIR=/usr/include/mbedtls3 - -DMbedtls_LIBRARY=/usr/lib/mbedtls3/libmbedtls.so - -DMbedcrypto_LIBRARY=/usr/lib/mbedtls3/libmbedcrypto.so - -DMbedx509_LIBRARY=/usr/lib/mbedtls3/libmbedx509.so -Wno-dev ) From 1a40508b4843ad1cdd2f45c9d251b087b745d24f Mon Sep 17 00:00:00 2001 From: dhh <2741+dhh@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:10:15 +0000 Subject: [PATCH 011/121] chore: sync upstream releases --- pkgbuilds/heroic-games-launcher-bin/PKGBUILD | 6 +++--- pkgbuilds/schist-bin/PKGBUILD | 6 +++--- pkgbuilds/sunshine/PKGBUILD | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD index 2bc7604..ead38ab 100755 --- a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD +++ b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD @@ -2,8 +2,8 @@ # Maintainer: CommandMC pkgname=heroic-games-launcher-bin -pkgver=2.22.1 -pkgrel=2 +pkgver=2.22.2 +pkgrel=1 pkgdesc="An Open source Launcher for Epic, Amazon and GOG Games" arch=('x86_64') url="https://heroicgameslauncher.com/" @@ -11,7 +11,7 @@ license=('GPL-3.0-only') _filename=Heroic-${pkgver}-linux-x64.pacman source=("https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v${pkgver}/${_filename}") noextract=("${_filename}") -sha256sums=(66ed041a93ac2817b744d3d0985194adfa408c8d35f64d9a8967fa5e2a58f2c1) +sha256sums=('4e4033ac70b8c407eaf70ce072e4e4d017200f07a3e88f7cfd4d3a597f3c09b8') options=(!strip) depends=( which diff --git a/pkgbuilds/schist-bin/PKGBUILD b/pkgbuilds/schist-bin/PKGBUILD index 06ee0b3..3df4afc 100644 --- a/pkgbuilds/schist-bin/PKGBUILD +++ b/pkgbuilds/schist-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Infrawrench LLC pkgname=schist-bin -pkgver=0.12.0 +pkgver=0.13.0 pkgrel=1 # Upstream's own package release, embedded in the asset name. It is # packages.sh's "release=" and only moves when the packaging changes under @@ -32,8 +32,8 @@ options=(!strip !debug) # script. source_x86_64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-x86_64.pkg.tar.zst") source_aarch64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-aarch64.pkg.tar.zst") -sha256sums_x86_64=('baff8848274f0121911a6408fd3dd082c5ab023c0ae5c9e5be35968c80beb069') -sha256sums_aarch64=('a7a4f062289a140ff0aa5c0c9c4b3cc9f386759e3bfe929a0382de2d20c04eda') +sha256sums_x86_64=('6070dd346ebd69898437d6dfb6c071cca80c82045581feeeba6542264ae23096') +sha256sums_aarch64=('d5eef7b737b35d32a31f3ae34de0a16ab3178348b44245a8096b8d70fe7b03c1') package() { # makepkg has already extracted the payload into srcdir; its .PKGINFO diff --git a/pkgbuilds/sunshine/PKGBUILD b/pkgbuilds/sunshine/PKGBUILD index 0e4d20c..170bb51 100644 --- a/pkgbuilds/sunshine/PKGBUILD +++ b/pkgbuilds/sunshine/PKGBUILD @@ -6,11 +6,11 @@ : "${_support_headless_testing:=false}" : "${_use_cuda:=detect}" # nvenc -_commit=cb72dffa3233c5815cd5ba88f09f049dd679ba75 +_commit=63d35f702ee9e362e43263742981836ec0710384 pkgname='sunshine' -pkgver=2026.906.222525 -pkgrel=1.2 +pkgver=2026.914.233613 +pkgrel=1 pkgdesc="Self-hosted game stream host for Moonlight" arch=('x86_64' 'aarch64') url=https://app.lizardbyte.dev/Sunshine From e15d4aa61e5c579d1cfdbcbad12ebd50975803df Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Mon, 14 Sep 2026 21:00:33 -0500 Subject: [PATCH 012/121] Add Omawake and Omaspeak edge packages --- pkgbuilds/edge/omaspeak-bin/.SRCINFO | 25 +++++++ pkgbuilds/edge/omaspeak-bin/.gitignore | 5 ++ pkgbuilds/edge/omaspeak-bin/PKGBUILD | 70 +++++++++++++++++++ .../edge/omaspeak-bin/omaspeak-bin.install | 11 +++ pkgbuilds/edge/omawake-bin/.SRCINFO | 25 +++++++ pkgbuilds/edge/omawake-bin/.gitignore | 5 ++ pkgbuilds/edge/omawake-bin/PKGBUILD | 70 +++++++++++++++++++ .../edge/omawake-bin/omawake-bin.install | 11 +++ 8 files changed, 222 insertions(+) create mode 100644 pkgbuilds/edge/omaspeak-bin/.SRCINFO create mode 100644 pkgbuilds/edge/omaspeak-bin/.gitignore create mode 100644 pkgbuilds/edge/omaspeak-bin/PKGBUILD create mode 100644 pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install create mode 100644 pkgbuilds/edge/omawake-bin/.SRCINFO create mode 100644 pkgbuilds/edge/omawake-bin/.gitignore create mode 100644 pkgbuilds/edge/omawake-bin/PKGBUILD create mode 100644 pkgbuilds/edge/omawake-bin/omawake-bin.install diff --git a/pkgbuilds/edge/omaspeak-bin/.SRCINFO b/pkgbuilds/edge/omaspeak-bin/.SRCINFO new file mode 100644 index 0000000..14b7359 --- /dev/null +++ b/pkgbuilds/edge/omaspeak-bin/.SRCINFO @@ -0,0 +1,25 @@ +pkgbase = omaspeak-bin + pkgdesc = Local-first text-to-speech application and daemon (pre-built binary) + pkgver = 0.0.1.rc + pkgrel = 1 + url = https://github.com/jacob-vincent-mink/omaspeak + install = omaspeak-bin.install + arch = x86_64 + license = MIT + depends = alsa-utils + depends = bzip2 + depends = gcc-libs + depends = glibc + optdepends = pipewire-audio: audio playback through pw-play + optdepends = openvino: Intel CPU acceleration runtime + optdepends = openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO + optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO + optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle + optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle + provides = omaspeak=0.0.1.rc + conflicts = omaspeak + options = !strip + source = omaspeak-0.0.1-rc-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc/omaspeak-0.0.1-rc-linux-x86_64.tar.xz + sha256sums = 49c1d0bc2954aad7865746d7edbbe81343ad3a1d33ff0dd6d21e0ecd3a26b115 + +pkgname = omaspeak-bin diff --git a/pkgbuilds/edge/omaspeak-bin/.gitignore b/pkgbuilds/edge/omaspeak-bin/.gitignore new file mode 100644 index 0000000..57436e0 --- /dev/null +++ b/pkgbuilds/edge/omaspeak-bin/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!.SRCINFO +!PKGBUILD +!omaspeak-bin.install diff --git a/pkgbuilds/edge/omaspeak-bin/PKGBUILD b/pkgbuilds/edge/omaspeak-bin/PKGBUILD new file mode 100644 index 0000000..6255d8f --- /dev/null +++ b/pkgbuilds/edge/omaspeak-bin/PKGBUILD @@ -0,0 +1,70 @@ +# Maintainer: Jacob Vincent Mink + +pkgname=omaspeak-bin +_pkgname=${pkgname%-bin} +pkgver=0.0.1.rc +_upstream_ver=0.0.1-rc +pkgrel=1 +pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' +arch=('x86_64') +url='https://github.com/jacob-vincent-mink/omaspeak' +license=('MIT') +depends=( + 'alsa-utils' + 'bzip2' + 'gcc-libs' + 'glibc' +) +optdepends=( + 'pipewire-audio: audio playback through pw-play' + 'openvino: Intel CPU acceleration runtime' + 'openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO' + 'openvino-intel-npu-plugin: Intel NPU device support for OpenVINO' + 'cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle' + 'cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle' +) +provides=("${_pkgname}=${pkgver}") +conflicts=("${_pkgname}") +install="${pkgname}.install" +options=('!strip') + +source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") + +sha256sums=('49c1d0bc2954aad7865746d7edbbe81343ad3a1d33ff0dd6d21e0ecd3a26b115') + +package() { + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" + + install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" + + install -dm755 "${pkgdir}/usr/lib/${_pkgname}" + cp -a "${release_root}/lib/." "${pkgdir}/usr/lib/${_pkgname}/" + + install -Dm644 \ + "${release_root}/packaging/systemd/${_pkgname}.service" \ + "${pkgdir}/usr/lib/systemd/user/${_pkgname}.service" + + local document + for document in \ + README.md \ + INSTALL.md \ + ACCELERATOR_SETUP.md \ + CHANGELOG.md \ + RELEASE_NOTES.md \ + DEMO.md \ + RUNTIME.md \ + config.example.toml; do + install -Dm644 \ + "${release_root}/${document}" \ + "${pkgdir}/usr/share/doc/${pkgname}/${document}" + done + cp -a \ + "${release_root}/assets" \ + "${release_root}/benchmarks" \ + "${pkgdir}/usr/share/doc/${pkgname}/" + + install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}" + install -m644 \ + "${release_root}"/licenses/* \ + "${pkgdir}/usr/share/licenses/${pkgname}/" +} diff --git a/pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install b/pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install new file mode 100644 index 0000000..4a33226 --- /dev/null +++ b/pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install @@ -0,0 +1,11 @@ +# shellcheck shell=sh + +post_install() { + echo ':: Run omaspeak setup to configure a model and runtime.' + echo ':: The optional user service remains disabled; on-demand speech works without it.' + echo ':: Accelerator instructions: /usr/share/doc/omaspeak-bin/ACCELERATOR_SETUP.md' +} + +post_upgrade() { + echo ':: Run omaspeak setup check to verify the current configuration.' +} diff --git a/pkgbuilds/edge/omawake-bin/.SRCINFO b/pkgbuilds/edge/omawake-bin/.SRCINFO new file mode 100644 index 0000000..c8d65df --- /dev/null +++ b/pkgbuilds/edge/omawake-bin/.SRCINFO @@ -0,0 +1,25 @@ +pkgbase = omawake-bin + pkgdesc = Configurable local wake-word daemon (pre-built binary) + pkgver = 0.0.1.rc + pkgrel = 1 + url = https://github.com/jacob-vincent-mink/omawake + install = omawake-bin.install + arch = x86_64 + license = MIT + depends = alsa-lib + depends = bzip2 + depends = gcc-libs + depends = glibc + optdepends = pipewire-audio: PipeWire audio support + optdepends = openvino: Intel runtime for an externally supplied OpenVINO provider bundle + optdepends = openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO + optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO + optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle + optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle + provides = omawake=0.0.1.rc + conflicts = omawake + options = !strip + source = omawake-0.0.1-rc-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc/omawake-0.0.1-rc-linux-x86_64.tar.xz + sha256sums = 52441cefcee285e6941fa25bc45770dc628391f0dd035260509e5cb47c0eeb15 + +pkgname = omawake-bin diff --git a/pkgbuilds/edge/omawake-bin/.gitignore b/pkgbuilds/edge/omawake-bin/.gitignore new file mode 100644 index 0000000..138f2fc --- /dev/null +++ b/pkgbuilds/edge/omawake-bin/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!.SRCINFO +!PKGBUILD +!omawake-bin.install diff --git a/pkgbuilds/edge/omawake-bin/PKGBUILD b/pkgbuilds/edge/omawake-bin/PKGBUILD new file mode 100644 index 0000000..a2bc8cc --- /dev/null +++ b/pkgbuilds/edge/omawake-bin/PKGBUILD @@ -0,0 +1,70 @@ +# Maintainer: Jacob Vincent Mink + +pkgname=omawake-bin +_pkgname=${pkgname%-bin} +pkgver=0.0.1.rc +_upstream_ver=0.0.1-rc +pkgrel=1 +pkgdesc='Configurable local wake-word daemon (pre-built binary)' +arch=('x86_64') +url='https://github.com/jacob-vincent-mink/omawake' +license=('MIT') +depends=( + 'alsa-lib' + 'bzip2' + 'gcc-libs' + 'glibc' +) +optdepends=( + 'pipewire-audio: PipeWire audio support' + 'openvino: Intel runtime for an externally supplied OpenVINO provider bundle' + 'openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO' + 'openvino-intel-npu-plugin: Intel NPU device support for OpenVINO' + 'cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle' + 'cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle' +) +provides=("${_pkgname}=${pkgver}") +conflicts=("${_pkgname}") +install="${pkgname}.install" +options=('!strip') + +source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") + +sha256sums=('52441cefcee285e6941fa25bc45770dc628391f0dd035260509e5cb47c0eeb15') + +package() { + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" + + install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" + + install -dm755 "${pkgdir}/usr/lib/${_pkgname}" + cp -a "${release_root}/lib/." "${pkgdir}/usr/lib/${_pkgname}/" + + install -Dm644 \ + "${release_root}/packaging/systemd/${_pkgname}.service" \ + "${pkgdir}/usr/lib/systemd/user/${_pkgname}.service" + + local document + for document in \ + README.md \ + INSTALL.md \ + ACCELERATOR_SETUP.md \ + CHANGELOG.md \ + RELEASE_NOTES.md \ + DEMO.md \ + RUNTIME.md \ + config.example.toml; do + install -Dm644 \ + "${release_root}/${document}" \ + "${pkgdir}/usr/share/doc/${pkgname}/${document}" + done + cp -a \ + "${release_root}/assets" \ + "${release_root}/benchmarks" \ + "${pkgdir}/usr/share/doc/${pkgname}/" + + install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}" + install -m644 \ + "${release_root}"/licenses/* \ + "${pkgdir}/usr/share/licenses/${pkgname}/" +} diff --git a/pkgbuilds/edge/omawake-bin/omawake-bin.install b/pkgbuilds/edge/omawake-bin/omawake-bin.install new file mode 100644 index 0000000..a5a993e --- /dev/null +++ b/pkgbuilds/edge/omawake-bin/omawake-bin.install @@ -0,0 +1,11 @@ +# shellcheck shell=sh + +post_install() { + echo ':: Run omawake setup to configure a model and runtime.' + echo ':: The optional user service remains disabled; enable it only when desired.' + echo ':: Accelerator instructions: /usr/share/doc/omawake-bin/ACCELERATOR_SETUP.md' +} + +post_upgrade() { + echo ':: Run omawake setup check to verify the current configuration.' +} From 9807177337dce829e03df4c2ba49745262a7bcf7 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Tue, 15 Sep 2026 00:09:29 -0500 Subject: [PATCH 013/121] Register speech packages with the current edge builder The builder discovers package directories directly under pkgbuilds and requires local package metadata. Move Omawake and Omaspeak out of the retired edge directory and restrict their channels to edge so the release pipeline builds them without promoting the release candidates. Co-Authored-By: GPT-6 Astra XHigh --- pkgbuilds/{edge => }/omaspeak-bin/.SRCINFO | 0 pkgbuilds/{edge => }/omaspeak-bin/.gitignore | 2 ++ pkgbuilds/omaspeak-bin/.omarchy/package.json | 4 ++++ pkgbuilds/{edge => }/omaspeak-bin/PKGBUILD | 0 pkgbuilds/{edge => }/omaspeak-bin/omaspeak-bin.install | 0 pkgbuilds/{edge => }/omawake-bin/.SRCINFO | 0 pkgbuilds/{edge => }/omawake-bin/.gitignore | 2 ++ pkgbuilds/omawake-bin/.omarchy/package.json | 4 ++++ pkgbuilds/{edge => }/omawake-bin/PKGBUILD | 0 pkgbuilds/{edge => }/omawake-bin/omawake-bin.install | 0 10 files changed, 12 insertions(+) rename pkgbuilds/{edge => }/omaspeak-bin/.SRCINFO (100%) rename pkgbuilds/{edge => }/omaspeak-bin/.gitignore (62%) create mode 100644 pkgbuilds/omaspeak-bin/.omarchy/package.json rename pkgbuilds/{edge => }/omaspeak-bin/PKGBUILD (100%) rename pkgbuilds/{edge => }/omaspeak-bin/omaspeak-bin.install (100%) rename pkgbuilds/{edge => }/omawake-bin/.SRCINFO (100%) rename pkgbuilds/{edge => }/omawake-bin/.gitignore (61%) create mode 100644 pkgbuilds/omawake-bin/.omarchy/package.json rename pkgbuilds/{edge => }/omawake-bin/PKGBUILD (100%) rename pkgbuilds/{edge => }/omawake-bin/omawake-bin.install (100%) diff --git a/pkgbuilds/edge/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO similarity index 100% rename from pkgbuilds/edge/omaspeak-bin/.SRCINFO rename to pkgbuilds/omaspeak-bin/.SRCINFO diff --git a/pkgbuilds/edge/omaspeak-bin/.gitignore b/pkgbuilds/omaspeak-bin/.gitignore similarity index 62% rename from pkgbuilds/edge/omaspeak-bin/.gitignore rename to pkgbuilds/omaspeak-bin/.gitignore index 57436e0..cd3c2c4 100644 --- a/pkgbuilds/edge/omaspeak-bin/.gitignore +++ b/pkgbuilds/omaspeak-bin/.gitignore @@ -3,3 +3,5 @@ !.SRCINFO !PKGBUILD !omaspeak-bin.install +!.omarchy/ +!.omarchy/package.json diff --git a/pkgbuilds/omaspeak-bin/.omarchy/package.json b/pkgbuilds/omaspeak-bin/.omarchy/package.json new file mode 100644 index 0000000..2537ec0 --- /dev/null +++ b/pkgbuilds/omaspeak-bin/.omarchy/package.json @@ -0,0 +1,4 @@ +{ + "source": "local", + "channels": ["edge"] +} diff --git a/pkgbuilds/edge/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD similarity index 100% rename from pkgbuilds/edge/omaspeak-bin/PKGBUILD rename to pkgbuilds/omaspeak-bin/PKGBUILD diff --git a/pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install b/pkgbuilds/omaspeak-bin/omaspeak-bin.install similarity index 100% rename from pkgbuilds/edge/omaspeak-bin/omaspeak-bin.install rename to pkgbuilds/omaspeak-bin/omaspeak-bin.install diff --git a/pkgbuilds/edge/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO similarity index 100% rename from pkgbuilds/edge/omawake-bin/.SRCINFO rename to pkgbuilds/omawake-bin/.SRCINFO diff --git a/pkgbuilds/edge/omawake-bin/.gitignore b/pkgbuilds/omawake-bin/.gitignore similarity index 61% rename from pkgbuilds/edge/omawake-bin/.gitignore rename to pkgbuilds/omawake-bin/.gitignore index 138f2fc..1deba1d 100644 --- a/pkgbuilds/edge/omawake-bin/.gitignore +++ b/pkgbuilds/omawake-bin/.gitignore @@ -3,3 +3,5 @@ !.SRCINFO !PKGBUILD !omawake-bin.install +!.omarchy/ +!.omarchy/package.json diff --git a/pkgbuilds/omawake-bin/.omarchy/package.json b/pkgbuilds/omawake-bin/.omarchy/package.json new file mode 100644 index 0000000..2537ec0 --- /dev/null +++ b/pkgbuilds/omawake-bin/.omarchy/package.json @@ -0,0 +1,4 @@ +{ + "source": "local", + "channels": ["edge"] +} diff --git a/pkgbuilds/edge/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD similarity index 100% rename from pkgbuilds/edge/omawake-bin/PKGBUILD rename to pkgbuilds/omawake-bin/PKGBUILD diff --git a/pkgbuilds/edge/omawake-bin/omawake-bin.install b/pkgbuilds/omawake-bin/omawake-bin.install similarity index 100% rename from pkgbuilds/edge/omawake-bin/omawake-bin.install rename to pkgbuilds/omawake-bin/omawake-bin.install From 55c564968c82ba6baf20b1192d9e3e15fc4bb528 Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 02:51:21 -0500 Subject: [PATCH 014/121] Update Oma apps to v0.0.1-rc.2 --- pkgbuilds/omaspeak-bin/.SRCINFO | 8 ++++---- pkgbuilds/omaspeak-bin/PKGBUILD | 6 +++--- pkgbuilds/omawake-bin/.SRCINFO | 8 ++++---- pkgbuilds/omawake-bin/PKGBUILD | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO index 14b7359..8f2813c 100644 --- a/pkgbuilds/omaspeak-bin/.SRCINFO +++ b/pkgbuilds/omaspeak-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omaspeak-bin pkgdesc = Local-first text-to-speech application and daemon (pre-built binary) - pkgver = 0.0.1.rc + pkgver = 0.0.1.rc.2 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omaspeak install = omaspeak-bin.install @@ -16,10 +16,10 @@ pkgbase = omaspeak-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omaspeak=0.0.1.rc + provides = omaspeak=0.0.1.rc.2 conflicts = omaspeak options = !strip - source = omaspeak-0.0.1-rc-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc/omaspeak-0.0.1-rc-linux-x86_64.tar.xz - sha256sums = 49c1d0bc2954aad7865746d7edbbe81343ad3a1d33ff0dd6d21e0ecd3a26b115 + source = omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz + sha256sums = ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503 pkgname = omaspeak-bin diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index 6255d8f..5e6d90e 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omaspeak-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc -_upstream_ver=0.0.1-rc +pkgver=0.0.1.rc.2 +_upstream_ver=0.0.1-rc.2 pkgrel=1 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' arch=('x86_64') @@ -30,7 +30,7 @@ options=('!strip') source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") -sha256sums=('49c1d0bc2954aad7865746d7edbbe81343ad3a1d33ff0dd6d21e0ecd3a26b115') +sha256sums=('ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" diff --git a/pkgbuilds/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO index c8d65df..793aeb0 100644 --- a/pkgbuilds/omawake-bin/.SRCINFO +++ b/pkgbuilds/omawake-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omawake-bin pkgdesc = Configurable local wake-word daemon (pre-built binary) - pkgver = 0.0.1.rc + pkgver = 0.0.1.rc.2 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omawake install = omawake-bin.install @@ -16,10 +16,10 @@ pkgbase = omawake-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omawake=0.0.1.rc + provides = omawake=0.0.1.rc.2 conflicts = omawake options = !strip - source = omawake-0.0.1-rc-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc/omawake-0.0.1-rc-linux-x86_64.tar.xz - sha256sums = 52441cefcee285e6941fa25bc45770dc628391f0dd035260509e5cb47c0eeb15 + source = omawake-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-x86_64.tar.xz + sha256sums = 198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc pkgname = omawake-bin diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index a2bc8cc..98fca7f 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omawake-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc -_upstream_ver=0.0.1-rc +pkgver=0.0.1.rc.2 +_upstream_ver=0.0.1-rc.2 pkgrel=1 pkgdesc='Configurable local wake-word daemon (pre-built binary)' arch=('x86_64') @@ -30,7 +30,7 @@ options=('!strip') source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") -sha256sums=('52441cefcee285e6941fa25bc45770dc628391f0dd035260509e5cb47c0eeb15') +sha256sums=('198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" From 4a5696c1341d849c5089acd6b61490292ab06f8d Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 13:48:22 -0500 Subject: [PATCH 015/121] Support both Oma release architectures --- pkgbuilds/omaspeak-bin/.SRCINFO | 8 +++++--- pkgbuilds/omaspeak-bin/PKGBUILD | 11 ++++++----- pkgbuilds/omawake-bin/.SRCINFO | 8 +++++--- pkgbuilds/omawake-bin/PKGBUILD | 11 ++++++----- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO index 8f2813c..d7f61b3 100644 --- a/pkgbuilds/omaspeak-bin/.SRCINFO +++ b/pkgbuilds/omaspeak-bin/.SRCINFO @@ -5,9 +5,9 @@ pkgbase = omaspeak-bin url = https://github.com/jacob-vincent-mink/omaspeak install = omaspeak-bin.install arch = x86_64 + arch = aarch64 license = MIT depends = alsa-utils - depends = bzip2 depends = gcc-libs depends = glibc optdepends = pipewire-audio: audio playback through pw-play @@ -19,7 +19,9 @@ pkgbase = omaspeak-bin provides = omaspeak=0.0.1.rc.2 conflicts = omaspeak options = !strip - source = omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz - sha256sums = ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503 + source_x86_64 = omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz + sha256sums_x86_64 = ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503 + source_aarch64 = omaspeak-0.0.1-rc.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-aarch64.tar.xz + sha256sums_aarch64 = 4a766ddc1218f48ed0622c96c4c93b2553e7a962b5d1ba766a301b1f29a4da3b pkgname = omaspeak-bin diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index 5e6d90e..aa32b91 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -6,12 +6,11 @@ pkgver=0.0.1.rc.2 _upstream_ver=0.0.1-rc.2 pkgrel=1 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' -arch=('x86_64') +arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omaspeak' license=('MIT') depends=( 'alsa-utils' - 'bzip2' 'gcc-libs' 'glibc' ) @@ -28,12 +27,14 @@ conflicts=("${_pkgname}") install="${pkgname}.install" options=('!strip') -source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") +source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") +source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums=('ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503') +sha256sums_x86_64=('ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503') +sha256sums_aarch64=('4a766ddc1218f48ed0622c96c4c93b2553e7a962b5d1ba766a301b1f29a4da3b') package() { - local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" diff --git a/pkgbuilds/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO index 793aeb0..a8affc9 100644 --- a/pkgbuilds/omawake-bin/.SRCINFO +++ b/pkgbuilds/omawake-bin/.SRCINFO @@ -5,9 +5,9 @@ pkgbase = omawake-bin url = https://github.com/jacob-vincent-mink/omawake install = omawake-bin.install arch = x86_64 + arch = aarch64 license = MIT depends = alsa-lib - depends = bzip2 depends = gcc-libs depends = glibc optdepends = pipewire-audio: PipeWire audio support @@ -19,7 +19,9 @@ pkgbase = omawake-bin provides = omawake=0.0.1.rc.2 conflicts = omawake options = !strip - source = omawake-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-x86_64.tar.xz - sha256sums = 198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc + source_x86_64 = omawake-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-x86_64.tar.xz + sha256sums_x86_64 = 198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc + source_aarch64 = omawake-0.0.1-rc.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-aarch64.tar.xz + sha256sums_aarch64 = 56d1a0944efa2bef7ac6049e9abaedb91de6dfd5bfc3a24f93d0964c88600118 pkgname = omawake-bin diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 98fca7f..8540bba 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -6,12 +6,11 @@ pkgver=0.0.1.rc.2 _upstream_ver=0.0.1-rc.2 pkgrel=1 pkgdesc='Configurable local wake-word daemon (pre-built binary)' -arch=('x86_64') +arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omawake' license=('MIT') depends=( 'alsa-lib' - 'bzip2' 'gcc-libs' 'glibc' ) @@ -28,12 +27,14 @@ conflicts=("${_pkgname}") install="${pkgname}.install" options=('!strip') -source=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") +source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") +source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums=('198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc') +sha256sums_x86_64=('198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc') +sha256sums_aarch64=('56d1a0944efa2bef7ac6049e9abaedb91de6dfd5bfc3a24f93d0964c88600118') package() { - local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-x86_64" + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" From f5b29f16e3fb80eb8abd6403403af843606d78ac Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 13:57:15 -0500 Subject: [PATCH 016/121] Update Omaspeak to v0.0.1-rc.3 --- pkgbuilds/omaspeak-bin/.SRCINFO | 12 ++++++------ pkgbuilds/omaspeak-bin/PKGBUILD | 23 ++++++++++++++--------- pkgbuilds/omawake-bin/PKGBUILD | 15 ++++++++++----- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO index d7f61b3..a3b5d1a 100644 --- a/pkgbuilds/omaspeak-bin/.SRCINFO +++ b/pkgbuilds/omaspeak-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omaspeak-bin pkgdesc = Local-first text-to-speech application and daemon (pre-built binary) - pkgver = 0.0.1.rc.2 + pkgver = 0.0.1.rc.3 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omaspeak install = omaspeak-bin.install @@ -16,12 +16,12 @@ pkgbase = omaspeak-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omaspeak=0.0.1.rc.2 + provides = omaspeak=0.0.1.rc.3 conflicts = omaspeak options = !strip - source_x86_64 = omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-x86_64.tar.xz - sha256sums_x86_64 = ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503 - source_aarch64 = omaspeak-0.0.1-rc.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.2/omaspeak-0.0.1-rc.2-linux-aarch64.tar.xz - sha256sums_aarch64 = 4a766ddc1218f48ed0622c96c4c93b2553e7a962b5d1ba766a301b1f29a4da3b + source_x86_64 = omaspeak-0.0.1-rc.3-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.3/omaspeak-0.0.1-rc.3-linux-x86_64.tar.xz + sha256sums_x86_64 = 7a78ee95d65905f29bae1ba3e00b873d268d03eaf27479f8a89d7fffc860dbb0 + source_aarch64 = omaspeak-0.0.1-rc.3-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.3/omaspeak-0.0.1-rc.3-linux-aarch64.tar.xz + sha256sums_aarch64 = 20723aac60195ed1f23b894c16dbb3fad67bf53baa1d5b6c8f1eb4e496f0690f pkgname = omaspeak-bin diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index aa32b91..48cafaa 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omaspeak-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc.2 -_upstream_ver=0.0.1-rc.2 +pkgver=0.0.1.rc.3 +_upstream_ver=0.0.1-rc.3 pkgrel=1 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' arch=('x86_64' 'aarch64') @@ -30,16 +30,21 @@ options=('!strip') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('ed247a8aaef6d18c9d134af902a6248b56ea439aebdb1e838eeda8f741e5a503') -sha256sums_aarch64=('4a766ddc1218f48ed0622c96c4c93b2553e7a962b5d1ba766a301b1f29a4da3b') +sha256sums_x86_64=('7a78ee95d65905f29bae1ba3e00b873d268d03eaf27479f8a89d7fffc860dbb0') +sha256sums_aarch64=('20723aac60195ed1f23b894c16dbb3fad67bf53baa1d5b6c8f1eb4e496f0690f') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" - install -dm755 "${pkgdir}/usr/lib/${_pkgname}" - cp -a "${release_root}/lib/." "${pkgdir}/usr/lib/${_pkgname}/" + install -Dm755 \ + "${release_root}/lib/libaudiocpp.so.0.1.0" \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so.0.1.0" + ln -s libaudiocpp.so.0.1.0 \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so.0" + ln -s libaudiocpp.so.0 \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so" install -Dm644 \ "${release_root}/packaging/systemd/${_pkgname}.service" \ @@ -59,13 +64,13 @@ package() { "${release_root}/${document}" \ "${pkgdir}/usr/share/doc/${pkgname}/${document}" done - cp -a \ + cp -r \ "${release_root}/assets" \ "${release_root}/benchmarks" \ "${pkgdir}/usr/share/doc/${pkgname}/" install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}" - install -m644 \ - "${release_root}"/licenses/* \ + cp -r \ + "${release_root}/licenses/." \ "${pkgdir}/usr/share/licenses/${pkgname}/" } diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 8540bba..ffd572c 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -38,8 +38,13 @@ package() { install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" - install -dm755 "${pkgdir}/usr/lib/${_pkgname}" - cp -a "${release_root}/lib/." "${pkgdir}/usr/lib/${_pkgname}/" + install -Dm755 \ + "${release_root}/lib/libaudiocpp.so.0.1.0" \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so.0.1.0" + ln -s libaudiocpp.so.0.1.0 \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so.0" + ln -s libaudiocpp.so.0 \ + "${pkgdir}/usr/lib/${_pkgname}/libaudiocpp.so" install -Dm644 \ "${release_root}/packaging/systemd/${_pkgname}.service" \ @@ -59,13 +64,13 @@ package() { "${release_root}/${document}" \ "${pkgdir}/usr/share/doc/${pkgname}/${document}" done - cp -a \ + cp -r \ "${release_root}/assets" \ "${release_root}/benchmarks" \ "${pkgdir}/usr/share/doc/${pkgname}/" install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}" - install -m644 \ - "${release_root}"/licenses/* \ + cp -r \ + "${release_root}/licenses/." \ "${pkgdir}/usr/share/licenses/${pkgname}/" } From 977e1c57eaaeeaafff69ee473ea63858d05eb0ed Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 14:06:38 -0500 Subject: [PATCH 017/121] Update Omawake to v0.0.1-rc.3 --- pkgbuilds/omawake-bin/.SRCINFO | 12 ++++++------ pkgbuilds/omawake-bin/PKGBUILD | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgbuilds/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO index a8affc9..91f162c 100644 --- a/pkgbuilds/omawake-bin/.SRCINFO +++ b/pkgbuilds/omawake-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omawake-bin pkgdesc = Configurable local wake-word daemon (pre-built binary) - pkgver = 0.0.1.rc.2 + pkgver = 0.0.1.rc.3 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omawake install = omawake-bin.install @@ -16,12 +16,12 @@ pkgbase = omawake-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omawake=0.0.1.rc.2 + provides = omawake=0.0.1.rc.3 conflicts = omawake options = !strip - source_x86_64 = omawake-0.0.1-rc.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-x86_64.tar.xz - sha256sums_x86_64 = 198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc - source_aarch64 = omawake-0.0.1-rc.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.2/omawake-0.0.1-rc.2-linux-aarch64.tar.xz - sha256sums_aarch64 = 56d1a0944efa2bef7ac6049e9abaedb91de6dfd5bfc3a24f93d0964c88600118 + source_x86_64 = omawake-0.0.1-rc.3-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.3/omawake-0.0.1-rc.3-linux-x86_64.tar.xz + sha256sums_x86_64 = 026ed87bcb44feac683f7087d611031b5ce01dbf2fe2f77e6838c9a27020f009 + source_aarch64 = omawake-0.0.1-rc.3-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.3/omawake-0.0.1-rc.3-linux-aarch64.tar.xz + sha256sums_aarch64 = c3d57b2e865eeb886660ced7bda6223b354975368162d637961c084c848fc5e6 pkgname = omawake-bin diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index ffd572c..490c75f 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omawake-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc.2 -_upstream_ver=0.0.1-rc.2 +pkgver=0.0.1.rc.3 +_upstream_ver=0.0.1-rc.3 pkgrel=1 pkgdesc='Configurable local wake-word daemon (pre-built binary)' arch=('x86_64' 'aarch64') @@ -30,8 +30,8 @@ options=('!strip') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('198b4a85b3760f024e088c7b45d5bf85c9eb4f000de0b33aa064b33a860b1acc') -sha256sums_aarch64=('56d1a0944efa2bef7ac6049e9abaedb91de6dfd5bfc3a24f93d0964c88600118') +sha256sums_x86_64=('026ed87bcb44feac683f7087d611031b5ce01dbf2fe2f77e6838c9a27020f009') +sha256sums_aarch64=('c3d57b2e865eeb886660ced7bda6223b354975368162d637961c084c848fc5e6') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" From edc411ae4d95a2e14f28f4b85c41221a1e15d864 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 16:13:12 -0400 Subject: [PATCH 018/121] Build Ghostty for x86_64 with pinned Zig toolchain --- pkgbuilds/ghostty/PKGBUILD | 27 ++++++++++++++++--------- pkgbuilds/ghostty/build-data-llvm.patch | 10 +++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 pkgbuilds/ghostty/build-data-llvm.patch diff --git a/pkgbuilds/ghostty/PKGBUILD b/pkgbuilds/ghostty/PKGBUILD index 23166e5..d0f0ed0 100644 --- a/pkgbuilds/ghostty/PKGBUILD +++ b/pkgbuilds/ghostty/PKGBUILD @@ -1,15 +1,15 @@ -# Ghostty for aarch64, built from the upstream release source tarball. +# Ghostty for x86_64 and aarch64, built from the upstream release source tarball. # -# Ghostty 1.3.x requires Zig 0.15.2 exactly. Arch Linux ARM currently ships -# newer Zig releases, so use the verified upstream aarch64 toolchain only at +# Ghostty 1.3.x requires Zig 0.15.2 exactly. Distribution toolchains can move +# ahead, so use the verified upstream toolchain for each architecture only at # package-build time rather than publishing a second Zig package. pkgbase=ghostty pkgname=(ghostty ghostty-shell-integration ghostty-terminfo ghostty-nautilus) pkgver=1.3.1 -pkgrel=1 +pkgrel=3 pkgdesc='Fast, native, feature-rich terminal emulator pushing modern features' -arch=(aarch64) +arch=(x86_64 aarch64) url='https://github.com/ghostty-org/ghostty' license=(MIT) depends=( @@ -38,16 +38,25 @@ _zigver=0.15.2 _archive="$pkgbase-$pkgver" source=( "https://release.files.ghostty.org/$pkgver/$_archive.tar.gz" - "https://ziglang.org/download/$_zigver/zig-aarch64-linux-$_zigver.tar.xz" + 'build-data-llvm.patch' ) sha256sums=( '3349d25600ffbda281197a18314f7d18791969cffe9474f0ff16a45a9ebfccdb' - '958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f' + 'd9f5781b748651fa1ff7b919f4a79cd8570118faefe2848f64f02ea4220257ba' ) +source_x86_64=("https://ziglang.org/download/$_zigver/zig-x86_64-linux-$_zigver.tar.xz") +sha256sums_x86_64=('02aa270f183da276e5b5920b1dac44a63f1a49e55050ebde3aecc9eb82f93239') +source_aarch64=("https://ziglang.org/download/$_zigver/zig-aarch64-linux-$_zigver.tar.xz") +sha256sums_aarch64=('958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f') prepare() { cd "$_archive" - PATH="$srcdir/zig-aarch64-linux-$_zigver:$PATH" \ + # Zig's native x86 linker cannot read .sframe relocations in Arch's crt1.o. + # Use bundled LLVM for the build-data helper, as the main executable does. + if [[ "$CARCH" == x86_64 ]]; then + patch -Np1 -i "$srcdir/build-data-llvm.patch" + fi + PATH="$srcdir/zig-$CARCH-linux-$_zigver:$PATH" \ ZIG_GLOBAL_CACHE_DIR="$srcdir/zig-global-cache" \ ./nix/build-support/fetch-zig-cache.sh } @@ -56,7 +65,7 @@ build() { cd "$_archive" # A '-' suffix is a SemVer prerelease and selects Ghostty's tip channel. # Keep the package revision as build metadata on the stable release. - PATH="$srcdir/zig-aarch64-linux-$_zigver:$PATH" \ + PATH="$srcdir/zig-$CARCH-linux-$_zigver:$PATH" \ DESTDIR=build \ zig build \ --prefix /usr \ diff --git a/pkgbuilds/ghostty/build-data-llvm.patch b/pkgbuilds/ghostty/build-data-llvm.patch new file mode 100644 index 0000000..629f3d6 --- /dev/null +++ b/pkgbuilds/ghostty/build-data-llvm.patch @@ -0,0 +1,10 @@ +--- a/src/build/GhosttyResources.zig ++++ b/src/build/GhosttyResources.zig +@@ -15,6 +15,7 @@ + // This is the exe used to generate some build data. + const build_data_exe = b.addExecutable(.{ + .name = "ghostty-build-data", ++ .use_llvm = true, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main_build_data.zig"), + .target = b.graph.host, From 5fe236736607b1a9f6df3c3a4b364515f70eed53 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 17:04:09 -0400 Subject: [PATCH 019/121] Release omarchy 4.0.4 --- pkgbuilds/omarchy-settings/PKGBUILD | 8 ++++---- pkgbuilds/omarchy/PKGBUILD | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgbuilds/omarchy-settings/PKGBUILD b/pkgbuilds/omarchy-settings/PKGBUILD index 9a10ab7..5eb5ca8 100644 --- a/pkgbuilds/omarchy-settings/PKGBUILD +++ b/pkgbuilds/omarchy-settings/PKGBUILD @@ -10,9 +10,9 @@ # provenance only (empty when cut from a bare commit). omarchy and # omarchy-settings must always carry identical _tag/_commit/pkgver/sha256sums. pkgname='omarchy-settings' -_tag='v4.0.3' -_commit='0534987009061cbe2dacdde4ad564092ab698d12' -pkgver=4.0.3 +_tag='v4.0.4' +_commit='c668141e9c42b13c80c9ca4ea108e11708c5e8a5' +pkgver=4.0.4 pkgrel=1 pkgdesc='Omarchy user defaults, /etc/skel content, fonts, plymouth theme, and support helpers' # Arch-specific because the shipped /etc tree is not the same on every @@ -125,7 +125,7 @@ if [[ -n "${OMARCHY_SRC:-}" ]]; then sha256sums=() else source=("omarchy::git+https://github.com/basecamp/omarchy.git#commit=${_commit}") - sha256sums=('3558399c3ddc0b9067d63c0d617d695829d8293689e9319a304839c3a6e0f9f3') + sha256sums=('8371b148aa06e9d0627c9e11668ef2dfdf54c4a9e5ffbee5aee08c3945073618') fi prepare() { diff --git a/pkgbuilds/omarchy/PKGBUILD b/pkgbuilds/omarchy/PKGBUILD index 684b448..41314ea 100644 --- a/pkgbuilds/omarchy/PKGBUILD +++ b/pkgbuilds/omarchy/PKGBUILD @@ -10,9 +10,9 @@ # provenance only (empty when cut from a bare commit). omarchy and # omarchy-settings must always carry identical _tag/_commit/pkgver/sha256sums. pkgname='omarchy' -_tag='v4.0.3' -_commit='0534987009061cbe2dacdde4ad564092ab698d12' -pkgver=4.0.3 +_tag='v4.0.4' +_commit='c668141e9c42b13c80c9ca4ea108e11708c5e8a5' +pkgver=4.0.4 pkgrel=1 pkgdesc='Beautiful, modern, and opinionated Arch Linux by DHH' # The payload is architecture-independent, but the dependency set is not: the @@ -94,7 +94,7 @@ if [[ -n "${OMARCHY_SRC:-}" ]]; then sha256sums=() else source=("omarchy::git+https://github.com/basecamp/omarchy.git#commit=${_commit}") - sha256sums=('3558399c3ddc0b9067d63c0d617d695829d8293689e9319a304839c3a6e0f9f3') + sha256sums=('8371b148aa06e9d0627c9e11668ef2dfdf54c4a9e5ffbee5aee08c3945073618') fi prepare() { From 46306a12eb829902e8d7fd1d978117b471820a08 Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 16:09:13 -0500 Subject: [PATCH 020/121] Package Omawake 0.0.2 and Omaspeak 0.0.1 --- pkgbuilds/omaspeak-bin/.SRCINFO | 12 ++++++------ pkgbuilds/omaspeak-bin/PKGBUILD | 8 ++++---- pkgbuilds/omawake-bin/.SRCINFO | 12 ++++++------ pkgbuilds/omawake-bin/PKGBUILD | 8 ++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO index a3b5d1a..674faf3 100644 --- a/pkgbuilds/omaspeak-bin/.SRCINFO +++ b/pkgbuilds/omaspeak-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omaspeak-bin pkgdesc = Local-first text-to-speech application and daemon (pre-built binary) - pkgver = 0.0.1.rc.3 + pkgver = 0.0.1 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omaspeak install = omaspeak-bin.install @@ -16,12 +16,12 @@ pkgbase = omaspeak-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omaspeak=0.0.1.rc.3 + provides = omaspeak=0.0.1 conflicts = omaspeak options = !strip - source_x86_64 = omaspeak-0.0.1-rc.3-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.3/omaspeak-0.0.1-rc.3-linux-x86_64.tar.xz - sha256sums_x86_64 = 7a78ee95d65905f29bae1ba3e00b873d268d03eaf27479f8a89d7fffc860dbb0 - source_aarch64 = omaspeak-0.0.1-rc.3-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1-rc.3/omaspeak-0.0.1-rc.3-linux-aarch64.tar.xz - sha256sums_aarch64 = 20723aac60195ed1f23b894c16dbb3fad67bf53baa1d5b6c8f1eb4e496f0690f + source_x86_64 = omaspeak-0.0.1-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1/omaspeak-0.0.1-linux-x86_64.tar.xz + sha256sums_x86_64 = 9e318960fb15fdf955efbb8dda9bc8eb2b9d0932a9acd9e31b85bf3492ca78ea + source_aarch64 = omaspeak-0.0.1-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1/omaspeak-0.0.1-linux-aarch64.tar.xz + sha256sums_aarch64 = 8a0d7728d0b6d3f447ab7a616389fc8c54a0617f14922b33593ca60b425deb8d pkgname = omaspeak-bin diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index 48cafaa..26d4d91 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omaspeak-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc.3 -_upstream_ver=0.0.1-rc.3 +pkgver=0.0.1 +_upstream_ver=0.0.1 pkgrel=1 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' arch=('x86_64' 'aarch64') @@ -30,8 +30,8 @@ options=('!strip') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('7a78ee95d65905f29bae1ba3e00b873d268d03eaf27479f8a89d7fffc860dbb0') -sha256sums_aarch64=('20723aac60195ed1f23b894c16dbb3fad67bf53baa1d5b6c8f1eb4e496f0690f') +sha256sums_x86_64=('9e318960fb15fdf955efbb8dda9bc8eb2b9d0932a9acd9e31b85bf3492ca78ea') +sha256sums_aarch64=('8a0d7728d0b6d3f447ab7a616389fc8c54a0617f14922b33593ca60b425deb8d') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" diff --git a/pkgbuilds/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO index 91f162c..951ca45 100644 --- a/pkgbuilds/omawake-bin/.SRCINFO +++ b/pkgbuilds/omawake-bin/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = omawake-bin pkgdesc = Configurable local wake-word daemon (pre-built binary) - pkgver = 0.0.1.rc.3 + pkgver = 0.0.2 pkgrel = 1 url = https://github.com/jacob-vincent-mink/omawake install = omawake-bin.install @@ -16,12 +16,12 @@ pkgbase = omawake-bin optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omawake=0.0.1.rc.3 + provides = omawake=0.0.2 conflicts = omawake options = !strip - source_x86_64 = omawake-0.0.1-rc.3-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.3/omawake-0.0.1-rc.3-linux-x86_64.tar.xz - sha256sums_x86_64 = 026ed87bcb44feac683f7087d611031b5ce01dbf2fe2f77e6838c9a27020f009 - source_aarch64 = omawake-0.0.1-rc.3-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.1-rc.3/omawake-0.0.1-rc.3-linux-aarch64.tar.xz - sha256sums_aarch64 = c3d57b2e865eeb886660ced7bda6223b354975368162d637961c084c848fc5e6 + source_x86_64 = omawake-0.0.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.2/omawake-0.0.2-linux-x86_64.tar.xz + sha256sums_x86_64 = 94f0677eb497babd351cb154e9adf057e4b796efe0241d809a7f7cf84742a515 + source_aarch64 = omawake-0.0.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.2/omawake-0.0.2-linux-aarch64.tar.xz + sha256sums_aarch64 = acb359b21bbe4909b13c18a0de63f8106c6b254943074b57d8fd70af41421659 pkgname = omawake-bin diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 490c75f..42b3ca8 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -2,8 +2,8 @@ pkgname=omawake-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1.rc.3 -_upstream_ver=0.0.1-rc.3 +pkgver=0.0.2 +_upstream_ver=0.0.2 pkgrel=1 pkgdesc='Configurable local wake-word daemon (pre-built binary)' arch=('x86_64' 'aarch64') @@ -30,8 +30,8 @@ options=('!strip') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('026ed87bcb44feac683f7087d611031b5ce01dbf2fe2f77e6838c9a27020f009') -sha256sums_aarch64=('c3d57b2e865eeb886660ced7bda6223b354975368162d637961c084c848fc5e6') +sha256sums_x86_64=('94f0677eb497babd351cb154e9adf057e4b796efe0241d809a7f7cf84742a515') +sha256sums_aarch64=('acb359b21bbe4909b13c18a0de63f8106c6b254943074b57d8fd70af41421659') package() { local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" From 3c671736ec336201fdc079b4c89b1d8269a3c3d1 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 15 Sep 2026 22:21:52 -0400 Subject: [PATCH 021/121] Put Ghostty on the fast release ring --- pkgbuilds/ghostty/.omarchy/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgbuilds/ghostty/.omarchy/package.json b/pkgbuilds/ghostty/.omarchy/package.json index 088e385..f9c4cf1 100644 --- a/pkgbuilds/ghostty/.omarchy/package.json +++ b/pkgbuilds/ghostty/.omarchy/package.json @@ -1,5 +1,6 @@ { "source": "local", + "release_ring": "fast", "upstream": { "watch": { "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)", From f868f3c76705024fcf2edae68ba9a0bb6c4b7cb8 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Tue, 15 Sep 2026 23:05:22 -0500 Subject: [PATCH 022/121] Preserve user keymaps in the Cua Hyprland plugin Give background agent seats independent keymaps and check foreground keyboard compatibility per operation. Package the downstream patch with separate source integrity and build provenance, retaining the upstream ABI verifier. Co-Authored-By: Codex XHigh --- .../DOWNSTREAM-PROVENANCE.json | 56 ++ pkgbuilds/cua-hyprland-plugin/PKGBUILD | 65 +- pkgbuilds/cua-hyprland-plugin/PROFILE.json | 4 +- pkgbuilds/cua-hyprland-plugin/README.md | 113 +-- pkgbuilds/cua-hyprland-plugin/downstream.py | 96 +++ .../cua-hyprland-plugin/downstream_test.py | 75 ++ .../independent-keymaps.patch | 719 ++++++++++++++++++ 7 files changed, 1021 insertions(+), 107 deletions(-) create mode 100644 pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json create mode 100644 pkgbuilds/cua-hyprland-plugin/downstream.py create mode 100644 pkgbuilds/cua-hyprland-plugin/downstream_test.py create mode 100644 pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch diff --git a/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json b/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json new file mode 100644 index 0000000..8fa0d3b --- /dev/null +++ b/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json @@ -0,0 +1,56 @@ +{ + "files": { + "CMakeLists.txt": "4a2027383ae39b052c4cf30732810f93ee1170b7987777aa9e8ea282abb17731", + "LICENSE.md": "c0779290c1d4783169aa3dbfb55feb505e563ef8a004bbf55298ceffcfbda8d9", + "SOURCE-PROVENANCE.json": "54f514664c84e1358a435f29cd6befd5661b0b133d76997191c000b10f021a75", + "cmake/DetectHyprlandAPI.cmake": "216133ec0eb141c3696bf3770a23e63e46521c9e91a0245a7cb75c20a75ba2c5", + "cmake/VerifyRuntime.cmake": "5869f79a418e7aa6178d2b9166c36cd01c3093c2579b647624968244db57b761", + "include/cua_hyprland/protocol.hpp": "7051463b3c61a2dc93c388e66b6136b7bb524f8694350f249f9d2b5c55826493", + "include/cua_hyprland/session.hpp": "e6a968e4f2ac28122cb7413a0e318f6222d2a0a1b7b0c45f4ab419a78639ebea", + "include/cua_hyprland/status.hpp": "56a9656647c0f4eeb0c588cd4b98a77df198d1f90421f973e9a80e6802f61495", + "src/drag_geometry.hpp": "c5b783d15ff197f22938f08f8d176bab5d45544fe989d150f15cb99295acedb8", + "src/foreground_route.hpp": "bf07e9ada1a3e25dd85611d5f3f4f725df50b1b8fc1d4c4903fb5c6dc9c3d5f8", + "src/inject_server.cpp": "0935283580c50fcf0e4ad956f858885700536002b1d86d2f078da9c4404ee9e8", + "src/inject_server.hpp": "67de008b4d6983371207bb22a57bab154b1dedda9b38d1207d3ac8cb379382eb", + "src/input_client_deadline.hpp": "00a91a789ff698820607449ff7152e2fb50d0f315e0fa9c5c3855752bfffe2ef", + "src/input_experiment.cpp": "358fa86abd21dbfda8460b21b3568d0199e47ed79ef6c5dd0c7e0c6d4c026290", + "src/input_experiment.hpp": "9da2ddab7f0de6e9cf02aea53e9119acef17ef8513af849bb5aa3d137ebd12c3", + "src/input_grant.hpp": "90b544b2f559bacd920b85ab5915f09ff201de3c05a052ce1b71ff71f767e6a6", + "src/keyboard_layout.hpp": "66d7d1ace6357c5be26f4a9b57730709fe21e30267437051c62b6697eb073300", + "src/owned_socket_path.hpp": "8e784656d944c700f3ded383c93a8cadf846dabdaa4cc12673bcb637c26d9fd1", + "src/passive_pointer_target.hpp": "ede36fd9fd6e95ae5923c751f12591084392be9d2270eb06ad64eb4f245169fa", + "src/plugin.cpp": "e36817f12b47f317dde300cfa6820ce2d408c8fe5bfea3a3e5c727b86d461d3e", + "src/primary_trace.cpp": "e9468d1a3f3be2a90d47bf8c4a638ad8a60fe10b6297582ab7825751cb707aa9", + "src/primary_trace.hpp": "8d62535fb0b24a02bb80d9a8dcd540b39204afb2f3b4bcb5cabd5275c3b5eaa7", + "src/protocol.cpp": "bd083d65efb05e80946566dc535b1a6fadaa581c66ec327eff41796feba795b1", + "src/seat_lifetime.hpp": "386cf5c72c178f8eec0824f2a7d46fa755b0bb000861f9a6e00802f6b81fb779", + "src/session.cpp": "0105c7ba5f9e2dbdd9a21f48be0bc1f2bde930f6aa19f77e2216403d7790e4df", + "src/status.cpp": "e46e81e5e8ae3b1f50af5dcaa6c1776e236321c788fe61b402c9923c797b1270", + "tests/agent_keymap_test.py": "9b112f520a97a77a0d55f1009cd2594988d3c1e8e7bcaa39f213ffad2644dc56", + "tests/cmake-api/CMakeLists.txt": "6a66c8f98023f029998af917fcd3ec6b1388607bdf7acaf5bdfaef9141962685", + "tests/cmake-api/include/src/plugins/PluginAPI.hpp": "86c8ad51e668908d18928cef1b04e8e6d32a33894525640b52f0b31769c870a0", + "tests/desktop_fault_policy_fixture.cpp": "ac24d675ebc64cc98148e852eb5aba5858bffc06332678d14276d04b317aaf15", + "tests/desktop_fault_policy_test.py": "c3f624c0239036babd23eaaf1bb6b722f3a0c3321a5d3d6668ae7ab4910ca95c", + "tests/drag_geometry_test.cpp": "d32ea649d008fc051fe18555d6fbc54ba5d057b61880b648c5df8aa076a53fbc", + "tests/foreground_route_test.cpp": "1024168828b13ee6abd8242941e73c042e9381b39108e3ada74823039c7e7932", + "tests/input_client_deadline_test.cpp": "d62373a7815d531f1269c9a838773595f43e8bcef6482fa140edb162e59a6cac", + "tests/input_grant_test.cpp": "1f327b7ee678189ebad6a50bb1b9bd06767521cebc9cfb478d92de4a8bf7e7fe", + "tests/keyboard_layout_test.cpp": "80f76d16896bbb77269a52e12c18c079d642618d29d0608f23a3d7ae2844f21f", + "tests/mock-hyprland/mock.hpp": "3aeb1a4b9d6b83506b66c129d3fa812330fad4509fe218a0dbb99dd2bb5b6319", + "tests/mock-hyprland/src/config/values/types/BoolValue.hpp": "47cf2cca89f71a273573968cb9b8ba46a1496841d6c892756ebf123500a7ecb3", + "tests/mock-hyprland/src/plugins/PluginAPI.hpp": "5654d90ec9090a88bea3d31f8a79617d4c79742b09068648e64448319d395110", + "tests/owned_socket_path_test.cpp": "eaff6b5c6f148eca6c8650ee3dc212a5e892f002ee4f68b2a1290c7205ee7e42", + "tests/passive_pointer_target_test.cpp": "2aeef1de1dc8932b26ab8c41b83fb16a4289ff96c177a5816088f07b9a168948", + "tests/plugin_api_test.cpp": "1e7e200c309996ee945c88e172273ae942be2837e24564d422dee79d8b77d8a2", + "tests/plugin_input_lifetime_test.cpp": "9d291fc6d7de5e9a80a07c2de16de85739e9ba6fe2ceace371f64b94af4724c0", + "tests/protocol_test.cpp": "119cfe0df81c0c00036a2d181764eda7601d6ee72459c2275a96226d4f670447", + "tests/seat_lifetime_test.cpp": "b07570edbe0a142f97c54560eeb93e8327c435ab3b8cbc7496d55175e387b78a", + "tests/status_test.cpp": "b8990efc53ec3820cfe498c920b9220c4b70615ad585468558e032e7619e32f3", + "tests/transport_test.cpp": "deef114a950a27eaff0a530165ddf7db0bfc0fe7e8fb55bdbb66135c8e0c04c9", + "verify.py": "fb35d62313ff4661f892f88666919b33b160f8b6d4fb2d5d52610708bf7f4a54" + }, + "patch_sha256": "5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4", + "schema": 1, + "upstream_manifest_sha256": "54f514664c84e1358a435f29cd6befd5661b0b133d76997191c000b10f021a75", + "upstream_revision": "cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7" +} diff --git a/pkgbuilds/cua-hyprland-plugin/PKGBUILD b/pkgbuilds/cua-hyprland-plugin/PKGBUILD index cfcf472..788b938 100644 --- a/pkgbuilds/cua-hyprland-plugin/PKGBUILD +++ b/pkgbuilds/cua-hyprland-plugin/PKGBUILD @@ -1,21 +1,21 @@ -# Verified upstream kit with a local package-revision profile; source/tooling are unchanged. +# Verified upstream kit plus a separately pinned Omarchy keyboard-remap patch. # Normal reruns need a fresh build directory; makepkg -e reuses verified extracted trees. # Profile kit: original source bytes and separately committed packaging tooling. # shellcheck shell=bash disable=SC2034,SC2154 pkgname=cua-hyprland-plugin pkgver=0.26.1 -pkgrel=3 -pkgdesc='Cua input candidate for reviewed profile omarchy-hyprland-0562r3' +pkgrel=4 +pkgdesc='Cua input candidate for reviewed profile omarchy-hyprland-0562r3-remaps' arch=('x86_64') url='https://github.com/trycua/cua' license=('MIT') depends=('hyprland=0.56.2-3' 'aquamarine=0.15.0-2' 'glibc=2.44+r24+g16be1518495f-1' 'hyprcursor=0.1.13-7' 'hyprgraphics=0.5.1-4' 'hyprlang=0.6.8-5' 'hyprutils=0.14.2-1' 'libgcc=16.2.1+r23+gd564253eb6c8-1' 'libstdc++=16.2.1+r23+gd564253eb6c8-1' 'libxkbcommon=1.13.2-1' 'wayland=1.26.0-1' 'python>=3.11' 'binutils') -makedepends=('cmake>=3.30' 'ninja' 'pkgconf' 'gcc') +makedepends=('cmake>=3.30' 'ninja' 'pkgconf' 'gcc' 'patch') options=('!strip' '!debug' '!lto') _stem='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7' _archive_sha256='47bca9e018f32f4fcfe683f91c7475c60368f3b65d318cc35c1f2de88a4ee9ab' -_kit_sha256='1391084a903254fb16d251522dba41ae34a06cfa4b2f6b7ba91a3cceeb895921' -_profile_sha256='eebba812a7513b471cf8969364334a4bde1eaa9c4519157701c771c1b6cd1b07' +_kit_sha256='aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2' +_profile_sha256='ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a' _verifier_sha256='480f649cbd35a0ddc7f49dc0a3a44785402c9e0ec9653b0f8ea4965d52d7f900' _cxx="${CUA_RELEASE_CXX:-/usr/bin/g++}" _download_name='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7-profile-omarchy-stable-20260910-kit-1.1.0-5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a-67f89ceb47edd973aa748820eadd02ddbfb3d3e4.tar.gz' @@ -24,7 +24,17 @@ source=('https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0 'PROFILE.json') noextract=("$_download_name") sha256sums=('a89bfa7f6490f598719dfabdd2a5badc137e27b0764fd25e6a05e1f969433520' - 'eebba812a7513b471cf8969364334a4bde1eaa9c4519157701c771c1b6cd1b07') + 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a') + +# Downstream inputs are also checked explicitly when makepkg integrity is skipped. +declare -gA _downstream_sha256=( + ['independent-keymaps.patch']='5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4' + ['DOWNSTREAM-PROVENANCE.json']='e87949fa29d8c006f1c829cb81e640980b349a704bedb5f1d4fe7dc47746994e' + ['downstream.py']='7c9725805ad038737bd4d346c85f27991ce9ddfff436a32ebf515cad1bf98ca1' + ['downstream_test.py']='7b9a992979b22a5e061fdf011ac6be59a3f1ae6e0d7c0a8ff631f74e71984c5a' +) +source+=('independent-keymaps.patch' 'DOWNSTREAM-PROVENANCE.json' 'downstream.py' 'downstream_test.py') +sha256sums+=('5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4' 'e87949fa29d8c006f1c829cb81e640980b349a704bedb5f1d4fe7dc47746994e' '7c9725805ad038737bd4d346c85f27991ce9ddfff436a32ebf515cad1bf98ca1' '7b9a992979b22a5e061fdf011ac6be59a3f1ae6e0d7c0a8ff631f74e71984c5a') _verify_download() { python3 -I - "$SRCDEST/$_download_name" "$_download_sha256" "$srcdir" "$1" "$SRCDEST/PROFILE.json" <<'CUA_DOWNLOAD_PY' @@ -65,10 +75,10 @@ require(payload.keys() == expected.keys(), 'outer kit inventory mismatch') # files as -2. Derive a version-only profile with the original source/tooling # and byte checks intact; record its own profile and kit provenance digests. profile_data = Path(profile_path).read_bytes() -require(digest(profile_data) == 'eebba812a7513b471cf8969364334a4bde1eaa9c4519157701c771c1b6cd1b07', +require(digest(profile_data) == 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a', 'local profile checksum mismatch') profile = json.loads(payload['PROFILE.json']) -profile.update(profile_id='omarchy-hyprland-0562r3', package_release=3) +profile.update(profile_id='omarchy-hyprland-0562r3-remaps', package_release=4) profile['hyprland']['package_version'] = '0.56.2-3' require(json.loads(profile_data) == profile, 'local profile changes more than the reviewed package revision') payload['PROFILE.json'] = profile_data @@ -76,7 +86,7 @@ provenance = json.loads(payload['KIT-PROVENANCE.json']) provenance['profile_sha256'] = digest(profile_data) payload['KIT-PROVENANCE.json'] = (json.dumps(provenance, sort_keys=True, indent=2) + '\n').encode() recipe = payload['PKGBUILD'].decode() -for old, new in [('pkgrel=2\n', 'pkgrel=3\n'), ('omarchy-stable-20260910', profile['profile_id']), +for old, new in [('pkgrel=2\n', 'pkgrel=4\n'), ('omarchy-stable-20260910', profile['profile_id']), ('hyprland=0.56.2-2', 'hyprland=0.56.2-3'), ('5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a', digest(profile_data)), ('7beb736adfd334eed52e84070177634269e3a09f8bb25971b38606933ff4c997', digest(payload['KIT-PROVENANCE.json']))]: @@ -84,10 +94,10 @@ for old, new in [('pkgrel=2\n', 'pkgrel=3\n'), ('omarchy-stable-20260910', profi payload['PKGBUILD'] = recipe.encode() payload['SHA256SUMS'] = ''.join(f'{digest(body)} {name}\n' for name, body in sorted(payload.items()) if name != 'SHA256SUMS').encode() -expected.update({'PROFILE.json': 'eebba812a7513b471cf8969364334a4bde1eaa9c4519157701c771c1b6cd1b07', - 'KIT-PROVENANCE.json': '1391084a903254fb16d251522dba41ae34a06cfa4b2f6b7ba91a3cceeb895921', - 'PKGBUILD': '4c5ef50c5a8d556d461afe283b13b228fb09d2558b37fb76257e13e25846325b', - 'SHA256SUMS': '2ea22af60f8c86df588fd7db103d9f444d9ac4018b704a48ddff2545ff7ce999'}) +expected.update({'PROFILE.json': 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a', + 'KIT-PROVENANCE.json': 'aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2', + 'PKGBUILD': '0e71ddab36e5d9214c35811f2cbf89cc98e5b4fdf6656f85e6b3885d07a1c021', + 'SHA256SUMS': '404cf40875ab14b8af84847abd4674945b1c7ab2e0bfb1605fa11e2d85d789db'}) for name, content in payload.items(): require(digest(content) == expected[name], 'derived kit checksum mismatch: ' + name) require(srcdir.is_dir() and not srcdir.is_symlink(), 'srcdir must be a real directory') @@ -132,17 +142,31 @@ _verify() { printf '%s %s\n' "$_profile_sha256" "$srcdir/cua-profile-kit/PROFILE.json" | sha256sum -c - || return 1 printf '%s %s\n' "$_verifier_sha256" "$srcdir/cua-profile-kit/profile_verify.py" | sha256sum -c - || return 1 python3 "$srcdir/cua-profile-kit/profile_verify.py" --kit "$srcdir/cua-profile-kit" --kit-sha256 "$_kit_sha256" \ - --archive "$srcdir/cua-profile-kit/${_stem}.tar.gz" --source "$srcdir/$_stem" --cxx "$_cxx" "$@" + --archive "$srcdir/cua-profile-kit/${_stem}.tar.gz" --source "$srcdir/$_stem" --cxx "$_cxx" +} + +_downstream() { + local name + for name in independent-keymaps.patch DOWNSTREAM-PROVENANCE.json downstream.py downstream_test.py; do + printf '%s %s\n' "${_downstream_sha256[$name]}" "$SRCDEST/$name" | sha256sum -c - || return 1 + done + python3 -B "$SRCDEST/downstream.py" "$1" \ + --pristine "$srcdir/$_stem" --source "$srcdir/omarchy-source" \ + --patch "$SRCDEST/independent-keymaps.patch" --manifest "$SRCDEST/DOWNSTREAM-PROVENANCE.json" \ + --kit "$srcdir/cua-profile-kit" --kit-sha256 "$_kit_sha256" \ + --archive "$srcdir/cua-profile-kit/${_stem}.tar.gz" --cxx "$_cxx" "${@:2}" } prepare() { _verify_download extract || return 1 - _verify + _verify || return 1 + _downstream prepare } build() { _verify || return 1 - cmake -S "$srcdir/$_stem" -B "$srcdir/build" -G Ninja \ + _downstream check || return 1 + cmake -S "$srcdir/omarchy-source" -B "$srcdir/build" -G Ninja \ -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER="$_cxx" \ -DPKG_CONFIG_EXECUTABLE=/usr/bin/pkgconf -DPKG_CONFIG_ARGN= \ -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=OFF -DCMAKE_PREFIX_PATH= \ @@ -155,6 +179,8 @@ build() { check() { _verify || return 1 + _downstream check || return 1 + python3 -B "$SRCDEST/downstream_test.py" || return 1 ( unset LD_PRELOAD FAKEROOTKEY FAKED_MODE ctest --test-dir "$srcdir/build" --output-on-failure --no-tests=error @@ -163,7 +189,7 @@ check() { package() { check || return 1 - _verify --build "$srcdir/build" --output "$srcdir/BUILD-PROVENANCE.json" || return 1 + _downstream build --build "$srcdir/build" --output "$srcdir/BUILD-PROVENANCE.json" || return 1 install -Dm755 "$srcdir/build/cua-hyprland-plugin.so" \ "$pkgdir/usr/lib/cua/hyprland/cua-hyprland-plugin.so" || return 1 install -Dm644 "$srcdir/$_stem/LICENSE.md" \ @@ -175,4 +201,7 @@ package() { for name in KIT-PROVENANCE.json PROFILE.json profile_verify.py; do install -Dm644 "$srcdir/cua-profile-kit/$name" "$pkgdir/usr/share/$pkgname/$name" || return 1 done + for name in DOWNSTREAM-PROVENANCE.json independent-keymaps.patch; do + install -Dm644 "$SRCDEST/$name" "$pkgdir/usr/share/$pkgname/$name" || return 1 + done } diff --git a/pkgbuilds/cua-hyprland-plugin/PROFILE.json b/pkgbuilds/cua-hyprland-plugin/PROFILE.json index ec78d11..81bbd99 100644 --- a/pkgbuilds/cua-hyprland-plugin/PROFILE.json +++ b/pkgbuilds/cua-hyprland-plugin/PROFILE.json @@ -12,8 +12,8 @@ "sha256": "da8fcacf347bcbed83edc40108c6e2298da095e22246bd764e9bb382786cebb2" }, "kit_version": "1.1.0", - "package_release": 3, - "profile_id": "omarchy-hyprland-0562r3", + "package_release": 4, + "profile_id": "omarchy-hyprland-0562r3-remaps", "runtime": { "basename": "libstdc++.so.6.0.36", "packages": { diff --git a/pkgbuilds/cua-hyprland-plugin/README.md b/pkgbuilds/cua-hyprland-plugin/README.md index 15820ef..652cae7 100644 --- a/pkgbuilds/cua-hyprland-plugin/README.md +++ b/pkgbuilds/cua-hyprland-plugin/README.md @@ -1,6 +1,6 @@ # Optional Cua Hyprland plugin -This package targets **Omarchy stable x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. +This package targets **Omarchy stable x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Package release `4` adds an Omarchy patch for independent agent keymaps and operation-specific foreground checks; the upstream native qualification below covers the unpatched source, not this change. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. The plugin is optional. Cua Driver works independently, and installation does not load the plugin or enable input. The package follows the normal edge-to-RC-to-stable promotion path instead of the fast release ring. Its PKGBUILD limits builds to x86_64; only stable x86_64 is a qualified target. @@ -10,9 +10,9 @@ The package uses the [Driver 0.26.1 plugin source](https://github.com/trycua/cua including the [desktop-fault cleanup repair](https://github.com/trycua/cua/pull/3702). It is not a repackaging of the unmodified 0.24.0 plugin. -The qualified Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with this pinned module; its production plugin source is unchanged from the source used here. Discovery protocol v2 is separate. A newer Driver release is a changed pairing and requires affected replay before promotion. +The qualified upstream Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with the upstream module; its production plugin source is the base for the downstream patch used here. Discovery protocol v2 is separate. A newer Driver release is a changed pairing and requires affected replay before promotion. -Profile `omarchy-hyprland-0562r3`, kit tooling `1.1.0`, and package release `3` pin: +Profile `omarchy-hyprland-0562r3-remaps`, kit tooling `1.1.0`, and package release `4` pin: - Hyprland `0.56.2-3`, headers `0.56.2`, and measured executable/header hashes. - GCC `16.2.1 20260810`, including compiler bytes and emitted ELF identity. @@ -24,14 +24,13 @@ its compositor executable and all 498 header/pkg-config files are byte-identical to `-2`. Both executables have SHA-256 `da8fcacf347bcbed83edc40108c6e2298da095e22246bd764e9bb382786cebb2`. The checked-in `PROFILE.json` changes only the profile name, package release, -and exact Hyprland package version. Compiler, runtime, source, executable, -and header identities remain unchanged. The download wrapper verifies the +and exact Hyprland package version. Compiler, runtime, upstream source, executable, +and header identities remain unchanged; the separately recorded patch changes the build source. The download wrapper verifies the original kit before deriving the updated profile, recipe, and provenance, then verifies every derived member against its recorded digest. The native qualification below was recorded with package release `2` and -Hyprland `-2`. This packaging update does not claim a new application or -Driver replay. The `-3` dependency must reach a destination channel before +Hyprland `-2`. The downstream keymap change needs its own application and Driver replay before promotion. The `-3` dependency must reach a destination channel before this artifact can be installed there; publication still follows edge → RC → stable. The generated `PKGBUILD` identifies the immutable kit download, outer checksum, @@ -47,7 +46,17 @@ and production flags remain mandatory. Packaging runs all bundled CTests even with `--nocheck` or `--repackage`; `--skipinteg` does not bypass recipe checks. Production input is built in; experimental signed input and tracing are off. -## What is qualified +The pristine upstream archive, manifest, and verifier remain unchanged. `independent-keymaps.patch` is applied to a separate source tree, and `DOWNSTREAM-PROVENANCE.json` pins the patch and every resulting source file. Build, check, and package revalidate both trees, including when makepkg integrity checks are skipped. `BUILD-PROVENANCE.json` records the upstream base under `source`, the applied change under `downstream`, and the final module digest; the downstream manifest and patch are installed beside it. This preserves the existing compiler, headers, runtime, and consumer checks without representing the modified module as an unmodified upstream build. + +## Keyboard behavior + +Each background lane owns a canonical US keymap and independent modifier state. The physical keyboard keeps its layout, Compose key, and remaps. No installation or activation step edits `input:kb_*`. Existing Driver keycodes are interpreted by the agent keyboard, so this does not add Unicode, IME, or new Driver text routes. + +Plain click, scroll, drag, and foreground activation do not require a canonical keyboard layout. Foreground keys still use the primary seat: the plugin checks the requested key and modifier sequence against its actual XKB map before activation or input. Unrelated remaps are accepted; a sequence whose symbols or modifier/lock transitions differ from the canonical meaning is refused with `unsupported_layout`. Arbitrary foreground layout translation remains outside protocol v3. + +Both routes retain target/conflict checks and cancellation on desktop/keymap changes. `hyprctl -j cua:status` exposes `keyboard_layout_independent: true` for installers to distinguish this implementation from an older mapped module. The marker does not identify every future package revision; plugin updates still require a fresh desktop session. + +## Historical upstream qualification The initial app scope is native Wayland Inkscape `1.4.4-6` with the canonical US keymap. Two lanes require independent Driver processes and distinct native @@ -131,7 +140,7 @@ kit-provenance digest: ```sh python3 /usr/share/cua-hyprland-plugin/profile_verify.py \ --kit /usr/share/cua-hyprland-plugin \ - --kit-sha256 1391084a903254fb16d251522dba41ae34a06cfa4b2f6b7ba91a3cceeb895921 \ + --kit-sha256 aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2 \ --consumer /usr/lib/cua/hyprland/cua-hyprland-plugin.so ``` @@ -146,98 +155,28 @@ hyprctl plugin load /usr/lib/cua/hyprland/cua-hyprland-plugin.so hyprctl -j cua:status ``` -Loading alone does not enable input. Before opting in, save open work and save -the exact current personal input configuration. The backup command refuses a -symlinked input file and refuses to replace an earlier backup: +Loading alone does not enable input. Use Omarchy's explicit Cua Input toggle when available; it verifies the installed profile and loaded capability and removes the legacy copied toggle's keyboard override. If it reports an older mapped plugin, disable Cua Input and log out and back in before enabling it again. Never hot-unload and reload the module. -```sh -test -f "$HOME/.config/hypr/input.lua" && \ - test ! -L "$HOME/.config/hypr/input.lua" && \ - test ! -e "$HOME/.config/hypr/input.lua.cua-before" && \ - cp --archive -- "$HOME/.config/hypr/input.lua" \ - "$HOME/.config/hypr/input.lua.cua-before" -``` - -If `input.lua` is a symlink, stop here: back up and later restore its resolved -target explicitly instead of using the commands below. - -The background-input admission guard requires the exact XKB keymap -`rules=evdev`, `model=pc105`, `layout=us`, empty variant and options, and no -custom keymap file. Stock Omarchy 4.0.3 English (US) is not that literal -configuration: it leaves rules and model empty and sets -`compose:caps,shift:both_capslock_cancel`. Those options make Caps Lock the -Compose key and both Shift keys the Caps Lock/cancel chord. The required empty -options restore ordinary Caps Lock behavior and remove both stock shortcuts -while Cua input is enabled. Any other effective value is intentionally refused -as `unsupported_layout`; do not weaken or bypass that admission guard. - -Append this override to `~/.config/hypr/input.lua` so it follows any existing -input settings. It both selects the exact admitted keymap and enables the -trusted local transport: +For manual activation, add only this plugin setting to a sourced Hyprland Lua configuration file, preserving all existing input settings: ```lua hl.config({ - input = { - kb_rules = "evdev", - kb_model = "pc105", - kb_layout = "us", - kb_variant = "", - kb_options = "", - kb_file = "", - }, plugin = { cua = { enabled = true } }, }) ``` -Reload, then read back every keymap value rather than relying on the source -file alone: +Then reload and inspect status: ```sh hyprctl reload -for name in kb_rules kb_model kb_layout kb_variant kb_options kb_file; do - value=$(hyprctl -j getoption "input:$name" | jq -r '.str') - printf '%s=%s\n' "$name" "$value" -done -hyprctl -j cua:status -``` - -The keymap readback must be exactly: - -```text -kb_rules=evdev -kb_model=pc105 -kb_layout=us -kb_variant= -kb_options= -kb_file= -``` - -A runtime keyword or Lua evaluation without `hyprctl reload` does not reconcile -the input sockets. Continue only when status also reports input protocol v3, -input capability, socket paths, and the expected compositor identity. Do not -disable NumLock; that was required only by a strict qualification observer, not -by the demonstrated background-input contract. - -Start Driver with `CUA_DRIVER_RS_ENABLE_WAYLAND=1`. For the activation check, -use background input in a new disposable Inkscape document to create a text -object containing `CUA activation check`. Save it under a new temporary -filename, then verify the text in both a fresh Driver snapshot and the reopened -saved SVG. Never test against an existing document, and do not automatically -replay an action with a partial or unknown outcome. - -After the check, restore the exact saved configuration and reload it: - -```sh -command mv --force -- "$HOME/.config/hypr/input.lua.cua-before" \ - "$HOME/.config/hypr/input.lua" -hyprctl reload hyprctl -j cua:status ``` -Confirm that the prior keymap values are back and status reports input disabled. -Retained inert agent pointers can remain until the compositor exits; disabling -input does not unload the mapped module. If you intentionally keep activation, -retain the backup until you are ready to perform this exact restoration. +Continue only when status reports `keyboard_layout_independent: true`, input protocol v3, input capability, socket paths, and the expected compositor identity. Do not change `kb_layout`, `kb_options`, or NumLock for background input. If you previously followed the stock-US override instructions, remove only that Cua-specific override and reload to restore your underlying personal settings. + +Start Driver with `CUA_DRIVER_RS_ENABLE_WAYLAND=1`. In a new disposable Inkscape document, test an admitted background key operation and pointer operation, then verify the result in both a fresh snapshot and a saved/reopened SVG. Driver text-route restrictions still apply. Never test against an existing document or automatically replay an action with a partial or unknown outcome. + +To disable input, turn the Cua Input toggle off, or remove the manual `plugin.cua.enabled` setting and reload. Confirm that status reports input disabled. Retained inert agent pointers can remain until the compositor exits; disabling input does not unload the mapped module. Before an incompatible desktop update, remove operator-added plugin activation settings, save work, and exit the graphical session. From a text console, run diff --git a/pkgbuilds/cua-hyprland-plugin/downstream.py b/pkgbuilds/cua-hyprland-plugin/downstream.py new file mode 100644 index 0000000..429b7f0 --- /dev/null +++ b/pkgbuilds/cua-hyprland-plugin/downstream.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Verify the Omarchy patch separately from the unchanged upstream source kit.""" + +import argparse +import hashlib +import importlib.util +import json +from pathlib import Path, PurePosixPath +import shutil +import subprocess + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def digest(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def inventory(root): + require(root.is_dir() and not root.is_symlink(), "source must be a real directory") + result = {} + for path in root.rglob("*"): + require(not path.is_symlink() and (path.is_dir() or path.is_file()), "nonregular source entry") + if path.is_file(): + result[path.relative_to(root).as_posix()] = digest(path) + return result + + +def verify_inputs(pristine, patch, manifest): + require(manifest["schema"] == 1, "unsupported downstream schema") + require(patch.is_file() and not patch.is_symlink() and digest(patch) == manifest["patch_sha256"], + "downstream patch checksum mismatch") + require(digest(pristine / "SOURCE-PROVENANCE.json") == manifest["upstream_manifest_sha256"], + "downstream base manifest mismatch") + require(manifest["files"], "empty downstream inventory") + for name in manifest["files"]: + path = PurePosixPath(name) + require(name and not path.is_absolute() and path.as_posix() == name and + ".." not in path.parts and "\\" not in name, "invalid downstream path") + + +def verify_tree(source, manifest): + require(inventory(source) == manifest["files"], "patched source inventory/checksum mismatch") + + +def prepare(pristine, source, patch, manifest): + require(not source.exists() and not source.is_symlink(), "patched source requires a fresh destination") + shutil.copytree(pristine, source) + subprocess.run(["patch", "--batch", "--fuzz=0", "-p1", "-i", str(patch.resolve())], cwd=source, check=True) + verify_tree(source, manifest) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("mode", choices=("prepare", "check", "build")) + parser.add_argument("--pristine", required=True, type=Path) + parser.add_argument("--source", required=True, type=Path) + parser.add_argument("--patch", required=True, type=Path) + parser.add_argument("--manifest", required=True, type=Path) + parser.add_argument("--kit", required=True, type=Path) + parser.add_argument("--kit-sha256", required=True) + parser.add_argument("--archive", required=True, type=Path) + parser.add_argument("--cxx", required=True, type=Path) + parser.add_argument("--build", type=Path) + parser.add_argument("--output", type=Path) + args = parser.parse_args() + try: + # PKGBUILD authenticates the verifier and this helper before execution. + spec = importlib.util.spec_from_file_location("upstream_profile", args.kit / "profile_verify.py") + upstream = importlib.util.module_from_spec(spec) + spec.loader.exec_module(upstream) + profile, kit = upstream.verify_kit(args.kit, args.kit_sha256) + base = upstream.verify_archive(args.archive, profile) + require(upstream.verify_source(args.pristine, profile) == base, "upstream source identity mismatch") + manifest = upstream.read_json(args.manifest.read_bytes()) + verify_inputs(args.pristine, args.patch, manifest) + if args.mode == "prepare": + prepare(args.pristine, args.source, args.patch, manifest) + else: + verify_tree(args.source, manifest) + if args.mode == "build": + require(args.build is not None and args.output is not None, "build evidence requires output") + native = upstream.verify_native(args.cxx, profile) + native["module_sha256"] = upstream.verify_build(args.build, args.source, args.cxx, profile) + native["module_runtime_sha256"] = profile["runtime"]["sha256"] + args.output.write_bytes(upstream.json_bytes(dict(native, source=base, profile=profile, + kit=kit, downstream=manifest))) + except (ValueError, KeyError, TypeError, OSError, subprocess.CalledProcessError) as error: + parser.exit(1, f"error: {error}\n") + + +if __name__ == "__main__": + main() diff --git a/pkgbuilds/cua-hyprland-plugin/downstream_test.py b/pkgbuilds/cua-hyprland-plugin/downstream_test.py new file mode 100644 index 0000000..60586d2 --- /dev/null +++ b/pkgbuilds/cua-hyprland-plugin/downstream_test.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +"""Exercise downstream integrity with real patch application and tampering.""" + +import hashlib +from pathlib import Path +import tempfile +import unittest + +import downstream + + +class DownstreamTests(unittest.TestCase): + def setUp(self): + self.temp = tempfile.TemporaryDirectory() + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.pristine = self.root / "pristine" + self.pristine.mkdir() + (self.pristine / "SOURCE-PROVENANCE.json").write_text("upstream\n") + (self.pristine / "input.cpp").write_text("old\n") + self.patch = self.root / "change.patch" + self.patch.write_text("--- a/input.cpp\n+++ b/input.cpp\n@@ -1 +1 @@\n-old\n+new\n") + self.source = self.root / "patched" + self.manifest = { + "schema": 1, + "patch_sha256": downstream.digest(self.patch), + "upstream_manifest_sha256": downstream.digest(self.pristine / "SOURCE-PROVENANCE.json"), + "files": {"SOURCE-PROVENANCE.json": downstream.digest(self.pristine / "SOURCE-PROVENANCE.json"), + "input.cpp": hashlib.sha256(b"new\n").hexdigest()}, + } + + def test_applies_patch_without_changing_upstream(self): + downstream.verify_inputs(self.pristine, self.patch, self.manifest) + downstream.prepare(self.pristine, self.source, self.patch, self.manifest) + self.assertEqual((self.pristine / "input.cpp").read_text(), "old\n") + self.assertEqual((self.source / "input.cpp").read_text(), "new\n") + + def test_changed_patch_refuses(self): + self.patch.write_text(self.patch.read_text().replace("+new", "+bad")) + with self.assertRaisesRegex(ValueError, "patch checksum"): + downstream.verify_inputs(self.pristine, self.patch, self.manifest) + + def test_changed_base_manifest_refuses(self): + (self.pristine / "SOURCE-PROVENANCE.json").write_text("different\n") + with self.assertRaisesRegex(ValueError, "base manifest"): + downstream.verify_inputs(self.pristine, self.patch, self.manifest) + + def test_tampered_missing_and_extra_files_refuse(self): + downstream.prepare(self.pristine, self.source, self.patch, self.manifest) + file = self.source / "input.cpp" + for content in ("tampered\n", None): + if content is None: + file.unlink() + else: + file.write_text(content) + with self.assertRaisesRegex(ValueError, "inventory/checksum"): + downstream.verify_tree(self.source, self.manifest) + file.write_text("new\n") + (self.source / "unexpected.cpp").write_text("extra\n") + with self.assertRaisesRegex(ValueError, "inventory/checksum"): + downstream.verify_tree(self.source, self.manifest) + + def test_symlink_and_reused_destination_refuse(self): + downstream.prepare(self.pristine, self.source, self.patch, self.manifest) + with self.assertRaisesRegex(ValueError, "fresh destination"): + downstream.prepare(self.pristine, self.source, self.patch, self.manifest) + file = self.source / "input.cpp" + file.unlink() + file.symlink_to(self.pristine / "input.cpp") + with self.assertRaisesRegex(ValueError, "nonregular"): + downstream.verify_tree(self.source, self.manifest) + + +if __name__ == "__main__": + unittest.main() diff --git a/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch b/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch new file mode 100644 index 0000000..1fbea31 --- /dev/null +++ b/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch @@ -0,0 +1,719 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8a80de2..5dedb8f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -39,8 +39,24 @@ target_compile_options(cua_hyprland_protocol PRIVATE -Wall -Wextra -Wpedantic -W + cua_hyprland_harden(cua_hyprland_protocol) + set_target_properties(cua_hyprland_protocol PROPERTIES POSITION_INDEPENDENT_CODE ON) + ++if(BUILD_TESTING OR CUA_HYPRLAND_INPUT OR CUA_HYPRLAND_TEST_INPUT) ++ find_package(PkgConfig REQUIRED) ++ pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon) ++endif() ++ + if(BUILD_TESTING) ++ add_executable(cua_hyprland_keyboard_layout_test tests/keyboard_layout_test.cpp) ++ target_compile_features(cua_hyprland_keyboard_layout_test PRIVATE cxx_std_26) ++ target_include_directories(cua_hyprland_keyboard_layout_test PRIVATE src) ++ target_link_libraries(cua_hyprland_keyboard_layout_test PRIVATE PkgConfig::XKBCOMMON) ++ target_compile_options(cua_hyprland_keyboard_layout_test PRIVATE -Wall -Wextra -Wpedantic -Werror) ++ add_test(NAME cua_hyprland_keyboard_layout_test COMMAND cua_hyprland_keyboard_layout_test) ++ + find_package(Python3 REQUIRED COMPONENTS Interpreter) ++ add_test(NAME cua_hyprland_agent_keymap_test ++ COMMAND ${Python3_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/tests/agent_keymap_test.py) ++ set_tests_properties(cua_hyprland_agent_keymap_test PROPERTIES ++ ENVIRONMENT "CXX=${CMAKE_CXX_COMPILER}") + add_test(NAME cua_hyprland_desktop_fault_policy_test + COMMAND ${Python3_EXECUTABLE} -B + ${CMAKE_CURRENT_SOURCE_DIR}/tests/desktop_fault_policy_test.py) +@@ -218,6 +234,7 @@ if(CUA_HYPRLAND_BUILD_PLUGIN) + message(FATAL_ERROR "Input is pinned to Hyprland 0.56.2") + endif() + target_sources(cua_hyprland_plugin PRIVATE src/input_experiment.cpp) ++ target_link_libraries(cua_hyprland_plugin PRIVATE PkgConfig::XKBCOMMON) + endif() + if(CUA_HYPRLAND_INPUT) + target_compile_definitions(cua_hyprland_plugin PRIVATE CUA_HYPRLAND_INPUT=1) +diff --git a/src/input_experiment.cpp b/src/input_experiment.cpp +index fc7e740..f256fc4 100644 +--- a/src/input_experiment.cpp ++++ b/src/input_experiment.cpp +@@ -9,6 +9,8 @@ + #include "seat_lifetime.hpp" + #include "owned_socket_path.hpp" + #include "foreground_route.hpp" ++#include "keyboard_layout.hpp" ++#include + + #include + #include +@@ -214,7 +216,11 @@ struct InputExperiment::Impl { + xkb_keymap* keymap = nullptr; + xkb_state* keyboard_state = nullptr; + int keymap_fd = -1; +- bool retired = false, suspended = true, us_keymap = false, physical_keymap_present = false; ++ // Foreground state uses the actual primary map; never share it with agent seats. ++ xkb_keymap* physical_keymap = nullptr; ++ xkb_state* physical_state = nullptr; ++ std::string physical_keymap_text; ++ bool retired = false, suspended = true, physical_keymap_present = false; + WP physical_keyboard; + CHyprSignalListener keymap_listener; + unsigned lane; +@@ -243,23 +249,37 @@ struct InputExperiment::Impl { + // No private key or input-enabled default exists in this component. + } + +- static bool canonical_us_keymap(xkb_context* context, xkb_keymap* map) { +- // Compare canonical compiled content, not a layout display name. This +- // deliberately excludes variants, options, remaps, and multiple groups. +- const xkb_rule_names names{"evdev", "pc105", "us", "", ""}; +- auto* reference = xkb_keymap_new_from_names(context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); +- if (!reference) return false; +- char* actual = xkb_keymap_get_as_string(map, XKB_KEYMAP_FORMAT_TEXT_V1); +- char* expected = xkb_keymap_get_as_string(reference, XKB_KEYMAP_FORMAT_TEXT_V1); +- const bool matches = actual && expected && std::strcmp(actual, expected) == 0; +- std::free(actual); std::free(expected); xkb_keymap_unref(reference); +- return matches; +- } +- bool layout_qualified() const { +- if (!kProduction) return true; ++ bool physical_layout_ready() const { + const auto keyboard = g_pSeatManager->m_keyboard.lock(); +- return physical_keymap_present && us_keymap && keyboard_state && keyboard && +- keyboard->m_xkbKeymapV1FD.get() >= 0 && keyboard->m_xkbKeymapV1String == keymap_text; ++ return physical_keymap_present && physical_state && keyboard && ++ keyboard->m_xkbKeymapV1FD.get() >= 0 && keyboard->m_xkbKeymapV1String == physical_keymap_text; ++ } ++ bool layout_qualified(InputRoute route, std::uint64_t capability) const { ++ return keyboard_layout_ready(route, capability, keyboard_state && keymap_fd >= 0, physical_layout_ready()); ++ } ++ void initialize_agent_keymap() { ++ if (keymap) return; ++ xkb_context_ = xkb_context_new(XKB_CONTEXT_NO_FLAGS); ++ keymap = xkb_context_ ? agent_keymap(xkb_context_) : nullptr; ++ keyboard_state = keymap ? xkb_state_new(keymap) : nullptr; ++ char* text = keymap ? xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1) : nullptr; ++ if (!keyboard_state || !text) { ++ std::free(text); ++ throw std::runtime_error("agent XKB keymap unavailable"); ++ } ++ keymap_text = text; ++ std::free(text); ++ keymap_fd = memfd_create("cua-agent-keymap", MFD_CLOEXEC | MFD_ALLOW_SEALING); ++ if (keymap_fd < 0) throw std::runtime_error("agent keymap fd unavailable"); ++ std::size_t offset = 0; ++ while (offset < keymap_text.size() + 1) { ++ const auto count = write(keymap_fd, keymap_text.c_str() + offset, keymap_text.size() + 1 - offset); ++ if (count < 0 && errno == EINTR) continue; ++ if (count <= 0) throw std::runtime_error("agent keymap write failed"); ++ offset += static_cast(count); ++ } ++ if (fcntl(keymap_fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0) ++ throw std::runtime_error("agent keymap sealing failed"); + } + void sync_keymap() { + const auto keyboard = g_pSeatManager->m_keyboard.lock(); +@@ -278,38 +298,20 @@ struct InputExperiment::Impl { + return; + } + physical_keymap_present = true; +- if (keyboard_state && keymap_text == keyboard->m_xkbKeymapV1String) return; +- // Prepare a complete replacement before retiring the old independent +- // state. Keep our own fd: primary keyboard replacement must not leave +- // later seat bindings referring to a closed compositor fd. +- auto* context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); +- auto* map = context ? xkb_keymap_new_from_string(context, keyboard->m_xkbKeymapV1String.c_str(), +- XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) : nullptr; +- auto* state = map ? xkb_state_new(map) : nullptr; +- const auto fd = fcntl(keyboard->m_xkbKeymapV1FD.get(), F_DUPFD_CLOEXEC, 0); +- if (!state || fd < 0) { +- if (fd >= 0) close(fd); +- if (state) xkb_state_unref(state); +- if (map) xkb_keymap_unref(map); +- if (context) xkb_context_unref(context); +- throw std::runtime_error("independent XKB state unavailable"); +- } ++ if (physical_keymap_text == keyboard->m_xkbKeymapV1String) return; ++ // Physical changes still revoke authority, but never replace the map ++ // advertised by either background keyboard. + desktop_transition(); +- if (keyboard_state) xkb_state_unref(keyboard_state); +- if (keymap) xkb_keymap_unref(keymap); +- if (xkb_context_) xkb_context_unref(xkb_context_); +- if (keymap_fd >= 0) close(keymap_fd); +- keyboard_state = state; keymap = map; xkb_context_ = context; keymap_fd = fd; +- us_keymap = !kProduction || canonical_us_keymap(context, map); +- keymap_text = keyboard->m_xkbKeymapV1String; +- for (auto& k : keyboards) +- if (!k->dead && k->wl->resource()) +- k->wl->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_text.size() + 1); +- for (auto& seat : seats) +- if (!seat->dead && seat->wl->resource()) +- seat->wl->sendCapabilities(static_cast(WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD)); ++ auto* map = xkb_keymap_new_from_string(xkb_context_, keyboard->m_xkbKeymapV1String.c_str(), ++ XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); ++ auto* state = map ? xkb_state_new(map) : nullptr; ++ if (physical_state) xkb_state_unref(physical_state); ++ if (physical_keymap) xkb_keymap_unref(physical_keymap); ++ physical_state = state; physical_keymap = map; ++ physical_keymap_text = keyboard->m_xkbKeymapV1String; + } + void start() { ++ initialize_agent_keymap(); + sync_keymap(); + timer = wl_event_loop_add_timer(g_pCompositor->m_wlEventLoop, tick, this); + if (!timer) throw std::runtime_error("input timer registration failed"); +@@ -389,6 +391,8 @@ struct InputExperiment::Impl { + cleanup_socket(); + if (keyboard_state) xkb_state_unref(keyboard_state); + if (keymap) xkb_keymap_unref(keymap); ++ if (physical_state) xkb_state_unref(physical_state); ++ if (physical_keymap) xkb_keymap_unref(physical_keymap); + if (xkb_context_) xkb_context_unref(xkb_context_); + if (keymap_fd >= 0) close(keymap_fd); + } +@@ -786,7 +790,7 @@ struct InputExperiment::Impl { + if (lease != &c) throw ForegroundFailure{ForegroundFailureReason::lease}; + if (c.dead) throw ForegroundFailure{ForegroundFailureReason::client_dead}; + if (!available()) throw ForegroundFailure{ForegroundFailureReason::session_unavailable}; +- if (!layout_qualified()) throw ForegroundFailure{ForegroundFailureReason::unsupported_layout}; ++ if (foreground_keyboard_used && !physical_layout_ready()) throw ForegroundFailure{ForegroundFailureReason::unsupported_layout}; + if (Clock::now() >= expires) throw ForegroundFailure{ForegroundFailureReason::lease_expired}; + const auto failure = foreground_guard(c).dispatch_failure(foreground_needs_pointer); + if (failure != ForegroundFailureReason::none) throw ForegroundFailure{failure}; +@@ -813,6 +817,8 @@ struct InputExperiment::Impl { + foreground_pointers.clear(); foreground_keyboards.clear(); foreground_surface.reset(); foreground_seat.reset(); + foreground_started = false; + foreground_keyboard_used = false; ++ if (physical_state) xkb_state_unref(physical_state); ++ physical_state = physical_keymap ? xkb_state_new(physical_keymap) : nullptr; + } + void start_foreground(Client& c, double x, double y, bool needs_pointer, bool needs_keyboard) { + const auto root = c.surface.lock(); +@@ -820,7 +826,7 @@ struct InputExperiment::Impl { + const auto failure = foreground_guard(c).activation_failure(); + if (failure != ForegroundFailureReason::none) throw ForegroundFailure{failure}; + if (!physical) throw ForegroundFailure{ForegroundFailureReason::physical_keyboard}; +- if (!keyboard_state) throw ForegroundFailure{ForegroundFailureReason::keyboard_state}; ++ if (needs_keyboard && !physical_layout_ready()) throw ForegroundFailure{ForegroundFailureReason::keyboard_state}; + if (needs_pointer && !g_pSeatManager->m_mouse) throw ForegroundFailure{ForegroundFailureReason::physical_pointer}; + const Vector2D local{x + c.geometry[0] - c.geometry[4], y + c.geometry[1] - c.geometry[5]}; + if (needs_pointer && (!point(c, x, y) || root->at(local, true).first != root)) throw ForegroundFailure{ForegroundFailureReason::pointer_target}; +@@ -843,7 +849,7 @@ struct InputExperiment::Impl { + const auto modifier_failure = foreground_key_modifier_failure(foreground_modifiers); + if (modifier_failure != ForegroundFailureReason::none) throw ForegroundFailure{modifier_failure}; + } +- xkb_state_update_mask(keyboard_state, foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], 0, 0, foreground_modifiers[3]); ++ if (needs_keyboard) xkb_state_update_mask(physical_state, foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], 0, 0, foreground_modifiers[3]); + foreground_surface = root; + foreground_seat = seat; + foreground_needs_pointer = needs_pointer; +@@ -893,16 +899,17 @@ struct InputExperiment::Impl { + } + void foreground_key(Client& c, std::uint32_t code, bool pressed) { + require_foreground(c); ++ if (!physical_layout_ready()) throw ForegroundFailure{ForegroundFailureReason::unsupported_layout}; + foreground_keyboard_used = true; +- xkb_state_update_key(keyboard_state, code + 8, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); ++ xkb_state_update_key(physical_state, code + 8, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + if (pressed) held_keys.push_back(code); else std::erase(held_keys, code); + for (const auto& weak : foreground_keyboards) { + const auto k = weak.lock(); if (!k || !k->good()) throw ForegroundFailure{ForegroundFailureReason::keyboard_resources}; + k->sendKey(event_ms(), code, pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); +- k->sendMods(xkb_state_serialize_mods(keyboard_state, XKB_STATE_MODS_DEPRESSED), +- xkb_state_serialize_mods(keyboard_state, XKB_STATE_MODS_LATCHED), +- xkb_state_serialize_mods(keyboard_state, XKB_STATE_MODS_LOCKED), +- xkb_state_serialize_layout(keyboard_state, XKB_STATE_LAYOUT_EFFECTIVE)); ++ k->sendMods(xkb_state_serialize_mods(physical_state, XKB_STATE_MODS_DEPRESSED), ++ xkb_state_serialize_mods(physical_state, XKB_STATE_MODS_LATCHED), ++ xkb_state_serialize_mods(physical_state, XKB_STATE_MODS_LOCKED), ++ xkb_state_serialize_layout(physical_state, XKB_STATE_LAYOUT_EFFECTIVE)); + } + } + bool pointer_enter(Client& c, double x, double y) { +@@ -942,8 +949,8 @@ struct InputExperiment::Impl { + held_button = pressed ? value : 0; + } + bool keyboard_enter(Client& c) { +- const auto root = c.surface.lock(); const auto physical = g_pSeatManager->m_keyboard.lock(); +- if (!root || !physical || physical->m_xkbKeymapV1String != keymap_text || !keyboard_state) return false; ++ const auto root = c.surface.lock(); ++ if (!root || !keyboard_state || keymap_fd < 0) return false; + unsigned count = 0; + for (auto& k : keyboards) { + if (k->dead || !k->wl->resource() || k->wl->client() != root->client()) continue; +@@ -1030,7 +1037,7 @@ struct InputExperiment::Impl { + if (kProduction && (!InputGrant::single_operation(requested_cap) || + (requested_cap == 16 && route != InputRoute::primary_foreground))) { invalidate(c); send(c, refusal("unsupported")); return; } + if (kProduction && !available()) { invalidate(c, false); send(c, refusal("session_unavailable")); return; } +- if (!layout_qualified()) { invalidate(c, false); send(c, refusal("unsupported_layout")); return; } ++ if (!layout_qualified(route, requested_cap)) { invalidate(c, false); send(c, refusal("unsupported_layout")); return; } + const auto pid = number(f[1]); const auto address = number(f[2], 16); + PHLWINDOW window; + for (const auto& w : Desktop::windowState()->windows()) +@@ -1090,7 +1097,7 @@ struct InputExperiment::Impl { + if (c.token.empty() || f[2] != c.token || !refresh(c)) { send(c, refusal("stale_target")); return; } + if (number(f[3]) != c.revision) { if (kProduction) revoke("stale_geometry"); send(c, refusal("stale_geometry")); return; } + if (!available()) { revoke("session_unavailable", true); send(c, refusal("session_unavailable")); return; } +- if (!layout_qualified()) { revoke("unsupported_layout", true); send(c, refusal("unsupported_layout")); return; } ++ if (!layout_qualified(c.route, cap)) { revoke("unsupported_layout", true); send(c, refusal("unsupported_layout")); return; } + if (lease && Clock::now() >= expires) revoke("lease_expired"); + if (drag) { send(c, refusal("lease_busy")); return; } + if (lease != &c || !(capabilities & cap) || (kProduction && !grant.permits(cap, Clock::now()))) { +@@ -1184,6 +1191,10 @@ struct InputExperiment::Impl { + if (Clock::now() + std::chrono::milliseconds(duration + 50) >= expires) { send(c, refusal("lease_expired")); return; } + } + } ++ if (command == "KEY" && !foreground_chord_compatible(physical_keymap, keymap, code, mods)) { ++ revoke("unsupported_layout", true); ++ send(c, refusal("unsupported_layout")); return; ++ } + if (!consume_grant(c, cap)) return; + start_foreground(c, x, y, command != "KEY" && command != "ACTIVATE", command == "KEY"); + if (command == "KEY") { +@@ -1227,7 +1238,7 @@ struct InputExperiment::Impl { + if (lease) { + if (lease->dead) revoke("disconnected", true); + else if (Clock::now() >= expires) revoke("lease_expired"); +- else if (!available() || !layout_qualified()) revoke("cancelled", true); ++ else if (!available() || !layout_qualified(lease->route, capabilities)) revoke("cancelled", true); + else if (!refresh(*lease) || primary_conflict(*lease) || agent_conflict(*lease) || + (drag && !drag->geometry.matches(lease->revision))) revoke("cancelled"); + } +diff --git a/src/keyboard_layout.hpp b/src/keyboard_layout.hpp +new file mode 100644 +index 0000000..ab7defc +--- /dev/null ++++ b/src/keyboard_layout.hpp +@@ -0,0 +1,102 @@ ++#pragma once ++ ++#include "foreground_route.hpp" ++#include ++#include ++#include ++#include ++ ++namespace cua::hyprland { ++// Wire v3 carries evdev key positions plus fixed Shift/Ctrl/Alt/Super bits. ++// Background seats advertise this map, independently of the human keyboard. ++inline xkb_keymap* agent_keymap(xkb_context* context) { ++ const xkb_rule_names names{"evdev", "pc105", "us", "", ""}; ++ return xkb_keymap_new_from_names(context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); ++} ++ ++inline bool keyboard_layout_ready(InputRoute route, std::uint64_t capability, ++ bool agent_ready, bool physical_ready) { ++ if (!(capability & 2)) return true; // Pointer/activation needs no key mapping. ++ return route == InputRoute::primary_foreground ? physical_ready : agent_ready; ++} ++ ++inline bool same_key_symbols(xkb_state* actual, xkb_state* expected, xkb_keycode_t key) { ++ const xkb_keysym_t *a = nullptr, *b = nullptr; ++ const int na = xkb_state_key_get_syms(actual, key, &a); ++ const int nb = xkb_state_key_get_syms(expected, key, &b); ++ if (na != nb) return false; ++ for (int i = 0; i < na; ++i) if (a[i] != b[i]) return false; ++ return true; ++} ++ ++inline bool same_consumed_modifiers(xkb_state* actual, xkb_state* expected, xkb_keycode_t key) { ++ // Toolkits subtract consumed modifiers when matching shortcuts. Matching ++ // symbols and effective state alone does not preserve shortcut meaning. ++ for (auto* state : {actual, expected}) { ++ auto* map = xkb_state_get_keymap(state); ++ for (xkb_mod_index_t i = 0; i < xkb_keymap_num_mods(map); ++i) { ++ const char* name = xkb_keymap_mod_get_name(map, i); ++ if (xkb_state_mod_name_is_active(state, name, XKB_STATE_MODS_EFFECTIVE) <= 0) continue; ++ const auto ai = xkb_keymap_mod_get_index(xkb_state_get_keymap(actual), name); ++ const auto bi = xkb_keymap_mod_get_index(xkb_state_get_keymap(expected), name); ++ for (auto mode : {XKB_CONSUMED_MODE_XKB, XKB_CONSUMED_MODE_GTK}) ++ if ((xkb_state_mod_index_is_consumed2(actual, key, ai, mode) > 0) != ++ (xkb_state_mod_index_is_consumed2(expected, key, bi, mode) > 0)) return false; ++ } ++ } ++ return true; ++} ++ ++inline bool same_modifier_state(xkb_state* actual, xkb_state* expected) { ++ // Modifier indices can differ between maps. Compare names, in both directions, ++ // including nonstandard modifiers and lock/latch changes on key release. ++ for (auto* state : {actual, expected}) { ++ auto* map = xkb_state_get_keymap(state); ++ for (xkb_mod_index_t i = 0; i < xkb_keymap_num_mods(map); ++i) { ++ const char* name = xkb_keymap_mod_get_name(map, i); ++ for (auto component : {XKB_STATE_MODS_DEPRESSED, XKB_STATE_MODS_LATCHED, ++ XKB_STATE_MODS_LOCKED, XKB_STATE_MODS_EFFECTIVE}) { ++ const bool a = xkb_state_mod_name_is_active(actual, name, component) > 0; ++ const bool b = xkb_state_mod_name_is_active(expected, name, component) > 0; ++ if (a != b) return false; ++ } ++ } ++ } ++ for (auto component : {XKB_STATE_LAYOUT_DEPRESSED, XKB_STATE_LAYOUT_LATCHED, ++ XKB_STATE_LAYOUT_LOCKED, XKB_STATE_LAYOUT_EFFECTIVE}) ++ if (xkb_state_serialize_layout(actual, component) != xkb_state_serialize_layout(expected, component)) ++ return false; ++ return true; ++} ++ ++// Simulate the complete chord before delivering any events or changing focus. ++// This is compatibility checking, not layout translation: physical key positions ++// remain unchanged. Unrelated remaps are harmless, requested remaps fail closed. ++inline bool foreground_chord_compatible(xkb_keymap* physical, xkb_keymap* canonical, ++ std::uint32_t code, std::uint32_t mods) { ++ if (!physical || !canonical) return false; ++ using State = std::unique_ptr; ++ State actual{xkb_state_new(physical), xkb_state_unref}; ++ State expected{xkb_state_new(canonical), xkb_state_unref}; ++ if (!actual || !expected) return false; ++ const auto event = [&](std::uint32_t key, xkb_key_direction direction) { ++ // A client interprets the press using the preceding modifiers event. ++ // Stock both_capslock_cancel gives Shift a Caps_Lock symbol at its ++ // shifted level; that level is not another press. Releases pair by ++ // keycode, but their lock/latch/group effects still must agree. ++ if (direction == XKB_KEY_DOWN && ++ (!same_key_symbols(actual.get(), expected.get(), key + 8) || ++ !same_consumed_modifiers(actual.get(), expected.get(), key + 8))) return false; ++ xkb_state_update_key(actual.get(), key + 8, direction); ++ xkb_state_update_key(expected.get(), key + 8, direction); ++ return same_modifier_state(actual.get(), expected.get()); ++ }; ++ constexpr std::array keys{42, 29, 56, 125}; ++ for (unsigned i = 0; i < keys.size(); ++i) ++ if ((mods & (1u << i)) && keys[i] != code && !event(keys[i], XKB_KEY_DOWN)) return false; ++ if (!event(code, XKB_KEY_DOWN) || !event(code, XKB_KEY_UP)) return false; ++ for (int i = 3; i >= 0; --i) ++ if ((mods & (1u << i)) && keys[i] != code && !event(keys[i], XKB_KEY_UP)) return false; ++ return true; ++} ++} // namespace cua::hyprland +diff --git a/src/plugin.cpp b/src/plugin.cpp +index 88b9900..2d24471 100644 +--- a/src/plugin.cpp ++++ b/src/plugin.cpp +@@ -218,6 +218,11 @@ std::string status_output(bool json) { + + if (json) { + auto result = cua::hyprland::render_status_json(report); ++#ifdef CUA_HYPRLAND_INPUT ++ // Installation checks compiled support before enabling input seats. ++ result.pop_back(); ++ result += ",\"keyboard_layout_independent\":true}"; ++#endif + #if defined(CUA_HYPRLAND_TEST_INPUT) || defined(CUA_HYPRLAND_INPUT) + if (g_experiment) { + #ifdef CUA_HYPRLAND_INPUT +diff --git a/tests/agent_keymap_test.py b/tests/agent_keymap_test.py +new file mode 100644 +index 0000000..78a3603 +--- /dev/null ++++ b/tests/agent_keymap_test.py +@@ -0,0 +1,86 @@ ++"""Exercise the production map initializer without a compositor or desktop changes.""" ++import os ++from pathlib import Path ++import re ++import shlex ++import subprocess ++import tempfile ++import unittest ++ ++ROOT = Path(__file__).resolve().parents[1] ++ ++ ++class AgentKeymapTest(unittest.TestCase): ++ def test_production_keymap_and_fd(self): ++ source = (ROOT / 'src/input_experiment.cpp').read_text() ++ body = re.search(r'^ void initialize_agent_keymap\(\).*?^ }', source, re.M | re.S) ++ self.assertIsNotNone(body) ++ fixture = r''' ++#include "keyboard_layout.hpp" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++using namespace cua::hyprland; ++void check(bool v, const char* m) { if (!v) { std::cerr << m; std::exit(1); } } ++struct Lane { ++ xkb_context* xkb_context_ = nullptr; ++ xkb_keymap* keymap = nullptr; ++ xkb_state* keyboard_state = nullptr; ++ int keymap_fd = -1; ++ std::string keymap_text; ++ // INITIALIZER ++ ~Lane() { ++ if (keyboard_state) xkb_state_unref(keyboard_state); ++ if (keymap) xkb_keymap_unref(keymap); ++ if (xkb_context_) xkb_context_unref(xkb_context_); ++ if (keymap_fd >= 0) close(keymap_fd); ++ } ++}; ++int main() { ++ Lane a, b; ++ a.initialize_agent_keymap(); b.initialize_agent_keymap(); ++ check(a.keymap_fd != b.keymap_fd && a.keymap != b.keymap && a.keyboard_state != b.keyboard_state, ++ "lanes share owned map resources"); ++ check(a.keymap_text == b.keymap_text, "lanes advertise different layouts"); ++ for (Lane* lane : {&a, &b}) { ++ struct stat status{}; ++ check(fstat(lane->keymap_fd, &status) == 0 && status.st_size == (off_t)lane->keymap_text.size() + 1, ++ "keymap fd is not terminated serialized map"); ++ std::string text(status.st_size, '\0'); ++ check(pread(lane->keymap_fd, text.data(), text.size(), 0) == status.st_size, "keymap fd cannot be read"); ++ check(text == lane->keymap_text + '\0', "keymap fd differs from advertised map"); ++ check(fcntl(lane->keymap_fd, F_GETFD) & FD_CLOEXEC, "keymap fd inherited by exec"); ++ const int seals = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL; ++ check((fcntl(lane->keymap_fd, F_GET_SEALS) & seals) == seals, "keymap fd not immutable"); ++ const int fd = lane->keymap_fd; ++ lane->initialize_agent_keymap(); ++ check(lane->keymap_fd == fd, "initialization replaced advertised map"); ++ check(xkb_state_key_get_one_sym(lane->keyboard_state, 21 + 8) == XKB_KEY_y, ++ "background lane did not initialize US map"); ++ } ++ xkb_state_update_key(a.keyboard_state, 42 + 8, XKB_KEY_DOWN); ++ check(xkb_state_key_get_one_sym(a.keyboard_state, 30 + 8) == XKB_KEY_A, "lane modifier not applied"); ++ check(xkb_state_key_get_one_sym(b.keyboard_state, 30 + 8) == XKB_KEY_a, "lane modifier leaked"); ++} ++'''.replace('// INITIALIZER', body.group()) ++ compiler = shlex.split(os.environ.get('CXX', 'c++')) ++ flags = shlex.split(subprocess.check_output(['pkg-config', '--cflags', '--libs', 'xkbcommon'], text=True)) ++ with tempfile.TemporaryDirectory(prefix='cua-agent-keymap-') as directory: ++ cpp, binary = Path(directory) / 'fixture.cpp', Path(directory) / 'fixture' ++ cpp.write_text(fixture) ++ build = subprocess.run([*compiler, '-std=c++20', '-Wall', '-Wextra', '-Wpedantic', '-Werror', ++ '-I', str(ROOT / 'src'), str(cpp), '-o', str(binary), *flags], ++ capture_output=True, text=True, timeout=60) ++ self.assertEqual(build.returncode, 0, build.stdout + build.stderr) ++ result = subprocess.run([str(binary)], capture_output=True, text=True, timeout=10) ++ self.assertEqual(result.returncode, 0, result.stdout + result.stderr) ++ ++ ++if __name__ == '__main__': ++ unittest.main() +diff --git a/tests/desktop_fault_policy_fixture.cpp b/tests/desktop_fault_policy_fixture.cpp +index 45c48ef..36be139 100644 +--- a/tests/desktop_fault_policy_fixture.cpp ++++ b/tests/desktop_fault_policy_fixture.cpp +@@ -1,6 +1,7 @@ + // Used by desktop_fault_policy_test.py, which inserts actual production bodies. + // Transport effects are counted here; native protocol/app behavior is separate. + #include "drag_geometry.hpp" ++#include "keyboard_layout.hpp" + #include "input_grant.hpp" + #include "passive_pointer_target.hpp" + +@@ -18,6 +19,7 @@ struct Window {}; + struct Surface { int client() const { return 1; } }; + using Target = PassivePointerTarget, std::weak_ptr>; + struct Client { ++ InputRoute route = InputRoute::independent; + bool dead = false; + void* source = nullptr; + int fd = -1; +@@ -34,8 +36,6 @@ struct Pointer { + }; + struct Drag { Client* client; DragGeometry geometry{1}; }; + struct Trace { void mark(const char*, unsigned) {} }; +-enum class ForegroundFailureReason { none }; +-struct ForegroundFailure { ForegroundFailureReason reason; }; + void wl_event_source_remove(void*) {} + int close(int) { return 0; } + std::string refusal(std::string_view reason) { return std::string(reason); } +@@ -79,7 +79,7 @@ struct Lane { + drag.emplace(lease); + } + bool available() const { return !suspended && session; } +- bool layout_qualified() const { return layout; } ++ bool layout_qualified(InputRoute route, uint64_t cap) const { return keyboard_layout_ready(route, cap, layout, layout); } + bool refresh(Client&) const { return refresh_ok; } + template bool primary_conflict(const T&) const { return primary_busy; } + template bool agent_conflict(const T&) const { return peer_busy; } +@@ -122,7 +122,7 @@ int main() { + for (bool session_fault : {true, false}) { + for (int path = 0; path < 3; ++path) { + Lane l; +- if (session_fault) l.session = false; else l.layout = false; ++ if (session_fault) l.session = false; else { l.layout = false; l.capabilities = 2; } + if (path == 0) l.guard_targets(); + if (path == 1) l.target_refusal(*l.lease); + if (path == 2) l.action_refusal(*l.lease); +@@ -133,6 +133,19 @@ int main() { + l.session = true; l.layout = true; l.guard_targets(); l.check_inert(); + } + } ++ // Pointer admission, dispatch and ongoing drag ignore keyboard layout readiness. ++ for (auto route : {InputRoute::independent, InputRoute::primary_foreground}) { ++ for (uint64_t cap : {1, 4, 8, 16}) { ++ Lane l; l.layout = false; l.lease->route = route; l.capabilities = cap; ++ l.target_refusal(*l.lease, route, cap); ++ check(l.lease && l.responses.empty(), "pointer admission gated on layout"); ++ l.action_refusal(*l.lease, cap); ++ check(l.lease && l.responses.empty(), "pointer dispatch gated on layout"); ++ l.guard_targets(); ++ check(l.lease && l.drag && l.held_button && l.responses.empty(), ++ "pointer operation was gated by keyboard layout"); ++ } ++ } + // Every passive safety guard still applies during either desktop fault. + for (bool session_fault : {true, false}) { + for (int bad = 0; bad < 8; ++bad) { +diff --git a/tests/desktop_fault_policy_test.py b/tests/desktop_fault_policy_test.py +index 68ca6c8..7a4d1b4 100644 +--- a/tests/desktop_fault_policy_test.py ++++ b/tests/desktop_fault_policy_test.py +@@ -35,10 +35,11 @@ def fixture(source): + ): + block = source.split(start, 1)[1].split(end, 1)[0] + refusals = [line.strip() for line in block.splitlines() +- if 'if (' in line and ('!available()' in line or '!layout_qualified()' in line)] ++ if 'if (' in line and ('!available()' in line or '!layout_qualified(' in line)] + if len(refusals) != 2: + raise AssertionError(f'production refusal branches not found: {label}') +- methods += '\nvoid ' + label + '(Client& c) {\n' + '\n'.join(refusals) + '\n}' ++ params = ', InputRoute route = InputRoute::independent, uint64_t requested_cap = 2' if label == 'target_refusal' else ', uint64_t cap = 2' ++ methods += '\nvoid ' + label + '(Client& c' + params + ') {\n' + '\n'.join(refusals) + '\n}' + return (ROOT / 'tests/desktop_fault_policy_fixture.cpp').read_text().replace( + '// PRODUCTION_METHODS', methods) + +diff --git a/tests/keyboard_layout_test.cpp b/tests/keyboard_layout_test.cpp +new file mode 100644 +index 0000000..dd7c962 +--- /dev/null ++++ b/tests/keyboard_layout_test.cpp +@@ -0,0 +1,97 @@ ++#include "keyboard_layout.hpp" ++#include ++#include ++#include ++ ++using namespace cua::hyprland; ++void check(bool condition, const char* message) { ++ if (!condition) { std::cerr << message << '\n'; std::exit(1); } ++} ++int main() { ++ using Context = std::unique_ptr; ++ using Map = std::unique_ptr; ++ using State = std::unique_ptr; ++ Context context{xkb_context_new(XKB_CONTEXT_NO_FLAGS), xkb_context_unref}; ++ Map agent{agent_keymap(context.get()), xkb_keymap_unref}; ++ Map second{agent_keymap(context.get()), xkb_keymap_unref}; ++ check(bool(agent) && bool(second), "canonical maps unavailable"); ++ const auto map = [&](const char* layout, const char* options) { ++ const xkb_rule_names names{"evdev", "pc105", layout, "", options}; ++ return Map{xkb_keymap_new_from_names(context.get(), &names, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; ++ }; ++ auto stock = map("us", "compose:caps,shift:both_capslock_cancel"); ++ auto nocaps = map("us", "ctrl:nocaps"); ++ auto swapctrl = map("us", "ctrl:swapcaps"); ++ auto swapalt = map("us", "altwin:swap_alt_win"); ++ auto german = map("de", ""); ++ check(stock && nocaps && swapctrl && swapalt && german, "test keymaps unavailable"); ++ for (auto* physical : {stock.get(), nocaps.get(), swapctrl.get(), swapalt.get(), german.get()}) { ++ check(foreground_chord_compatible(physical, agent.get(), 30, 0), "unrelated remap blocked A"); ++ check(foreground_chord_compatible(physical, agent.get(), 30, 1), "unrelated remap blocked Shift+A"); ++ check(foreground_chord_compatible(physical, agent.get(), 28, 0), "unrelated remap blocked Return"); ++ } ++ check(foreground_chord_compatible(stock.get(), agent.get(), 30, 2), "stock Omarchy blocked Ctrl+A"); ++ check(foreground_chord_compatible(nocaps.get(), agent.get(), 30, 2), "Caps to Ctrl blocked Ctrl+A"); ++ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 30, 2), "Ctrl/Caps swap sent wrong Ctrl+A"); ++ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 29, 0), "remapped modifier key accepted"); ++ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 4), "Alt/Super swap sent wrong Alt+A"); ++ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 8), "Alt/Super swap sent wrong Super+A"); ++ check(!foreground_chord_compatible(german.get(), agent.get(), 21, 0), "German Z accepted as US Y"); ++ check(!foreground_chord_compatible(german.get(), agent.get(), 3, 1), "German shifted punctuation accepted"); ++ check(!foreground_chord_compatible(nullptr, agent.get(), 30, 0), "missing physical map accepted"); ++ // All supported wire chords remain compatible on the independent map. ++ for (unsigned code = 1; code <= 247; ++code) ++ if (code != 58 && code != 69 && code != 70) ++ for (unsigned mods = 0; mods < 16; ++mods) ++ check(foreground_chord_compatible(agent.get(), agent.get(), code, mods), "canonical chord rejected"); ++ // Two lanes never share modifier state and never mutate the human state. ++ State first{xkb_state_new(agent.get()), xkb_state_unref}; ++ State other{xkb_state_new(second.get()), xkb_state_unref}; ++ State human{xkb_state_new(german.get()), xkb_state_unref}; ++ xkb_state_update_key(first.get(), 42 + 8, XKB_KEY_DOWN); ++ check(xkb_state_key_get_one_sym(first.get(), 30 + 8) == XKB_KEY_A, "agent shift not active"); ++ check(xkb_state_key_get_one_sym(other.get(), 30 + 8) == XKB_KEY_a, "agent shift leaked across lanes"); ++ check(xkb_state_key_get_one_sym(human.get(), 21 + 8) == XKB_KEY_z, "human layout changed"); ++ // Same symbols can hide a changed XKB action. Simulate an A that sets Mod3. ++ char* serialized = xkb_keymap_get_as_string(agent.get(), XKB_KEYMAP_FORMAT_TEXT_V1); ++ std::string changed = serialized; ++ std::free(serialized); ++ const auto at = changed.find("key "); ++ const auto end = changed.find(';', at); ++ check(at != std::string::npos && end != std::string::npos, "test action fixture unavailable"); ++ changed.replace(at, end - at + 1, ++ "key { type=\"ALPHABETIC\", symbols[Group1]=[a,A], actions[Group1]=[LockMods(modifiers=Mod3),LockMods(modifiers=Mod3)] };"); ++ Map lock{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; ++ check(bool(lock), "action fixture failed to compile"); ++ check(!foreground_chord_compatible(lock.get(), agent.get(), 30, 0), "hidden lock action accepted"); ++ // Equal symbols and modifier state can still alter toolkit shortcut matching. ++ serialized = xkb_keymap_get_as_string(agent.get(), XKB_KEYMAP_FORMAT_TEXT_V1); ++ changed = serialized; ++ std::free(serialized); ++ const auto type_at = changed.find("type \"ALPHABETIC\""); ++ const auto type_end = changed.find("};", type_at); ++ check(type_at != std::string::npos && type_end != std::string::npos, "key type fixture unavailable"); ++ changed.insert(type_end, "preserve[Shift] = Shift;\n"); ++ Map preserved{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; ++ check(bool(preserved), "preserved modifier fixture failed to compile"); ++ check(!foreground_chord_compatible(preserved.get(), agent.get(), 30, 1), "consumed modifier mismatch accepted"); ++ // A modifier that preserves Shift state but emits another symbol must fail. ++ serialized = xkb_keymap_get_as_string(agent.get(), XKB_KEYMAP_FORMAT_TEXT_V1); ++ changed = serialized; ++ std::free(serialized); ++ const auto shift_at = changed.find("key "); ++ const auto shift_end = changed.find(';', shift_at); ++ check(shift_at != std::string::npos && shift_end != std::string::npos, "shift fixture unavailable"); ++ changed.replace(shift_at, shift_end - shift_at + 1, ++ "key { symbols[Group1]=[Delete], actions[Group1]=[SetMods(modifiers=Shift)] };"); ++ Map badshift{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; ++ check(bool(badshift), "shift fixture failed to compile"); ++ check(!foreground_chord_compatible(badshift.get(), agent.get(), 30, 1), "modifier press symbols not checked"); ++ for (auto route : {InputRoute::independent, InputRoute::primary_foreground}) { ++ for (uint64_t cap : {1, 4, 8, 16}) check(keyboard_layout_ready(route, cap, false, false), "pointer gated on layout"); ++ check(!keyboard_layout_ready(route, 2, false, false), "key accepted without map"); ++ } ++ check(keyboard_layout_ready(InputRoute::independent, 2, true, false), "background depends on human map"); ++ check(!keyboard_layout_ready(InputRoute::primary_foreground, 2, true, false), "foreground uses agent readiness"); ++ std::cout << "keyboard layout tests passed\n"; ++} +diff --git a/tests/plugin_input_lifetime_test.cpp b/tests/plugin_input_lifetime_test.cpp +index ff09451..b999925 100644 +--- a/tests/plugin_input_lifetime_test.cpp ++++ b/tests/plugin_input_lifetime_test.cpp +@@ -51,12 +51,17 @@ int main() { + check(setenv("XDG_RUNTIME_DIR", directory, 1) == 0 && + setenv("HYPRLAND_INSTANCE_SIGNATURE", "mock", 1) == 0, + "select runtime"); +- Config::Values::configured_bool_override = true; ++ Config::Values::configured_bool_override = false; + static_cast(pluginInit(nullptr)); + const auto toggle = [](bool enabled) { + HyprlandAPI::registered_bool->set_mock_value(enabled); + Event::bus()->m_events.config.reloaded.emit(); + }; ++#ifdef CUA_HYPRLAND_INPUT ++ const auto initial_status = HyprlandAPI::registered_legacy_command->fn(FORMAT_JSON, {}); ++ check(created == 0 && initial_status.find("\"configured\":false") != std::string::npos && initial_status.find("\"keyboard_layout_independent\":true") != std::string::npos, ++ "disabled production module advertises compiled keyboard support before enable"); ++#endif + for (unsigned i = 0; i < 20; ++i) { + toggle(true); + #ifdef CUA_HYPRLAND_INPUT +@@ -64,6 +69,7 @@ int main() { + check(status.find("\"state\":\"input_v3_candidate\"") != std::string::npos && + status.find("trusted_local_per_action") != std::string::npos && + status.find("\"input\":{}") != std::string::npos && ++ status.find("\"keyboard_layout_independent\":true") != std::string::npos && + status.find("operator") == std::string::npos, + "v3 status advertises its actual admission mode"); + #endif From b9a3863787f53c84954ed7b3154d68b35cb2094b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Wed, 16 Sep 2026 13:39:52 +0900 Subject: [PATCH 023/121] Add Android Binder support back to the base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- .../0010-archlinux-base.patch.sig | Bin 0 -> 594 bytes .../0110-bore-6.8.0.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0120-tlbpull.patch.sig | Bin 0 -> 594 bytes .../0121-smp-preempt.patch.sig | Bin 0 -> 594 bytes .../0130-sched-detach-tasks.patch.sig | Bin 0 -> 594 bytes .../0131-sched-avg-idle.patch.sig | Bin 0 -> 594 bytes .../0140-sched-always-inline.patch.sig | Bin 0 -> 594 bytes .../0141-sched-urgent-fixes.patch.sig | Bin 0 -> 594 bytes ...sched-itmt-no-debugfs-dependency.patch.sig | Bin 0 -> 594 bytes ...3-sched-hybrid-cluster-balancing.patch.sig | Bin 0 -> 594 bytes .../0144-sched-nohz-idle-core.patch.sig | Bin 0 -> 594 bytes .../0150-adios-3.2.0.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0200-idle.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0210-pstate.patch.sig | Bin 0 -> 594 bytes .../0211-amd-pstate-fixes.patch.sig | Bin 0 -> 594 bytes .../0212-amd-pstate-epp-cache.patch.sig | Bin 0 -> 594 bytes .../0250-zsmalloc.patch.sig | Bin 0 -> 594 bytes .../0260-mglru-exec-protect.patch.sig | Bin 0 -> 594 bytes .../0270-ksm-rmap-walk.patch.sig | Bin 0 -> 594 bytes .../0280-mm-updates.patch.sig | Bin 0 -> 594 bytes .../0290-zstd-bmi2-fallback-aliases.patch.sig | Bin 0 -> 594 bytes ...1-zstd-bmi2-cpu-feature-dispatch.patch.sig | Bin 0 -> 594 bytes ...2-crypto-zstd-defer-cstream-init.patch.sig | Bin 0 -> 594 bytes ...3-crypto-zstd-defer-dstream-init.patch.sig | Bin 0 -> 594 bytes .../0295-af-alg-restrict.patch.sig | Bin 0 -> 594 bytes ...x86-mm-pmd-modify-keep-dirty-bit.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0300-btrfs.patch.sig | Bin 0 -> 594 bytes .../0301-btrfs-fixes.patch.sig | Bin 0 -> 594 bytes ...s-zstd-decompress-direct-to-page.patch.sig | Bin 0 -> 594 bytes .../0310-fuse-eof-zeroing.patch.sig | Bin 0 -> 594 bytes .../0311-fuse-perf.patch.sig | Bin 0 -> 594 bytes .../0312-fuse-writethrough-uptodate.patch.sig | Bin 0 -> 594 bytes .../0313-fuse-background-wakeup.patch.sig | Bin 0 -> 594 bytes ...nge-from-displayid-adaptive-sync.patch.sig | Bin 0 -> 594 bytes .../0360-gpu-mem-cgroup.patch.sig | Bin 0 -> 594 bytes ...pm-limit-pr-alpm-to-panel-replay.patch.sig | Bin 0 -> 594 bytes ...r-exit-panel-replay-for-alpm-lag.patch.sig | Bin 0 -> 594 bytes ...0402-psr2-early-transport-panels.patch.sig | Bin 0 -> 594 bytes ...e-display-no-stolen-framebuffers.patch.sig | Bin 0 -> 594 bytes .../0420-safe-window.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0430-fbc.patch.sig | Bin 0 -> 594 bytes .../0440-xe3-peak-bandwidth.patch.sig | Bin 0 -> 594 bytes .../0450-amd-hdmi-vrr-allm.patch.sig | Bin 0 -> 594 bytes .../0451-amd-vtem-tmds-links.patch.sig | Bin 0 -> 594 bytes .../0452-amd-hdmi-frl-default.patch.sig | Bin 0 -> 594 bytes .../0460-vesa-displayid-dsc-bpp.patch.sig | Bin 0 -> 594 bytes ...vesa-dsc-passthru-mode-match-fix.patch.sig | Bin 0 -> 594 bytes ...72-amdgpu-userq-post-reset-error.patch.sig | Bin 0 -> 594 bytes .../0473-i915-ptl-cdclk-sanitize.patch.sig | Bin 0 -> 594 bytes ...-amd-display-oled-vesa-backlight.patch.sig | Bin 0 -> 594 bytes ...ert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig | Bin 0 -> 594 bytes .../0510-sound-updates.patch.sig | Bin 0 -> 594 bytes .../0511-sound-updates-fixes.patch.sig | Bin 0 -> 594 bytes .../0512-sound-fixes.patch.sig | Bin 0 -> 594 bytes .../0513-xps13-sof-quirk.patch.sig | Bin 0 -> 594 bytes .../0514-rt766-stream-config-type.patch.sig | Bin 0 -> 594 bytes ...ealtek-rog-strix-g733zw-speakers.patch.sig | Bin 0 -> 594 bytes ...asoc-amd-yc-acer-aspire-a314-23p.patch.sig | Bin 0 -> 594 bytes ...ia-ipu-bridge-ivsc-no-cvs-lookup.patch.sig | Bin 0 -> 594 bytes .../0541-cvs-nova-lake-acpi-id.patch.sig | Bin 0 -> 594 bytes ...s-wake-irq-without-claiming-gpio.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy-bore/0560-input.patch.sig | Bin 0 -> 594 bytes ...565-i2c-asue140d-touchpad-100khz.patch.sig | Bin 0 -> 594 bytes ...yboard-init-reports-to-touchpads.patch.sig | Bin 0 -> 594 bytes .../0600-usb4stream-fixes.patch.sig | Bin 0 -> 594 bytes .../0601-usb4stream-busy-poll.patch.sig | Bin 0 -> 594 bytes .../0610-typec-cable-altmode-check.patch.sig | Bin 0 -> 594 bytes .../0620-usb-string-sanitize.patch.sig | Bin 0 -> 594 bytes .../0650-wireguard-tstamp-type.patch.sig | Bin 0 -> 594 bytes ...-btusb-mediatek-mt7922-13d3-3625.patch.sig | Bin 0 -> 594 bytes ...661-rtw89-command-offload-source.patch.sig | Bin 0 -> 594 bytes ...i-mld-skip-tx-when-firmware-dead.patch.sig | Bin 0 -> 594 bytes .../0700-pci-target-speed-quirk.patch.sig | Bin 0 -> 594 bytes .../0750-applesmc-cache-race.patch.sig | Bin 0 -> 594 bytes ...smc-key-backlight-workqueue-leak.patch.sig | Bin 0 -> 594 bytes ...-swift3-sf314-56g-power-resource.patch.sig | Bin 0 -> 594 bytes .../0800-platform-updates.patch.sig | Bin 0 -> 594 bytes ...d-pmf-util-unbind-use-after-free.patch.sig | Bin 0 -> 594 bytes .../0850-futex-wait-multiple.patch.sig | Bin 0 -> 594 bytes .../0851-futex-wait-multiple-fixes.patch.sig | Bin 0 -> 594 bytes ...52-futex-wait-multiple-abi-fixes.patch.sig | Bin 0 -> 594 bytes ...shrinker-return-freed-page-count.patch.sig | Bin 0 -> 594 bytes ...runtime-pm-for-non-system-memory.patch.sig | Bin 0 -> 594 bytes ...r-release-through-the-put-helper.patch.sig | Bin 0 -> 594 bytes ...8204-mm-opportunistic-compaction.patch.sig | Bin 0 -> 594 bytes ...05-mm-hint-uses-allocation-order.patch.sig | Bin 0 -> 594 bytes ...carry-order-and-hint-in-one-word.patch.sig | Bin 0 -> 594 bytes ...uge-page-allocations-as-failable.patch.sig | Bin 0 -> 594 bytes ...-mm-thp-deferred-split-uses-hint.patch.sig | Bin 0 -> 594 bytes ...-shrinker-use-opportunistic-hint.patch.sig | Bin 0 -> 594 bytes ...-shrinker-single-backup-decision.patch.sig | Bin 0 -> 594 bytes ...-bpftool-strip-wformat-bootstrap.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy-bore/PKGBUILD | 375 +++++++++++++----- pkgbuilds/linux-omarchy-bore/config.x86_64 | 3 +- .../0010-archlinux-base.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0120-tlbpull.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0121-smp-preempt.patch.sig | Bin 0 -> 594 bytes .../0130-sched-detach-tasks.patch.sig | Bin 0 -> 594 bytes .../0131-sched-avg-idle.patch.sig | Bin 0 -> 594 bytes .../0140-sched-always-inline.patch.sig | Bin 0 -> 594 bytes .../0141-sched-urgent-fixes.patch.sig | Bin 0 -> 594 bytes ...sched-itmt-no-debugfs-dependency.patch.sig | Bin 0 -> 594 bytes ...3-sched-hybrid-cluster-balancing.patch.sig | Bin 0 -> 594 bytes .../0144-sched-nohz-idle-core.patch.sig | Bin 0 -> 594 bytes .../0145-sched-eevdf-tunables.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/0200-idle.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/0210-pstate.patch.sig | Bin 0 -> 594 bytes .../0211-amd-pstate-fixes.patch.sig | Bin 0 -> 594 bytes .../0212-amd-pstate-epp-cache.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0250-zsmalloc.patch.sig | Bin 0 -> 594 bytes .../0260-mglru-exec-protect.patch.sig | Bin 0 -> 594 bytes .../0270-ksm-rmap-walk.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0280-mm-updates.patch.sig | Bin 0 -> 594 bytes .../0290-zstd-bmi2-fallback-aliases.patch.sig | Bin 0 -> 594 bytes ...1-zstd-bmi2-cpu-feature-dispatch.patch.sig | Bin 0 -> 594 bytes ...2-crypto-zstd-defer-cstream-init.patch.sig | Bin 0 -> 594 bytes ...3-crypto-zstd-defer-dstream-init.patch.sig | Bin 0 -> 594 bytes .../0295-af-alg-restrict.patch.sig | Bin 0 -> 594 bytes ...x86-mm-pmd-modify-keep-dirty-bit.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/0300-btrfs.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0301-btrfs-fixes.patch.sig | Bin 0 -> 594 bytes ...s-zstd-decompress-direct-to-page.patch.sig | Bin 0 -> 594 bytes .../0310-fuse-eof-zeroing.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0311-fuse-perf.patch.sig | Bin 0 -> 594 bytes .../0312-fuse-writethrough-uptodate.patch.sig | Bin 0 -> 594 bytes .../0313-fuse-background-wakeup.patch.sig | Bin 0 -> 594 bytes ...nge-from-displayid-adaptive-sync.patch.sig | Bin 0 -> 594 bytes .../0360-gpu-mem-cgroup.patch.sig | Bin 0 -> 594 bytes ...pm-limit-pr-alpm-to-panel-replay.patch.sig | Bin 0 -> 594 bytes ...r-exit-panel-replay-for-alpm-lag.patch.sig | Bin 0 -> 594 bytes ...0402-psr2-early-transport-panels.patch.sig | Bin 0 -> 594 bytes ...e-display-no-stolen-framebuffers.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0420-safe-window.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/0430-fbc.patch.sig | Bin 0 -> 594 bytes .../0440-xe3-peak-bandwidth.patch.sig | Bin 0 -> 594 bytes .../0450-amd-hdmi-vrr-allm.patch.sig | Bin 0 -> 594 bytes .../0451-amd-vtem-tmds-links.patch.sig | Bin 0 -> 594 bytes .../0452-amd-hdmi-frl-default.patch.sig | Bin 0 -> 594 bytes .../0460-vesa-displayid-dsc-bpp.patch.sig | Bin 0 -> 594 bytes ...vesa-dsc-passthru-mode-match-fix.patch.sig | Bin 0 -> 594 bytes ...72-amdgpu-userq-post-reset-error.patch.sig | Bin 0 -> 594 bytes .../0473-i915-ptl-cdclk-sanitize.patch.sig | Bin 0 -> 594 bytes ...-amd-display-oled-vesa-backlight.patch.sig | Bin 0 -> 594 bytes ...ert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig | Bin 0 -> 594 bytes .../0510-sound-updates.patch.sig | Bin 0 -> 594 bytes .../0511-sound-updates-fixes.patch.sig | Bin 0 -> 594 bytes .../linux-omarchy/0512-sound-fixes.patch.sig | Bin 0 -> 594 bytes .../0513-xps13-sof-quirk.patch.sig | Bin 0 -> 594 bytes .../0514-rt766-stream-config-type.patch.sig | Bin 0 -> 594 bytes ...ealtek-rog-strix-g733zw-speakers.patch.sig | Bin 0 -> 594 bytes ...asoc-amd-yc-acer-aspire-a314-23p.patch.sig | Bin 0 -> 594 bytes ...ia-ipu-bridge-ivsc-no-cvs-lookup.patch.sig | Bin 0 -> 594 bytes .../0541-cvs-nova-lake-acpi-id.patch.sig | Bin 0 -> 594 bytes ...s-wake-irq-without-claiming-gpio.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/0560-input.patch.sig | Bin 0 -> 594 bytes ...565-i2c-asue140d-touchpad-100khz.patch.sig | Bin 0 -> 594 bytes ...yboard-init-reports-to-touchpads.patch.sig | Bin 0 -> 594 bytes .../0600-usb4stream-fixes.patch.sig | Bin 0 -> 594 bytes .../0601-usb4stream-busy-poll.patch.sig | Bin 0 -> 594 bytes .../0610-typec-cable-altmode-check.patch.sig | Bin 0 -> 594 bytes .../0620-usb-string-sanitize.patch.sig | Bin 0 -> 594 bytes .../0650-wireguard-tstamp-type.patch.sig | Bin 0 -> 594 bytes ...-btusb-mediatek-mt7922-13d3-3625.patch.sig | Bin 0 -> 594 bytes ...661-rtw89-command-offload-source.patch.sig | Bin 0 -> 594 bytes ...i-mld-skip-tx-when-firmware-dead.patch.sig | Bin 0 -> 594 bytes .../0700-pci-target-speed-quirk.patch.sig | Bin 0 -> 594 bytes .../0750-applesmc-cache-race.patch.sig | Bin 0 -> 594 bytes ...smc-key-backlight-workqueue-leak.patch.sig | Bin 0 -> 594 bytes ...-swift3-sf314-56g-power-resource.patch.sig | Bin 0 -> 594 bytes .../0800-platform-updates.patch.sig | Bin 0 -> 594 bytes ...d-pmf-util-unbind-use-after-free.patch.sig | Bin 0 -> 594 bytes .../0850-futex-wait-multiple.patch.sig | Bin 0 -> 594 bytes .../0851-futex-wait-multiple-fixes.patch.sig | Bin 0 -> 594 bytes ...52-futex-wait-multiple-abi-fixes.patch.sig | Bin 0 -> 594 bytes ...shrinker-return-freed-page-count.patch.sig | Bin 0 -> 594 bytes ...runtime-pm-for-non-system-memory.patch.sig | Bin 0 -> 594 bytes ...r-release-through-the-put-helper.patch.sig | Bin 0 -> 594 bytes ...8204-mm-opportunistic-compaction.patch.sig | Bin 0 -> 594 bytes ...05-mm-hint-uses-allocation-order.patch.sig | Bin 0 -> 594 bytes ...carry-order-and-hint-in-one-word.patch.sig | Bin 0 -> 594 bytes ...uge-page-allocations-as-failable.patch.sig | Bin 0 -> 594 bytes ...-mm-thp-deferred-split-uses-hint.patch.sig | Bin 0 -> 594 bytes ...-shrinker-use-opportunistic-hint.patch.sig | Bin 0 -> 594 bytes ...-shrinker-single-backup-decision.patch.sig | Bin 0 -> 594 bytes ...-bpftool-strip-wformat-bootstrap.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/PKGBUILD | 371 ++++++++++++----- pkgbuilds/linux-omarchy/config.x86_64 | 3 +- 187 files changed, 559 insertions(+), 193 deletions(-) create mode 100644 pkgbuilds/linux-omarchy-bore/0010-archlinux-base.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0110-bore-6.8.0.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0120-tlbpull.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0121-smp-preempt.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0130-sched-detach-tasks.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0131-sched-avg-idle.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0140-sched-always-inline.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0141-sched-urgent-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0142-sched-itmt-no-debugfs-dependency.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0143-sched-hybrid-cluster-balancing.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0144-sched-nohz-idle-core.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0150-adios-3.2.0.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0200-idle.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0210-pstate.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0211-amd-pstate-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0212-amd-pstate-epp-cache.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0250-zsmalloc.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0260-mglru-exec-protect.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0270-ksm-rmap-walk.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0280-mm-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0290-zstd-bmi2-fallback-aliases.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0291-zstd-bmi2-cpu-feature-dispatch.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0292-crypto-zstd-defer-cstream-init.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0293-crypto-zstd-defer-dstream-init.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0295-af-alg-restrict.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0296-x86-mm-pmd-modify-keep-dirty-bit.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0300-btrfs.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0301-btrfs-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0302-btrfs-zstd-decompress-direct-to-page.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0310-fuse-eof-zeroing.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0311-fuse-perf.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0312-fuse-writethrough-uptodate.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0313-fuse-background-wakeup.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0360-gpu-mem-cgroup.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0401-drm-i915-psr-exit-panel-replay-for-alpm-lag.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0402-psr2-early-transport-panels.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0411-drm-xe-display-no-stolen-framebuffers.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0420-safe-window.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0430-fbc.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0440-xe3-peak-bandwidth.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0450-amd-hdmi-vrr-allm.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0451-amd-vtem-tmds-links.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0452-amd-hdmi-frl-default.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0460-vesa-displayid-dsc-bpp.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0461-vesa-dsc-passthru-mode-match-fix.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0472-amdgpu-userq-post-reset-error.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0473-i915-ptl-cdclk-sanitize.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0474-amd-display-oled-vesa-backlight.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0510-sound-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0511-sound-updates-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0512-sound-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0513-xps13-sof-quirk.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0514-rt766-stream-config-type.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0517-asoc-amd-yc-acer-aspire-a314-23p.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0540-media-ipu-bridge-ivsc-no-cvs-lookup.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0541-cvs-nova-lake-acpi-id.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0542-media-cvs-wake-irq-without-claiming-gpio.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0560-input.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0565-i2c-asue140d-touchpad-100khz.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0566-hid-asus-no-keyboard-init-reports-to-touchpads.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0600-usb4stream-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0601-usb4stream-busy-poll.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0610-typec-cable-altmode-check.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0620-usb-string-sanitize.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0650-wireguard-tstamp-type.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0661-rtw89-command-offload-source.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0662-iwlwifi-mld-skip-tx-when-firmware-dead.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0700-pci-target-speed-quirk.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0750-applesmc-cache-race.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0751-applesmc-key-backlight-workqueue-leak.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0800-platform-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0801-amd-pmf-util-unbind-use-after-free.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0850-futex-wait-multiple.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0851-futex-wait-multiple-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/0852-futex-wait-multiple-abi-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8201-xe-shrinker-return-freed-page-count.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8202-xe-shrinker-runtime-pm-for-non-system-memory.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8203-xe-shrinker-release-through-the-put-helper.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8204-mm-opportunistic-compaction.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8205-mm-hint-uses-allocation-order.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8206-mm-carry-order-and-hint-in-one-word.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8207-mm-classify-huge-page-allocations-as-failable.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8208-mm-thp-deferred-split-uses-hint.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8209-xe-shrinker-use-opportunistic-hint.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/8210-xe-shrinker-single-backup-decision.patch.sig create mode 100644 pkgbuilds/linux-omarchy-bore/9999-bpftool-strip-wformat-bootstrap.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0010-archlinux-base.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0120-tlbpull.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0121-smp-preempt.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0130-sched-detach-tasks.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0131-sched-avg-idle.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0140-sched-always-inline.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0141-sched-urgent-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0142-sched-itmt-no-debugfs-dependency.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0143-sched-hybrid-cluster-balancing.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0144-sched-nohz-idle-core.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0145-sched-eevdf-tunables.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0200-idle.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0210-pstate.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0211-amd-pstate-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0212-amd-pstate-epp-cache.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0250-zsmalloc.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0260-mglru-exec-protect.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0270-ksm-rmap-walk.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0280-mm-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0290-zstd-bmi2-fallback-aliases.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0291-zstd-bmi2-cpu-feature-dispatch.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0292-crypto-zstd-defer-cstream-init.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0293-crypto-zstd-defer-dstream-init.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0295-af-alg-restrict.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0296-x86-mm-pmd-modify-keep-dirty-bit.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0300-btrfs.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0301-btrfs-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0302-btrfs-zstd-decompress-direct-to-page.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0310-fuse-eof-zeroing.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0311-fuse-perf.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0312-fuse-writethrough-uptodate.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0313-fuse-background-wakeup.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0360-gpu-mem-cgroup.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0401-drm-i915-psr-exit-panel-replay-for-alpm-lag.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0402-psr2-early-transport-panels.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0411-drm-xe-display-no-stolen-framebuffers.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0420-safe-window.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0430-fbc.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0440-xe3-peak-bandwidth.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0450-amd-hdmi-vrr-allm.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0451-amd-vtem-tmds-links.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0452-amd-hdmi-frl-default.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0460-vesa-displayid-dsc-bpp.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0461-vesa-dsc-passthru-mode-match-fix.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0472-amdgpu-userq-post-reset-error.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0473-i915-ptl-cdclk-sanitize.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0474-amd-display-oled-vesa-backlight.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0510-sound-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0511-sound-updates-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0512-sound-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0513-xps13-sof-quirk.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0514-rt766-stream-config-type.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0517-asoc-amd-yc-acer-aspire-a314-23p.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0540-media-ipu-bridge-ivsc-no-cvs-lookup.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0541-cvs-nova-lake-acpi-id.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0542-media-cvs-wake-irq-without-claiming-gpio.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0560-input.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0565-i2c-asue140d-touchpad-100khz.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0566-hid-asus-no-keyboard-init-reports-to-touchpads.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0600-usb4stream-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0601-usb4stream-busy-poll.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0610-typec-cable-altmode-check.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0620-usb-string-sanitize.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0650-wireguard-tstamp-type.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0661-rtw89-command-offload-source.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0662-iwlwifi-mld-skip-tx-when-firmware-dead.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0700-pci-target-speed-quirk.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0750-applesmc-cache-race.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0751-applesmc-key-backlight-workqueue-leak.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0800-platform-updates.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0801-amd-pmf-util-unbind-use-after-free.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0850-futex-wait-multiple.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0851-futex-wait-multiple-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0852-futex-wait-multiple-abi-fixes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8201-xe-shrinker-return-freed-page-count.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8202-xe-shrinker-runtime-pm-for-non-system-memory.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8203-xe-shrinker-release-through-the-put-helper.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8204-mm-opportunistic-compaction.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8205-mm-hint-uses-allocation-order.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8206-mm-carry-order-and-hint-in-one-word.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8207-mm-classify-huge-page-allocations-as-failable.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8208-mm-thp-deferred-split-uses-hint.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8209-xe-shrinker-use-opportunistic-hint.patch.sig create mode 100644 pkgbuilds/linux-omarchy/8210-xe-shrinker-single-backup-decision.patch.sig create mode 100644 pkgbuilds/linux-omarchy/9999-bpftool-strip-wformat-bootstrap.patch.sig diff --git a/pkgbuilds/linux-omarchy-bore/0010-archlinux-base.patch.sig b/pkgbuilds/linux-omarchy-bore/0010-archlinux-base.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..a7eaa24f4bf207e6053acb0224871d56101abee1 GIT binary patch literal 594 zcmV-Y0;&|8IZldMXQ<#V;G3n=eJ1 zEo7?0)uY?&2^w?QXJ}QsqW*GO)*Q4s(Y2f3M_JjuHV>)U#;-rHU7wDgn>sPT&e=}| zh0+i+23Yag=5VQ#!XFB~9K_t)G&lN!G9b`6bf7}VIIm#X1eyuT?-DprG&agYMd3K2 zW<4VXUNl87qK>ai+wk#b4muSqn^Y(?7|o0oF}xmRp^k8v3P!V4!3zOtkpiSSN-37-j=eLEZr33HLGjq*3nRuZ!ez} z0wS2KYn;x97jT8mtasgsoFAVi2D_V?q0*N?JuSdUxD>eGZVPM(7=yeEeK63oJ$EQ8Yhg+Bx$G#|1>F z7WJ)b1JT3Fp*RZFtpjKc8QIs;bdH=$Z)xi3Gq%{lkJYy<)|Xnszsn-RW~1y~VJ5H} z?j;-zm5#T*0pxUyWZB+d1BZ=%y7bUr23ugEC)e53Y>P946;0Ta5@64_fl8#wvuO~OFF&+tv@=>)OH z5YZtUt{CR-T-}8tSGQxID;<`f&dhSzx$*$t`FKvG6ta1%r8%txTji&~<$g8S{c6b_!;MSqiJ;3Y?R~3k7URudi3TTgaVHQZ5t&7fn(a zD`2K~qs&wV?NT3yI({#=yvH|&;5pd71&#o%40?v-e)I(}RjGN|9Dft&(FScY04=@} zhhFirHysuISaqv{62x3Pg=fY}7>o+8u3S3^kUi>mI#Fu-%SY%)ORAF0;bR|YY}{~K z2WO3Ih)B^w*lUs$&PQ5Q=?vUFz)%U|&G$a4xd1H-w}@bl*hDuclyof`uQ7Hk)5@u< zRDZX5jWfB#ukS*;{8j@9s`NzO_0Mxd0d0;K{TuybbcWs6#yaEy>1Wv=D1Ywcp$YS@ zDwZM_QMc>Xgww{Mo3ccQ$@8W9loe6|5|t2y7?WvXtI6Jo;8B$z6DKt|XHdHBkgB|% z{nb{)_BtkzZ?tqWw2HnuFdFwY7*CcQ*;IoegFUf literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0120-tlbpull.patch.sig b/pkgbuilds/linux-omarchy-bore/0120-tlbpull.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..54e6137b6343676db9cac15ee5180adccdb523a8 GIT binary patch literal 594 zcmV-Y0^8`6i`SbnyLa{*wjSU9)W#PWHe0@-!7hWi%`!u4yLtqWbxMn7#>gk6U`U2r zvMCocDHXJ77e;Do7HtTE z#k{;>++UVSgi{q{beXUTN!WOFgwL?YO#j{O&Q+NjLS}O~Ql}(jk?URV0ZWtrYmYFQ zt!;C9&XxR=yT>*GENcS{FbkS-rZMDxEi5j3XEYCI`M^?-0ZQUQb1G$sMnMk=W6HhJD<71nMpO5hs4mTIjntIpRhp_UgKDu(Ukb$d+9E_?&PCjfnG4L6 z`}gY8(_LD0g23SsHH_N!VOQ`V6wBmf%BZ2Ni-Db+%ev?d@B|LJX;UZ6uDgbV7^yXW gSmL3*F|Ap7Mc=%2_BeK^^h>aJMufsm$QLXqz8bk7(f|Me literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0121-smp-preempt.patch.sig b/pkgbuilds/linux-omarchy-bore/0121-smp-preempt.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..078bc7705df59e261032048b47963fbb1e42244e GIT binary patch literal 594 zcmV-Y0XAmiA~RRB8uztqS0fJ9gUu>c`Ci_)=>nV(3$U|2Qy(^HgoC!1gYuJAXoc~#%aa>A zZD){?21U-ZRyB2g)V(}oy!RW=F4@JMNbKVs!YkjbBgr(5LHZkNt&hd915lqSDs4^r z-k&!F7Ci|jzt^UAoThv)UGFu(1Ll4mWk6M`t7>`!3Nj0AZ2A!?=Tq1;&dlPuDEwMCU2to%F&00v^s%W6Do(wrdf$He&Zw}zJhgJPO^_sjb$E3tBZ{1O$@Kap1` z)PI$Z)#`w|kNlJ?Un~3T>uTJf0g!u(gl0YQl}FR)#>jg(KF`p~w`nK6ZZ4y?2XW|4 z*rO&frQ-c~QE=NWS#-Q7+3K$rrLm!;D#bEF=BX|0L7E;?4J#X#cLE|91S&_?pc5-_ z9vY15Da(%0V+$12nwU&5iG6gpXv()f_E8?khPc*NMc;Ozbi=TjT3)n&d}=GJDe+GAV4i%@Y?(*M(e-9cq$ g-|DkwBmVf4coAkfOm^JG}zI#o{IF?H>Hr#^GK*@D5 zY*n~aQy(t<|BRz9*nc)t)>{VDP!mf#& zbN;y$kvHlj&RQ)gd$nJW<}t)^Z!;L$qpSL@K`7IhLg_B$v$`Y8O=bn1>pg--;o!Hm zh(?Arke&}Ov~GRw;^S%6N6XdVlNvLlnZ6#&R4|q^fLFImTn=y^2&0>fk$n}+^XBfJ z_a7vm5%QX~lI_;!!OPbdglZC`UCI}Hdz`kqAln7*QELy{K@(Tw#9pWG8MPtQNV+5O zN0dG}WlBvK?_Yzhjw8cT%zKfBi^Qm;%~fYem-VfPsN@rGFe$_zxvF#SKF7D`XF_(5 z(YW>4obes%>w@Lt%3z$i>52ILfMvff4+NFjnC3$j$XRF`Ih8Y!*)H7iyM{+*IcOrr z^)&3`GRKFbvt!rZ?YqAszi?*!{})=Dn~{4B(iLDi^ETKDFf8oe&iV2_ld@Hmh!W}; gQxJzvmqC_g$lQ+B_M;%)_cpIqjLuu}0$u{hCZwJosQ>@~ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0131-sched-avg-idle.patch.sig b/pkgbuilds/linux-omarchy-bore/0131-sched-avg-idle.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..3407a4e9af918a3a9396efb8d8859a3a13ff6fca GIT binary patch literal 594 zcmV-Y0n2f)U+?$Bzq2~SfvZ&CguqTtc#S9BB4^9p`CW_l?^b# z{YS@Il>%gHt+mOnRZR~%gE_PJxeXNTNDF-gkPE=cazP3xtp6rTFWi9Ax9 g2v4lGF04l-m^REun+}Vza@tZ%#mA3hbwjexANvdyYybcN literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0140-sched-always-inline.patch.sig b/pkgbuilds/linux-omarchy-bore/0140-sched-always-inline.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..290ce7ca68272c7ce17ffcbe4885f51dd0a1e2e6 GIT binary patch literal 594 zcmV-Y0#=I8GWl!T<%_OCoya6?c9qQ~|qo~S|nyVSt0j?$G@boVMUUg1J^@T_`d#=c3I za@Xp7uUEJlw|+cq;+e#v^tM_OsPNIB2fzgO5PZvzkg4k`8!K`WC-b$9p*8m^q7z(3 z22;G#O*NgwCICj%)IpaKvaeYOrkIu<9xAZ*EorvXDOujj31GRZmrs@QLrioyJBY`UEv1%_u%`{eb?ii|#B{<%l`56yYx`VHAqmUG+GluO7 zGAy2h=?0FxC8=Ai2}zuM%!Nd}r)!Fs2d1fx zm|1WgmhpK~8+m$JBXvzu{H`pqvUB?2zM)70+zDj|{BrAaCl;dvY@IX3xgZ>{?;y-e zl3WqDdQHQ7Jy*y%BbUMO1^Z`QNPBg}tyQG{@due^QML~d&FQSq3R#meUD`IIUiS51 zP*&oY)l6jeUh4O$O+=#kaCoRI5)x68Qsz~4-#C!>Wl2=4^UP5m62>5E+FLbz21G(J zBy1_IHfDEmvfKjyS!L*+(Vdlxb9eO1S}d5+3%!>PWq-jy+{g{oRB$0P>Ih34&rb7? zfF+@Q$Y115A)88<&#s2*ik;5^(T*azRGCr(sxJJE_iRkC-LN=U)b{A6>naUaTvXOJ zv#nb;Z3Ke7E)Njiu_9^%P0^;==0=G@o=cpSsYV!%Sk?QY@J)(o{y}fjPKzLz)+SxQ zTsn3c+Mkwvjh-4NB=W{Dm?1E%jKDMQ{P00MG3JV=(vbSrfXGa*G=b`CH-jwu(YGrJ zT%>@Sh(?H#1I^*3thw g+~f)k_V$?uf#L2OK7I~8tD|#cBVi`6ST;P zQR9SeCO~1c>e>TbZ}5K(9E#Wt3Q2~!`&9izqs%e`)`N@kz4vj09|kj2;QW4xyckHN z{8i{?P=P`gQ@{X9xk_M+gbkDp3gsC!`y-4!CEP$Rpf*2|^5gR|Qe%WW#Hs z&?rc78D2pW!Ayp;vsMiqN0+fXIJ@lXKZ+m2z+FBiY|FWFAwlR- zDV&%0S|V?- g-2jIqsb)suI|yFVp)c>~(wjfQA^AGF&gbN(ZN-HTDgXcg literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0143-sched-hybrid-cluster-balancing.patch.sig b/pkgbuilds/linux-omarchy-bore/0143-sched-hybrid-cluster-balancing.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..91abc021f493231f793f7c355fdd39d5d233f77f GIT binary patch literal 594 zcmV-Y04LVmcs5JuFE01q7&{tRjsjAmOw%?aS9_qtT^7MMdkCvdgct68Y zrj*4fO-$9wq{0J8pUCBWznMbfMe%kGzl$=3UlOEkMt(!2ka6`fD$)l$z<#iIXGxYX z7QQ9$+%`aA)zE|_Yj*?-s1-$ot^^T6xWARvaZnptgrs&o`Nm#UG_ywlMU~{GERRD+ z3XB}JkRp_fP+=TnUeNTQU=;(YZtZ)qmRVL3YdfrRyx+=<4&8IBxPseuix!-0H}@Mi zkA5M7-K5(+V4Y`lg(sa+rcA=wqEko*h7eT6)8ieoAwbYBQ3}uRooT5fVr!q{v-(<8 zIIr&0x&D)qDKjIggvDW&Dp#3t>NT@-1@Bs6>Cd?Wa6s*Y@5O(&2a77A%A(MGl86e= z42-%zn~E_wDC_5Rs=?kmXq%fLR@?*@`3&|ppSJ(*iJ4G54~mq7M9jF9Z%X-;pxnr3 zB|Em?B?C^$1_D*CD~)XP)WR%8X2HC#% z8XDCk2<@y2?euB855iFRjLPQVnM|Tspq)N@mxw1V&OU-0bO#N0;F~#+J}D-<$Pseu zuw7DauJr9oW**EppcMz=?*wFO6oUT~6kLX;p8^n1m*4P^>=Y;?+_!c5j}h;6mj0RF z&FCuhkfaeZ#Nua21KQX6IQUW{mVSfG!<)h6KIb8)Y2U1nD3)0@W%90?MM@RJ-XCBl z%f3slz>UfhqyM*?Uvoy3SK0IIn96E`uzyl0<_6KOtWX1v(ne1hVmeXLJ+7T^y&_DK z?>co!6hi7rlooeOn<);H;TRfaV=rwd$YZMy~+SpGG{Bjm*8e2wjE}D}F3Z zM|hHlL4vnx4VDS+w?@-wHpwlaso8zUCvfw#76~ZT?9#{?l+KdFU4>5@W6Y_Y)*$*% zFx|YC#{!jQWr?fbEQf+)lZ#tDbuX6}Ud|vr8P%GBhTHYgAmTZII+mfUC#@+O_)=Ck zTjj@(==-#Ze0ZZX2wAwYsrBM0ZbCZ}qd^G&N*1lxJh-K0MfvpC2@oa<@U9 zj@N%N)AGAQmSwY8h&31>idUY*xGb^{O~g zj-Q6%z5=_eX&%Ni9Q=esc6`T@DD+o$P_|+Ag(#tIYkpZUdFKy;EShU}b2f_kK_z-% zwD9^IQ0!U6MM5n;g(+^aq$IbX8mf_*0!zP zJ!_B<&J%3(zbC?_MxnSHvm&zRar~3ZY gz$ZX1*jPpBjXe8K+&_P=WzFHG9u(k2o-C(B7x5MtN&o-= literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0200-idle.patch.sig b/pkgbuilds/linux-omarchy-bore/0200-idle.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..20c915778941d4d33f9bd90e8833fb4ee7d9a4b2 GIT binary patch literal 594 zcmV-Y0Lu0ec$#k2BgqnvFbK z|G>&Qv&(B31HRH4Yd=nFQZ`BWCcch22jjRq{?mkS9K+dhEDYwEZ6qe~a5r?$=+%YT zwX}S<#QubUFqzv_sV7D7O=8f!p%``X`)9bv5pHjNIs{N#p{4(O+Rk+^+j|aIhEAdD zW|5-DVLM=Y7t_BFCF?b_D9LNggSl41!UM35v8&p?MfLnSmiPTb-Va*+;CPpu7I6$ z0X`nZ<8HttnMw&Aj!v`rJ?*U3Kt9B=^v;a#bRICsab>T4!g)yz0 zvP;6QSuB8Y58GXM@gWkxt6&TVt3B}#-&S(_Y&ZU2ir&5I2E{Ut89;gha3K$E#phV! zLfm^Rbq1Cg!Eh}Ig^wZ7&=lz79SPO3vZC$7HmcsN`#hB~oLXY^VbC(Wqq@@+yrB|w zw=Ph-CX`KKVdOLCA0LU4J!XGYrrs`bU0b@A+9f`m3>OVb(nw zT0AK=701kEROG~>OwR7;C+z+=^+qPSs6$nU)6ScUJGvEeTY^x?7JXF+j1w)`8 gZ?DP?ECr5`!C1o+_X-*Ri3pg*{%Iru>Nz<_JO^WT16wSSq;KEmCfYt9|!}FJ_v6NLtHUL3eBZHDa1CH)L0*wv;-}w7`1-B6$0_4@Tv3*XNhB+Naq@kzW$pO_ zpE=;*hjYwT%*m9j!s}YD$#`5MU;A+&jc4o$(_G$Q5QMM&YSNH^Qgb3{aO^y)L&5Ym zp@eFHk@SLA=36}m^R?#~4^D7%`947r<^F7PL0Zf-qthDEW;G@4@(BHwf=}eD`woX# zn+-9asU}!SR-YuAbSyEY5dE0zf^{r&-2INm@}=1vvoxnCnPih6JgHWHR#&6?Kdpfr zt7s?Glat66?06P<^86DX+@y8)@T(oV?@-coG~^KVwAoOPMOO|WK*4du*)#(?3j2-r6+x2_!t;ZHQRyx+wz4zzP;6BR}ioA!Bdfk1n& zM=Qa1m&6YvgEocYHW#!%sE2cHJB;YbW4M?~mMYl%LFrm|{%y12ar*HoqqniqFZ`)O gZc_6gSLhBV70h^6AB$zlH};2Jmo)$K7WQ7hX4Qo literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0212-amd-pstate-epp-cache.patch.sig b/pkgbuilds/linux-omarchy-bore/0212-amd-pstate-epp-cache.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ef0e5daa2272780360db4dc6b1080bdde3dbb02b GIT binary patch literal 594 zcmV-Y0V}KxrfS%!E~SI_mJKG)7ZE%!qM|40jdz^+$H+i!QeN?^6SzC>EowLQh6E2FAHk3?**Lnd>_eh z(qBgZVUmySks50h3lOw;^w1m*;&5HiMiWX{cg=E2h{#@uMcNRkVjBsSgs&>sN#k*9 gO%tMJy*~Cjg9FY#%X<8;2nhB?Q0OsvhtD)vfa%`2YX_ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0250-zsmalloc.patch.sig b/pkgbuilds/linux-omarchy-bore/0250-zsmalloc.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..24e9d2046451b7126af37876f3bc7e542f1677e9 GIT binary patch literal 594 zcmV-Y0qNCrk8C8VeavLBT^%gw_0Xq zUto}PhJa>vb>3zBD85=37-R{Vu5yR*wg6^Umj&ah^;|y^tp%3o!JF6_X!92+gZ)fmr?lZIG6YnX@7PL2@VEbHe89AkZC9PYepCm^ zD3}UDKYjEf4bhyCs`ouFw@dt^^SZ=oq0q(@6oP{*VO>+j5K2O7pwApP_BA{S( zV)n0Dr|J1LWle_p^5!W6cC9EzS9OsI4CD{hx)LF#AqML&F zZAwa4}3WU|vddL%E%Ytysz@tBjjhMT0~cS3T0R7?+jBAI@RN&Vq|ntI$axY}S+=6|P_M@IxO6e>{S zYKKW_dnKt`qRUI$MHVJJ&eT13*D4H;0QavrsGV_cD+5zUf=aF=4zbS^dJC*+BPF|m zbVwMOOp8AH5l}+JyA~2VuwODcD;KpT=Zxn}(ZUM+>FF_gx_iQ7B@x^ttxvQ%r{J9Ci(?%eMesI}qFi`dYoy*ToT5?-QKh|>HmaVIh;UB99V|{=UsSmbjii;En)ClX z2j#E`@h4cA3`>?sZrKr&JfpWE)Zx8i_wYl0R%tg5H7;IaZL^^mJf z0EGtB9mJvD5W`;*jC9(RDk?7VY|zhp_&RxK3f}WB9%YEtLI5pPIploiFe8tggYIp7 z**J`1_082>yq<$pdUROfkdaO_ZY{UeVbx59BHd;t7HmS_;Bh0t!Uy_r2E$3IUZGAb zySw|jd}Q`DxCuz#+98x7z#Y2P9Ape6kf&~A1rXx9AkH-wUU+8bHhJYE9rd{QdHw12 zi+tn1a!=|F?srh;cE_k#0?7}DWM|E}X(+^NX3>@arcxME2Xcq%xeVdCJe?dcA{3eV zO|*nk^_)+00~Ia0{jmf3aefUyu0zK*OQ#7Ap7+ZTiM-LL_vmz96;bnml2el1K$8V! zy~r0X3z0p6JDS$P78Php3g~A1^EgSIa|v}H!%c8@#PV_XuIq_T zQsSs8P{F#u)NP!=1LKew+n=Yo+H>FN@rYun9K@%IHY%EQ@ySpFzn?rhdq0C73*}(<6u}c$1 z5p2}`4eU^G(M_Hzo_4_@a|r|$%91Rpmx2s>Uv(iYGlji~TqH!|$67pIg-8y|BPQ)y gS|Dj{qHe_}aw7_k!WLh%Ds+ppFEdt%=Xqujg_(>LMgRZ+ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0290-zstd-bmi2-fallback-aliases.patch.sig b/pkgbuilds/linux-omarchy-bore/0290-zstd-bmi2-fallback-aliases.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..66df3c4daee154c0b2fc0d0e29388f20481f1650 GIT binary patch literal 594 zcmV-Y0iZ0OSnE$$gAV!!v?3yk!VwnED7GBs`o%czNu|XelR~Ip$DWH}^#f zsA2m&x2;u?ZfN07_@?~G#hkm7P0q*NV7k&n~}qvn%wWeTZOK- zqsHe=z6*iPi5w=>ic#b3rfQYz`H}{_9DHS*E~|P?~Zk; z-AzchBrd`w?FdH!7q9DI+9>+ z{7?Je!mEKxe`sS8rR%UtDLd_)ZTHdPlQ$CPoLph~h>W51Id zsQBC~eX)wWL!JdMs=@1vdIF*?p~`CKo8UmWrLMF~ND2|Dc&N10n8_QD5PVejgs*G) zjKG>FEvmPB!IXIn0<>-ulum`l{2M(X3U=qxuS(n+f`{GKo?InYnGiUs@Whj7jO`-7 zSb3WaS$(q*aMsdGV!muX8*17~%y&Uc%rk3PcFy^*Y3#Lvj)SUg(Wf+A0qP|eB@zuu z8`??`gD8Ix?A?ws#*>AHc9iRiytv1{t8HG(F4arldlK4Zb)g{@8{0fqB17*cEa6&0kk{kn36&7v&7XV`cbIBp>cOU>e+Of;`oh{z8Y}> zj7ebm8~3uV7i(MDw~v%QkzhcaIe8GRv>Kqznzjb6KuLDR`jzfnj_CxWKSct*ku_<- z+JTxJx*%5zeKm7sv=wZNX!|!pw-DBBrL`m0uO<9!kBDW_j1QX6>CL`IJ3r_A74v?f zT%Ju&oz&~sfwz{DgTG42V(j5UmB=+STOuEyHlW1Pfv`n|{9tMK4tj>*gh?T^l{Sf^i>1v()0mIAp(*aBq+b?e-5 zzl?;UDMXy5f$Tvk^@wyeW@&{CKP=6rRpS%zeqB9wEcJr}wnyNMZyQ~IOa0A-A4q;} gYPpj`4iD70_J!Ygp?hEvovvtIwOoDM4rCj~eK^S)5C8xG literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0293-crypto-zstd-defer-dstream-init.patch.sig b/pkgbuilds/linux-omarchy-bore/0293-crypto-zstd-defer-dstream-init.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..5edd1faf73c7a8bcf402581bbfb12d737988e8ad GIT binary patch literal 594 zcmV-Y0 zO+Qhw6EdO^I8|aPpDv5DiGrY+B+)_CM@s^;avG~RrvvtZ=!-a|)}#09AT)h(hCcbM zV!;o2vTqAyhmeCGDMS*TNXe@|;kFsU;SfYZzsaIUOxr(;^PpYxOD&2MsO}y@q9LU_ zcHCJ&D4I1 zXh$_&RMq%O{B0@o$0hK5FK#>+8s~hW-8g;uPIKI)sh;Z+w6$34@=?&Ztkm&8Nj7n% zrd8VsF;CEzbkzKs)hUcxAZ@Plo*pPwGFDcp4_S~Nk+EuwU)B}*_y|N*q7@S#&smw- z(JGm(=81TC%YCD@I^d?#N>f&F#N;}lPv6~g52GD43e5bzbsP5O!TSSr>)C18^_TB3 zYz;Y$_&~R0bk~zNn!@FrjF?y6-n;EE0$bjbReB^gaeAWqB4py5g(OU|AWHBJp&qA! zQoCub$io!S;!v;*{xSJ!|qPq8vn07JLw+ckVA8&ar4zhuwnf) zT@2O0#J)I5_cPAV6G%ISl0aOFW~Vf#v~`R)WPW`Cq~_#iy-xKG2*r~Z@vxh0ZYWU4)bMG9 z8)%GQK}0e)7N*wx-7b{AbYi*~dMC*e)^DOo@lV)Zx|(#ySDa*V0yRi&unKnqXNSEt zlH>&awdDVT+JR9!Zrv{Setg1vL32f%bhiNV^UNTbw4;`Jd3UsL^lsk$?Gb4${)8*^UKiZGS#oJPYE?;{8OiA+GQru24w7if5i#=MgCDH(w-b-sI6|pR0kw>Lv z#zX!^ECLS|IBd`cA5nd-iAVn#pm=y^f)mVOX>*VNn1Ii3UoLk)7=We;C>9Yxqtjhm z{TJOnAe6~t>mBYDTUuue#+0X`3h9ho{KW7w74Y`zIt`5&4>+<{S4)zL;V0KiH|nwb zLOzkZjlfD9C;EqKbn_+QNHzv&Q;q+FR!S6ZJIhy{h6&-nm=D1QExSnQ_t(&eg2$B) zoI?bJoC2)GUVCd(59qEv6zr{7E_jj{#1(5vmJC!HRyk?m400000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=ZokM{xpGgKr|xsl(5_G@e8=! zAPMT1$MD>0V+rGJP5E%gERCSy>4rIb0?40$bt1)k-{N22fv4GEep)iVNt9s{$z%3S z5}P-0^IGlhZo~WEvxHG%n%@|jmlIO?q6QsGf`u(S?TJP0p6woQ3sIEKqB?8)8g+7tuY)$)XT1$-x?I8q2s3ZOoJJ>~2JMa&^XiEHmheM_RkyEUTC%6S-|47-xxfgA9Na8{$#P#&5clJq^{$dbGkVr^_lw2}p`d zxa}9S!P`1^G6NhI!L|LX{!iGnK5a#P!M5-|N3q!wcXKz@!f~F5J$XtZV9$&yPkWt0 z!JQ;F)R)Zgy?qxUD334*I_cqM&dXZQ)9aS8l=j5HF-=CaK#vvgDpa%U0|Wg|=INW+ zp^5tO1qesdws&K_aUi3)yoCAn7&hb0j|m>6YCux6&{{7pYNKp$urQ=oC-0UV8M^)W zTQa$laE*q@feHFOOSd=8a-bR%f>G(p>?S_cb=Ry^Dnrq~CSfAMt8L;NR5}TVViYR@ zvKG6eN+H`{l4Xujoj6E%k0uUq7!PnEi0O+|>b7BT;S$pq5HN`POrr+!Q>Z!1yvspO gl*oiS6AdJLAhfN=2`Ze^lBtxUJK;Y{0BpZBg)}A<#Q*>R literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0300-btrfs.patch.sig b/pkgbuilds/linux-omarchy-bore/0300-btrfs.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..15860852f8e13213c996d95f1cf436a1c3c8d85f GIT binary patch literal 594 zcmV-Y0hWKYb|=y# zeUx*uWujKhN%7UW_C0-Lc>h zk*DsB2GMq(p?}Xn0x$a{tHqVyXepR{e06k9k5w*HKx z+E2LMRSN&jm#>nB*-RfSp{ZcU)>~o3-^`%)_q!I2AY=r=W)i#!cYNqUQZw%ngcT_9m-hDAgXqy(QG&xD@zUcZ5}{PEabvzyi;1!3>o1{ glUo9Ijm{@1I0OVQOKKQ&wd6^KHdP5*$<3)KzES5MGynhq literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0301-btrfs-fixes.patch.sig b/pkgbuilds/linux-omarchy-bore/0301-btrfs-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..b319318622000400a235173f7103539efb87b261 GIT binary patch literal 594 zcmV-Y0OR+Ukf+(+v zJU&OhZaekL#vWmjJPxm$0pT^I`lzKgq}4>LyJn$zNu}HOT7zC1(H{_s5k$ML`$RhN zqT0c~wPz~l8eHU$Tb-mhiV_#m1tj28JcCuOZmqAScy6MCTMy&O-tg>d7w?RxA3ex0 zBnhmO9-2yOEAnhQax6Zz!_nlYMa9gGeSjv)tfmGcbsVs$&PFqa3h4`T&3wjOd8d5E zFz67Q6kk^ZxrCU(A+|Ug>{)01L9R}^DW==OYKlL9WuZB|#>gWLy^nakNmtH2Xqu_N z2)Qu#%HGs86~1+PrSbHIF{u zBp&Kctl``P#uo2#0yFr56bimeB7->E)Rj0RPZXzFpO3-I9lG z!(z{ndY=E5=oQWPC5wl%YA`w2BqoZOgwmC$nZ=q-xgpu1h>}6wddSXm%N1xf2II_x%1t$9d_{ zEQpXsv;~x;!?MXZd!{8v_d9Hd*@^N`+$dEd6)@w2RodNOL4@Y^Uh_?B3d2&=B`|P@jG;`{CaJg_L<~q|61#rF6ut*o{`0r zgBHYaQYxjDy~`;!dKs5-%>bYQf%D#CpWvc$)B~v9$kYp4eJ1nb_>U=2RQnTzjK${l g=hLh{#D*Zdp?$b&>3$9cdvrV+pnj3jmruGP^#A|> literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0310-fuse-eof-zeroing.patch.sig b/pkgbuilds/linux-omarchy-bore/0310-fuse-eof-zeroing.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..dc63cd64e34f443cdb6fd9d21d0b912525303df5 GIT binary patch literal 594 zcmV-Y0L@A-{+UZyplv2Dc|OtV3O%Lo2s}t{DB(?{?$pDhpgS{yjdC zm2>ITUWKimte@`{eF9*#9=1$tE`j%leEB`gk}kF;aGU!=y6s7)uZ+Hwi4_cW}p?W3Mwrl z->&77<5OWk=i(t@V9x7=DQ)4eLv_3UyxZ-f?+%p%wixR9OvAC_?(o=*Zr#AF6*_aE4)2kTZ0}%Ny<(!l+3@IRBZMWF0X`B5Sx6prTeS ztFB$8*QQY^W)!QAcpS%@h?m2+vS4wKS;(0RA!)|@Se^82?8cAn-1b}{D-=|afd-s~ g&Bx(hHMKLs^HYJQ6%|ScxoJd2rh)8HFzXtO8r(P;4*&oF literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0311-fuse-perf.patch.sig b/pkgbuilds/linux-omarchy-bore/0311-fuse-perf.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ff6a7822b7223701c20fd545a95598875dfb9835 GIT binary patch literal 594 zcmV-Y0KaY#R@5`>q7$@X50h1os);mJXOJ#D!J`K^;T z6qiq2I6`FF#-V_<4Zw^NraUeWv(Sv^wiV##f#Stoha6B4H{(v0RM@}dku-pos;#X) zF_l_-J4@leEph-eurz4Fxcl%*vl~AU1v4ZJqM1A^w;mYzdkwg5wCd=84cbK*%=Iq8 zz+gkMTS&&>`@O^}^$YNg@TAfhfSdG@G?r&M*Zgq#0|~B*8PfY0HnA<;nz|{F(6`rC zN&OX&u=hA@9(*K9T3}t;I#Ibp`&tZ>ztDOQ6O$y61o~n*`KCA+KQ{id?RMx?BCLI& zgu81r5cjaJ*08eH4f!mDNG^!_eBQB*2T8iuUNxP{>7n;ehq-?&uE!JvTaF^p)^sp$ zm@tD#(!6fw9HG@>)fi$C;u1Bn5wRU{5x}6Q}Kf`x%tp2t$y*!&jD>>d$ zccwhHAEPd2?Zr$%TfU%fbYP&|E*lLSP~n+pc1dp)e^_at?EXI7nHUgq(Ie>#l?|n5 g)gl?SuK@#8^p2K>b&ut&rK_ZUrf!G?!x26J*S7o?wg3PC literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0312-fuse-writethrough-uptodate.patch.sig b/pkgbuilds/linux-omarchy-bore/0312-fuse-writethrough-uptodate.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..bd3d135802999f5c25bcf706c3137e60ed8efd10 GIT binary patch literal 594 zcmV-Y0$~Yt{XEDL+x4#&g~%ebl3RwFI$)Cx+8G8H$rKH}nv*yf zTH+b+gf3){_WaHnAQDlsl-?WM`mI?Mq%gpRYKGi$`uKmlksR%^NFEpU%~UD%3NJgGy%D< zvSa!?dTA(jBSj@Ok(H(iL)0(W}&}{Z9v$TBDH_+8g=5GED_$Y1b7X}8K(m3 zGUoXrn*ZdMIS~pyFA4(Ifg}UbJlp9OZW$YqP1hoX8O%t5mIhr~C{re_E;QbcCn|p6 z2UTXiv)6DRIwxWcjtQh9gyalN4_Vo5&n!gvwc0mmYO^(ECA7G$=*JdrHn2^7jqwCsO gEtC2SZrV^vlUnXRj6!EP0cI^69jQMvO2XMlO|l&j>i_@% literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0313-fuse-background-wakeup.patch.sig b/pkgbuilds/linux-omarchy-bore/0313-fuse-background-wakeup.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..8ec069b3ad02842ed6546bf04eb1d3ad2b6fe545 GIT binary patch literal 594 zcmV-Y00dNG9a>`_@dbM z=Q<$F>}7f>jCv$-{86Rz{44ra@1zJX> z#y50kR2iuQcf>JL-IiMScEOm?T2QDG$CDA>0V+zs5?n`1W0U z*PK)VP{+H>&$PiarY8 z!B?W_5cw%iM)p6M_7dTxF9)Og>T9R> zhhd%9P5ByJ!x9-KsoeSo!YTX_q47*PjWG!$292hx-)flxbsWQkE8pOe$^i6)uRD!W zn!mMl)HYd8wFA?8*4yDhFglD`n4#`q>R4yULg_iXzn-tjaX5GOiN@VDg^GXlcA-Lz z!>(N^)8P!BGmK-7nn0MeDEkX9*(sdXgsmXXK|p=J}Gmvijw6wF@UX|5jv zPPkG)$~QGW`vQU0;3CHZEq|WmZ8B9wjDgRE35`iGjdm2Pa0$U#fA|zq`^w>hxR7~_ gh`lYH_{}7|-Uv@s3GXn)93W!lO*M8n7#W+JNT{V2wEzGB literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig b/pkgbuilds/linux-omarchy-bore/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..a00bf83ae892ffb5c7661e23632e0dca006541dc GIT binary patch literal 594 zcmV-Y0xGAt*wg=5t_L$H z>tx2kDW~GffTj4)1HO9pj*0fFH%#h>Ow_!SP_j8E;x-5=7-o#Ls`1`%$I3it|fYdeb~ z1g;PeTqx4YI?+Xdt^;MBQblvoWx(%*#8$HVaS-gdt%sI9K%lI2)_XiK;zXqpm^QL( zfNH7m@C?0Buq;$EX~|pwZ`SrL94m+#6J3K03UTKEE+Rh)2@-V7Ch5ex!X;6vCYI^6#EX?Q|0F{A@-(T~J1a9qoD@agc#eE75ma$}oE?4uu~y z%~QHytYSkMfZgG84}n73RU7_U?$oYD*4%_DzIHM_j3mGGyl{LGbC$YY*=v|qh=<-|#3SqVc9pIznpe{MEm|o6x|FL*b zv!?UBGZO|3hTa)E{^{w2iWRa{hapk`mqloJZst|lielV%KR#_DlYRxrkoOa}18cg? zO(A_p^J=a(BJM`~Y1-UCq@~0orwghx7|S@!s4#5l+f&h@%(IBdj2yl8t4)i`F7R!8 z#76mHvUpnoMqIqojWsAQ)aIqHmT{MsS)o9S#?8-Qq18cuBxc^;6YZe950S?x7NFSh z3G?I(NuiKtTT}RIF9{lGKFUT>%6XkSGqZpz38)*VT?9L+W1CI}YXOm&U(!^wh(71C g_j-sy>rSK0lG%1cC$>>d>S4Ye$S?{jZJvi}7I8QgsQ>@~ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig b/pkgbuilds/linux-omarchy-bore/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..80b2f7b13beaab021f628edfe94586ef615e6b93 GIT binary patch literal 594 zcmV-Y0lO-<^G!bTOmKn2NYZiHb;{ZzA0&UHgzwDaHU3I6g>kYLMLh z+WrKA*j`#vYJoHJBdv#R6pBwy#eWsNp+T18Wgm@nD25thnceChs{X15fKBlBhq|Sf zJ|VT#U#&>&beabq!q8b~qFjO#mP}{EF6%OTfD3g6h#!NbVAT%*JZNGEq zggR`{dc9HP!&B-?fz`uXJ9&KiB1AMttOY8;3}rvPxvT>J}JRKAM(V z1?N$3@87?9kpBiQ9WtMO(J-kCNUJ2+=F+-p=ke5@B0*S2L52ILF(n$G?Rr_nyW{IQHH<=;EMRW=JxPRm~bZ;4ypaKBjge-;?2><{9 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0401-drm-i915-psr-exit-panel-replay-for-alpm-lag.patch.sig b/pkgbuilds/linux-omarchy-bore/0401-drm-i915-psr-exit-panel-replay-for-alpm-lag.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..6e91496ccd9ac6fe7a0bbe8a95244ea530e7b4de GIT binary patch literal 594 zcmV-Y0SOYe(R32#XmOvn&D!Sy*ni?3g+C;Ad^-(sb*@o@Cdp?=CxV5m}!x z>KI2$JQbueL2$iihmL)TR?0k~k&IbFd2x3z;Cu^O`U8rD*>v3Lzfr^j5wix$FfaAx zt+qfBh_wc^q0+8cbN9Pbo*Y9;to3*!hwBq`uAk(-9~`_muKl2Ui_~svzjEH`0(756 zBJ;G|Z=5kizVQ|YN*R9wN16@Yfp1axj+Y0-J?v+Dr{Q3yE#6(%tH|}@&F4}T@jxdy z1spFZ3C}}b*i8K!jC-#goR+4N#pdt#T}rO14ZGgutD#ud$I5RL8h-Djk2EBvi&L@J zNp!7c3G@ukdQ5lh4)USU4TlB3-M6Bp9#1wa{MrRLe$evXNiW}l>n2KwaUt9DN!mV1 z5OH;oGyW<+3~<=z!S>q@=Y%iJ$^7_=Zl^xuw7_#Mj`}V7z}wm_muQsaxyNs}EeysY zA`!kZ=5H=i>veYq5C9nuh=aJDSH2dIVC0Ke3&xam?U+1Xm!#OS`(HobA_t9!fs0ZH zs-hR6{N7CRSf4FNE_=(W*g-#jojmD1_ljj$;3F*({-Vy!0Gw)n*8@J0aZ5{sq8 gzt#Q&d*q-B2)rpZC&0|bFllzgO_a-mmei5#bc@OwT>t<8 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0402-psr2-early-transport-panels.patch.sig b/pkgbuilds/linux-omarchy-bore/0402-psr2-early-transport-panels.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ff5430cde71ff0e7b44e2755d9c96c8bf3dec66d GIT binary patch literal 594 zcmV-Y0X^fLQg+JY$oKruknY4^cq_IE<` zkAPmfRm`!!5RkVMj|}iGT#R-~px1>)Oc|!O*(`Y}Fc(6_BajXfcu$Q`GV&^jR3qwznCUbe?oB;bvf+1w&z7GdQTmJ%~L^7-p z8*cuguIeGAvk-0;sn^>hY{ru|gU4J(RRUBkwV*kJ6+|tI*uKU{Kau&9G>N>*Kpa|G zD^Qk&()ucovVUJ;shbu;rYcJ5b*{qz{YpD$T)C!AznL*6`CbC^W6$zlS7`!leEVmu zu_ZEVGR&kS9tM2plU#dOc>`bg@rnJ++@ze1W;%hjr-!a%Ya>SLnj&h!LtMEa3}b@L zE8)zDYBXMCO$tQIC=3WuQpDBs-$AncgKAfdsEg~YjwVcKC>I_FLVb*RKKoWG`z~b??dUA50%h7PnD&3SzX=|t}$q)=W6`lMS+e& gIiAI;jGSYEVkKrm-sEwfuhrVk)r-+J_5|@yIdF0m+yDRo literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0411-drm-xe-display-no-stolen-framebuffers.patch.sig b/pkgbuilds/linux-omarchy-bore/0411-drm-xe-display-no-stolen-framebuffers.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..67e82c076bb6aa79e97ed3a08fea4bf0fc5c21cf GIT binary patch literal 594 zcmV-Y0pn5tska1{3$41zkxNr*+Zvr`}aG)+K%QfFC#2A^a=@O9#f2673{&U=T%^k8qi!L<`3ieq_0UzXVoyH&g)yxC>;<0meiNN3~FuVeQ)^gPuF)c&T zoj6lC4e6EBMDnPdB+v@Kg+ee+gv#qi$4Kz?f_+LbB#^(&Z@%i76+8;vAb+C~7IUE_@ayjWi`E>w ze9+#y-p{$RhDCIwq-w0l*Cq{VQ2=!6gNp=$pu}^^`B`%OY5TXI-P^#A&1E& z5v&Z(w^y*^q_8fi5BG~kcGXRidtRaIrMy}U2+RRs6*QLLm=$Tigg(Jr+D949jFh3%UV!d(TERyAi0+u znAhWx7x)BhVRZvC9IiIYKI_#kq6^lVWo(sI-Fi_!Rik`*%Y7T%ZR0w$X|u`3w=78K z{DFCnlzRwJr{6~HCbOR(cq0;w+HMH-Wx8$FD%PdUTLRp`lKxIssG@UNb#85`pD6I?@_>I~!&WWKA_R8_x7csdZ-L~?#; zJHt1ln^?=3?_jbN0$`1F^x~@Bs=TPWc_v=+&5BMgnus7C!F|S9IC0avM0rFcr5>9A z`~aT>F?-Q{%(9e4f0R#uMOln{$EFQsr0Yfna_-5#nFyY^&Xw^sS;H{fSvU#@(Usdvm;J*+}@damVD8|Tdc%0#z4Gn+m5ZW8RMY3;A8@*Zrg g*uyk83%^Kr0xSIGzl5}Iy`~-}(JyNw_(j}D7Y@W6vj6}9 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0430-fbc.patch.sig b/pkgbuilds/linux-omarchy-bore/0430-fbc.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..f0db1f310f62223cc9f92bdba5f9cc503334887a GIT binary patch literal 594 zcmV-Y0x5(%_av&n4dXSxqD8is) z9lH2Gd^(x@eShO-zNHKETzyxuaKFj)XB6@~KM_l9;=^#xp07M;AI+|KPml)TWLv~n>3Sy`8S~fI#O%wI) z-HwjBu?R1_O+kCws~2L7PgncyBD)$nAoXSq+q}f~4 z@SkeYdu#q7)^Ys%5r5bz-kwFlbPl5cOXC7-1rs($bIC{s+6e2gf43sBgt+l=@G1za zI$Zb8_qTE_+4kp)V&aS%?acK&=rzKD``NFxtRK3q%-S^h>F#)u{aL@ZO@L$f@Yx9W zM1+!5hn(K(w93pJGHk$-_1!j0>F3+H{O@2G{9gKTMuPMKZr8|Do>|v82rY z0g`WxyBXylU_zHEx;ebkFk!RVww<&Wr~6gJ5y(fuC3i%`!I%=R77OSm(J_+KE{W%8 z8xrRMVd$nOQg#}jX%4mH+yS;`$a{A1ZiGiiWl+k+00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=abBjHk@n@dE zCW+Fy?V4d5&>B<%T$wJQ|AnCNG{(6vy=Z*8P|bSQOa4J4+5r$p}t{>9>AoJC?ZjNL1x zlx zHV4+wj7cC%+F!Gy0v@0FY!y*tcguB{!CB1gSyLU-VXBdW+}XFXYewhghnrx&?+FGJ gMvFxwGF?p&Um`%FSv16BO4m+=NuZH8nY76TA|mb-{Qv*} literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0450-amd-hdmi-vrr-allm.patch.sig b/pkgbuilds/linux-omarchy-bore/0450-amd-hdmi-vrr-allm.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ee3553797db1b8ee57ccdd4aae5e6de4eaa82c6f GIT binary patch literal 594 zcmV-Y0g< z+C7He8qK?S;>;*z?2C1A%A4L}MNri!9-VLS+b%a$3Xv*PyNs-7{zA|HJ#XhE9F=*_ zlATQ-*oo;sbjoIlV-YaDI8m6<$}J08KP(Fi7lN2|GrNXz_6V{51v`iCk#D*M?jX8G zjpEv@2Tz>zn9IA32w{g#`GwtB-cU{JXYAn`=vn;c-m-hNpG*kDatk}R$H=nvMfor` zPd5kHePpV{xE{^PW2l@n>TDf-o&|!O;B7)P7;>w5c<=sGXTUS-x7Y_Z=TgJDQ=HPO z28$7R8Lj}5trpE{1Ct=e1Z<7Xt#)1rHQ4b=HVS0$wix6KOl*+Lsh{|n{dUD*)R#txJRWn;4I{(`XYI(gORx@|B7Wa&%6{Cb+ubNeJkiq((lQJbm g&u8(xraIQ#`l$Fic3)H8FoWk2Ksz$p-UVlVd9NBEssI20 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0451-amd-vtem-tmds-links.patch.sig b/pkgbuilds/linux-omarchy-bore/0451-amd-vtem-tmds-links.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7077a0e08a71e178e66bc32c85360952027acac1 GIT binary patch literal 594 zcmV-Y0lR|HH}ChfZYJ_C<}NS@JH$JVxGvdp#asJdEZ8%Z z!brp~-f(tMEZts`*fCEa*W_cyFv8XZN|rK@DNr&dfjU0!ydSY*WXmErXsmqYvy39~ zQE3EaNd~#y{V5v!EyQqdzkV*c)b6U_ha8tl!LB?YT%W$yhAg+|rRU~fjH?8wZz=ha z7%li(MR3)hd1K%4q1Us0$nv5${U#ue^O6rpMU!KRqA>6N*%njbBw~z5S zS>WE9nqtfU2}rB03PEk}`$e9IEHAyM70BB7re>XIjC&$u$onjDL^+@KmB39>T%SwwB_DyX)6a9WN&YW?)D72b gItSiK<>dRHX_ROMT6tr?w0zM-XM5OgP? zh3UQvXYumWH>N(qk3=NzY7k!2#+XIcO6J|@SwAE#4U&R&=oJSi7(7?|>-x7iG?B~a zsbSl5vwk-mjvusF1l^lCY!C;{Xv8aN%C59TR2Hr5h{klJ^3U1byS#4N~O}O0e7sj{9o>O-4&y(O%j*o+y5}Ki^z;U zXE0V^&p$0`EzB?K@dS=%81ssW^TFueKu=Uiy#B404~1ke#x+2rSZ!TtiUw!hwhSld z?(1tO;k*~}dCvHxdGcWDE)(hPIm8BRi`n)`_b+=vA&T4>H`0!xMDv%sAavVVtecU$ z_irY~gzD_Gv~!^W))A+B`((a$U6E7d!6txlABN}dDxaprIsS){6gB5j&_;-meYVXV3E=4Wed-kXJ18Q^->$<%VUUOEI^iTgngK^FF;Tl+ zbcnv_I`&|X&r=DA;+nVySeh29qTv5| zbw9)ztY7#>IN|@Gj}W;X-g;)tg$`_qad>ZsFden4H=yG@U?;)LD^hN@2; zOetKUM`l=sXEa9>JqgVJU@>;0b(^4&_=kW&^}M1 zw-T?;_7N7KB&RWc`$4o^=GFryMbw6`BdqPFf5nS*y;D~q&rx|5iLC&vK-qicudVb< zn6{vf+C?v7@os@HF36faSnD`4xMlMSJYI}zKm!@sjbaP&THYof8O{zNZJmQ{D9ExH ge_mH`blN79G-d=TdZgcwrY56~X+VM!u*P51d2GZFyZ`_I literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0461-vesa-dsc-passthru-mode-match-fix.patch.sig b/pkgbuilds/linux-omarchy-bore/0461-vesa-dsc-passthru-mode-match-fix.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d303e5299fc0e45e293feb9de1e2ef2b3aeb39fe GIT binary patch literal 594 zcmV-Y0TvLP!nz{trgiJaSXZQ}PufXrJWK~$qKzX}4!uZoXY=|R<> z(p;%sfzn+TG|;@sCI5|e%yQ#U6L_@2)qpio(0|x7l*J?GJ~K9IvX$__ooJQgq2TNa z22!neKa@S;#JjY_a%UgPI6cKQ1}S-kIv^N8{i+Kt^|vOpHfxvGm3Ux*4h}{) zisW7=oGHe^knYFPslx#3vkJxc2^-1VY2-2atm#O(IZa}Ad#&kOEko$TgYtjkk?A#VCX1eN)G$;+i+T#UM2brx zcLzbkh%=|r!IZFK*)i3ymyM|@3US-O9st~HKI(doI?&P5b%?xkNAkP1W&pw$e@XWQu;=MQKFaJ;2D|0{N8g zHY9sA$df$-X+x1~R1T zi2R!kJHcr*vtuTrA7In^{Sh!AZ36N>%`Au@1F&{$80^tFbR%(85E2!^66DWngzb zPi!&Hs&6Hu;GaU6e<08C*?;=X7+&F`N}4A7;n2K1oDyPMu`@;37n{WX$-z6@yex2y zPyVZ?ye7_uhIH~olh8=(6sO0=?fxNhDgI%%uwqr<^NK+RV)W8F^vY@nyU$)NOGjOP zIx(MOk)dxm$6Ny`?FCnHe=sjiJu6ajEI3`ek2j3#hxZ{kf`%_&Lt)>ff!8nvD`l#~ z@SU*ODRO!@b+a9JqTi9<+ gnr5t;>5fYRo;K*t7B*BnbopX&qXk~jGP|y%(8Ky8cmMzZ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0473-i915-ptl-cdclk-sanitize.patch.sig b/pkgbuilds/linux-omarchy-bore/0473-i915-ptl-cdclk-sanitize.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..1048bf7d1f6ac3f00349befd58627cbfaeb2f14e GIT binary patch literal 594 zcmV-Y09Pmx!; zlwFw3oEA#O+)Zoj6>IL)ct^&NGE=bPNO=biLs@Mwh?aA=vc^LjLr}-KwMZU5anc_Z zjio!wnq*YTB@wHN&^6S36vj8?YJ@`7A~3^+`*FEayKmsSD%^LoZxRmTWRfK?J9Ex- zSv;B|{j84a4p%f?Ob@01Wm;RM2o972Lubb+D=4NwZ3o2207v2YI;6=4oM9SCW)aJm z+`HT|&_<2166;PMMn@|=3e%N`vi`G(^j%k&vVu_*C?v@_AnzI+wnjH8UC?L{(6$o- zmbC$({bv+Lj%loyCz8ko<#1dx((pm?iCsE%S@H{SEnc$2#JO;bTj0By)wiP8+v5R; zi?xBQ6x**~yS~3#K<8c{G;Z_`TFW8SNn2^K{*OamID0l|)mx>8J!^p;DAG!(jTymt8roBBs-s^|^F?^u^FCs7mTqLElU^VwI28z_q8Z g!0X*&kk#{T2Wo$WA^-104lC^pCk}1CRl8K0&c=Hhod5s; literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0474-amd-display-oled-vesa-backlight.patch.sig b/pkgbuilds/linux-omarchy-bore/0474-amd-display-oled-vesa-backlight.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..14aa526cd24e76236d50893ead02f137cbbde1fd GIT binary patch literal 594 zcmV-Y0Fscx(mbL@Ix34W-Rb(i}Z7f6ypBFS>i7I=q&Oity#rQIB%?$$BCe)H zrrnjBfAj0nIxs8|;F#RjI^p5`zCiuOO5C-vU%U{#0YEiWB&)o{*~NGZHx9zCQ=E^) zAz9Xn)5{w~@RN(oe}MTPAT zn2wIjZSp5#rwzZ0?o18U=YW(rKO?SpEqt8BX}k`RRE7;Q4?`%PzWuMCY8wMC{ZtGn zCSg)UP3`8#1FQzh`Xx&QdmoHD6hytd6+Rmp0bB7}G1Lernq8L|?FHuoq9=ERFzzzy zsWfO+>7iP6$X9$~V;#xC86>pJKG{wTE7oTLzhZ|wlUkRFQ<%=P58!{TKQ8ZJo-w9X z+wH~KpbL{`jt%l}@SlA+N9*eH|M;sc%JW1$)lftWz+Vfd3EexH&7DE4h+yM%2KUXA go&h%btxj|QCU^?*twvQIY2Z>Sy_(FyOThl-OdMh!ZvX%Q literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig b/pkgbuilds/linux-omarchy-bore/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..3ddfad0a331d357f85eb04d5b5620e507cb27330 GIT binary patch literal 594 zcmV-Y0;S|8XATGaY^P);}-nEx)o| z7vB}P)Jf1W>XF&+(h{HdUAeIs;lLnH`}ujB8U+xlBn4DxJX^}g#^1p#8s$d>iBSA} ze>~As6(u1PDhfLqu@K$@{-*cwiha`E>j&?cbeC~4yH*(ZTz2|7iGAzh4vRhZ`JTPL zb-cD|l!||0M@B$p%sgZJ{`FkF;s9=Y?FMklr9HKD9#L0YfoK~z{7^X%n?q~=Nw>jJ zfpvpEizC@C3f}8B|Fc?^)|#S(&B%(&P-$!7$!pGK4a3$6Q3E!d9VdEFB9`>_G~5xu zzB*-eQxB!Ka89kc;EI(&8FqO&{<2V*#`3BV^7xqJNUX5T#ybc|v-6`|lpE*!;U&<@ zO;mv-8BmSCT2pr_Fa*>fmv#o{8Cf2DKQI4U+3c_z7)Hf@P0VHTgi+Ga6JDp7_mE~E zvDXVNcv(4i3dZ$0!$$AKUL~g+^2u>Sv4A6W%jKb*rZsn?zPG>DoB);7Op((-FcZ_tZasmMgmxB@kgmmfL4K=}*VBE@IR8xiIgd^k)aD_qT(d9jSxh z$tDg1KDasyCg$YuXSNRi6(~B|D-jQq&~Qj2zWYy!j1dP@gk%fo$WTU3o^}_MNe+0j gcVQ)K4ouwvY)699tu&9VcKTp6A(zkI_k*L3>+q%+761SM literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0510-sound-updates.patch.sig b/pkgbuilds/linux-omarchy-bore/0510-sound-updates.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..cfb31fcb8ad262b99923737370a3f061d7c7cec0 GIT binary patch literal 594 zcmV-Y0}BXqso|Go_xA$xM9H_$Z>Zosk!H0z^z#w zM5da(cjU@$$iwn;lpI&=6y7Jgs|c&Nop4Hb`#sfE9vTz1mY*KqD{^XqnBxDo^n-!-)fS`(sFo`FTp+XeTEZfSjN zO2q%SkBF)Ly@wwVTKOF1xXfu9SfSO@gDW0r9I%PD?78XV*vLej+I+l#nY1~g!al-f zCQQsZ&{$$&Qv!Ei=u;rDL-OaW^&F&zWB(2eI!$tJ9fshNhQ*I3i$54)MXn_&c515H z0uH=`v2I-HG?vEUw+K>f%vVcvW06&xkn*AR`3-LyBNs>eleH%%-E%GlVbX^@qR{`i gD7jIs_xC%3HvocR;LN1J4>{uHQ!lmPCd!>+tZ^wqd89+kjb!%I}^Z zm;*f(Op(LSb2t^@Ssli^PUW!Vr#tUq=C*vWXqDPH&;a^qx$S+A?54F z#LkBRuL>hY!I|qKl<-`AlmTojds?&8q9&+X?#Nguy#iiK-|kTtW=LG;JTPL$w7Geh zPuo6MI3y(IG;ePxi6qNsTiES;0`9ScE)^7+4*8bjwi(=8qF>f**^R8AWB=f)l^}Gl z)x_x$$gW|FVWEdfqGTSF^m*})nTZ8^J%oG;t_Prbd}k<&CebJ=>&N+@X|-*2g&V~! zAeT1CC)W*B8*k&@|wjzuor{e giEc~Da0wtnIg)+m_hd018q>|=O&e%%dT$bru=UdrivR!s literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0512-sound-fixes.patch.sig b/pkgbuilds/linux-omarchy-bore/0512-sound-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..c02c1df77237c139dcb0b141236fe6be8a62de92 GIT binary patch literal 594 zcmV-Y0C>*3M6v2f*{?0ZA+^?~IFR@jT zFD9B{A?m}^ZLcyz6#>uwtSgx0xOtU$=Za@Lqwj|m_fHf2o_`QsK~qdbB=Sie?}n<4 zrjf?uMZx52=w?`>y#UIs)YBxemga@T3+}*^0lT?Qm<0sve$#* z5ikIoQZM|QJh_KT*~OHCON$u-*Qig#yj%@VofOjDT_{uByn3+5Y*?YVi=o!&K!F?T zB=gwMMF`>>)DO8mV`&d>G-*U<9e-y?ql9lPJY_)IqDJ6aVHE6?^==e~j>P;*^$VrB zO8ug^y8I>3EwV-BD-jljt8U)++{d2fh`qe_Ou4i(B)aOzcSM>(t)1At#tyE~?vB?) z+2(GB6gpufMNC}(h$AP1G}v;;L17SV3vU2^T5;?C1|vH&M`Yr#+NGQdstI!wFZ6qK z7XFov2vGq*7(iQ_^}%`+5ID8}^w=ynoM>!EO5K^w8^jIHYjtmnFJ)Mwby>YTZ*ksZ gAp(uuy|O1rjqUcq*>y@et26-X1pHAO`3{s2=M#MzQ2+n{ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0513-xps13-sof-quirk.patch.sig b/pkgbuilds/linux-omarchy-bore/0513-xps13-sof-quirk.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..3ded939bf35f40a2a971879471c0e42b89aea777 GIT binary patch literal 594 zcmV-Y0NvY)axecBj30!;fX6H4>>qj9{l($E7Q!V6Q!+6y{Bw!l8C)I382CdSmH zI*0{^Zztz;u{f|M$Mkl(l=;@lb4tfvEf>kQ&WqjTkc+ za3z8P)J@>_FX0n+0li^Vc!S!~ zONSg8qO;W5_GeI@s=f_H$5a|gN2Hxot-1_J3SrfJ2buw$SHrecZ-z)_D<$WC9ngO7#>8v{=G320#XVs*+!Fi z%E1kPUcO{f7#?qYkM(Ce(iuVTc|wn0oi~3kNYu??S6yEX?SRfRjRd>)ZUry>%!|t- z6jA1h%v2e=pU9-}5{RV(Cmj?3R7(UO6Z}=jB^oQ^#z)YI)9l3;2#bD&Z>P)@_lpj9 z=r=Uo!Xd*Nw9_O*1i~nQG`3=7oiTJ%dOsrY^p5I;s%Bm1IL*{CrcI65cd(MgCu!R? gGJpZ}a}d;(=k?m%d)j$Ls6+@}pb(N=$?iM0PB1MOz5oCK literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0514-rt766-stream-config-type.patch.sig b/pkgbuilds/linux-omarchy-bore/0514-rt766-stream-config-type.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..47fe225b43f9f28f9fccec0815f4b32dfb322a33 GIT binary patch literal 594 zcmV-Y0I}ew~K8l z9!_HbbXsyM`D+A8E)kqD`!MCBKzNQECrRIu|0gCA;>$z0Tl{_r#X@LIw9G(6-oY*< z7=dHRi^F1NV;LI-lZG6{@U68i+CahyU`(5iZD6u&jr$D6|EH$96YDozM=XAQkS_gJ z!S;fcZNt|z)T)K>S-CjK+g>|p)Y0PtUUML#nue7{$JV*G(2{SKiP))De^q#z@Z`;r z!z6%+{xxSc5A8k)c|$sz=+l9^AM{`IZ&DM>rWWowdQtYl9(gmTvkd4b#AJP(XyH%d z5BdfDxNxwZuJVd)?8Rjxt;3nKd>Ris&s(-`zv7;Csn7i>?X)SRvk2!?mgJkNQFepFG0e?BaY gT;D#CC2TNG{>+D10NQ?d%&Q}}y#sOB@z8(kr0C)p=>Px# literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig b/pkgbuilds/linux-omarchy-bore/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..edb27fd8fa7c6b8414275024f1856a3843243743 GIT binary patch literal 594 zcmV-Y0J2|UDSjF2>!+1QI-o0|80=jp^KTS^pP#=_f{zPT z=4Xs)m?U}<7!glyIByHrId^SKXlIFh+(8Ijw^@)@m<+?axf{OR{Qo?mpnhUfV#?Jq z2xhrY*WB>AjsLyF)9$sclWETwga9`b>xCur(IFil%k~z4{XiA}#fm+HJeQQtR4A}R zn!Ck55J|6JZWIR)v9iejpL9E9t=(hELCk$#Yf5*R>!HC*2Qo6Oxs*t_m1oD&vmzB? zn@dG1d{^=TLi-NSrkA+f`LjWy=jJOi2nT!_xja-0%w&B|d=_~vBz~vx#HHjFowktN z?iuW%E>+BmJ59H+aMsd}?hS$1`X-!iGfa3Q=()u+aZa#fDSH<0>R^vsx0!&z>Ft1|J(Y3nWf2c5mB}v#FfltBEWJ}~G g2o5+#O#iu8`2t0c$nv6sV@U3Qe)8O9dornd0=05)%?gR5swjF_xt6R?jZ`VI=Smcr{mPP9o%{E?U{$&nem$v8Gn@5v z-}eYM#m-MG+oZ0PS#sCXQ0>CmKpH%_D1~4Ub*96T*h#!h4Df{5J3hT~+0f`u;x$bv zIu*k}OOoeGn8@_K?fDew2E?w-Gk6@S+;V1Hm2^E2O>=_gy!Gb{QV7k{rE<82dbqwxi>P{Wp@Z6 zPw-SkmW=WiGxZ%*y-DGKmTS1z2ALi=oEQ-F^Vt?|B`?frP-6VD+4M2X8KO3|m&g8> zI}Rly*f_Ng^i&(&k9tj4kTDG@A@cEJkYP$15OCtMX7#zI#Qy*6XvqUG9b^4$U&U@A zcfA}bDF|(b934}qd2fC2XA3{!+wm@Jr2WFd14fI!KnLdT)ZbZ~oq`doF&`JhIf2Il gS`12I5H|_#Jt)e-{1t~4K(g-!_cEg*qlctZxge_(1)zav-~-9R5}zb-w0GjC zU!=iR_OmnKW)*iyU4fg!U#Vc#A47#pcI98cY0UM;6r0Vk7zzvF zS0{uh5k!#bKAU2wKT^WaF}!jout04mlq&B2#qwiywK|n$;T*d^1F&7d>(|}%9G-`k zUracw761kK5+6i|joqNQNs6CGcb%^(FMD_pz>H+{{2GVY=qubWi%c{%Almov8|?8g gKhV_OcH&m;w9>4(x(6fP1%T;D@tj!8a&gE9Jg5&D{Qv*} literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0541-cvs-nova-lake-acpi-id.patch.sig b/pkgbuilds/linux-omarchy-bore/0541-cvs-nova-lake-acpi-id.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..92c4d7b14ad82c7105fb0a5cd431e091dca0c010 GIT binary patch literal 594 zcmV-Y0EcCJD8!>W9<01D_xtF`rrJU z2-Nw6cQZG?glclb8=}@fQ&3Gi@{W2qiG*YQ*nEyuon9;=_j zQW7yRR#WW%zorP>h2<`<0JMn1EQr*aWZwcyYVwH^&zbWFP|j^h_e zYsVjo-;_&q@M9gzjeXyCeJIj=ytG4pr$1U2$b3T|T@X3oE%(7atz%R<9ozvp}}a~Z|pVgHkX zncX=&iM5n=m!=jap$Y&teun#VMdHV6^vS`LE<2Vn5qM1hrT&0PDS7|erWh3G2lZi$ zEqyn7YUt|n0iwac3B`ZCnMd$FbC^oZ`(+)vaeL-Ac%F%swZw6!{v!4%+rbYHHUKs> zL}R2I;sJ<#I4B6vm!J#iwL2y4m)eMudqDrJzx)zVsz`!35TA3{@L~eR0?H zNYOU(=|0FqP8bi!8xF$H#|zCd9^I`INChGoIcv(W_HHlHO7Obrnqn*CNSL)PahbW+ zlHGi?SJ9vZ}R$8H#?ZY(SQljHWs7zvAR g0KbQ7Bn%zJ9+78}t<_>5?_m-gkD6ix&5_^gfX

V$;qSQOzF00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=fz?W0E&hmDb7H(fx~!9VM1)x zED*1jfuU}S6_v!&)-Ii4-*e^ZP%4pZJipyB0F0ida)!|knFW&?Fq_fwxvD$+&5xtt z>OrY0hD>GqjpCb`^JWRYQqUgm&#;y_W>@L+OmYoY>`bkLLp+K^Y841A_rojS{>~Po zF^1^jb`4Fju6h->6^5s|%H6a#*rbH8*jYvZKE`4zR6>R6qmss*fi{*x;LP_1_Zxvs zuBH%wGo^88nC|nyy)L1qSM*{cKl)tc8yZ5@4GE}6smxxIGA$Nv!mOvs`0YUv7pb>n z(^qh~2d2U$lg?+%WHA-9d?B{u%Gl{)Dgd4fU}FdHO|pR24H4VFFG-8eJe`>6uY5I^ zyOL7a*f_B_%HLO$KM}CT#(O?Dm$PYBqjv-1c3$A=UI5G-Zli)W)UkcJ1yIh z6_*1IZ-#U|QU161M}7Pr=m`Llqby@F*A&Cw9!ecK^7J zv@P+tt)9R`VU~hQP2ACUiUkJr(;d+|?#zfNrJf8OzF00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=UZV9|4PcqK}0sngj1?rP2Ea} zR!LTSCj-$YpsMnQyAqi-{_N#AvYuQn393AdP{&vfOtn(C#S4&lk7VW(sR_4oFSWnY z`BNB5d>&m7==w$IYQD`9$R>=Su?TcpYN=@1(*83}7kDVXs(w@=Ktf}3fo@Pkx zJdFhJUUQYx=11Apv&DZB3S71ji1VmNL_{;LLYpEg%I4Y5yiM~=qaX$canZs>VZ`-J zNJ7K!zqS9lSegIj87pnLV1ae8%nfnz@IJ;N`jEG|%W$jLqjzWA+O6)#RntiClAt4g zbrR(kro7;<{IP$7p-_>M+=R9ny5|8JG>w#H>w@=O_JpU7cW4O0X$VjdLv|5zL1CuA>#M}pWbN!6NYVxyg!K+N*#&) z){Yy7@FK{*KmX!O%8#IX0*cHRB3SVhrxr4xXw)*~z(Z=He01X1w*8T;yBH)fz3~_4 z2nM+?EfdjC191$mtlsqwc#zsm_LRb#&_&19?1qB$PZGU;qFB literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0600-usb4stream-fixes.patch.sig b/pkgbuilds/linux-omarchy-bore/0600-usb4stream-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..33208c2800a36b030d7318ca9ac2918af88e820f GIT binary patch literal 594 zcmV-Y0*TrOGtP4A9sPC`_Y4`zX>`}pEHi=SF zmmdTz2BO{+l0$jr=M}-0)6I&*uLuB7iAondXA6HM3@jAHVl4)?2x!YwU=W?u`PJrz zNL3646@`m;rytEOVz%z>Qt+}yE@nd^2lhfhRIHNm-(y7oO#d|?YUHiGH=XE)IzVTM zq^#R3CZ)7*BaZ!f?{cc=Bdk#_K9CcSs{})d@-}muPTL2pzEqpX6$EC;JI7mpQmZ_U z+D$!#w|1m3pP|x2)4x*`RMn9O8B>Rqnln8#x{>$4m#0}!2gYE+nyRt57lF26*NyTU zd4%n&bxKkO{Yc>~N!6+A!gb4qjq&MD0K92+?D~P1=qQ~k%we&DgjB!p`o^Njy66$~Gg2#Pv9I*yn2 z;em)l^2FKK1aU9CNTA!p(#wRI3qba1;1jtV*Sz-8QQ_)U6JCXRT_pTU@@ThNf^Ec4 gWQnMBPa;%P{R_z-gBWfnaURd4X@V4~P4^{by@O^L{Qv*} literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0601-usb4stream-busy-poll.patch.sig b/pkgbuilds/linux-omarchy-bore/0601-usb4stream-busy-poll.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..8f8f07d201fa54eb3e55395cfc408c90e77cff07 GIT binary patch literal 594 zcmV-Y0AHSH#E0HK=xCb)`2gH^WBsi--!7`4j$0x?-Xw{WJAbju1kAc z%~P^4vgK51D09~}>1&vb(z%HAR7ZxVrj1)X&1kE|pVHQxrq5hDBn>|+dL`0JEA_;q z7LXj>%PI*|Y+DHwq4PxkntX|t%F@)o!H6hntE@f}=PIOvS{-C0?3_iR$cKqZa@g#M z>$cgUBlRzIuY`0%p8Cn$CA1~t&VF_kGz8(ys}>w{I?g<=bU{-Q%fYv7ceDyanVH9hj88TY0Hv^N*-V>qhe)F$^(mAqyim0&+d*-u*EB+9 zl2bG%$00U8lO>TqgEXf->B_=O!wcv z&HjfcQ)pj2g`G4(mml=>N-Xx`#5@tIz&j?YuqG}gpN-{KEQmg^Z}N;YLAc%mwO!0; g&p9J*Q)ix+1GK&#R^~~?Al$KD%U(IY2gV!ZdNT00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=ecwb{0lAPUWB2=A_-0bzTFF4 zG)kboEKe-u&%jOzFA7=iC9D#dVC`dnYNo`RZ`s>?Ya&u7lbggr@p9w;tLAqrc3B8a z$l-+TxoLy1W=#mhHHl80DDATKGC8k`ow<0^7`;!bq((^JUzDC){Q|}! zqh=B`mranGsM=&0f5(kG)c_~KSL*}ICBWucHN05K-{M#tG^6`e$OSR? z6^L4kq)(-_9XR`M3WIfUve}^J-2(CBgM%&lYN@KKY-0-kGcEv1)}sb ze$=$js50BV(g7g!M->aRDhsGLq#BC5@#s7^I$a;xcfMKfoUcW68*jQ$vad2p3n1Rl<4IIeH%8D57(iw<>~~w~$cX zU10Z2z6Vjvj*MQ~k9rH<&Koo+l#wABuI9q39{&|%3)5ly#DwCK$DQq$&CVxCB8kX$ zm%g=3kEJUEbLKnt!kF-8k*Onx@5y5yNGU*Nrr;#Xo^3z giZMk3B^K`iqsFqC!?8JQbYjLQt+OiBdPw-;tbJk|Pyhe` literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0620-usb-string-sanitize.patch.sig b/pkgbuilds/linux-omarchy-bore/0620-usb-string-sanitize.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..9ed271f5d43971bd55f822d80b97ec3e0a9190dc GIT binary patch literal 594 zcmV-Y0?6In$j;U1ADXY9vSWrb+oplXB2|GS7R-;>Dy>c4?#E=bUtkGwGzC&+s-Ts&>%_ie z*hAy#B`y@)xJytbu;tDO(y9?kKGQ)DJ)QWirdMhsjj3&H#~!SRKQ}Gt9#=4dhz`TgAFtaSV{%_6ctfPWRuCljkx-UJAh*UF1cD!@Umg zegd@8(D(udvd5UeNC;jXxcX{mWtn+0n?_6WJ>V2E4}xcMTiB7t8`9mitQijP>~dwn zz#yKaR!AuQfKK>D899N4%v}SifdLRMpWKk#Z92`lt9Ir;+`gnzjUqzBlKnX@!k)^A zzRp1V;2yr%$#uy1NKQdfCAB@79cB)5G2v}l7tzJs=!3#p^m#(UumPZ&Oo{W!O(kgj zkALWL4553t+AT`!DBC@GUwNNWkNfyJcf3+d#_9wIJ*5`({mqwXp-8I%?tVXA=TOst gspy5G%MbG_VL9R;_>Ct-00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=OUXB0HMDLdbX%m!)MtV=qzDs z-so1$XTz3H&qioi%y`%zv99@7)B7*BQiGfu`GB2;YzTc;bKPl;qC_IB^jeK8ih?=) z{bA4GB6SeeIJ&dU7h#Ks!@t@9s zO*&v=a$i|-lc%<6eB90p)QXD;8%020sCxe9$D*Si2IukXh%Oi7V{O5~x_L4L2iVp} zX+xN4J^I;0p{EhGfc|P^%tq8-Kn-Fh_l-bmoPF`t)|}ea%36G-9vl7B5xZRraN{Vz zH607`dW0+P-0#pFa!vo24e<-;J!b^&GByb<7TOgosl!goOVyy<-LX6>0g$S4-Uk9$ zFcBdL%VCyvFb`i}&j>HH#HZ&h}o=xFbRPvFM(-nYU$Pvghy8{sXJY zy@q#M_A-|ZN_&e#o<$X&*o=s^jLmT0QXDi51%-$@%jZ=b$&<+QAg$3*?ANF%2oG gzQE1~(G4?GW)VOr<@KAJ5Hfc9M1i4L1jBmFd@-#YcK`qY literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig b/pkgbuilds/linux-omarchy-bore/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ceec933b47232d02093e85007ebfe9b7856f409e GIT binary patch literal 594 zcmV-Y0OzF00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=kWRv0E{-sH@vX-msdgoRwJB= zWw8z!Tfz6te| zf4~+=m$diiw~Iaq?mZ(=BVZF%&ADuZp+iS=NktXC*(JYzV@aS8X&k;v%$xa|bLnRf zPrT{-$i;jY?bFCf*%iWn^CTk!euvLJ$J_2-69tjiP$XiHi$MmMNcnj}@PbzZ{CN#* zD}>OP#zXgZr}}M>PX?L++mR-$!48HC)s-va*~#`w1@N4#?*3+i)Gix9v?8*1M9-!%-smhYRNeaweaZ-)=&G|D?z;yqW}N^ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0661-rtw89-command-offload-source.patch.sig b/pkgbuilds/linux-omarchy-bore/0661-rtw89-command-offload-source.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..a9714f12e8f7afce2c1cddc556c14dd96e5d2009 GIT binary patch literal 594 zcmV-Y0BZB?xB5!*~#Mi2dy`*+R4l#_+u`mg=9qp|zbq#Grw@N|c=#Ain-JD1y z4MNi3zN7KOF0Rp2`#atMsrfkjg-0S2edRq6ztc2CSPnC(B2~dDuhDcxOlUd70`~sI zoTTQ#pT=dTS_>%rN-b0uX{(^u(HC*ss81`p8d3R3MrQ>%nmzQJ>C(ruI*yh|z;DNJ*WkNuHe) zA3?D$#|{JyL(=Zvmw(*C56X%2dy>ULRSDOWTB52epo!*spX+vF9pYHIv zm@cvOiE;3v#4~z6Cf95se}{CZC^&1=yMM#kEP#s4K5^^KHNRBC^sdL+q#ALqw-Jw4 zrN=(FboL`}4*dn70G6TR7UMyolo>BQo{02uuL8$(7HMbkY~8+s(76QS`9j>d!|nSgB2#v? zdIZKk?INfVI)Q7z%k>VEg}`$2yx@8OAOsIK?pf5#-g6J#v9W2~Tv`&C6V8QA zK#ViA;)9&v*;1=XILO#%w=-G}vTN8EIInb44d-GAnk)y)Lj2iJ3uUOb<(%;lO@ug3 z_A>>V(r@3ddBq^xUdfgnU|X_e0JB}aYAE9T>K7?l$PaKJb9B|vt_|JhHu&4KL>CW` z{@+6C#L08@7Y&wT;XitBq>E|~;t*To+GBOejZ91*rB+B_Q9d9EUEcFILAjnBHbGEm zvGCBVqwz5@r!dvWt=#>s;DuKGw^rxwDaWJ}VLc-j-g`W8X)Y^+GJxb;z49E6Otxu00Cx)S~X=|bmgIN5tWWzD|EZVP@s zH^|_jP7FnMu+DbXm(j+C7BqW^&7%_f3{4QQAE$ljw#^X%uq`&sMwLsEoXJ=lTWG)v z_(Fyh8^TVq*yf(|fW2l=D`~^diF6M4KZmIFzFRgL@wyQZtt%>E!6S6PQdH1dD4JU) gJNZw=te)7q%;_!9khj|&XP~aG%CyLcK+`_eKI#4#ApigX literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0700-pci-target-speed-quirk.patch.sig b/pkgbuilds/linux-omarchy-bore/0700-pci-target-speed-quirk.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..897fa758a6b6f91a5df9046d22a86b9bcde9fe46 GIT binary patch literal 594 zcmV-Y088Qmk`4gTgMN~ z+rE4zw2Y7)6tKdMBUjG&7+qK3bcNjZB5_BI~2N!&7#*VsK1t&8xTLs(_^snT>9E1w3Q^KH zsB;wP>1f#4WGBP*bY!5PvcN$|cb(C(=2f;lmZr(up$v~UGohgV-Io^sQXyOYN?Mwc2)Olb7JwtFS2{Ev8TVD~7j>NN~?=-LlC?J!ms3MnAJ zwvn6;#dIPw5{>P8C$aheX%y{7DR2r=AwA+|p6rp^#Kl7tH}qtMb&ebttiO)j)MA&j zPjV_prRmUWIMdd7d+s^y%WST9Z-`p>8C+pR&gpD#LC^ZhF$2*FJ+fKx5-5yFsuVm+ zp+PzF=);b^6A2)vh8lo1D-5*C;$SdV4Tqd=BjOXa@wiPlL7NhdNHBntC4 z67$No53)6}GU9bjX&Msvb10dK+4#NHwhemdR!2-?Wf+~JdXEWwsz@FLX&jWIOt1@# gP*5We*KS2{_D1ygK&A%I6_tbsR4I@T&d3CMIQ7Q%!yh4RDX+rF}vNe+%F;ZlQ}7$oLe| zR-2vp%N`6%Luw1apjLf=7iJcjt1;73u`tkK%~K0>-INF@RyS}MMec2!SuFN?c5uK- z+ncX%S8r1`FxaR@wy@srg}dNyUfK-b5huvT8uB!Z2Ux66_=JJw^QuE}mltT02}r?2 zrJcOYamR+(P`md{@R-OxHh(>2bL9YG8&vv$Cc9A=Y=xW1752t7&eIM5YRZ(NUH2kp@dGIN*V>IIHwM$0RmA+X0D%?Sis z1H-h+Hl4dPM8PD*Y`OI(W7H}$X@?=MYkYiwNBahFfmMoq2|KwD(ih%iZXM^EzQ z))efI&M^(=@F%kFfqtL)r9=$03FgX9IV*X_>IB$32aP zcP?w}Eb=sAf^s8TY3#5oX4wu+HXwGMi(I4&Qx?xN+>Pqby6>gGkI3R2IDP=H;p(T- zf$rKUngiZ;8zSX2eE8eD{?+i`!W%y|l7+Ny+yV4wVde!e$43a-@Vi)oY->}J>^Y*D z@6)@Fe&0=5JV5Y#PQ~bE?g|=gk>aq`e12vqOPRA(VIxZ_NJXKddH5PGba!oDT5;b0wtSP<<+_B=Ln4ZoWuXy zi_(7t`DRwzoQ@K^r_gV)le6WgF2^}QKupP9_foYv0PB6pumzGG0lYBQ>Y#8#oliQR zDJx6I9tOrvvUKBF{G;M(a`bx3s%_3-U5NvR5g-8_erC3%nu~`;B+>$KZ6<6_@rRaS zb+$e=f#bcQW9!{a3UF8a-^#!N>>U$!;@XJ~NVlYlXUu%hRHMeQss5R3-9Axa;jWr@ z;g`hg>V+yplNy*i(&?`RyB`DSN-d*vb?ijPXF9zm;(KeHDP3tq7tPHnUSZ2Ysg3U0 gK#lWolO9Uvb+yveyk%|H_I6sgNUn9k%f?o)$d584TmS$7 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig b/pkgbuilds/linux-omarchy-bore/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..281de72a9c0f60fd0e632879f7717b9a3ae73234 GIT binary patch literal 594 zcmV-Y0Qy*r?7#;>5r9*RLfK6pkVg^5}GB1bwwx zawuZFiA%TBBu)wPys=0E&r0g*{gDa(ewn380FInOYdw9a25VM zOvQx9KLs3lHSAWtunZWAToNT5-|D6Mu_M0Qovfu|ruwoQM36~k>)?fnOKXS5CV7bV zz980H;9Qg1>$6~lTW$L?#SZYOd6{@d5_q4e`owf_cSm#QA&Z^|RjV8!J z8yB+=*~-o)HE$qa(-h+9V9D$h9$UMVZ8Ciz><`g!JlhOaq2rOJq?Yl#a9jAw-XD-Cv1r>^SNOPL|j!)DC1sx%iDt1L##$oE&rkF*; zhoZzO#naf^EG>h>*#iLo(PDaViFN=AZTRANETQ9+T;tJM=5$qZOAE`Cr9_@%XclW6 zRtIWUtU+)Yfn}*uhZ)agOzOYm)lf_xf;DcZe)} gEI#oeB-Y4WtB%UWSZwT|uKo`|Fl8KYSL-PWz~X!wXaE2J literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0801-amd-pmf-util-unbind-use-after-free.patch.sig b/pkgbuilds/linux-omarchy-bore/0801-amd-pmf-util-unbind-use-after-free.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..91d6150ca707da49f15dd26da66cd49506fa3fe3 GIT binary patch literal 594 zcmV-Y0r7g-MYGZ1QAs8kl+-k3w9VdEa{aw7{v1SK5z6>2f3{3>;q~2sHK}|> zA>MgFR!#-60N`!{;p2Nh!;_e=RUC$M&6{UAOZvg%|%>$ycNkZZ)_KXHcfLtJv0jIx< z^*_p`ol$noRV3TAzj)V)qNuW##6c=EjeZ9?g)sUj7@ML-#sKQsPp%Y-Qq`3~vM-DJ ztfiPCCt2X zyMh5LsBb~HQqCL6V>S`T#5af28hk>r#pB|*sHCn!^Z?>Z2FD=9N};WI7yrqwmJYlX zAR%#p;d8im8k+om`Z3rkQwYB3$n`P&oL?l+2&@sAkhfLdc9_OfOl;vwTD)y{0fN*J zOK|Ck3M=EDgL#4B6Hu|mLiiA5aqtVZhzEQWk z&>f<$YK>q@lVuh02EdjyH|?e=H11&M>m#MV3^%-70Cd4lamdf??>T3;b#0aZxNzJF zWXZO+B^0rDFveXZn&PtNDAPE}++O?*N!4E>mS4+HCVFpqa6>Nx<;)s?KtIPWKot}P zj9|FluN}@C(2S&Pk#eCU@V;k9 z>75UT*lT`U{0-8ABxb(SilsDrj^IbTpUqbV9^eC&i(zcalfI50I-&N5Yp$@CCe-t{ z#fjGskQP*hgJR`F&DAF*^P{Vw5hyJ~d>=qagf-~r4NbW@^^Wl=y%Y-?$TK{W{_|Ll z?;;koWsZ{MK8nboQ^0NJc!2b$X*jdg3sfn1f>P3Ks500000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=QFbp{vsJHQ5j`>B?#~;uxa!B z|F7M0$lBL-B7Q7$QH^R{JvSB%qiUBbv7wb^2yUF_%p_7%LGEo z7#F9^BlP?MgMT8RBSpQxm`EsfuV@oqv#ua%!u{QFBo}rlzdR#g+dAC)0Y@Trq0EEX zEgvNja9$CObUO6jhKfy$I>5A<(|^KT?2P?@c@EOqMzC&hmp6vjgs1H$+Lh!fkW5od zV3Lqv{)?URaAW&=d5HGs`EP#Y{sUJQuQtiTfZnPMMDL&t?H^c2*w0%9I#f%fZ(h9& z)GU41SK^QQsaX;d!f2#2!k!KrHFq|l4`X^DV?bYE_l?0#H2s~yXH#^U^D zjkuIWdUsZHrKf!o-eJ*}^{{X+jHfLH;5A~w|F?|-L_%4XA7+AJf9A4gKL+E{ttezc+J$MINMqU8o{H@*bzfzNz# gv_1D~k$NR_*L?cI_TxJh{XiAJ@|%fbV41da+@ahcpa1{> literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/0852-futex-wait-multiple-abi-fixes.patch.sig b/pkgbuilds/linux-omarchy-bore/0852-futex-wait-multiple-abi-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..4a420133b55faf11d4be6593f2aaf23c0a06f982 GIT binary patch literal 594 zcmV-Y07nFwwWIBd1jBqgj&+xFeR%$$Iq|2NJ!93bDBEO4U(4Gs*>{mDi5;e zeN&%M9u3u0mab3q^8biTDK89xY4z>u<~SSs`6%8#G0UV}@QfERNOZ$iXrs5o*C)D7 z5&zqcjwmW(kfQ(f%3Ua6=<)Ivfdh^Ot*NT*F3B`avvG(GyD_1bx*P+!{P|mt`-pe* z)927Q>@-df0YWlwSV`RmUpI$U2gk(XRq4TVW| z!Xg`?93kh`QfqCXF4CeL%zpepFMLr!Et|n2rpELOlJ+EU{-8%A`9(1uR5#s%Rls2W gY)zbg?5lJ1I1%rDRAX#2Cez2ZL~qc5UBp%Co}uj`p8x;= literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/8201-xe-shrinker-return-freed-page-count.patch.sig b/pkgbuilds/linux-omarchy-bore/8201-xe-shrinker-return-freed-page-count.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..bbe1ce3f12da4a47a0371e7cea9175df30ea526a GIT binary patch literal 594 zcmV-Y0A()q{1-hxlGq zyo`62=sVY+%@L=r`G5GLzBa2eV}a46$fVcm<3&5Qgx6k^8+E?UIy!*WBH|H-bK4gw zKE!z=!7Ni2ORKiQ(t;KT6&Q~zJUaxp)+u(~hw};B(cc|E(Eu!g<>_|11T%>lsW=}r z?)vE9;?~pzXp*Yeyo3ATc6)6)8^iCXr{GPa0f$?E2fbtF0J?*x(RAIX=sJ zNBAzwY_ms{Fk4p&F$sdhW&j%zvILe-nsFNbGIt+}IEuynwm%O$F{ zmG+Q#Q}Q#5X8;CrXg-}N9bBb7YzPmssT^~Fq@{XXyT4Xw%S~-)79-~bZkV>RatSuo g6uqfZ>OOPH5atY*q*ja+&G182f+w_4B0Ca&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=TnFf0D+&WByqaj7j9c9pr_q5 z<0j<=flW}5$?pgUpkavMd2gE8dpm~~gW@SOd0PmoGZXx~n`gUK<}2*s9rITq9T?x2 zQOp9O(g68K)5GL`weJLFYujUy4s`OOO$<5aKL}@5x=`|+C}q~JosNyHLd?Eu>pV?g zi=tRg;==;Uw}(UEdNT!Vu~a13MoAe?$CWP!sa-oyhpd~zTB4(9_2R>mNSz9}7n4nk z@&1+?}@_?yKHKK({(V0RHc;V#EL`1-j-4q@+?Wd9PD%DB9;-zf|S}|B-mmn@F z>zUV%$7ctVo5EopY^dlJj{Fz98Xx)|@5_jWv5XQJs$FvX>oT}w%%9g@_uo1Y-W!L_nwg$<6c=8FTk~^>D z``le*pv`+~QTVtX4~dNHssmYji(ZwvV`lfN^dkqF`@=Sv+@NCB)E;fSp<%Is(Ixet zi0D>shj&=Jxr@u!(1CPDI4>pRp5t8f`;!32i`fwuKnJ8zzKL`a&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=VUw&{TARhgC%+pNiux%=PF95 z2{0Um$lW4^jxu_xkMXP^P*3j+30||6&G}+$_@&>pqMnUKn3UV~G<5t4sb zl-qt*RtLc=?nov~nn{m^w{yuiRpzK9@6PJ#0a=`>#_g=<^0jj12}OEx?o zdDI%ZkocTdt7`c&I=qeF_(h{}45}l=ZpCJMzJur97)w9}l()NkDLwb@YXLx~ohx?O zZqWA*xPWJS+i8Dll!FB(Se1i6_y4ECOJfR5%!ET9`po5<(DJxNJx)&5Y3+V=yT7*( zbNIxO@5uDzC{qh|^7H-Ya0FX}F?k g<5XX8Jn^`_MTKgM@8a&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=W$UG0F=``Lr`0r9(jt}H(j3N zA{FLS=LZfy#=1rGb~7YWq!<0`FynplH8oHrt`i*sGGyY6)o*A>fdv7Ot9(r@T{<9~ zbA~O^`Q2sJlr+ZUz(?g=x2i}|>k2}EqLeK*L^@YKgTak+1URDyVV&w7 zi6vo%Z*#{W2W1P$$XW3;zybbwky3SVFxYxYZMj)vfFiv%B|qhQH(Tf$IO=pv*Em{L zuPtXeVhbJ@+tDj_;S=N0_Q|seu4-;kleR;{tH@^kg5CwJ2NOWLZ+FkKZB44ghY+Tv zXR9f|m2gD&JPiVwSW4bR6{Nv>$9Oe2w_7>P?*!QgcW<9bgdM3vP>{>xt}PVoUumjD z`+w|JGL(eZR$t_jy8F$Ab{Wu6ysN(GW6I13nD+*HT>2F_(IhVxT1SWph#|zoz?gLz zpme40V+eJmYI|iILRDOP_*}zze@}GFtbW%VE50_rNG)Mz96ZHj^?^XLr-UW|UKP%F zC0}NIJhae8wX<3Tf~|)X{BM%e2*zIflRe#p{`jxdi62mClU+DJdyWN6pH2CDm>^{g g^hVAyehbDtAgSPM-;6NP|6mWO%Svq?NvAH$HSay0D3rc#TL4u^{|2A$-ugX0Yk`GK{$g7d%oL^22S=Et`8g-74SyK?dr+^K^SJHZ`I1Tr{I|x1%8D` zqzI6nuqT+@1ZKLWP`eP)n8-=E^33yDM91( zy@WlCJ>npKjobNwHm1{8&K+HS!O(J2ny@q@@94jCn%#!}*gYqaj&~ga0q5I{9r-5< zB`)e_3WVZ(L9eHOPYLoG9NIPU`8c=XDI|m1{HnZ$M9JfAw8E@C` zR=IRdSyj^yg56IL+{yc!Co=fDTX&sZV0)slq&{D2Gb~o3GeF%gTHyQsA}>IIaPEqT z?w=Ia5nx#uBV<`lj00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=L%I1{T`Z*tNLV&%YK^q(c^JX zvB!2)?Ej^K+Jy~r%^o$sInDExxbiSJ zyu;INB*7$g3Ne8JbCVh|Tm7ar`BY7nKO%}WSarJ8x;|?(Ojp1pSF#4T5P&5v?sp$# z;mBP_ERl^qF7(6fga?LtM7K7hqvSexbl&j+($gc|7YdB*vKe4jY1aXRSf6U**8+|> zdR~{RKWx8^;?h%8FK}9NH?0sJ?jQZcGDP5|@u5F96JNR}fkYlLLOgem{FC7hhS7iyKwk zjxUVC$fKg*ruDDZgMmCHg)L8X|yZL%(gXpTEQwS-o^u>W&6aq*UIQ{O5l)nlTAO22aCke$Xi%G g!yQKsTRs3j00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=k5Cs{yp+!1n?BoGP0#eq5~iz z%d3&DbLpzI*JPT{eylTrDHvIPYa)T0Smr-O2Kj>Wt zE)K79IqR4(S`a1Bp*Tg-whGr&z`~C?2?l0%kn5@Y(thrOW3PF^izb<0o4_Pjdk$~h zOrCO|qcLWG5Ftpo*f*r3 zXR_SPpq#Q8iVG{ZzW`l2t0HGy_u;As&~K~c8D8j99zHLy%EgFcMIU%wt-MaMK-t2oiHU&qM>*6`im<_;uheT0CWY~jUIz?H4;BN*F8 zv+K3QN^bdA)%Wzt6QU8<>9TKn^Vo%r>T^sv;NEeadts_HWEl&s;^TDyW)>3fET{zD zMn^EtT`$9C^EFU5mf>Eu!IeHVcI&t)?+zu^bWs_TpPj(DJO-@TC)>{$B-mo0RxdRb g(C=SuyUxjTqL0E{fgGTg`iCCg1)rv(9gLTrVn8IN$S<5-KA&?KwYX%nyh$( z4nc@RY=n#`Zy%4LS#W}*UT}b^1Me}q-)fuKp%1}Wod=0cfl)1C`gqfj0gMR~9oC~1 zzO}(2gh6aH{m*j1!}LCq)%o;@JNt-_ex<~7AwqaAjeB3&TE@j?q%z9u9B01N8-uyF z6XdO2KF6umEDe)mKbzS+P?p0!mUD$GRzTOh#QLSLNDZrwc1m)3!c$~yeS-_F(8p%l^RmWL$A0~gK8xy#R52jpiw{Qxa{$|;@syq3pi5qnOrzvP zWrMuapcqe?(>$bX@!u>ocGd}e>YWL)gmK!{KNekGZ@Ol_XsA|GLqf@5na5W%croGd zc-3ecvzaFxX)0Z#>=DJ8rE@du`px;+xxp&R9bA1)3=q=AT|ZHo<(9>A=8Z<2F#e`{p^ppuT9(Gw1OKoSGa| zkmvgWgF70ScZS5*0)D4hxH9ylsLJq1V}PE$#MzwXV>~`rGlO_wL39LE?U5<%1lyyH grME@qV6#fEeLcn2ZuFV?_UXWlB~eDM&3O@0O%3`Twg3PC literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/8209-xe-shrinker-use-opportunistic-hint.patch.sig b/pkgbuilds/linux-omarchy-bore/8209-xe-shrinker-use-opportunistic-hint.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7928b4ee0dcbc148b07fd44f0fb52cd369749037 GIT binary patch literal 594 zcmV-Y0j00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=WbdL|90C93g)f}u_3C;r%Z8+ zDhY4(*ndyrP!QY*S#g9smhKC`ktrz{45qh8GqUsS#^yhu{!^VXX`rXtCd>bU4zJjo z6uR4Y(!5DX^)BM3jSp$uL|CEQsXSR$_1K0jQu*y`tt~IQ;I}9XXn*`ynDEKwb2Vq& z4~ddxIDi?-W!;BgEr*QEY!8Yt#iV1M+np-IDT^@ih#JAUb&v@}N`HGqZH?%ePT(v-t(Sg*J^>>Y(<-F&fS3A`y=u`6lx*)@aXGn1W-;25~yy4Z76*Q z?|~zy{=-|2)S)fD@fdael+t`SwYJ_kO9oz=!U)xa-8?1CJ8mx-3kf|H6qMGKR z=Y|Dqva2q|)beU|Q6Aga-Dwd`P{F}CH!BOR_RJJ`r8Zdl^t>dF=cm*P<+$a`8$zalW>DqykH?!H>)F7;(cj>hdpveMka1 zoHe@Su*V{XiWpZkGq51;xLFb^2`y_HB<-XRc*1R_{@cN08+8LK`lH71H{%)BPK34X zZ0?3d(jA(AXeqEQ*8aT5n0Tn3_ivQ)$DYG#)KOKXnaGgfq^2+euX27iM+zF8}Zge~6~AS?@Whon& zS})R;=A$U&cvNsko<;0_VvbCv-Kcr5M^>v$;J45k0UNgiwpyUn&l3n6UJ5^(oO6FeC7s1CQ zAtu1{0rIlK-ClB9E-|`u;LZHFECpd7bd-6fV9ll)Y!n6ARTytzJ?b0$Vyh$G7z2oy gOU*B@;?|iEsih}nr!}`7e;0*F3h5=9TVBjfU(2jcFy(7 z(}vXdDcNGyF$tQkr!)URCE+rp=5;(DmH24;s?j@m2vuJPTu&ccxqYOW5MOnMOtZ0_ ztl&othF-p;ZeCtfKZ7TA;LC*wHIl-*5y4`^)qKpelXf^O_!Y%)Vo>JnzM>vfvby{ws@n%=sY(hQ$0=Wo zg}g-~#oa;gO=)H2(JPu`#ZiOzF00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=TWH-{w-%i{PzT*1z0#IQX|nG z+p=5lzB_r*A1UHJGd~lMIx&%JX=tg}y9!6QVm}|H+G10msFYv9*oR5tbc}hq;xD@1 z^NMZb-6kc+W>L3db${LN>R{piIN8`sjKdn4q$C^F$-Lm3Xd5HDV&B_YX`wPz;*WXr zg+0H6M)iTJ6MvE zN%E3mvXaxX-M;jcOAxMWx>JvNDI2noAHbynoDb*y_Jfr6gOHHImfu*Nm-N~qtRDaJ zapV}|1bY$jrxJYhKY?)>ASsH5%?9vnt&zsG3YK_$Br^eFt3v<49~ksLFR2&2$!Zmk z57hUVXu1|1cuCWc@&N^77hfjaiNg=@6^)oQXPl?@8DLYz`=0>*`arHPZ%!<` g(?0u(SIEe}0u`$M)WwJ<%KXQ;qR;JATt1>eMp;B6|II#pVn+xP3g)%cDJjE9(0Pd+cPzpH?LT88o??AM#x?<$9qc32u3ZaX*oI&uJYRH2?qr literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0130-sched-detach-tasks.patch.sig b/pkgbuilds/linux-omarchy/0130-sched-detach-tasks.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..88fd7203ec98e3a7b7b98648fb7dcbc1233b7d36 GIT binary patch literal 594 zcmV-Y0W z$L40@KjfkaN>SAAVv}?J=B)+(AIAs2moS5eOa3z5eYvI_x^9&fM>wyO=AJWELv|tb zaAOK~cO+_ycEe@m)e zcPI~HDcI#^oFgEesFF@i$nI=vh>d@hYza&YCQ~(IejJ^i05eQZv)?PpZ?HKj13$iT zUV4_z3@BOiF3HEY$zV~Ll}0kXJSZV5oiHQ#Y4%l-Tk`F>v;y9+y}(O4t?b`!vi9xt zk7mVX??LZgbwD*5Olm_Fa3Y7bcF(@xYg%7SKQLb6o)D?RAF?Xzx4b0E^yGFaEQBz? zTsYM>d_grE*%W{ysJqCmsP3pw@7I1b*+W{2-^4}F*1&;^KG^@xqPW9Gf|356(#|e{ z?4AT&0!oIC3ejhcRIjwvO7?bN4(C+?O~;cG^3Eo zZmzta6qbbO^i8;&1A_qMtsetJ&sT1F^}JGUP_OjzEO#VBI!%okbMKM9m4DFwj})v& gLA`ECFR4c&j6x7Iq1!x?CN8&gI~gZbM|zSvJ4#~~=>Px# literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0131-sched-avg-idle.patch.sig b/pkgbuilds/linux-omarchy/0131-sched-avg-idle.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..a9f0fa6380bda5a5ed0cd0352df078e9a3a3fa16 GIT binary patch literal 594 zcmV-Y07=d!zxTFeOyO+Jb2*qK>q@9f-18HD$YL0SQ?yZZ6VK&W7e~rBoePsK~s|t=eh}Tv@g?x6c zL9C?VL!=4Kz05XuthtfUOn+{*(d9qqAQ2$WhsLh?z5lwKwG2WkyI}_rCVqXMGT)(M zj1w=x0Avct!UGNRwhqJS|}@Q_lPuF44)K11Wl=!=_61>4ya)z8=u- z-8GV0wq9PzJ7a&oC67)dE|ZMh_MK4}nsW8YdFl}Bt!I4)7)z`KmxG9i$fpf#`|;|j z6Zwl2IuWJ?|02J9Hd3wv;?dN{gVNs2p&;Aq?cI$xNDrLIRZfhf-Q(NgA)nt4Rnh?S gP^7RPSvE2ni)8|h##TxCZc3^c*!JTCxib7p?ae%F1Wn&f2{Yr{s8^w3@YJi&@E_C?aC1bt6`*bdXWQ?8 zD5!D>Q*)f8YwVTLf$=G;ON)YM#v|L#bq{F+L&_=?kG19PWf??Im**EnqH|IV z-1}e(((GFS-G1~YGlncLxZg{ymOoQX058y$6c#N_9m>V1#>T`o|3gZEjc*m%Q#>>J1_ z1?-C;lYpGK=Es5P!T3hytsuM2%YGerq|aFJ2RYqXtJU`m+AWW(&9~*9(4DirhW!jY zvCIGAW=)=sBEn3x+7|$?%{^JYuE8Rr*hBs9ZJz1rYomzW@LL literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0141-sched-urgent-fixes.patch.sig b/pkgbuilds/linux-omarchy/0141-sched-urgent-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..49834038e4e72ffe285c8e063aeb37eb9dcadf59 GIT binary patch literal 594 zcmV-Y0W@8To6K(-pD z4r&8gyis#4o$M~;KUJA-DzqzzuN0&@nJ;87{5O^f6Si1VZUOEqCigV>{8O&ztnuRx z?qT+N2!D0I{f#c~^eCne4T5SrpJ=GNL{=XU7yLq*Jpbi6Lnu9_YYwn2H9IohE6;+~ zt<)B7x}nd8Hnj3vx4;zhk5;s>`Oz@IaUxY$U&(N`&)Hs*GM8Q`JVWen1>0kAj2ox$ zh2!nm^;;9HYOHBun@*?z4u_G<&XjQ1^Pgi*u{5TNv|mY;Z7jTnMqrN+hf_eQt&EBN g^|OeYyKL7v# literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0142-sched-itmt-no-debugfs-dependency.patch.sig b/pkgbuilds/linux-omarchy/0142-sched-itmt-no-debugfs-dependency.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d96b7f9f6dbf105f7b6219eddfe098e4f8a26956 GIT binary patch literal 594 zcmV-Y0?F19VRB!)LZ<}? z%zj|C-%!Za=6s27#K#5c#In}=?eb>*0@xTz%9`DmF{iy%+yT9J2@=rKcVGfu_(NxF z2!IAE(IvC9k9p4uyZq9S%V=)abfDao*c*Rxo1azGcY>Yf04I9aGtT0>_^{>+@OH_l zmY%8Glvx~guGP&gqP3&vSF=x&qCLvnd%%q!w}%^0!^yhH4zny z0}^snW4xs-i{$>QYl4=}C@B=!c#T)6`)BsI3=Dv<(gca*+1?^^cYuNMD*uXrWO>m?@ZlH2GEx4LcQqkN`^n%YzMVle_u-y7_>i zgcpW#?Zb*k-7u0eD3a+%3`*!KrVYerMuTlqXoNR$8KB2<&g%dxn3M|&@=@CRI@)>Bl}G0aTooU( z{!|a3er&8_q$hwK*ui{ME84_~8z!V&m0;9r8gMHqRj{9=ebZIkdr0N-f7dEK|K$k9 g3bcCvb6uv`^K|`@c2JOG^6tso%Jn}oZpoVEQssCZ)Bpeg literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0143-sched-hybrid-cluster-balancing.patch.sig b/pkgbuilds/linux-omarchy/0143-sched-hybrid-cluster-balancing.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..b191450f30caa4b43cb1661c58bd589fb15dc559 GIT binary patch literal 594 zcmV-Y0w+!{qDnE-in zV3@}o3;pIRE)OaU*H$_B+KA1XvlQ1Rm~09L$~4%|4cpdv?}-4oa|Vn%Jge=AHYzH& z`Z6wJqgk38zWYih|5{V`=iWjN6*Ir(hhALtzgN-z$pyA~!5HZraDs@}jX`zSv{ z^9yuL@I-%#1bNC!DY9n)l1xh)ocOHQos132dA$lA^)I|{?=VD{FlQIZYfJGlI4rt& ztmOkS5h7@m1-1cFTlNgk)^yntEQ!v3V7o_p$Q>o~Dd7pS)JWe1M-R*bh1t+eVSo*Z2qx8s)!?K83GCvEKpOKHaI1k#) zw3aRtCxSoV$@h^VQ{sJs@JB}&ZPkE!s|oT>fLqOliLtE1)GYTuW~nfs&@FI-`OnEZ zpB{VSom)Q4Q1z2a9jm6B9&PW;q0W*CR(&Z8#F;)Q{u1>FIAQ*Fw4jDg!Upm`UuPZS^N{mI?ShUj5g z9SN@Fv>*D^@VYzkU{dHLmKN0(1Oo*eIneRF-C)=)hMlU!pW@~0zpYOXz7RwXEP3@p zHaOzM4~(>td2=Qy0d`sw4e8E04-eC{G5u(ra3*pVS|PrE6~4oudg_^3$FUFH`mo`RO!kwzdpO&1F{LdDTXk43Pp>taXW g@&v9;0PKBYxdgxrAwQBJ3=u}4(Uz3Z7&IrPQan^0NB{r; literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0145-sched-eevdf-tunables.patch.sig b/pkgbuilds/linux-omarchy/0145-sched-eevdf-tunables.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..efd3bb25ddecd8a7a418bc46cf5fd582a06d9f46 GIT binary patch literal 594 zcmV-Y0n4D@{N7BaY)8^X25vd`qN=1)aJ2LJ(`5UkW6zHBU(}Ic-8O-!Y!jhKE>rJV zR3WLDN=lB%Cz>olPuD6JabMe~GZHR0sXRnmhlDQTaoZaiqv=wNXofNTd%lIyKYeE! zq3Us=$PqIl=;Y!x3X2yDo8MM3PU8C42R@$QT;acq^NlFw2juDa+c6Fppz;yH8nl(6 z$(31YH0>cF`%LRp+CU~nKeKU{K&Hd4&gVG-$d@&5Q*HMkR7@=UE!Tc&dlFu#hQWZ; zz_~hknDw9U&x7X>$R5XeF46SxY)r5NosDbB1)Zh``h9(F7mv~8th7`nldwy)@tWOH&LBoEOzAkC`3U04vPK^B2L^=m;>aJKTpvQbn;Culf;b59P;xpUcSU%jY3C)47gX<>{ zPX0`k>bwdz?xpz|eW2$3~PyAt|<*+J@>5T}1efGbCL2~1KQ zE0r$gAs*$1|2Af;?NpLZJe#kYrLN?vYd?HBvA4YNvI)KYVK^e3%l+T`RFnL%7C^-J z9SGnNaJG@D@B!=N138=9%V$;+6zddN1SD_&3J!_2rjycsC~$^1;AR9NeiE-MTmHXI zQ>C*H`<-7KDu>H+oLv5T^fBI?^>Ju)9d+3~sOULH*VEODtO@cu9t!tph(ZL-Pd$#0 z&h;iCbP)dIh|LgeHKgLMr>dY+$`@e=?%h$Cx|C$@9_v!Jc#3FrK(B6B;q9GI>gP#6 zecmgs?tM+bjx`@>tk8)=cc{W7(gn@5V~vv~@N$ZEC`5#t&!W+d+_F7eX(Nm9hck+` gbzL(KiLwZouCQ@Rd3yxiH-|%(gy?#m)E+RsT6a_%R{#J2 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0210-pstate.patch.sig b/pkgbuilds/linux-omarchy/0210-pstate.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..1d30612505c8947621ec675ff18a170df80e402d GIT binary patch literal 594 zcmV-Y09$V zx&rJ`Xo+lEc3g-Y5jwQG^7?FBqN{Ne@nc@$g{>4gDy$&fc_+nO=Kh{|eh38q9C@7E z=%@qmGSYn-Vl@8&o*B6$!^DopROb+*@VRC}Tj9bx(x#JGn=$53=WIzzr4D$j|z&FnuF*Z=?k literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0211-amd-pstate-fixes.patch.sig b/pkgbuilds/linux-omarchy/0211-amd-pstate-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7f218b58fa6363a74495cf75ba156d49807685bc GIT binary patch literal 594 zcmV-Y0szMoKtTdO@wz}P z7SK((u1tPW$EK~gxX^n}deUty29{BxL%R;hIoYXNJB77_*UqCnfed?p1D>yp$+zD3 z2eWSk5DY~|M8tBb^G`6S*<3ux?cd88u#n*|?ZvsmDagW^7w-`Sr{2hUIVgxuL7vcb zE=f1|{W(HrnI;X`@A{^&nIjbovnOxJsa#X z@Y1?hvGq@5F}xYGpTEY}aB=7%z7f;Tvb(qT!qh9b56E66lXxyA0gZWSw&0HLNj+-w z0N8Qt!6k3bPi9n6Iq9?t5%tE35(@?RO#0&m5V=P+JnOdIP`)uoS*v4FqLG$dnn2c5 z&E=HE}bKUP=6q?%IZK#52Qc({%m#iN3I~SUa9{nEX!GNSQy|1_@C~fQd z8G7B2bcJO9@J+bICO3JqH?p3rtz!KF?ibgsh60nlGXc2?EdnnC*75HxG~Zb2m#8Lh gA7U`2qa#R7LPNb<>nM>~N9`>19-?hsV`(|UinBNvq5uE@ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0212-amd-pstate-epp-cache.patch.sig b/pkgbuilds/linux-omarchy/0212-amd-pstate-epp-cache.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7371ce62ecc990c4697c069fc5b0d2280713e57b GIT binary patch literal 594 zcmV-Y0XZ@T>YokKN)>l;Oorf zhuamt8!(Cu-1nz;D|d*c&Ey<-J349(ID`wPNu}+*Dl!A`kd|i&PG5$Xz0{D4fT$AR z$E*xTQ#OUIEKYC7xuL%2vKTle-y`BZ@TYumreXPA`4MhSs@==Bz_f> z_-=|{`7jX|44;Iyu?_0uq1d71wdY8ws1K;!9gJ~ptv1I_))Hq$c#;WQ8X}v<^eub@ zK!Ub7`>oqZ!^*H-1rQ@Zm4yC$aJQF$&)ZP2;*9pO-x}JzCf&yFn4e@}Z%WPC)jv?h`*4 gwL1;)@f>%2qHC{+aoM;wYx)P6v%(=*pgvdzRbGM>Jmqd)b{fGH?NdaG(Mk0owzEj>Xxv~^qLl^tC@A-_4u!Rb%{O3M=UC z4`F557up96r-&_P-+Yupc#HzI33>&Nv{eXPJS;dQhr{mv>jPp+r!L#-MUl5Jt-Wwn zaEM6-53!wh1gu*Kd@bgOFN1}TDXzO=M65u_1_WPAC%s?2+Z;Jr*tNLf^Iiu|kl%Ea zEn#eE0SLD0uak!FCKP77JW@z6v#4N+-XowQx@-u80;x-Nl@ZI>E!j{1SL={`9HGOO zSj3fj_x~K_8^=)p>bH9*NL{FHq|zPJ{mt9)IB-@cDlNbQKyUiq6s(DPC zbfP_p`qtbbgtrT>NzsXRX_o@;P%cttGJmAbAO2;-xz>NcD-jAeog7u_cj(zn$b#3f zQbxEWMH1vcl5$E{)y@}0G;Tadf-Xs=me2GJe8E{XkR)N1)RkcX@kw1P!W=w&xAbeR zQvFXzi18aq!ImtRW~47E(}Q||6l}ULb+EG+l^g8HC~LJ%l^u!_`KAoDEeq^G4)@=J g$g^Y^hh-q;`p=n-o!}XygTgEHi6+x2CJ)UQ@`kMs^Z)<= literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0260-mglru-exec-protect.patch.sig b/pkgbuilds/linux-omarchy/0260-mglru-exec-protect.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7023e215561fa9e1b008337875dd42e397811f44 GIT binary patch literal 594 zcmV-Y0w$Ea0Q>D3=ux$CU6S0ySM~i8EwZ>cS4B4`#!l zT}}tOaT(G{+3$2z71plU?to0VZ9}Qj|4N%t=aqIwtvN5r7@`4o%`|)ApWySann8$Gi zJ9?s7(dM5+R14klMYY8;ZDI#7+$xM!%9K05$Y%DXncwHEjjLNeX?rUd43sI0+Wkfm zXTe^x@^=Q}s~P(N06o=oagO?CCZa<0>VYLo_wU4JU4yYJwnTHwFF~qS#z*}A;c%so z->XZH?R6z@GhunKIT5@^!1#1fY?PGh93+YlZF$c^Q_WGMm ga{;uV2aBWJA4;UDfm9fyTGXddBtd!g?%^4hm4p%!FaQ7m literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0270-ksm-rmap-walk.patch.sig b/pkgbuilds/linux-omarchy/0270-ksm-rmap-walk.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..32623479925aebb423e2f2d46d312e7e78179f15 GIT binary patch literal 594 zcmV-Y0DRQbzgvC7T>|OSZXF{>l`&;a2p%NE+8&@8$7Itqs3IRH^n>Wt+jGcr8|v$ z@4a$7a+)m}C(YZm#+_+DrFVoFu?S{KdJK_m4|QXnmIH@G>xXMKFNqjyK81k@{g|e9 zW&kKWM3}K+c!qgwwTVaHm8JTYVuB{ykV4@Z(mfosW+YipbyKuZ6KePEbp)NyCMX4# zL5^G9Am;qAK*}e4?i|u8$z0uewwIG4K(}Pe zvh{K0+7tw-;-LO@>NOg+a`%UN~g<%f*2OpS&h3NrAmw6&3N8Rn`2 z)Yw!che}%$)=BM)Xa3Y}4Sysemr-WrX0m`#h5Pxsh9o---9M zCF^(V{dfXeOzG;7>I7Y&)7~@;zEI)aL^PPWtqT gaGDx28wsV`af=DCW!R|^-jA6_6A~lRh8pxR+6bQ$r2qf` literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0280-mm-updates.patch.sig b/pkgbuilds/linux-omarchy/0280-mm-updates.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..4e1b3381df3afc6a9a4ad0f8cf206598cb37b592 GIT binary patch literal 594 zcmV-Y0n=Yo+H>FN@rYun9K@%IHY%EQ@ySpFzn?rhdq0C73*}(<6u}c$1 z5p2}`4eU^G(M_Hzo_4_@a|r|$%91Rpmx2s>Uv(iYGlji~TqH!|$67pIg-8y|BPQ)y gS|Dj{qHe_}aw7_k!WLh%Ds+ppFEdt%=Xqujg_(>LMgRZ+ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0290-zstd-bmi2-fallback-aliases.patch.sig b/pkgbuilds/linux-omarchy/0290-zstd-bmi2-fallback-aliases.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..670730161a73afd28b6fe9aa39d8d8773adf5d6d GIT binary patch literal 594 zcmV-Y0f<>uRw35Z>u0;v6YO~bRHy7G_%QV* z4DHwQpI3SVp>k@1_9mQy$gY|L_i#hZGj50_j8KVBEqsq!Rzn2~LOUh;^YUb~kAJ1+E z6OCxq0P^Q6CJf%u7I<#{0KR&fpOw79nCbB++Q6ev0mP}7@hv^dqfKYJjf>>|ZAq&- zcn)U*-5tf%7Ny@e5X3*9w2OwhE;`Ys`-I80|6=DqaAZpDNoJYFn83C6shTeh5 z|70W+Wq4NL#Nu1FAq}x-Cg?Y?T)C=Yk7je$NB6l5&sq^MQGn79^sc{RTGPk+qN?K7 z3|?A8Hl~B^o--z@Zv*InQ2CeNluPWc=Pk5mS{t^QkS8_>@1Fre)~;D{fYHu9TCE$I zs?pr0Wf&8lS}YXyBNLgXCuho-;Mi;RXbxyi&qa?Ck~pI3XHewL4Fm^!bV(?SfQ(Am gzaSyMo|bzfLa<_@#Caf(kx>oF<$3-d9Z~||aa5HWAOHXW literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0291-zstd-bmi2-cpu-feature-dispatch.patch.sig b/pkgbuilds/linux-omarchy/0291-zstd-bmi2-cpu-feature-dispatch.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..e39aa6cb83bc310b2e47c6e541b6e4b37f9bdf77 GIT binary patch literal 594 zcmV-Y0$`gUfYX8Gy#U`sY4_m;c?020 z-5{mq07!O7k3pIz0lOgCee+Um*;YHr{Am~b22x1G^6wBTno4*-v-rInar(1OwgcE` zq&WNIguAkpMy@xM=wCA+sql9Cd|$%;ru44l#KPP19R%ULW5IzvP#}_TH;-=M?;!EX z&~FeT2s)CO*KiOXBCnb&B^7qREWT+m=SFKp(6uk$BKdt0Cr`L31;p16zSn>$rYR*b z?mN9u^ZjMQ30mA`cnCT_<{&5chbGQSB+L6gaID+21qcH*Cw=U-!VDR!ztB8;KI5t6 z;`sfyB0NCreie-5n8{ohX-xG?ci;f?B1ze?68*6r+xF_-dF$&)SyoH-qk|CoP&)6S zONf_p;O_r2Gu zOrj~s)RoAYC~@i%6$SAMh@lNBNXgUGB2QMa0_Kb_<+Lxm+4LdMQz-X)et~kZl9)q zJZ!lX7Af)!To9bFwj(k;v@t)3?Y|Lcd{h+K=FyOK{q@j>uqgn$K{%ViJ^os4&pgc& zpPS4mA27{ZcCj=)+-D_DYBnfB9tHJGC@Qhsbh@=OjQvF=6D}d zxPp-w7Q9~BT6bIxRG?K7T&jD0>0>JU!-biZmZ%PR1M;`}IWbeabBByMgo(t4Iod9? zNrx17Bv_lg`Fs11|kgl zdQ|9Q>kF=76Z>tOT>l#q2@3{@B!lpz@}SJwo+RoRkDOXvJ>XiR_vQAMpz)!Zk4sW0 zR~Bys)Qy8|pe+#f2Zz!3&V*;2;1}(3A-J>_SZ~Q_=s+X10jj zVvT0O^-646xqrq(J6vPYMs@VxKwAjW>(D8b&u>=D`$#8 zMKbyzw?+IQKl0salvO0aX0RMMd1~$fS-90P!DoH?t*dS$YP401WI!{HkQ!PY=-d4f z=Xq$S`(S}o>J|m3&Qie-Uf?J8IwN;PK&|#v!Wl#M2Nms|gOe|$Ls?OdVHD7lf#DuV33&}TSSCGMm)e$GDZKk$_{_ypQXy~;o3a!Q_Uqy5}%;nhe@~$ z+?{n%nPYSDNYm>wb%>4OQz|sAgzw-dVW)RIO5ZHw%wC)s3w?DSNK}A{cT}qEWKep;tgNPFR)nz gUXlqO4@rV1uo*8TMVQ1KY)g%D(f=>;v2`>b#pk^jeEaeIiRya0B|UubMknq& z_;0>GyJUnYk+^OGk@<4sDv2|bN^>bCP@@jS=t@s1Y2FxJ@L`w<-b@N}wu*~qoRa}4 zU_K;5;0ECw#;KZwa&u9PD&?lUcuQUN_OmG`>1pAewn*YBZFU41bzg%&f{U=ED1YzdVTs@dU!89$8m4lPAXVTMz}-dd#Y=nre0zPIIFSB!gJqw zPLHxyP*N4S-07Efu3uoMuqI*|7|Sbt7)FvkKLf>}S za;DTSgO4&c!ae*{#?hLHkm#F*!Jf3sq1ksp)-(XvoB)e++WPfPx`IPLwfq^3Yd78F zW96hFehxOASQay$5!-LSq~$$}ad=w>ds2bO(e${^Qd6EzI-6$QZzUIMg8rai={C1M z_qT2Lu@KSG;#l;sWiw?h$4bg_esWX-SVl>v*>l06!N}x&klNAJDHh~qJ-zQibU1;Z zd+gB=mw;r@^C8P|Vd5?jM8q6S*Wv=B)sgNA1qvsS58~x7ehl%7Z=jEwvq7NX0^i~c zL|jCes*RV4TwC^$tNf6FM#Nv=Zwyi9+3hfe0^O)WS8jB#Lv>-#VJ(GY*X z+&T&rFslGttYXIjKKd4ds(b0HbLv3Ah7q}y&>9E~+Lx%nMk&=yU(Qz00zn40tYA6* zSWh>T>*=G-qzC;DbX<5k>Bx6AnyO`j!P-ld_3Z{=nyQrHyPrMk8{$;*RnjG=MEhgR z0Z>(v{%#!4@ZErdIIcaWJ|jF0G-7fMibrb~8ldz`LWsGJ5oHnf0G7!b8;)uPwB@Ko zkV`c{FdS6OpC4zs*LccVmFyo?DCO4HhOE6SZ+$QumVk14*(U~}R?JxOFDw@Jhy_T6 zfgQU>S}D>G-r~=g!*RH>y&T^JsnS@{G=_Gk@Jy!WI!HfK$@NLvb?nH>ud3LVV+0wO0@$J+yDRo literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0301-btrfs-fixes.patch.sig b/pkgbuilds/linux-omarchy/0301-btrfs-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..53ac4a1480ee6437e64057fbdb2be9ad896d993d GIT binary patch literal 594 zcmV-Y0$f!ck@#9~= zZQ=ENI*9^~?^szcj^%0L&L^=f9`hf4zIS-RQHuu#*vW>d)X={{YYbcFuW}RR(%E*b zjtAh$4P%1@kF0dxu6~ny6=^N#_PM~oMWomLCkgEa$)6p}5YkjhFQE+ycV&yh#qq?rxLWCtqkbHVlJYpJ zEhMywJ^1>_mrv7gK0~IE+-~vFET?TM%^`NRmX&22MF89+Nmuh(a{kj#8!$zJP|{Yg z$WbiptMXwbq|o<#8cI@SpFC&xZ_RN38nwUE45q?uoS{U$7l*V?1w{#);)fiuNp7<& ghZ_EZre}nm*S{VEOja$p+hNMlrQjIhArBbS_F#S^00000 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0302-btrfs-zstd-decompress-direct-to-page.patch.sig b/pkgbuilds/linux-omarchy/0302-btrfs-zstd-decompress-direct-to-page.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..a75cf5126579aae916bf666e2ddc9a3e1465e0ee GIT binary patch literal 594 zcmV-Y0O3-I9lG z!(z{ndY=E5=oQWPC5wl%YA`w2BqoZOgwmC$nZ=q-xgpu1h>}6wddSXm%N1xf2II_x%1t$9d_{ zEQpXsv;~x;!?MXZd!{8v_d9Hd*@^N`+$dEd6)@w2RodNOL4@Y^Uh_?B3d2&=B`|P@jG;`{CaJg_L<~q|61#rF6ut*o{`0r zgBHYaQYxjDy~`;!dKs5-%>bYQf%D#CpWvc$)B~v9$kYp4eJ1nb_>U=2RQnTzjK${l g=hLh{#D*Zdp?$b&>3$9cdvrV+pnj3jmruGP^#A|> literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0310-fuse-eof-zeroing.patch.sig b/pkgbuilds/linux-omarchy/0310-fuse-eof-zeroing.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..c65855efd194078fb92f0c698a05e044ef89b7e0 GIT binary patch literal 594 zcmV-Y0jqCWYVQ$71 zlT9Pn$L1=Twp`RB5*itMM$!fOoerVeY5?-q8Bw)49dk&kUB#BqNBI18HN6J$l%Cj? znjtGWhSB5rp_!eXpLx70cM&b%7S$Nq9xjDXf97My8y0!qee5CXJjgaMc^rA>Jd)lq0_(-uxyeWlSVrVNaR+j>sz}0GCEAQj zwutn;LGfNG61!>Q2V$cVG$=vDWQlMRi3rfTfKOjFjNQe?#K--dGXJ_)nXV$?pE&=9ke9^Hlm_O7y_Ar#j)1`UIi z^oDQqM^eBmFLu|N`=XMg?Cy-EKMrk_d~3AjHm~m$_WE;&9ez?6f4v`eMH?l1Cbz2K g1p$;eWi`2_JzlQu z5Qb+_%xF}h&%P!tNh($YV>@ST5H2?m;T17UW;AD+G ze0g^l3~GJ^m1bp*MpnA#=$-%}f8s3M7ejD#wYJ}k$u0t20dM6w2y;D2n9Zijnh2FD zZpkD*@O)yob{9lKuuxF~4EmJb&^deQl)Xk`R%cTT4xK@1L@LK7-noPpq)L<^!yQD6 zC(}^2$}z+aGcMi*7gICE)3AZ^#fm{}F~r^^nE;TOGaFqISvcUbql4YZv{wg*>R!fG z{)y72jYg%v*%Sl`w6d`s`IQ=;j09EN9VVGT1JCIS0tE2-q8{tOuHC0v$Li8F+7$1o{!#9kT*hDzYJwH#KZp>{I gKYy4=kUzsIR{4CJW&bv(&bdXzSl15&4@K2j)aQB-jsO4v literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0312-fuse-writethrough-uptodate.patch.sig b/pkgbuilds/linux-omarchy/0312-fuse-writethrough-uptodate.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..391ede6f95fc98d4884f13c9b114520dd48768bc GIT binary patch literal 594 zcmV-Y06&Ea;MZ#g- z=N$lxogZqKxKLz3gE6eF4I|xV2|7E37jO0x5w`Re>89wch5FYVH@mg&3G}?M<6zzjoi%hlL5cSi5Uo#Fi5bniD4AO zcfEN=KOi0Vb}K0jDUnD~d`|{vo)1jEnjWqnqA)zio?GP-l+;W>2S*Xlw1grOVgG#7 zj7hf9RiMK5^qD-Qpt2)or8vl@!oKU4;{kP4%)o&En;G4 zqD9pZK4(F8ak9)?eE|z9X3DEh^L)Tqj75A@_WG?2>P|+jC4~AQiu*$}G;b1p27;c3 gW}0*OVcndteInzYkbz}j`Dl@rYz;BEmR-36nwy~xcK`qY literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0313-fuse-background-wakeup.patch.sig b/pkgbuilds/linux-omarchy/0313-fuse-background-wakeup.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..e1612773de7a03661341a918debd305971d60726 GIT binary patch literal 594 zcmV-Y0WS` z)k75P)s}60_R_5v6H1qf1+X5gqC}VSkR=WH5^z3vAE!DGHA2i$*+j%1jjr7g+4JuX zf;nck;3g1=#re3wQNn2l*Q`1!RTF`Elu-?bw16aZ5c{r*d6`!Aev&;|6}Yte{baBv zrGiJTHzFz%_Z@lo{tX2Au`HslM7v2}^*;1V6Y50pDtMF7SZSD|A@ue1H&mb!gGorv zSZTILd#TY#_o<*>-TJunYq1}`pryMtKwmn#jbcnk z@4|f(@C;!wPrU~K_T8H0`l%0Hmrsp!xcy3hLq$hrzMS^a{{H}qrMT6rRHhsqv2GU^ zE?-Ts`;9<)wSo`Wr}E>~uxl79ZLo`WpKdF61F-r{eKtK+Z?|NoSPxbv g6dV=ATchFb3hfUHQ83V+h{`-(exxLWC7YK_!f@*krvLx| literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig b/pkgbuilds/linux-omarchy/0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..f46a1a472991a4580b9e007111035758315c47fa GIT binary patch literal 594 zcmV-Y0d!bl^Isp zE(_-)9#fmedC)9#1OSP~8Q25NqiUZPc3oy1aeY#EPYTQiJ7c%Jw5|v?iL`H)O)8!` zbP#=z5Nb+7h>(rj-qzdDkB_f+J=3YUMZ&4Q%}Q`0Uf(f5NmnN_3Z#n5wXi(-lOK#? z>3l(c-GzSGm9wx(Ws8!-Bv`h{D1(Ovq06)9Pcduw&x5+q4ZCJt=ZOyf_jxVt*_AX= z`>-saIWxvofXJi9IiP)G1Zarup?dHea zV=*}&V!~>Ieve~#GdC^^okx7O(Mly3LK00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=S#H@|8a35vt(ht*h16(oYf|K ztHixZ(fP?1hSoXQd=msb;j_~*ZI+VMROPl~oeR%J<*}qE7@C1~kJGifzgx;FCARVVVmDY+2oiA8yYg7t#K~%zrA6*xGtuHY z_B0lTw4&V2YyM#%EGvSH=Hl?mMNYLhC}^# zUSEXE@>ovTlXnDBD1oBQtBM!>NA$e@!tLa>f$Q z9mSy}ds$Dv8q|0R`(W#NmtbYi?`ilY@}%OoRoiU8O~Pn>^p>#lL{Jd1BSkag z#xCp9as5FRO3FQv>44XYhA4n@Gp0F7?@92@7vKK#=A&-diuq6=7FXvwBX|{}(Jg3! gMt{=wZ5W)_G=Xi{JE%jvVV+SV3VD=(AjDp9CGY7Z%m4rY literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig b/pkgbuilds/linux-omarchy/0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..b591f47302cf6fbccf98ad9aaef2bf090dc3c1e8 GIT binary patch literal 594 zcmV-Y02(vh8XX1p*n$PtMEJ5dOZMUWHmx`bvKDS*Kb>KY{||XDCFHNCmDd_PFOIQ z4(UU#JQFONG^OSm-2#MEDL zkEsD55zq+PI8vsw7;+>XAokET>hkxtAM`l=AOlz;Ku9kQ3H*d^Z9*bW-@aJ;I$`Ii zjT94q#2*jqz#q$>bGcCx$*BRiISu?sUbbAQP&T4g_w)`&j>wjZ``hSglJ>NT?`ha- z_a6n(&iOPMQr;HWJ~ZajpaZGzR`$3pH6i@9HdLdTTh=zy3B~=klXNa1x&;LgST^V} zl77YB)7yvMmb_6ojVuwt_1I0ScG$d{@86bND>UaqCE?8Q&{#BamJgZzqe-{j;t^Kd zL7pQ1oF4D2IVZX>Qn?6-hFA87m6#Hnx0MKcz;H;BY0gg=zRtOKthA<|j+|^3JA$;B zz;J$S2wMYmYaCsvv@8k8E`>eAFMQ_CP=`_gbC3ZbXPjz=|D{w(4arZ- z?nhKt1SM=RsMd3SkOR9GMJ2$R=K7U{?xNrus_q){g{wEHoOALxMFj20&oF2*C2>R4drODk%PE(d- zO!GQc#~92aC2U4S0Ifzzh79jvd(l+R%?qEP7i5~C zkO6W02S6+chlx}rF1qTPO^IAYp+}s^EdDA`Wy_(k<7Ud%PEaj#OS40Nrj^v%?)*zM z!;_TQk-K&%@Jsj2#`vV=qaNI6FCcJ1x?}-(9)*nbx5e&C?w5{{0yZ`?WK&D;IRTgT z%GY?VH$^t~q6dNM2*aDdbP8uwy2@hNk4E}UwELF|yoX@fl_VP&ihhEv;~Q4dnVT-7 z3bvMp37G6@fK=ue9nF?~NQNdm#6fH9LY9?vMZzk)ne^mlcd#|ngVNPh`w_E5vAJCO zG;6q_V}|Fr)OFSJ^DY=E^}ssXh4zQ+jCok%Q>f0sfeCdp5TRN8|BeFu0g__Cz61Dr zvbtXs>I8DS>wwDaLXPg2xZp!3JfALM5i!XPe{VQ$ISoljrWUXpJ5(5GjzwJQD3*po zc9jTaA`Tp- gD!WPETZxtFTh3(oIPOC`pd2W*22f_(YOcyQYg~~SA^-pY literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0402-psr2-early-transport-panels.patch.sig b/pkgbuilds/linux-omarchy/0402-psr2-early-transport-panels.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..1b2c03944de353798157447aa165f62787a9d18b GIT binary patch literal 594 zcmV-Y03i}EwRr&!^@N}*BnMP zWV*QfJ93-Dz^vA$^egv;0Odu>@?EEZg!ck0TSwU3dmetfrk#GkYw-@1s-GCbOz(q| zQH}LcyEqLx44tT#prH=GI#{|n6a_TUhzv>Bu1nc}s7bc^xw_>$;Q-}oD0**y5n0)_ z05)Iun%&)p?MJ;g)?t2O7?g}%kJXg|i-pEcQOQk?xPI&R+I@-t4JzEJ=iSn+{z5B8 zj?z=n2@CY{sC}GI8+NWM7&>-mv^U&MPsqLD5M)9RTTMtTIkUJyV-CFiL_8BGu7!K|Poy77*Wh;JFZI`B+ z&;4No`XOCAc#5fF?bFY+gb=<>!Vs#HE``E*fXJyaCe7WI8ET>|WJxkkM2EayaPc?g1Kd+40#J zAYB)a-P}~tNW$~{N8+l`@+DYwT;?C#BCg{G@|#-?SvjrJr^edqf`Xyrzu<}a=!_Zg gt=~h5C}fM$Cgb7V3v+iNks{pE%6AW;^EU}YTlBiI6aVTo;)zDCGMOd!AV z&e1o$bV@?IP;>6;EFco9!E(e<3iKqt$8KT#9bQ7JOx13o;NLGyHm?bYd9oY#tf?*3 zU$nxucn1M-qg%d*81;lV%aSk;&{jnQKGK5<1Rl9S6?XW}_C+%yKjw^59;N!>S^vNw z^l=xiLplgv6~eS>ng#|!OjD}W+>Xu05-3X#uxvyqH~0WWRUC|OT@{Q3t+vLwjw5QZ z&qgizyh(=KY;B(!|J}B^jN&pK*(MV)Azpvj05^SPi4s%F;G0D;3BL02yHID@t-pf& zpLO-4S*Fax4Q)~I6^iu5xKA*nOw1<)-!kA9 gG&fOgvOnb39jRd0kVg26h8e6=5cs0asw zDQSe95|&kU7skdmrAr0QyytxdavaU%IAl9|a=r@=pi~vG(4!Oh3kH0bHGM5&|0V&N+6*d_0iQUeG zoEdokN3mN?OFM;xB^C`?+(Q{l0-UV^L^YF}>7f#OcgIDD$uJQy4!(kRRUyf2n@7Qe z)bfwXG&F1boY`LmN%6i<2<+xo-2D%v1#2;0@bpl#fIEAZNG!eO;`26^WW#z0Q6$1gpJncjQ%zvzULczLh+?~%4lJ_q21uGi zx!ekZ7yOk@(;#Lyjez}B7Iv~T4Y^T~q+LtV0WA>LXRE-)Z3_=5GYW$0B&D)P56rTwn2`y$3&@k? g?#=45=K#f~8c9@3v;sS^o`tkQ1y4)o1gPdE&-=#^f&c&j literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0430-fbc.patch.sig b/pkgbuilds/linux-omarchy/0430-fbc.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..f0db1f310f62223cc9f92bdba5f9cc503334887a GIT binary patch literal 594 zcmV-Y0x5(%_av&n4dXSxqD8is) z9lH2Gd^(x@eShO-zNHKETzyxuaKFj)XB6@~KM_l9;=^#xp07M;AI+|KPml)TWLv~n>3Sy`8S~fI#O%wI) z-HwjBu?R1_O+kCws~2L7PgncyBD)$nAoXSq+q}f~4 z@SkeYdu#q7)^Ys%5r5bz-kwFlbPl5cOXC7-1rs($bIC{s+6e2gf43sBgt+l=@G1za zI$Zb8_qTE_+4kp)V&aS%?acK&=rzKD``NFxtRK3q%-S^h>F#)u{aL@ZO@L$f@Yx9W zM1+!5hn(K(w93pJGHk$-_1!j0>F3+H{O@2G{9gKTMuPMKZr8|Do>|v82rY z0g`WxyBXylU_zHEx;ebkFk!RVww<&Wr~6gJ5y(fuC3i%`!I%=R77OSm(J_+KE{W%8 z8xrRMVd$nOQg#}jX%4mH+yS;`$a{A1ZiGiiWv!_#VQ;?H!~Ur+s=eVm<)?~{ za0HuQGfb+Cb^BB*V{(c4&&Ss9esJ?`%4x$Aa+<;GjppK-yTJp}izTWZT6zjr++m>e z;Z~L`)IvOpmE(oN-Oo!RiT%$ex?C@o%}CTj^qA>g zmiWGtiwy=Z5E`8@i;~>1x3dADJ=*UgmqL0m@#FJ7{QFNb%p(CXXzyFsK$!pc{uq)l zJg)eoSIRMUq<8HzoAF1;(SUhVM?39TmgF_af1RNLuO~(oD(7KGhpi;uE>xs??(Axh z>T#Y}QnXpU1DO*P)|vHKc?j%kxe|l+@^36#S4~~h#FoLRTiPx@EV#1IU_0gzS>Qd4 zrh&L?C_(mm^Ni8-chKU8!?>Y>5v{PEoO@@sk(h|?Y40PrpeoXGpHwx_r4z2beRd1_ g_giCHw&9KXWR*^QNlAcKF*O0xp-=vDJO7ig< z+C7He8qK?S;>;*z?2C1A%A4L}MNri!9-VLS+b%a$3Xv*PyNs-7{zA|HJ#XhE9F=*_ zlATQ-*oo;sbjoIlV-YaDI8m6<$}J08KP(Fi7lN2|GrNXz_6V{51v`iCk#D*M?jX8G zjpEv@2Tz>zn9IA32w{g#`GwtB-cU{JXYAn`=vn;c-m-hNpG*kDatk}R$H=nvMfor` zPd5kHePpV{xE{^PW2l@n>TDf-o&|!O;B7)P7;>w5c<=sGXTUS-x7Y_Z=TgJDQ=HPO z28$7R8Lj}5trpE{1Ct=e1Z<7Xt#)1rHQ4b=HVS0$wix6KOl*+Lsh{|n{dUD*)R#txJRWn;4I{(`XYI(gORx@|B7Wa&%6{Cb+ubNeJkiq((lQJbm g&u8(xraIQ#`l$Fic3)H8FoWk2Ksz$p-UVlVd9NBEssI20 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0451-amd-vtem-tmds-links.patch.sig b/pkgbuilds/linux-omarchy/0451-amd-vtem-tmds-links.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7077a0e08a71e178e66bc32c85360952027acac1 GIT binary patch literal 594 zcmV-Y0lR|HH}ChfZYJ_C<}NS@JH$JVxGvdp#asJdEZ8%Z z!brp~-f(tMEZts`*fCEa*W_cyFv8XZN|rK@DNr&dfjU0!ydSY*WXmErXsmqYvy39~ zQE3EaNd~#y{V5v!EyQqdzkV*c)b6U_ha8tl!LB?YT%W$yhAg+|rRU~fjH?8wZz=ha z7%li(MR3)hd1K%4q1Us0$nv5${U#ue^O6rpMU!KRqA>6N*%njbBw~z5S zS>WE9nqtfU2}rB03PEk}`$e9IEHAyM70BB7re>XIjC&$u$onjDL^+@KmB39>T%SwwB_DyX)6a9WN&YW?)D72b gItSiK<>dRHX_ROMT6tr?w0zM-XM5nb1ey|d}t4&q`u!UUih}s z1CTBB8&dTX(kVR!U7~e8rd{*g+Qvh;p)e>@%lWCj++*dS)Ap=ve4)!DIo^U`6%z%2 zn2aEg(A*3h@FS)?vG-DRePO38Yw-kTuWqUC#79VQgTBICIl6hHw*UtJa)Ap|ROpvW zIG`4~UuX0>Kd7vf%Q>(zBsPz0)EI3J11=};xN)uA8X(*hNy2++?c^F`x6&d1I`Q-k zS8eQVVIM~`Ic?Yc#W3`@--#+RhMYr!4Ozh4*FX`ZI4bWq7C&h9{;wu`x|bIZ!CKrY zl>Xv!l7x(k1$$mc#Mh5wA1uC-UNCQXs6~;Pg?joKZsHX631nLG8!%DvN*+`Xh|=ES z3vj=pKeDalLS__QaE)o87K`_ex9Ni43N{9vcG~Ctcz1nJF~Ms}$5hK`pQgC!f8&&R z6MJGX1XI6qsO#SZu$VQ3UHideCMv080@{v7HGm@eD!RE4ex|6Z03(jR&oA^j#*&ASXC^I0CVuNM!DlDb4Rs5_e%!+wb8<%VUUOEI^iTgngK^FF;Tl+ zbcnv_I`&|X&r=DA;+nVySeh29qTv5| zbw9)ztY7#>IN|@Gj}W;X-g;)tg$`_qad>ZsFden4H=yG@U?;)LD^hN@2; zOetKUM`l=sXEa9>JqgVJU@>;0b(^4&_=kW&^}M1 zw-T?;_7N7KB&RWc`$4o^=GFryMbw6`BdqPFf5nS*y;D~q&rx|5iLC&vK-qicudVb< zn6{vf+C?v7@os@HF36faSnD`4xMlMSJYI}zKm!@sjbaP&THYof8O{zNZJmQ{D9ExH ge_mH`blN79G-d=TdZgcwrY56~X+VM!u*P51d2GZFyZ`_I literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0461-vesa-dsc-passthru-mode-match-fix.patch.sig b/pkgbuilds/linux-omarchy/0461-vesa-dsc-passthru-mode-match-fix.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d303e5299fc0e45e293feb9de1e2ef2b3aeb39fe GIT binary patch literal 594 zcmV-Y0TvLP!nz{trgiJaSXZQ}PufXrJWK~$qKzX}4!uZoXY=|R<> z(p;%sfzn+TG|;@sCI5|e%yQ#U6L_@2)qpio(0|x7l*J?GJ~K9IvX$__ooJQgq2TNa z22!neKa@S;#JjY_a%UgPI6cKQ1}S-kIv^N8{i+Kt^|vOpHfxvGm3Ux*4h}{) zisW7=oGHe^knYFPslx#3vkJxc2^-1VY2-2atm#O(IZa}Ad#&kOEko$TgYtjkk?A#VCX1eN)G$;+i+T#UM2brx zcLzM76&YkLq}n!-^vUwrP1 z)(Xh=24E#*jEK}JRwz8z%Y-uCDa@&d<>yhi@TomYK}s_N{AEi9mrT+(Q!cpw(4z3= zrPsP|kNIv+m9X^+RpdEW`N>OH+@itZZ}R@i7BZvljz-3A*$8WVPXgmf%K}NWS&b#K zh#krds1|D};?`WZu-?WSx0(iJgt4Y&TwaDHlLb2y5D3ZlD@BZ!vB=F3bu zJJLq`1wN##Y+T3iJwS{Fw$E#UpHG$PGF2Ei`+=Mv8vD1eD>P2E1-$gX8JWozj24l;0(GI6^5ye5_BSmDQEfue}ogKr1vlU-4v;yr~Eat^nL>a=)4*_Hrjvg27!FnO}NpsSLGOYSb6gULZi($8o= zsX!VqsvvLs=frQZ4>T$qjnNXV_R8V>A77T?Qp?Pq0MlgvS!Z2YI%S=|qde@+v zFN-XXKLkx%M)|Y#(tfjJ5SU35D~c9S)|5rLu4wgNpNH8la3bV8h)()|K}!qZt|szwFXF~q<^R4t`+XYsu8Ou)&sQ>@~ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0474-amd-display-oled-vesa-backlight.patch.sig b/pkgbuilds/linux-omarchy/0474-amd-display-oled-vesa-backlight.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..14aa526cd24e76236d50893ead02f137cbbde1fd GIT binary patch literal 594 zcmV-Y0Fscx(mbL@Ix34W-Rb(i}Z7f6ypBFS>i7I=q&Oity#rQIB%?$$BCe)H zrrnjBfAj0nIxs8|;F#RjI^p5`zCiuOO5C-vU%U{#0YEiWB&)o{*~NGZHx9zCQ=E^) zAz9Xn)5{w~@RN(oe}MTPAT zn2wIjZSp5#rwzZ0?o18U=YW(rKO?SpEqt8BX}k`RRE7;Q4?`%PzWuMCY8wMC{ZtGn zCSg)UP3`8#1FQzh`Xx&QdmoHD6hytd6+Rmp0bB7}G1Lernq8L|?FHuoq9=ERFzzzy zsWfO+>7iP6$X9$~V;#xC86>pJKG{wTE7oTLzhZ|wlUkRFQ<%=P58!{TKQ8ZJo-w9X z+wH~KpbL{`jt%l}@SlA+N9*eH|M;sc%JW1$)lftWz+Vfd3EexH&7DE4h+yM%2KUXA go&h%btxj|QCU^?*twvQIY2Z>Sy_(FyOThl-OdMh!ZvX%Q literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig b/pkgbuilds/linux-omarchy/0475-revert-drm-i915-dp-as-sdp-vrr-or-pr.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..3ddfad0a331d357f85eb04d5b5620e507cb27330 GIT binary patch literal 594 zcmV-Y0;S|8XATGaY^P);}-nEx)o| z7vB}P)Jf1W>XF&+(h{HdUAeIs;lLnH`}ujB8U+xlBn4DxJX^}g#^1p#8s$d>iBSA} ze>~As6(u1PDhfLqu@K$@{-*cwiha`E>j&?cbeC~4yH*(ZTz2|7iGAzh4vRhZ`JTPL zb-cD|l!||0M@B$p%sgZJ{`FkF;s9=Y?FMklr9HKD9#L0YfoK~z{7^X%n?q~=Nw>jJ zfpvpEizC@C3f}8B|Fc?^)|#S(&B%(&P-$!7$!pGK4a3$6Q3E!d9VdEFB9`>_G~5xu zzB*-eQxB!Ka89kc;EI(&8FqO&{<2V*#`3BV^7xqJNUX5T#ybc|v-6`|lpE*!;U&<@ zO;mv-8BmSCT2pr_Fa*>fmv#o{8Cf2DKQI4U+3c_z7)Hf@P0VHTgi+Ga6JDp7_mE~E zvDXVNcv(4i3dZ$0!$$AKUL~g+^2u>Sv4A6W%jKb*rZsn?zPG>DoB);7Op((-FcZ_tZasmMgmxB@kgmmfL4K=}*VBE@IR8xiIgd^k)aD_qT(d9jSxh z$tDg1KDasyCg$YuXSNRi6(~B|D-jQq&~Qj2zWYy!j1dP@gk%fo$WTU3o^}_MNe+0j gcVQ)K4ouwvY)699tu&9VcKTp6A(zkI_k*L3>+q%+761SM literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0510-sound-updates.patch.sig b/pkgbuilds/linux-omarchy/0510-sound-updates.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..cfb31fcb8ad262b99923737370a3f061d7c7cec0 GIT binary patch literal 594 zcmV-Y0}BXqso|Go_xA$xM9H_$Z>Zosk!H0z^z#w zM5da(cjU@$$iwn;lpI&=6y7Jgs|c&Nop4Hb`#sfE9vTz1mY*KqD{^XqnBxDo^n-!-)fS`(sFo`FTp+XeTEZfSjN zO2q%SkBF)Ly@wwVTKOF1xXfu9SfSO@gDW0r9I%PD?78XV*vLej+I+l#nY1~g!al-f zCQQsZ&{$$&Qv!Ei=u;rDL-OaW^&F&zWB(2eI!$tJ9fshNhQ*I3i$54)MXn_&c515H z0uH=`v2I-HG?vEUw+K>f%vVcvW06&xkn*AR`3-LyBNs>eleH%%-E%GlVbX^@qR{`i gD7jIs_xC%3HvocR;LN1J4>{uHQ!lmPCd!>+tZ^<7TTbefXSo?n1P}`@&`P?1hz;w`jC;9dNaY^ z3%pZ3@SI9ClthKS(otq0NUcDul%cU%3PdCzJJlcGTJY8(=eQxwgOXgNa8DoEk zdp$Ct=y+$4Yk2N7GkeWA*FUtJkM_>mbz+fZHtou_7T!zt#!+|4-Q_smEdg2yA6Ia3 z?1_#%2%wX&$^Wot^E=F7QN)=YXo6n6+`YI+34b5^1V;4UNz5PctNbry#uOB-I!0^M zAHT^_g{oGW!T4tUmn53(M2gd0?f@)toQF8sS?nea^czSuAR-HZfV>wr!fKkmk&g-S zKGmsO(P^Jo5)+mNTRTD>W2{E(do)Y_cqrq|a&u0{&Asi&6ElqQ__{czldIfA{F`^8 gCI40u&Ysy~#d=q=EiJCa0Vk*F0JI?1_J%#rNvxd}%m4rY literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0512-sound-fixes.patch.sig b/pkgbuilds/linux-omarchy/0512-sound-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..c02c1df77237c139dcb0b141236fe6be8a62de92 GIT binary patch literal 594 zcmV-Y0C>*3M6v2f*{?0ZA+^?~IFR@jT zFD9B{A?m}^ZLcyz6#>uwtSgx0xOtU$=Za@Lqwj|m_fHf2o_`QsK~qdbB=Sie?}n<4 zrjf?uMZx52=w?`>y#UIs)YBxemga@T3+}*^0lT?Qm<0sve$#* z5ikIoQZM|QJh_KT*~OHCON$u-*Qig#yj%@VofOjDT_{uByn3+5Y*?YVi=o!&K!F?T zB=gwMMF`>>)DO8mV`&d>G-*U<9e-y?ql9lPJY_)IqDJ6aVHE6?^==e~j>P;*^$VrB zO8ug^y8I>3EwV-BD-jljt8U)++{d2fh`qe_Ou4i(B)aOzcSM>(t)1At#tyE~?vB?) z+2(GB6gpufMNC}(h$AP1G}v;;L17SV3vU2^T5;?C1|vH&M`Yr#+NGQdstI!wFZ6qK z7XFov2vGq*7(iQ_^}%`+5ID8}^w=ynoM>!EO5K^w8^jIHYjtmnFJ)Mwby>YTZ*ksZ gAp(uuy|O1rjqUcq*>y@et26-X1pHAO`3{s2=M#MzQ2+n{ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0513-xps13-sof-quirk.patch.sig b/pkgbuilds/linux-omarchy/0513-xps13-sof-quirk.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..1ccaf57e763ea9a077559c29f489db036e0cad01 GIT binary patch literal 594 zcmV-Y00 z2V|IC|1VOttskQo>iIGY*74DR8iMp4Nm0#o+{TE|^ac};L*Dz^{vLpQqcDk#tZH*(x&2-N#NK`wcJ|0yVmw#c(=#Lt2PqwFYI`1>YSp3m}r(UIP z3P8qi9C*T(0#Kx1YdY<25%QHVuG1{hJ6a^j*q>*$lVcN=!DD3=9~PpYOv`c%_J&&a z^sb(?uxFxH!)xS!^0qiG&Cbdp%fip;w1Hjw;0Z+xovs*q0*1$i(7$XIRy*?sJx@IN z^J7zOcY4}r1V8U`J%KNqSwK*Ki&ID;(huAKSHO7Hc#d&)iut2EJQl*EOpUEH9VEU`3>cbt{~iH9{0TfX8L#hZiLXYnCtQP9g)LSD*(zVx7$67M-!1Pp7PC$=k+(2U zK+YXmuzO~>()Iw+|6skLM$S=aLWIVvnQGW$wmg@}0W<*Q>VauBlh0K==yi6j1>=hP zM|ol1cD35|N*Acv#rh^zZ^80)&h70zP2qiGMCjO_E}|SC8|8Okq!j&sl|^tzy?1JW z+yS)E0@CY@z_tcq8U3;s13NDwP&UE?)tW^_P-Cf;+;(swSuTL8uR7UZ{T0faYT2Ih gcne!A-`bh+VRMDNMPOHPLEdUQq2x^QNM%!LaSk=~=VCdQ=2aRM*&*g(8L)x^onApGL%NYeo6`j<_& zgvfT5o}6-TVk|OB%MiV&L#Z z%-O(S$ALM9xeuqKvX8)W>wk#r4|Cc{!ujEaz$Th)?J;fQM2XTMlDSBzn5A7cx9*jJ!&yks~QqLAMo%jD)vy1c|s`UzMK-FMB82BHS?c>o;k6LjN*0#1tU^l=Hul9=ieTB?86!K!*&%4)^Cnx z_NJN$V97E{iEF?S0cKuNFF`}s3g;i73 gB|P&KH`<05u#7zBYj$>R2F9+%%?Qi!Tp1yh>;e@Yw*UYD literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig b/pkgbuilds/linux-omarchy/0516-hda-realtek-rog-strix-g733zw-speakers.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..0cfe941d936844dc219afb20251867f06e7a882a GIT binary patch literal 594 zcmV-Y0dBtz z?&8^qjD9qt<~M$)!Ad4vNIC|bkNPwwE>_Ts8c#h|FFDpCY;CX^`>kKJ@6Z;MLMNfO zdmdF5E7fzgM##!pXT56vz7#WC)(L;6dB(@q(R;cn_`E3&)BDL}`AsmtzFa^!oJ*Dh g^;9?91OQs{QEh;MqQgP&>RlL%o{?`YHI;eikd~MqRR910 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0517-asoc-amd-yc-acer-aspire-a314-23p.patch.sig b/pkgbuilds/linux-omarchy/0517-asoc-amd-yc-acer-aspire-a314-23p.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..62063af0744a884333808ccf63ceba7af7d7ec75 GIT binary patch literal 594 zcmV-Y0Zr~ASM<%#rT2bbZ~7r>GCKnS zIDLyq)0B?m&gGfhC?FhZsDc4+{GYvKSmuK}% zyoEDyhTC8$2-z&ramGBSKfE%(%fy8lfv;k?@SK|VZfrl|rfkJB#lVE*CA9_5ti$z` zyc|RXo58W-yMr>Wp;e-<%BOK!SeS)ndrAajf775SsD@s*?s0^bkM$ddX&It$;=#Q|I z7xDGW=T8b+jqcOcBKC7!J6GWML0E*kzBp{}Ise6@JWX`ZtrRrL5AC$XJZkiPBO3Qq g%1N)X){T({0 z?arn!fm6&wm8iImcB=6AP6khLU#}Soc+Y*6+``FM5*UF51O~y2DM(tCtfERowkUcv zJ-qSx3?sZDCYrX<6ZkkB0YTZ}{g90Tvp+kCI@M(HO}LB zlWOC}N=E+HST$qefAgD5AKi8#KzStZ(O#>N4W_W7R0eW<89*QA2NwLq?N7L{RhaUk zQcXe>qdBKyV?}EjP7uW8fH9NYzJ3b8o93< zeIRUrW0Zfl_We8*X?#O{)_oo zC>OxOas5mHQ+1bx)LLQTMDr#FT|{xBCjrY-!B2%}jwIxGU)9nXjTUQra+ci>@Y@Ufm&u(b_eh+s(UYur^_R literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0541-cvs-nova-lake-acpi-id.patch.sig b/pkgbuilds/linux-omarchy/0541-cvs-nova-lake-acpi-id.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..6ea6cfabbc81e08d97ecfb7eb124a08b279c7ef3 GIT binary patch literal 594 zcmV-Y0 zqb!F6aal~L0g#dy5Y`ePDtLM(pWHGuZ`?h20y6)zKdgXJif=-DBCA~6%T;a z7T(@J?@oejL(D>e-Mt7c-ive+N8vMm|kKxplLl-Arl4mOdU4k!)QsAMx=nZkQ?uHEUcOdp8Z+nXE;QZK{ zNw17~1}{GP)<%o6eYL=?r?>Q{m`r4Jl#$(zG>Ly5Z(zB2tI~aq^X&dsT6Vuf*%^3n zrTRFxxZkqQ`9TjPM7a?Y(0c8+8+^uq7+AS@b045YfW3K}hP?Iak)#0z$A$|7hZyf7 zPRg*35|xy{gpVO8D+Kx_KfDTv_Ik$?)^Ye2na_=lRXSq6%qEm3ABtgdP6nF=^I&Cv z5E)F>$v!TyxN2XB`g3dQs6>Y8MwLbG@Kr*{m1;HeLI(F1#U5c;NQO^msZJ0RR91 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0542-media-cvs-wake-irq-without-claiming-gpio.patch.sig b/pkgbuilds/linux-omarchy/0542-media-cvs-wake-irq-without-claiming-gpio.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..69eeeeae97d7c42d1c5458a501381885bd099862 GIT binary patch literal 594 zcmV-Y09?zW$rQy5x{rl*ld$&bok>8$C^px94*8B_wp5BN$#1 zQrtli)hrMEBu4Bz;8(mSx(x5$nXE)gv2>yR&nlwaIna+x`cU&2Jh{q9q7gUZV_BH< zQvwZarQ^vV&KU%Qq)aZP$R}cN>V3ljs=O<#iJa^Ochnr?kS)?$Pr6}cZ^~=U2l^i_ zi?%m7N2yJL)Fb3}NZ9qsRuaz?^0b-)ZqG*e?3TDknIuhFlw7;;w&vyyM{-4&_3;DkqbD0Z z=i_&&;ey}f;%uSb3_uz7LUeQOk)Zx8wh6!-098*gVgUH~mVg!zJt%mSpU$Cq6%)Yo g#I5sL+`l7zR4jZQrhc!kFtp7%4+)x+kM&H2Mr5J!YPn^Q%=8zr?dk z0!6F#)^C(C;f%vR zM@Yi|jZ&)14m$TcpwJnk3K_bSK+iUb$KYl?axa&PNxkRLO4N?IXX6YYwWZyj)i-Ax zcMXndH_;*po5WyyGcI?@|IN=@gRy>$j60twX-W+=N6m|!D2Xw55ApcT)fzVgp+iw_ zIHrtKdvF*EbY?o)ipsPid(epdnx1^v3N*bxWn9h2v0fY*_zf~7!olf{f>Jx+=bGmMM8ES>;M1& literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0565-i2c-asue140d-touchpad-100khz.patch.sig b/pkgbuilds/linux-omarchy/0565-i2c-asue140d-touchpad-100khz.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d5acafd04e22cc6ad6e754e55ed0edebad70e883 GIT binary patch literal 594 zcmV-Y0-M-HLBBlIa$lF(LuG4Q6YN)MtZw=hT6&{PvF4l`D7U|GadO@UAxiiyTHw(${;*QMkT3%Y=FYl)W zWRgJl9-$ADjbA;J5H)*rOmE4~_jeWg%P!Bl!U3P`6Z2S%*P%vz#!bUw9;hi{-;YU` z?czu4(5nqx0!mA7@ut*x?brlTTPwt$jqlraKlM48^qpi5B^#XLjL*<#?P1lV!848q!K*hcZ|t1pcB{pRdz+a28;q1 gke>XD=iXPr+14l})TU;DhiOwBpey+%FLsg6@j@aO@&Et; literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0566-hid-asus-no-keyboard-init-reports-to-touchpads.patch.sig b/pkgbuilds/linux-omarchy/0566-hid-asus-no-keyboard-init-reports-to-touchpads.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..dbe7b904b6887ad70205cb67347f719f82e8fa2d GIT binary patch literal 594 zcmV-Y0rYMr3VeA;dF+gH3{hr=S&wy|TYM0vb#LCcicO>&4E zMD(`6A@yNfwp4nl?=PQE?DlbP#V*v`9q)pTSuqY78WptQz=x}4@ryP7-%0;s7o5Z5 z`&btyJrz)Rs81rZn^Rp8IY0RlEf;Q!F+a$(VzwA{;hJC0z^3* z$6zTc#kovO%plS*T~%6NUn($hOq7y{{ANNXp^P~{DZ6U7xKt}e;c==N%_Y}n8jIHy zEp8xfD{(gbqY&<^REBQ_m=7voY{%LBOaj7IMQfGZiru*+DjgNm9qmTMXYc{2&Qb`k z+tm&~oFnoD!xzSq7%$PTkHAAYto0@^Q(~=`QX^uA*{bt1Fq}+`!@4g~G!I g`M#bnrY|+2*x0<@DO2>^qFj5E(@4Vi8>+)wb?`A5L;wH) literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0600-usb4stream-fixes.patch.sig b/pkgbuilds/linux-omarchy/0600-usb4stream-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..753b73528dcf9fc477c8ca2704cf2ca445f2181c GIT binary patch literal 594 zcmV-Y0SvWfT3g-a#hFKJq!`U-tdlIXL~ zsJ$p@hj56Va*+#>M&a^txSR?noOzumXufGO=Y7S}>=zCmFw-1Id;c{HnZoCt>NCBD zG{*`nL4CCh!7dr>W!&@>BzG%87T!b&;7tsdVt|!q5y*GF94b&CXIveI80|=jpB5FG zL(mOKj-V#it8aXO3txslD)reroj08vjiAiWGHXda0_QEM@q|8}WN%NQ9{iwjG!yjq zT~@jxL;AqS=B@2(5q7%nEt01Lcy%~SK%oDU;9kL+0=w>^UTM}$fe{nMEglPHWrdCE z$erOX>CoTTb%*$%BA`*je61=}G8^KM?G*$bAenv_2`O}-q1B1XI+Y~0OOv=cwER4m zC=5p^XuDDt=!*pE&CJ2CbBs zRgnDakr=%^;gEYh$Zf6YW37}lrRr+&Tf5hycnI!K24H~vod;&X!a}Z&*HohCIcXR{ ziHb&cx-_M-<7WKpWDi|<+!;%IGnu_-(KKqrM+DxTQ{-Ne>B@Te9$gg|$aQd&$!YfF gd9I^SbTnDhW*jpTI(U$_MAltd*9qPB~T1|`@ z^Rnf5`W&&mc<%|~i6W+9mHL0F>6H0ytN9xh0E&4DoR^&6&@Z$F`tsF-MIfCu980N> zuT-X)+A&gkj7>}$l|7+frERfv%i?v>#OJnh%yt7{u>=pF-|1uZx}c}A2m@ZMetu*r zcRAgcMZ@1DR&izA?wwONXSch@Uk5N?$Q%%`sy5Pe;lbY>?GLp$u4sS-t zld%u1H9`Xru@h0}lI_M|xva`i+CmP5TMxS<%lW@sIM3UonJ7kb8d^5M zl=2o578qOn z>OiyV{cMg3&eG9PgR+2KMBMJ-!0$b-D?UZLg5Ia3)egDRZloh{(JyS%RdA6%wqoh@ zlE2OxuRIi`*bx9@%+!PhRJ{i_0?8WAxTL-}bNC(rHwBt|M*Mc)RBE@bMRbLGwiPjx zKpr|Z48#bsa(7``h3I?TD18}@pU|Py7>4|$bt_GLrHgdkVQ%6#vEg2ZpJ2T_)b=#i zoUwLHhE=_lva)7vOG=I`IhWIxjx;E$J=1q%wt$@YWPyk+Tdup{%A+4}Mn=an`t!6a zT0_Jkkkb58h?lQN$<9faHt^f>*yDnJ+sVlklP$;Dzx#|++@Jh{b-3xCn^aMdooL7Q zx3I%atW^}-9;P~x+zAKTU$VM2CD3eMLp!^lDeesK2`LiW(G(zmv`^~FrmZKRGnx>A zOHNY(G>~aBqe={;C3CfoFVUw1%slMKlA9ZZ}a`*ze`T(MyiiOZ_p2)VZ45{ z_ZHP3Fm|l#K6==c_PtEXHH2LG9kB6zfM!3K&4dM_^;HQ8)KpzhNH%E%^Bw^oVx<@H gmZfEf_I1OiCyQ@bg7oOs` zV%M!zEm*_ZVWVPly?;(e7k&ec(#UZarVs!6YW`$|a>i+HUq1m=SdKJ zIR;g{Ib5Wh5rv*L^%ScuyBKqPjXET_8c#fQlsyCSi9ZZ=cHjM*nnr6Kmbmq$+iAyW z&29B-?nkw);K8Ez>8BR!jVw#bLQ4qB=rhm(RMp7w)TU<;K`7RneKTYdpAB#_BWAxD zbC%sj0l#oejP$iaxjS|lFY+f$oFD?PzmYfQ7;B^MwU)7BrH z(AeAz*WyS5A3jS^UAZ!QS=|Dl1EaP4_*ulC=$MZOEVCDfg@aBODasDmJ{Ul`)pb22Mb{^xe2yD(cuZF+KBP%Ta+DEIr}e(0Kkfabi`Py@;ON zRSp^jQRE^WBJRkxQscSAR|+$g(u-oKEVyHVxrJ0f&MtI)+i0jK3Xiaqu!|gc^fdJT zMEOHXDJyTlsiG~L(55ARG6|jvWRxcp<@>Tw@7NXHQC}=}L}d7;>ND?~%wp{pTkZ=&tQ+Rsua}7Aw(g z9c!CwY`D$h9$8zl!1#E`LSD)jn$$m%!SO3a4NPbYUnnNt*<$cKpJE4k4#WO3QhBe8 g7b79i0ns!g!SM7Qk+|vLjh#UK0n;V7G8-V-eDHV})c^nh literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig b/pkgbuilds/linux-omarchy/0660-btusb-mediatek-mt7922-13d3-3625.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..ade8cc2ac302d687bb89a6b16cff3d0cb22cee19 GIT binary patch literal 594 zcmV-Y0H`!qHA)>J<~|Ak+G|T2f@2bm~hu}~$) z!HH$RC?^}Q)d3v#J?F1-=&a)p*MYXrv@PK@3>$ZTWyTX`Rl1;aM~Joc6mae)B5q;! zrj$V5g&9Lpy7$uA9iuRUnuKc-F_33Hf!DG1X?(O-k!QBk6}Fv`iC|*XVq$8mjP7I* zs{~&q5+H##&z?P0Vf5^}bKzoH+rhSWKQ{uIQdZ1C6t|36l%`%gx`)F+cKP2}L)qH< zm+pigrOnIq-85E$DT?E&`~F-8xMG$9U+dw~X+U4@5+BrFixrs0%q03j^yy&Ja9}rh zJ-Lrjz_<2j(csRdj?fVLT~>(+I5#srL>1W0<;c2)fMhsM<(u9exwM|wB!OZEgvx-V z%_OR61A^GEd4e0gtvKCeOff;Bj0PGEvau_LEgYbz4R6BNW3l%=%s;wLk?rl23$$k3 zF!+rUU9OnHxo6AyA!HDne;4mf^C3Q7diK;9xPpts8F)6jsBj}+%1c=BK zlu|lL@|l?;mBx>r<^YcJIj|9AVt1#Rz<|l45EIB`aNNONsopp>Bx1DUY{Ve#F1}uU zs2qQ_4h53nDoG1}0yF8?5T)V_x*Ki;epp_*a7TZ9=Up02o^D7)>q$}fPY|qRIan1J;k8x5bS%|F3n5gnXtF5yN_AP+gdeS3_oCVr)9>Gd8 zFXCbI&S`e9zh%o}8red^mP8~z0;Ub<3Xobp^!t9_=D5eRvVy24e_y~}>K~5FlU6u; z(6RUr*2DOY6^6b*OGDDsJ2qDcM!QEaRry1MZ{+|j5>6_)-PVnB#wD@^Ys7ARCL^C89&Hw-a literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0662-iwlwifi-mld-skip-tx-when-firmware-dead.patch.sig b/pkgbuilds/linux-omarchy/0662-iwlwifi-mld-skip-tx-when-firmware-dead.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..f2bc1c6f85074dea8ac690ac580e013aaa8694fb GIT binary patch literal 594 zcmV-Y0f>%S_1-hRqX&WUq1-ZMpb^XO`{ap*E3P}{n_118ouI) zn^&$Fw-~z`hN|U371;`!*5V7RBjqOfpSztwX$s}DLZZA6-J% zao9XL9Qg@X5TWdwo}ZFkpGmFjaytbZ>}=z3Xq16U>=$ZP)vM_lZ1JU-_3KAUfOzZs z)7&l_@doFvp(?_Ue)R(>zV-J#D|)tK7gI;|trz6YAoR{{{}HLbHs7eY8%V#;LsSJspMsWkP@)&f^UA&nW*wlS{Z~6oYz&fEZbum(b#Ec8 zsIp0wUsB_mFLy3O=xI`E)`q9;^5Q00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=a}LT{Tb@%%y*R0dWV!(kYe&M z7bK9hVjJHRzN;+SoZ(q3|5ERVV@iGo&pbE{I2MKcG%QkxTTZDB{cwrLK!%Z6R05SEx zI zc>jGXfPsA8g;C972%m7vOYpuv4UrmOj&(9TRS4GnGbK$)ZGw4`Eo%Bv(t*4@AggQt zo(`rXVXcGU%0wjbh}ZuV>`y#lTiffck`^rXvdR83-_rv=s_v^UH&~=`IKrdNP)nzr z#RW)-NzWCMwmWBtqf&ZCr>4>jnq}K)yUt3* zu!+wBMa>)`!bf|0fhSFr_odhugv=-yZ`_I literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0750-applesmc-cache-race.patch.sig b/pkgbuilds/linux-omarchy/0750-applesmc-cache-race.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d3799b15ef7c026e5dae1b85b25619e6c67f57b5 GIT binary patch literal 594 zcmV-Y0&A72b@IK2p(nZ z|5*vDWnU{ks$tEpWlOFH*OPiLpjFO9sQZOQ1J7+ljIYLO=NijL_DvgSMf z)dV4@<3?K${+kveIku~f2Ai!yM{d~IaLrL`B zI7E0^f$Ilju|r%cS3-9OqXL^fsT~1to1%7lddHbZq@4R|6K|o5tbL?mMQ#{-g%8oL zGI!(JNay;<%_cHL6S*vn<*~BjjcX^45L*Mf-EV3#29P|9c%pMT4b5F|gm_pwFc!q} z(VVJ|nMSkM3nz0xv(6~|v%Eh10?9IDLj1H#2rgdE2NIXK;(h_Bm)TjeS3c7gkuWdUF26`-1S z@B1{qK7r@hE<0aaW6f_q9?;NswBqtRc&FOjiS(~|;^2?Kgyc8jf^tYu#tPKG7U1XI g(Yh@vnh&3spZdX5<#6esvD$uc7BLyRs|6e)owc7B^#A|> literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0751-applesmc-key-backlight-workqueue-leak.patch.sig b/pkgbuilds/linux-omarchy/0751-applesmc-key-backlight-workqueue-leak.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..f0da51230cfe523a354a28d161f07bd7147d252d GIT binary patch literal 594 zcmV-Y0H=c31+gh0CTUX9 zPJX13u$G+>Ja;ZNBmtd#ctF~W3+IGwaFP-)O4zZvvRXzy7enf?433hSk8wTR##GC{ zXOA<*obMt+NTlK!J)K{2t4R?2;PbSqNR~#uHh+^O#Dt&o%C{TIAOtfAb>T`<7_SzS zEP=KPT7#j7vM#<5VZMY~qF)O)A!kPMOlUAl4+CtF7*OVX)vDZWcy-O99vFd7^guDl z{FT8IjtU>Vfb{(*u_&qd(S)732+zXOuHho+1-;7rR ztxbnIFin;+r$T?vs&W~5+!yp-kd;-1yID%+1AqCheUM(Z%sBg``f1DPhYhlN-|SE|5i(BItWULr;V g=TG_CCe4{;kk>p(IS~&WC(nUJz21!;&foEOmWkX8SO5S3 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig b/pkgbuilds/linux-omarchy/0770-acpi-pm-acer-swift3-sf314-56g-power-resource.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..8744164ac3a4d90610b19b46f85c3a5bc00cda88 GIT binary patch literal 594 zcmV-Y0ox9x6Eg?(6uhdi<11!X(M^}!(cvhIb=wosq3<7tWj_u2v;0oG0 zI)bvGnH=Hb8m;Rm>{cB6y(g>ECW4vtwy;VoXXtrjFhXa_ujr-J{)#p}DM2E2_1X`b zKj$N&_&!M`5207L(ORLp2%I$F0a~cDX2KohLC!fasE9fmx(Bm8hTVV3W1Pg;ktfw>K?=hcP?|mWE7R}J%>GEQRF}^mp-~rEK4)M0fH+est>N4wDRV6IdBio%8 z?Dz{q$g zcSJvg$(aJU0%0v$$kB}-G&z72v8Tc19%Fq2X-K@bjILVR)-TxBUe(e^1bwmfK(`$u z;*<*#42^D=T)A{Direpfg-Bv%Q+J2xWa=aNR1R~*FWFG)Ua2cMasv9*2RdyF;l_-{ z3oRWxRe$s&iJvwQu3=M7B{noJ(uZn{P6Ag?Sn!L<%IH{Ido*lA2*W6B`-Ib|&UOzu gxY%}?=-wJ~lQ=E(cZ99`LfgSE;~A8JbhJ$K>MBMTu>b%7 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0800-platform-updates.patch.sig b/pkgbuilds/linux-omarchy/0800-platform-updates.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..1afc8bb4a55df0c0baa1219760b1fbd1c8b86a71 GIT binary patch literal 594 zcmV-Y0fc{IknN}H(cH!8o59fHs% zOf`P<-SqhAct)?vVB#C1bm2KJ`M~!0PH|6kf2I8qKWpbiT)a+?$=0xJG+&JY$$7l@0 zs%oDkfA*E$sIgG3gZ;bN^B<-P$3AEFHL=Uby-j?CY}rp8VtWNI9$uO$BbCQ?=J~ko gnG~CaEivq)sErppcULF336~&W-!D?IPZ`G9EiJAbVE_OC literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0801-amd-pmf-util-unbind-use-after-free.patch.sig b/pkgbuilds/linux-omarchy/0801-amd-pmf-util-unbind-use-after-free.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..6bc45ffb7a97b2dcbf0e57527c8e21121903ac33 GIT binary patch literal 594 zcmV-Y0BYI{rc}F z$#0sUD*U&t&W%dTT2m=!x)(Qi0!hB^o76Zw|3=7_u0S?(DwBO}l;YSnsCY>ORkeyW zSl%*)73SPln!ek#@3b`;G_no!(V3DbnU6vxJYuX!&Y3ToQ)YR2om355@@M+VnJnqm zCAI)nh9u%;*~5YG+|d2L1KE=JfILDhBW2Yt7Gm>rH95b|D0yaUv$fzP7IYKIY2oBQ z2?2LT;kkuIjTh0JkvghMwQ@Llw7r*?C(qaJHd9ydM!ebpzlWYv-PBjGS&aa|LtQgY6tB|AD@(Sy zNYX($ycelcciImh7z~apRm&Qc2q|VTI=FEqjtoUPV=cZ(LIYbX`^J0T9zgWwz*H_r z#b7%+0uj-;wIg|uO67R$5@8OECGK$skf{UT7qDb`Ig)nFcDjVp3VExjlw6b$wEHes go!=}-A^~_&l!&+4Tqq5>9`s{yg9Fck7;0C)Fw2G$3jhEB literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0850-futex-wait-multiple.patch.sig b/pkgbuilds/linux-omarchy/0850-futex-wait-multiple.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..c9e1f4ed1b8a6e4b269c96b432ba932588f2af0e GIT binary patch literal 594 zcmV-Y0d3g)id+HbK;;DY2|+jzAr!^^7W<2F(u4&ycD3Ajb6Wg{EvV{k0_OSTMFYv zV`C!EcMv}4`eZ^c$U0ya|N1m&-M_+bB@9FF4?Y2$iU!xPP)9Z!B$l@4amn$+*$&`| zOLigSP4;k&TT%BfLs}Zn)+uCaGocKQ$h`~}W z@);rL7yzx+6oh?-&GawsWI46%FwS7ND`X6308csXF@A_bGS!KMvC%R}xA-X0*82et%? zA8|qA?7$*eGt2V3m$+U;(ylbMlMdm6%^mT#^@+qK}cKIbn@wN1sB8px`H93$y z5giJ6qbRqF|nXoD2<3*?ARqrdHd!>p{iVzrz geHs?N6#J0XU;$G#A$|U{_X_@h-Y6WhyC8KUWvQAW1ONa4 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0851-futex-wait-multiple-fixes.patch.sig b/pkgbuilds/linux-omarchy/0851-futex-wait-multiple-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..e3fb191030a9b3c9f0267dedbcfaa0876da62870 GIT binary patch literal 594 zcmV-Y05ZTgYoUc%#m*PMyk zK7xT78HA2pfQ+SJYXN5GFg~q_IedA^>}v+fWMB2gCOmsCtXm(-{O=T+@Y*S83F>Q> z&b~ZTnx>%@lQs2!oKVt#RiiC?$$KA;&FKyL;Usr&J0178fO^Klo7Y^9t7rcGG%XPTaS|M+2haOyYi#*n zwT}s1`iT*gwvZi>@bebgvR_`c4#N!D5rW9&G!boevh8W&Civhfu_XjFvCK4afewnQ zfX{W~4C+sKS!UkYARKFr+5;M9E)~SHo+IA@awGY7P^8|{ZQo=)1;-L1-~a;MhW1vY zi8sC}fc1UnG(x-^Xqv|=^!-Fh8bynFV5p~Z;y~(T+I;ji@vI@M9>NK%v-dFnSjrhs z==AMVC#wBX%pdZd#M-(K^w&gIUNj$rm1r{1v@d zzeTfSPR%9xcCq76I+ho5$Hn?PwAEih^utpET3 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0852-futex-wait-multiple-abi-fixes.patch.sig b/pkgbuilds/linux-omarchy/0852-futex-wait-multiple-abi-fixes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..d3db2d880064ffae4554c728580169d8baf652aa GIT binary patch literal 594 zcmV-Y0*NE7BEw7kFN3nubr%kHC{2r?hNc+%YR}XYJ|0K^3^B*YJ@et2OIDkcW`KLt6=s;v ze#t2&c3xsq!$IiSUbUA}r1M`J5p|l;e}|jBw+Ewng{{o+swcA-!$-cO0a6f7N(G9* zC}e#YhUl5~mia{iGDSUKU%iMh(KQ^3e@R%uHOjNokYH7jH>ZdGZvz%@zRs;3w!+-_ zc=0{L;&V*L2ff%-)r}K^NJfsAQZ%KCcJRW)v7NImQ~b%|zsOQN+%dSp;Bz`WtZjv!q+{uGK(NZq+XJ?vrB4 zGD%`L1Zq=^H$9B6ujr+;OPN=2n=#fIfRI6~iSJM0CZ>^*^l1do!n8d9P#FI>l*D%R zZ0NRPgwv^CFt4XPoEpWD@h|UY5cdJbm&JnW>~TSuoQ}#ul?+Y_=s_VFumAu6 literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/8201-xe-shrinker-return-freed-page-count.patch.sig b/pkgbuilds/linux-omarchy/8201-xe-shrinker-return-freed-page-count.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..bbe1ce3f12da4a47a0371e7cea9175df30ea526a GIT binary patch literal 594 zcmV-Y0A()q{1-hxlGq zyo`62=sVY+%@L=r`G5GLzBa2eV}a46$fVcm<3&5Qgx6k^8+E?UIy!*WBH|H-bK4gw zKE!z=!7Ni2ORKiQ(t;KT6&Q~zJUaxp)+u(~hw};B(cc|E(Eu!g<>_|11T%>lsW=}r z?)vE9;?~pzXp*Yeyo3ATc6)6)8^iCXr{GPa0f$?E2fbtF0J?*x(RAIX=sJ zNBAzwY_ms{Fk4p&F$sdhW&j%zvILe-nsFNbGIt+}IEuynwm%O$F{ zmG+Q#Q}Q#5X8;CrXg-}N9bBb7YzPmssT^~Fq@{XXyT4Xw%S~-)79-~bZkV>RatSuo g6uqfZ>OOPH5atY*q*ja+&G182f+w_4B0Ca&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=TnFf0D+&WByqaj7j9c9pr_q5 z<0j<=flW}5$?pgUpkavMd2gE8dpm~~gW@SOd0PmoGZXx~n`gUK<}2*s9rITq9T?x2 zQOp9O(g68K)5GL`weJLFYujUy4s`OOO$<5aKL}@5x=`|+C}q~JosNyHLd?Eu>pV?g zi=tRg;==;Uw}(UEdNT!Vu~a13MoAe?$CWP!sa-oyhpd~zTB4(9_2R>mNSz9}7n4nk z@&1+?}@_?yKHKK({(V0RHc;V#EL`1-j-4q@+?Wd9PD%DB9;-zf|S}|B-mmn@F z>zUV%$7ctVo5EopY^dlJj{Fz98Xx)|@5_jWv5XQJs$FvX>oT}w%%9g@_uo1Y-W!L_nwg$<6c=8FTk~^>D z``le*pv`+~QTVtX4~dNHssmYji(ZwvV`lfN^dkqF`@=Sv+@NCB)E;fSp<%Is(Ixet zi0D>shj&=Jxr@u!(1CPDI4>pRp5t8f`;!32i`fwuKnJ8zzKL`a&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=VUw&{TARhgC%+pNiux%=PF95 z2{0Um$lW4^jxu_xkMXP^P*3j+30||6&G}+$_@&>pqMnUKn3UV~G<5t4sb zl-qt*RtLc=?nov~nn{m^w{yuiRpzK9@6PJ#0a=`>#_g=<^0jj12}OEx?o zdDI%ZkocTdt7`c&I=qeF_(h{}45}l=ZpCJMzJur97)w9}l()NkDLwb@YXLx~ohx?O zZqWA*xPWJS+i8Dll!FB(Se1i6_y4ECOJfR5%!ET9`po5<(DJxNJx)&5Y3+V=yT7*( zbNIxO@5uDzC{qh|^7H-Ya0FX}F?k g<5XX8Jn^`_MTKgM@8a&i00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=W$UG0F=``Lr`0r9(jt}H(j3N zA{FLS=LZfy#=1rGb~7YWq!<0`FynplH8oHrt`i*sGGyY6)o*A>fdv7Ot9(r@T{<9~ zbA~O^`Q2sJlr+ZUz(?g=x2i}|>k2}EqLeK*L^@YKgTak+1URDyVV&w7 zi6vo%Z*#{W2W1P$$XW3;zybbwky3SVFxYxYZMj)vfFiv%B|qhQH(Tf$IO=pv*Em{L zuPtXeVhbJ@+tDj_;S=N0_Q|seu4-;kleR;{tH@^kg5CwJ2NOWLZ+FkKZB44ghY+Tv zXR9f|m2gD&JPiVwSW4bR6{Nv>$9Oe2w_7>P?*!QgcW<9bgdM3vP>{>xt}PVoUumjD z`+w|JGL(eZR$t_jy8F$Ab{Wu6ysN(GW6I13nD+*HT>2F_(IhVxT1SWph#|zoz?gLz zpme40V+eJmYI|iILRDOP_*}zze@}GFtbW%VE50_rNG)Mz96ZHj^?^XLr-UW|UKP%F zC0}NIJhae8wX<3Tf~|)X{BM%e2*zIflRe#p{`jxdi62mClU+DJdyWN6pH2CDm>^{g g^hVAyehbDtAgSPM-;6NP|6mWO%Svq?NvAH$HSay0D3rc#TL4u^{|2A$-ugX0Yk`GK{$g7d%oL^22S=Et`8g-74SyK?dr+^K^SJHZ`I1Tr{I|x1%8D` zqzI6nuqT+@1ZKLWP`eP)n8-=E^33yDM91( zy@WlCJ>npKjobNwHm1{8&K+HS!O(J2ny@q@@94jCn%#!}*gYqaj&~ga0q5I{9r-5< zB`)e_3WVZ(L9eHOPYLoG9NIPU`8c=XDI|m1{HnZ$M9JfAw8E@C` zR=IRdSyj^yg56IL+{yc!Co=fDTX&sZV0)slq&{D2Gb~o3GeF%gTHyQsA}>IIaPEqT z?w=Ia5nx#uBV<`lj00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=L%I1{T`Z*tNLV&%YK^q(c^JX zvB!2)?Ej^K+Jy~r%^o$sInDExxbiSJ zyu;INB*7$g3Ne8JbCVh|Tm7ar`BY7nKO%}WSarJ8x;|?(Ojp1pSF#4T5P&5v?sp$# z;mBP_ERl^qF7(6fga?LtM7K7hqvSexbl&j+($gc|7YdB*vKe4jY1aXRSf6U**8+|> zdR~{RKWx8^;?h%8FK}9NH?0sJ?jQZcGDP5|@u5F96JNR}fkYlLLOgem{FC7hhS7iyKwk zjxUVC$fKg*ruDDZgMmCHg)L8X|yZL%(gXpTEQwS-o^u>W&6aq*UIQ{O5l)nlTAO22aCke$Xi%G g!yQKsTRs3j00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=k5Cs{yp+!1n?BoGP0#eq5~iz z%d3&DbLpzI*JPT{eylTrDHvIPYa)T0Smr-O2Kj>Wt zE)K79IqR4(S`a1Bp*Tg-whGr&z`~C?2?l0%kn5@Y(thrOW3PF^izb<0o4_Pjdk$~h zOrCO|qcLWG5Ftpo*f*r3 zXR_SPpq#Q8iVG{ZzW`l2t0HGy_u;As&~K~c8D8j99zHLy%EgFcMIU%wt-MaMK-t2oiHU&qM>*6`im<_;uheT0CWY~jUIz?H4;BN*F8 zv+K3QN^bdA)%Wzt6QU8<>9TKn^Vo%r>T^sv;NEeadts_HWEl&s;^TDyW)>3fET{zD zMn^EtT`$9C^EFU5mf>Eu!IeHVcI&t)?+zu^bWs_TpPj(DJO-@TC)>{$B-mo0RxdRb g(C=SuyUxjTqL0E{fgGTg`iCCg1)rv(9gLTrVn8IN$S<5-KA&?KwYX%nyh$( z4nc@RY=n#`Zy%4LS#W}*UT}b^1Me}q-)fuKp%1}Wod=0cfl)1C`gqfj0gMR~9oC~1 zzO}(2gh6aH{m*j1!}LCq)%o;@JNt-_ex<~7AwqaAjeB3&TE@j?q%z9u9B01N8-uyF z6XdO2KF6umEDe)mKbzS+P?p0!mUD$GRzTOh#QLSLNDZrwc1m)3!c$~yeS-_F(8p%l^RmWL$A0~gK8xy#R52jpiw{Qxa{$|;@syq3pi5qnOrzvP zWrMuapcqe?(>$bX@!u>ocGd}e>YWL)gmK!{KNekGZ@Ol_XsA|GLqf@5na5W%croGd zc-3ecvzaFxX)0Z#>=DJ8rE@du`px;+xxp&R9bA1)3=q=AT|ZHo<(9>A=8Z<2F#e`{p^ppuT9(Gw1OKoSGa| zkmvgWgF70ScZS5*0)D4hxH9ylsLJq1V}PE$#MzwXV>~`rGlO_wL39LE?U5<%1lyyH grME@qV6#fEeLcn2ZuFV?_UXWlB~eDM&3O@0O%3`Twg3PC literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/8209-xe-shrinker-use-opportunistic-hint.patch.sig b/pkgbuilds/linux-omarchy/8209-xe-shrinker-use-opportunistic-hint.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..7928b4ee0dcbc148b07fd44f0fb52cd369749037 GIT binary patch literal 594 zcmV-Y0j00000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=WbdL|90C93g)f}u_3C;r%Z8+ zDhY4(*ndyrP!QY*S#g9smhKC`ktrz{45qh8GqUsS#^yhu{!^VXX`rXtCd>bU4zJjo z6uR4Y(!5DX^)BM3jSp$uL|CEQsXSR$_1K0jQu*y`tt~IQ;I}9XXn*`ynDEKwb2Vq& z4~ddxIDi?-W!;BgEr*QEY!8Yt#iV1M+np-IDT^@ih#JAUb&v@}N`HGqZH?%ePT(v-t(Sg*J^>>Y(<-F&fS3A`y=u`6lx*)@aXGn1W-;25~yy4Z76*Q z?|~zy{=-|2)S)fD@fdael+t`SwYJ_kO9oz=!U)xa-8?1CJ8mx-3kf|H6qMGKR z=Y|Dqva2q|)beU|Q6Aga-Dwd`P{F}CH!BOR_RJJ`r8Zdl^t>dF=cm*P<+$a`8$zalW>DqykH?!H>)F7;(cj>hdpveMka1 zoHe@Su*V{XiWpZkGq51;xLFb^2`y_HB<-XRc*1R_{@cN08+8LK`lH71H{%)BPK34X zZ0?3d(jA3GY3=+a-^vw}*9jU9G5EDj%C5%}n6L;E^e8M^`(Z78?C8K=O)kz@jed940SG0j?t(R2QW?l8NS-uXeIg_+cgcR(;8Uc1V1}~Ut0r_{dUyw&!{4c+h?xRgQ zm Date: Tue, 15 Sep 2026 23:55:59 -0500 Subject: [PATCH 024/121] Preserve Num Lock during compatible Cua foreground input --- .../DOWNSTREAM-PROVENANCE.json | 17 +- pkgbuilds/cua-hyprland-plugin/PKGBUILD | 28 +- pkgbuilds/cua-hyprland-plugin/PROFILE.json | 2 +- pkgbuilds/cua-hyprland-plugin/README.md | 14 +- .../independent-keymaps.patch | 504 ++++++++++++++++-- 5 files changed, 488 insertions(+), 77 deletions(-) diff --git a/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json b/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json index 8fa0d3b..7cf8f23 100644 --- a/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json +++ b/pkgbuilds/cua-hyprland-plugin/DOWNSTREAM-PROVENANCE.json @@ -1,6 +1,6 @@ { "files": { - "CMakeLists.txt": "4a2027383ae39b052c4cf30732810f93ee1170b7987777aa9e8ea282abb17731", + "CMakeLists.txt": "7e874a595e1abd708cb0626bd9f0f58d79b4b4bbc6d99b45a0cbe1c5c53b43bc", "LICENSE.md": "c0779290c1d4783169aa3dbfb55feb505e563ef8a004bbf55298ceffcfbda8d9", "SOURCE-PROVENANCE.json": "54f514664c84e1358a435f29cd6befd5661b0b133d76997191c000b10f021a75", "cmake/DetectHyprlandAPI.cmake": "216133ec0eb141c3696bf3770a23e63e46521c9e91a0245a7cb75c20a75ba2c5", @@ -9,17 +9,17 @@ "include/cua_hyprland/session.hpp": "e6a968e4f2ac28122cb7413a0e318f6222d2a0a1b7b0c45f4ab419a78639ebea", "include/cua_hyprland/status.hpp": "56a9656647c0f4eeb0c588cd4b98a77df198d1f90421f973e9a80e6802f61495", "src/drag_geometry.hpp": "c5b783d15ff197f22938f08f8d176bab5d45544fe989d150f15cb99295acedb8", - "src/foreground_route.hpp": "bf07e9ada1a3e25dd85611d5f3f4f725df50b1b8fc1d4c4903fb5c6dc9c3d5f8", + "src/foreground_route.hpp": "4aa016c237b33c15e352a9f5f64bbbca7e1a9c1671ffd593a95a0d87994fb519", "src/inject_server.cpp": "0935283580c50fcf0e4ad956f858885700536002b1d86d2f078da9c4404ee9e8", "src/inject_server.hpp": "67de008b4d6983371207bb22a57bab154b1dedda9b38d1207d3ac8cb379382eb", "src/input_client_deadline.hpp": "00a91a789ff698820607449ff7152e2fb50d0f315e0fa9c5c3855752bfffe2ef", - "src/input_experiment.cpp": "358fa86abd21dbfda8460b21b3568d0199e47ed79ef6c5dd0c7e0c6d4c026290", + "src/input_experiment.cpp": "7017748c782b64b0bc1d257f4ade1a8d46fd19ce940ecc21f22d628614fcef37", "src/input_experiment.hpp": "9da2ddab7f0de6e9cf02aea53e9119acef17ef8513af849bb5aa3d137ebd12c3", "src/input_grant.hpp": "90b544b2f559bacd920b85ab5915f09ff201de3c05a052ce1b71ff71f767e6a6", - "src/keyboard_layout.hpp": "66d7d1ace6357c5be26f4a9b57730709fe21e30267437051c62b6697eb073300", + "src/keyboard_layout.hpp": "bc2ec039ac1974caebbb66fe4acb7a2a81832c9054b3aa644a9adcc8954a2467", "src/owned_socket_path.hpp": "8e784656d944c700f3ded383c93a8cadf846dabdaa4cc12673bcb637c26d9fd1", "src/passive_pointer_target.hpp": "ede36fd9fd6e95ae5923c751f12591084392be9d2270eb06ad64eb4f245169fa", - "src/plugin.cpp": "e36817f12b47f317dde300cfa6820ce2d408c8fe5bfea3a3e5c727b86d461d3e", + "src/plugin.cpp": "712fd73ef8e9046e0fd91531b7bf5da50ce37ccca9df174160137e1924a74b09", "src/primary_trace.cpp": "e9468d1a3f3be2a90d47bf8c4a638ad8a60fe10b6297582ab7825751cb707aa9", "src/primary_trace.hpp": "8d62535fb0b24a02bb80d9a8dcd540b39204afb2f3b4bcb5cabd5275c3b5eaa7", "src/protocol.cpp": "bd083d65efb05e80946566dc535b1a6fadaa581c66ec327eff41796feba795b1", @@ -32,24 +32,25 @@ "tests/desktop_fault_policy_fixture.cpp": "ac24d675ebc64cc98148e852eb5aba5858bffc06332678d14276d04b317aaf15", "tests/desktop_fault_policy_test.py": "c3f624c0239036babd23eaaf1bb6b722f3a0c3321a5d3d6668ae7ab4910ca95c", "tests/drag_geometry_test.cpp": "d32ea649d008fc051fe18555d6fbc54ba5d057b61880b648c5df8aa076a53fbc", + "tests/foreground_modifiers_test.py": "abf0ddde2d51c6639c8bdca8fdda51cdc8f922b57575a00fc8925c683ccc3bb2", "tests/foreground_route_test.cpp": "1024168828b13ee6abd8242941e73c042e9381b39108e3ada74823039c7e7932", "tests/input_client_deadline_test.cpp": "d62373a7815d531f1269c9a838773595f43e8bcef6482fa140edb162e59a6cac", "tests/input_grant_test.cpp": "1f327b7ee678189ebad6a50bb1b9bd06767521cebc9cfb478d92de4a8bf7e7fe", - "tests/keyboard_layout_test.cpp": "80f76d16896bbb77269a52e12c18c079d642618d29d0608f23a3d7ae2844f21f", + "tests/keyboard_layout_test.cpp": "3bb0fade4675d7ad92a81eb4a1c5201dd1d01bcc418b7ea59a4284dc235e5fb2", "tests/mock-hyprland/mock.hpp": "3aeb1a4b9d6b83506b66c129d3fa812330fad4509fe218a0dbb99dd2bb5b6319", "tests/mock-hyprland/src/config/values/types/BoolValue.hpp": "47cf2cca89f71a273573968cb9b8ba46a1496841d6c892756ebf123500a7ecb3", "tests/mock-hyprland/src/plugins/PluginAPI.hpp": "5654d90ec9090a88bea3d31f8a79617d4c79742b09068648e64448319d395110", "tests/owned_socket_path_test.cpp": "eaff6b5c6f148eca6c8650ee3dc212a5e892f002ee4f68b2a1290c7205ee7e42", "tests/passive_pointer_target_test.cpp": "2aeef1de1dc8932b26ab8c41b83fb16a4289ff96c177a5816088f07b9a168948", "tests/plugin_api_test.cpp": "1e7e200c309996ee945c88e172273ae942be2837e24564d422dee79d8b77d8a2", - "tests/plugin_input_lifetime_test.cpp": "9d291fc6d7de5e9a80a07c2de16de85739e9ba6fe2ceace371f64b94af4724c0", + "tests/plugin_input_lifetime_test.cpp": "82e57b335ea1216ea24cca07fe4feebafebdebb779785fde20b8dab6ee222e1b", "tests/protocol_test.cpp": "119cfe0df81c0c00036a2d181764eda7601d6ee72459c2275a96226d4f670447", "tests/seat_lifetime_test.cpp": "b07570edbe0a142f97c54560eeb93e8327c435ab3b8cbc7496d55175e387b78a", "tests/status_test.cpp": "b8990efc53ec3820cfe498c920b9220c4b70615ad585468558e032e7619e32f3", "tests/transport_test.cpp": "deef114a950a27eaff0a530165ddf7db0bfc0fe7e8fb55bdbb66135c8e0c04c9", "verify.py": "fb35d62313ff4661f892f88666919b33b160f8b6d4fb2d5d52610708bf7f4a54" }, - "patch_sha256": "5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4", + "patch_sha256": "e74d9021111a5c217b12f3e13c1bbdd260e829c60db5fc2f7293ba4846e1a7d7", "schema": 1, "upstream_manifest_sha256": "54f514664c84e1358a435f29cd6befd5661b0b133d76997191c000b10f021a75", "upstream_revision": "cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7" diff --git a/pkgbuilds/cua-hyprland-plugin/PKGBUILD b/pkgbuilds/cua-hyprland-plugin/PKGBUILD index 788b938..9fba2d2 100644 --- a/pkgbuilds/cua-hyprland-plugin/PKGBUILD +++ b/pkgbuilds/cua-hyprland-plugin/PKGBUILD @@ -4,7 +4,7 @@ # shellcheck shell=bash disable=SC2034,SC2154 pkgname=cua-hyprland-plugin pkgver=0.26.1 -pkgrel=4 +pkgrel=5 pkgdesc='Cua input candidate for reviewed profile omarchy-hyprland-0562r3-remaps' arch=('x86_64') url='https://github.com/trycua/cua' @@ -14,8 +14,8 @@ makedepends=('cmake>=3.30' 'ninja' 'pkgconf' 'gcc' 'patch') options=('!strip' '!debug' '!lto') _stem='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7' _archive_sha256='47bca9e018f32f4fcfe683f91c7475c60368f3b65d318cc35c1f2de88a4ee9ab' -_kit_sha256='aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2' -_profile_sha256='ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a' +_kit_sha256='089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9' +_profile_sha256='fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b' _verifier_sha256='480f649cbd35a0ddc7f49dc0a3a44785402c9e0ec9653b0f8ea4965d52d7f900' _cxx="${CUA_RELEASE_CXX:-/usr/bin/g++}" _download_name='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7-profile-omarchy-stable-20260910-kit-1.1.0-5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a-67f89ceb47edd973aa748820eadd02ddbfb3d3e4.tar.gz' @@ -24,17 +24,17 @@ source=('https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0 'PROFILE.json') noextract=("$_download_name") sha256sums=('a89bfa7f6490f598719dfabdd2a5badc137e27b0764fd25e6a05e1f969433520' - 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a') + 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b') # Downstream inputs are also checked explicitly when makepkg integrity is skipped. declare -gA _downstream_sha256=( - ['independent-keymaps.patch']='5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4' - ['DOWNSTREAM-PROVENANCE.json']='e87949fa29d8c006f1c829cb81e640980b349a704bedb5f1d4fe7dc47746994e' + ['independent-keymaps.patch']='e74d9021111a5c217b12f3e13c1bbdd260e829c60db5fc2f7293ba4846e1a7d7' + ['DOWNSTREAM-PROVENANCE.json']='e0c95350ec3ff2dd54a05e9377d79ddffffdb1cf494d05553a90207a3a919f7e' ['downstream.py']='7c9725805ad038737bd4d346c85f27991ce9ddfff436a32ebf515cad1bf98ca1' ['downstream_test.py']='7b9a992979b22a5e061fdf011ac6be59a3f1ae6e0d7c0a8ff631f74e71984c5a' ) source+=('independent-keymaps.patch' 'DOWNSTREAM-PROVENANCE.json' 'downstream.py' 'downstream_test.py') -sha256sums+=('5847cd2c300a9b3c7dc1e836722a0e2b222892e308290195d973300c7f74e0e4' 'e87949fa29d8c006f1c829cb81e640980b349a704bedb5f1d4fe7dc47746994e' '7c9725805ad038737bd4d346c85f27991ce9ddfff436a32ebf515cad1bf98ca1' '7b9a992979b22a5e061fdf011ac6be59a3f1ae6e0d7c0a8ff631f74e71984c5a') +sha256sums+=('e74d9021111a5c217b12f3e13c1bbdd260e829c60db5fc2f7293ba4846e1a7d7' 'e0c95350ec3ff2dd54a05e9377d79ddffffdb1cf494d05553a90207a3a919f7e' '7c9725805ad038737bd4d346c85f27991ce9ddfff436a32ebf515cad1bf98ca1' '7b9a992979b22a5e061fdf011ac6be59a3f1ae6e0d7c0a8ff631f74e71984c5a') _verify_download() { python3 -I - "$SRCDEST/$_download_name" "$_download_sha256" "$srcdir" "$1" "$SRCDEST/PROFILE.json" <<'CUA_DOWNLOAD_PY' @@ -75,10 +75,10 @@ require(payload.keys() == expected.keys(), 'outer kit inventory mismatch') # files as -2. Derive a version-only profile with the original source/tooling # and byte checks intact; record its own profile and kit provenance digests. profile_data = Path(profile_path).read_bytes() -require(digest(profile_data) == 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a', +require(digest(profile_data) == 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b', 'local profile checksum mismatch') profile = json.loads(payload['PROFILE.json']) -profile.update(profile_id='omarchy-hyprland-0562r3-remaps', package_release=4) +profile.update(profile_id='omarchy-hyprland-0562r3-remaps', package_release=5) profile['hyprland']['package_version'] = '0.56.2-3' require(json.loads(profile_data) == profile, 'local profile changes more than the reviewed package revision') payload['PROFILE.json'] = profile_data @@ -86,7 +86,7 @@ provenance = json.loads(payload['KIT-PROVENANCE.json']) provenance['profile_sha256'] = digest(profile_data) payload['KIT-PROVENANCE.json'] = (json.dumps(provenance, sort_keys=True, indent=2) + '\n').encode() recipe = payload['PKGBUILD'].decode() -for old, new in [('pkgrel=2\n', 'pkgrel=4\n'), ('omarchy-stable-20260910', profile['profile_id']), +for old, new in [('pkgrel=2\n', 'pkgrel=5\n'), ('omarchy-stable-20260910', profile['profile_id']), ('hyprland=0.56.2-2', 'hyprland=0.56.2-3'), ('5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a', digest(profile_data)), ('7beb736adfd334eed52e84070177634269e3a09f8bb25971b38606933ff4c997', digest(payload['KIT-PROVENANCE.json']))]: @@ -94,10 +94,10 @@ for old, new in [('pkgrel=2\n', 'pkgrel=4\n'), ('omarchy-stable-20260910', profi payload['PKGBUILD'] = recipe.encode() payload['SHA256SUMS'] = ''.join(f'{digest(body)} {name}\n' for name, body in sorted(payload.items()) if name != 'SHA256SUMS').encode() -expected.update({'PROFILE.json': 'ee9b7cf5fbcc78ab169a87b5edb061a85c4425f7ddf41c90328cf020550c5f9a', - 'KIT-PROVENANCE.json': 'aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2', - 'PKGBUILD': '0e71ddab36e5d9214c35811f2cbf89cc98e5b4fdf6656f85e6b3885d07a1c021', - 'SHA256SUMS': '404cf40875ab14b8af84847abd4674945b1c7ab2e0bfb1605fa11e2d85d789db'}) +expected.update({'PROFILE.json': 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b', + 'KIT-PROVENANCE.json': '089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9', + 'PKGBUILD': '0cbf2cd34c3c5038a5ed51e6bf84acd81844e4c2bb08ad7203959201bba61da9', + 'SHA256SUMS': 'd01b9e0be4c5bcf84cc2ecef9f11f44cedfc1ca5b31afbfcf52aa2efbd636a09'}) for name, content in payload.items(): require(digest(content) == expected[name], 'derived kit checksum mismatch: ' + name) require(srcdir.is_dir() and not srcdir.is_symlink(), 'srcdir must be a real directory') diff --git a/pkgbuilds/cua-hyprland-plugin/PROFILE.json b/pkgbuilds/cua-hyprland-plugin/PROFILE.json index 81bbd99..fe5eff2 100644 --- a/pkgbuilds/cua-hyprland-plugin/PROFILE.json +++ b/pkgbuilds/cua-hyprland-plugin/PROFILE.json @@ -12,7 +12,7 @@ "sha256": "da8fcacf347bcbed83edc40108c6e2298da095e22246bd764e9bb382786cebb2" }, "kit_version": "1.1.0", - "package_release": 4, + "package_release": 5, "profile_id": "omarchy-hyprland-0562r3-remaps", "runtime": { "basename": "libstdc++.so.6.0.36", diff --git a/pkgbuilds/cua-hyprland-plugin/README.md b/pkgbuilds/cua-hyprland-plugin/README.md index 652cae7..61946b4 100644 --- a/pkgbuilds/cua-hyprland-plugin/README.md +++ b/pkgbuilds/cua-hyprland-plugin/README.md @@ -1,6 +1,6 @@ # Optional Cua Hyprland plugin -This package targets **Omarchy stable x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Package release `4` adds an Omarchy patch for independent agent keymaps and operation-specific foreground checks; the upstream native qualification below covers the unpatched source, not this change. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. +This package targets **Omarchy stable x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Package release `5` includes the Omarchy patch for independent agent keymaps, operation-specific foreground checks, and compatible Num Lock state; the upstream native qualification below covers the unpatched source, not this change. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. The plugin is optional. Cua Driver works independently, and installation does not load the plugin or enable input. The package follows the normal edge-to-RC-to-stable promotion path instead of the fast release ring. Its PKGBUILD limits builds to x86_64; only stable x86_64 is a qualified target. @@ -12,7 +12,7 @@ It is not a repackaging of the unmodified 0.24.0 plugin. The qualified upstream Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with the upstream module; its production plugin source is the base for the downstream patch used here. Discovery protocol v2 is separate. A newer Driver release is a changed pairing and requires affected replay before promotion. -Profile `omarchy-hyprland-0562r3-remaps`, kit tooling `1.1.0`, and package release `4` pin: +Profile `omarchy-hyprland-0562r3-remaps`, kit tooling `1.1.0`, and package release `5` pin: - Hyprland `0.56.2-3`, headers `0.56.2`, and measured executable/header hashes. - GCC `16.2.1 20260810`, including compiler bytes and emitted ELF identity. @@ -54,7 +54,9 @@ Each background lane owns a canonical US keymap and independent modifier state. Plain click, scroll, drag, and foreground activation do not require a canonical keyboard layout. Foreground keys still use the primary seat: the plugin checks the requested key and modifier sequence against its actual XKB map before activation or input. Unrelated remaps are accepted; a sequence whose symbols or modifier/lock transitions differ from the canonical meaning is refused with `unsupported_layout`. Arbitrary foreground layout translation remains outside protocol v3. -Both routes retain target/conflict checks and cancellation on desktop/keymap changes. `hyprctl -j cua:status` exposes `keyboard_layout_independent: true` for installers to distinguish this implementation from an older mapped module. The marker does not identify every future package revision; plugin updates still require a fresh desktop session. +Foreground typing preserves Num Lock and admits a requested key sequence only when its symbols and shortcut semantics still match the canonical meaning. Num Lock does not block unaffected letters, top-row digits, Enter, or compatible shortcuts; a keypad sequence whose meaning changes is refused. Caps Lock, other unsupported lock states, held or latched modifiers, and nonzero layout groups remain guarded. + +Both routes retain target/conflict checks and cancellation on desktop/keymap changes. `hyprctl -j cua:status` exposes `keyboard_layout_independent: true` and `foreground_numlock_compatible: true` for installers to distinguish this implementation from an older mapped module. The marker does not identify every future package revision; plugin updates still require a fresh desktop session. ## Historical upstream qualification @@ -102,7 +104,7 @@ background refusal never authorizes a hidden foreground fallback or unlock. Build the unsigned candidate in edge: ```sh -bin/repo build --package cua-hyprland-plugin --arch x86_64 --mirror edge +./bin/build --package cua-hyprland-plugin --arch x86_64 --mirror edge ``` In a fresh worker matching the reviewed profile: @@ -140,7 +142,7 @@ kit-provenance digest: ```sh python3 /usr/share/cua-hyprland-plugin/profile_verify.py \ --kit /usr/share/cua-hyprland-plugin \ - --kit-sha256 aa88498fc9635e493a64aaf4e2a08cdb5249d576d7e00c3cf100799d5c9f23f2 \ + --kit-sha256 089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9 \ --consumer /usr/lib/cua/hyprland/cua-hyprland-plugin.so ``` @@ -172,7 +174,7 @@ hyprctl reload hyprctl -j cua:status ``` -Continue only when status reports `keyboard_layout_independent: true`, input protocol v3, input capability, socket paths, and the expected compositor identity. Do not change `kb_layout`, `kb_options`, or NumLock for background input. If you previously followed the stock-US override instructions, remove only that Cua-specific override and reload to restore your underlying personal settings. +Continue only when status reports `keyboard_layout_independent: true`, `foreground_numlock_compatible: true`, input protocol v3, input capability, socket paths, and the expected compositor identity. Do not change `kb_layout`, `kb_options`, or NumLock for background input. If you previously followed the stock-US override instructions, remove only that Cua-specific override and reload to restore your underlying personal settings. Start Driver with `CUA_DRIVER_RS_ENABLE_WAYLAND=1`. In a new disposable Inkscape document, test an admitted background key operation and pointer operation, then verify the result in both a fresh snapshot and a saved/reopened SVG. Driver text-route restrictions still apply. Never test against an existing document or automatically replay an action with a partial or unknown outcome. diff --git a/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch b/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch index 1fbea31..245ba60 100644 --- a/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch +++ b/pkgbuilds/cua-hyprland-plugin/independent-keymaps.patch @@ -1,8 +1,8 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8a80de2..5dedb8f 100644 +index 8a80de2..2d48237 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -39,8 +39,24 @@ target_compile_options(cua_hyprland_protocol PRIVATE -Wall -Wextra -Wpedantic -W +@@ -39,8 +39,28 @@ target_compile_options(cua_hyprland_protocol PRIVATE -Wall -Wextra -Wpedantic -W cua_hyprland_harden(cua_hyprland_protocol) set_target_properties(cua_hyprland_protocol PROPERTIES POSITION_INDEPENDENT_CODE ON) @@ -23,11 +23,15 @@ index 8a80de2..5dedb8f 100644 + add_test(NAME cua_hyprland_agent_keymap_test + COMMAND ${Python3_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/tests/agent_keymap_test.py) + set_tests_properties(cua_hyprland_agent_keymap_test PROPERTIES ++ ENVIRONMENT "CXX=${CMAKE_CXX_COMPILER}") ++ add_test(NAME cua_hyprland_foreground_modifiers_test ++ COMMAND ${Python3_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/tests/foreground_modifiers_test.py) ++ set_tests_properties(cua_hyprland_foreground_modifiers_test PROPERTIES + ENVIRONMENT "CXX=${CMAKE_CXX_COMPILER}") add_test(NAME cua_hyprland_desktop_fault_policy_test COMMAND ${Python3_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/tests/desktop_fault_policy_test.py) -@@ -218,6 +234,7 @@ if(CUA_HYPRLAND_BUILD_PLUGIN) +@@ -218,6 +238,7 @@ if(CUA_HYPRLAND_BUILD_PLUGIN) message(FATAL_ERROR "Input is pinned to Hyprland 0.56.2") endif() target_sources(cua_hyprland_plugin PRIVATE src/input_experiment.cpp) @@ -35,8 +39,29 @@ index 8a80de2..5dedb8f 100644 endif() if(CUA_HYPRLAND_INPUT) target_compile_definitions(cua_hyprland_plugin PRIVATE CUA_HYPRLAND_INPUT=1) +diff --git a/src/foreground_route.hpp b/src/foreground_route.hpp +index 0b675d3..c3af461 100644 +--- a/src/foreground_route.hpp ++++ b/src/foreground_route.hpp +@@ -68,11 +68,13 @@ struct ForegroundSeatBindings { + bool unique() const { return primary_candidates == 1; } + }; + +-inline ForegroundFailureReason foreground_key_modifier_failure(const std::array& modifiers) { +- // The KEY mapping assumes a neutral US state, including layout group zero. ++inline ForegroundFailureReason foreground_key_modifier_failure(const std::array& modifiers, ++ std::uint32_t allowed_locked = 0) { ++ // The caller may admit a keymap-resolved ambient Num Lock mask. All other ++ // human modifiers and nonzero layout groups remain unsupported. + if (modifiers[0]) return ForegroundFailureReason::keyboard_depressed; + if (modifiers[1]) return ForegroundFailureReason::keyboard_latched; +- if (modifiers[2]) return ForegroundFailureReason::keyboard_locked; ++ if (modifiers[2] & ~allowed_locked) return ForegroundFailureReason::keyboard_locked; + if (modifiers[3]) return ForegroundFailureReason::keyboard_group; + return ForegroundFailureReason::none; + } diff --git a/src/input_experiment.cpp b/src/input_experiment.cpp -index fc7e740..f256fc4 100644 +index fc7e740..5d80d3e 100644 --- a/src/input_experiment.cpp +++ b/src/input_experiment.cpp @@ -9,6 +9,8 @@ @@ -174,25 +199,75 @@ index fc7e740..f256fc4 100644 if (xkb_context_) xkb_context_unref(xkb_context_); if (keymap_fd >= 0) close(keymap_fd); } -@@ -786,7 +790,7 @@ struct InputExperiment::Impl { +@@ -782,12 +786,40 @@ struct InputExperiment::Impl { + .exact_pointer_focus = root && g_pSeatManager->m_state.pointerFocus == root, + }; + } ++ std::array capture_foreground_modifiers(bool needs_keyboard) const { ++ const auto physical = g_pSeatManager->m_keyboard.lock(); ++ if (!physical) throw ForegroundFailure{ForegroundFailureReason::physical_keyboard}; ++ std::array result{}; ++ const auto observe = [&](const auto& kb, bool primary) { ++ const std::array state{kb->m_modifiersState.depressed, kb->m_modifiersState.latched, ++ kb->m_modifiersState.locked, kb->m_modifiersState.group}; ++ if (needs_keyboard) { ++ const auto failure = foreground_key_modifier_failure(state, foreground_numlock_mask(kb->m_xkbKeymap)); ++ if (failure != ForegroundFailureReason::none) throw ForegroundFailure{failure}; ++ // Hyprland combines shared raw masks. A lock from a different ++ // encoding must not be reinterpreted as the primary Num Lock. ++ if (state[2] && state[2] != foreground_numlock_mask(physical_keymap)) ++ throw ForegroundFailure{ForegroundFailureReason::keyboard_locked}; ++ } ++ for (unsigned i = 0; i < 3; ++i) result[i] |= state[i]; ++ if (primary) result[3] = state[3]; ++ }; ++ observe(physical, true); ++ for (const auto& kb : g_pInputManager->m_keyboards) { ++ if (kb == physical || !kb->m_enabled || !kb->shareStates() || ++ (kb->isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(kb))) continue; ++ observe(kb, false); ++ } ++ return result; ++ } + void require_foreground(Client& c) { if (lease != &c) throw ForegroundFailure{ForegroundFailureReason::lease}; if (c.dead) throw ForegroundFailure{ForegroundFailureReason::client_dead}; if (!available()) throw ForegroundFailure{ForegroundFailureReason::session_unavailable}; - if (!layout_qualified()) throw ForegroundFailure{ForegroundFailureReason::unsupported_layout}; + if (foreground_keyboard_used && !physical_layout_ready()) throw ForegroundFailure{ForegroundFailureReason::unsupported_layout}; if (Clock::now() >= expires) throw ForegroundFailure{ForegroundFailureReason::lease_expired}; ++ if (foreground_keyboard_used && capture_foreground_modifiers(true) != foreground_modifiers) ++ throw ForegroundFailure{ForegroundFailureReason::keyboard_state}; const auto failure = foreground_guard(c).dispatch_failure(foreground_needs_pointer); if (failure != ForegroundFailureReason::none) throw ForegroundFailure{failure}; -@@ -813,6 +817,8 @@ struct InputExperiment::Impl { + } +@@ -803,24 +835,31 @@ struct InputExperiment::Impl { + p->sendButton(event_ms(), held_button, WL_POINTER_BUTTON_STATE_RELEASED); + p->sendFrame(); + } ++ // Synthetic events only change our private state. If human input ++ // cancelled the action, restore the current real state, not stale locks. ++ const auto restore_modifiers = g_pSeatManager->m_keyboard.lock() ? ++ capture_foreground_modifiers(false) : foreground_modifiers; + if (foreground_keyboard_used && root && root->good() && g_pSeatManager->m_state.keyboardFocus == root) + for (const auto& weak : foreground_keyboards) + if (const auto k = weak.lock(); k && k->good()) { + for (auto code : held_keys) k->sendKey(event_ms(), code, WL_KEYBOARD_KEY_STATE_RELEASED); +- k->sendMods(foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], foreground_modifiers[3]); ++ k->sendMods(restore_modifiers[0], restore_modifiers[1], restore_modifiers[2], restore_modifiers[3]); + } + held_button = 0; held_keys.clear(); foreground_pointers.clear(); foreground_keyboards.clear(); foreground_surface.reset(); foreground_seat.reset(); foreground_started = false; foreground_keyboard_used = false; + if (physical_state) xkb_state_unref(physical_state); + physical_state = physical_keymap ? xkb_state_new(physical_keymap) : nullptr; } - void start_foreground(Client& c, double x, double y, bool needs_pointer, bool needs_keyboard) { +- void start_foreground(Client& c, double x, double y, bool needs_pointer, bool needs_keyboard) { ++ void start_foreground(Client& c, double x, double y, bool needs_pointer, bool needs_keyboard, ++ const std::array& modifiers) { const auto root = c.surface.lock(); -@@ -820,7 +826,7 @@ struct InputExperiment::Impl { + const auto physical = g_pSeatManager->m_keyboard.lock(); const auto failure = foreground_guard(c).activation_failure(); if (failure != ForegroundFailureReason::none) throw ForegroundFailure{failure}; if (!physical) throw ForegroundFailure{ForegroundFailureReason::physical_keyboard}; @@ -201,16 +276,55 @@ index fc7e740..f256fc4 100644 if (needs_pointer && !g_pSeatManager->m_mouse) throw ForegroundFailure{ForegroundFailureReason::physical_pointer}; const Vector2D local{x + c.geometry[0] - c.geometry[4], y + c.geometry[1] - c.geometry[5]}; if (needs_pointer && (!point(c, x, y) || root->at(local, true).first != root)) throw ForegroundFailure{ForegroundFailureReason::pointer_target}; -@@ -843,7 +849,7 @@ struct InputExperiment::Impl { - const auto modifier_failure = foreground_key_modifier_failure(foreground_modifiers); - if (modifier_failure != ForegroundFailureReason::none) throw ForegroundFailure{modifier_failure}; - } +@@ -831,24 +870,16 @@ struct InputExperiment::Impl { + for (const auto& k : seat->m_keyboards) if (k && k->good()) foreground_keyboards.push_back(k); + if (needs_pointer && foreground_pointers.empty()) throw ForegroundFailure{ForegroundFailureReason::pointer_resources}; + if (foreground_keyboards.empty()) throw ForegroundFailure{ForegroundFailureReason::keyboard_resources}; +- foreground_modifiers = {physical->m_modifiersState.depressed, physical->m_modifiersState.latched, +- physical->m_modifiersState.locked, physical->m_modifiersState.group}; +- for (const auto& kb : g_pInputManager->m_keyboards) { +- if (!kb->m_enabled || !kb->shareStates() || (kb->isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(kb))) continue; +- foreground_modifiers[0] |= kb->m_modifiersState.depressed; +- foreground_modifiers[1] |= kb->m_modifiersState.latched; +- foreground_modifiers[2] |= kb->m_modifiersState.locked; +- } +- if (needs_keyboard) { +- const auto modifier_failure = foreground_key_modifier_failure(foreground_modifiers); +- if (modifier_failure != ForegroundFailureReason::none) throw ForegroundFailure{modifier_failure}; +- } - xkb_state_update_mask(keyboard_state, foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], 0, 0, foreground_modifiers[3]); ++ foreground_modifiers = modifiers; ++ if (needs_keyboard && capture_foreground_modifiers(true) != foreground_modifiers) ++ throw ForegroundFailure{ForegroundFailureReason::keyboard_state}; + if (needs_keyboard) xkb_state_update_mask(physical_state, foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], 0, 0, foreground_modifiers[3]); foreground_surface = root; foreground_seat = seat; foreground_needs_pointer = needs_pointer; -@@ -893,16 +899,17 @@ struct InputExperiment::Impl { + c.foreground_attempted = true; + foreground_started = true; ++ foreground_keyboard_used = needs_keyboard; + foreground_activating = true; + // Activation intentionally persists. Never save, borrow, or restore focus. + if (g_pSeatManager->m_state.keyboardFocus != root || Desktop::focusState()->window() != c.window.lock() || +@@ -858,7 +889,16 @@ struct InputExperiment::Impl { + if (lease != &c) throw ForegroundFailure{ForegroundFailureReason::lease}; + const auto focus_failure = foreground_guard(c).dispatch_failure(false); + if (focus_failure != ForegroundFailureReason::none) throw ForegroundFailure{focus_failure}; +- if (!needs_pointer) { require_foreground(c); return; } ++ if (!needs_pointer) { ++ require_foreground(c); ++ if (needs_keyboard) ++ for (const auto& weak : foreground_keyboards) { ++ const auto k = weak.lock(); ++ if (!k || !k->good()) throw ForegroundFailure{ForegroundFailureReason::keyboard_resources}; ++ k->sendMods(foreground_modifiers[0], foreground_modifiers[1], foreground_modifiers[2], foreground_modifiers[3]); ++ } ++ return; ++ } + foreground_activating = true; + ::Pointer::mgr()->warpTo({x + c.geometry[0], y + c.geometry[1]}); + if (lease != &c) throw ForegroundFailure{ForegroundFailureReason::lease}; +@@ -893,16 +933,17 @@ struct InputExperiment::Impl { } void foreground_key(Client& c, std::uint32_t code, bool pressed) { require_foreground(c); @@ -233,7 +347,7 @@ index fc7e740..f256fc4 100644 } } bool pointer_enter(Client& c, double x, double y) { -@@ -942,8 +949,8 @@ struct InputExperiment::Impl { +@@ -942,8 +983,8 @@ struct InputExperiment::Impl { held_button = pressed ? value : 0; } bool keyboard_enter(Client& c) { @@ -244,7 +358,7 @@ index fc7e740..f256fc4 100644 unsigned count = 0; for (auto& k : keyboards) { if (k->dead || !k->wl->resource() || k->wl->client() != root->client()) continue; -@@ -1030,7 +1037,7 @@ struct InputExperiment::Impl { +@@ -1030,7 +1071,7 @@ struct InputExperiment::Impl { if (kProduction && (!InputGrant::single_operation(requested_cap) || (requested_cap == 16 && route != InputRoute::primary_foreground))) { invalidate(c); send(c, refusal("unsupported")); return; } if (kProduction && !available()) { invalidate(c, false); send(c, refusal("session_unavailable")); return; } @@ -253,7 +367,7 @@ index fc7e740..f256fc4 100644 const auto pid = number(f[1]); const auto address = number(f[2], 16); PHLWINDOW window; for (const auto& w : Desktop::windowState()->windows()) -@@ -1090,7 +1097,7 @@ struct InputExperiment::Impl { +@@ -1090,7 +1131,7 @@ struct InputExperiment::Impl { if (c.token.empty() || f[2] != c.token || !refresh(c)) { send(c, refusal("stale_target")); return; } if (number(f[3]) != c.revision) { if (kProduction) revoke("stale_geometry"); send(c, refusal("stale_geometry")); return; } if (!available()) { revoke("session_unavailable", true); send(c, refusal("session_unavailable")); return; } @@ -262,18 +376,22 @@ index fc7e740..f256fc4 100644 if (lease && Clock::now() >= expires) revoke("lease_expired"); if (drag) { send(c, refusal("lease_busy")); return; } if (lease != &c || !(capabilities & cap) || (kProduction && !grant.permits(cap, Clock::now()))) { -@@ -1184,6 +1191,10 @@ struct InputExperiment::Impl { +@@ -1184,8 +1225,13 @@ struct InputExperiment::Impl { if (Clock::now() + std::chrono::milliseconds(duration + 50) >= expires) { send(c, refusal("lease_expired")); return; } } } -+ if (command == "KEY" && !foreground_chord_compatible(physical_keymap, keymap, code, mods)) { ++ const auto modifiers = capture_foreground_modifiers(command == "KEY"); ++ if (command == "KEY" && !foreground_chord_compatible(physical_keymap, keymap, code, mods, modifiers)) { + revoke("unsupported_layout", true); + send(c, refusal("unsupported_layout")); return; + } if (!consume_grant(c, cap)) return; - start_foreground(c, x, y, command != "KEY" && command != "ACTIVATE", command == "KEY"); +- start_foreground(c, x, y, command != "KEY" && command != "ACTIVATE", command == "KEY"); ++ start_foreground(c, x, y, command != "KEY" && command != "ACTIVATE", command == "KEY", modifiers); if (command == "KEY") { -@@ -1227,7 +1238,7 @@ struct InputExperiment::Impl { + const std::array keys{42, 29, 56, 125}; + for (unsigned i = 0; i < 4; ++i) if ((mods & (1u << i)) && keys[i] != code) foreground_key(c, keys[i], true); +@@ -1227,7 +1273,7 @@ struct InputExperiment::Impl { if (lease) { if (lease->dead) revoke("disconnected", true); else if (Clock::now() >= expires) revoke("lease_expired"); @@ -284,14 +402,15 @@ index fc7e740..f256fc4 100644 } diff --git a/src/keyboard_layout.hpp b/src/keyboard_layout.hpp new file mode 100644 -index 0000000..ab7defc +index 0000000..f5f51c8 --- /dev/null +++ b/src/keyboard_layout.hpp -@@ -0,0 +1,102 @@ +@@ -0,0 +1,127 @@ +#pragma once + +#include "foreground_route.hpp" +#include ++#include +#include +#include +#include @@ -359,16 +478,37 @@ index 0000000..ab7defc + return true; +} + ++// Resolve the virtual modifier through this map; Num Lock is not necessarily ++// encoded as Mod2. Ambiguous encodings are deliberately not admitted. ++inline xkb_mod_mask_t foreground_numlock_mask(xkb_keymap* map) { ++ const auto mask = map ? xkb_keymap_mod_get_mask(map, XKB_VMOD_NAME_NUM) : 0; ++ return mask && !(mask & (mask - 1)) && ++ !(mask & xkb_keymap_mod_get_mask(map, XKB_MOD_NAME_CAPS)) ? mask : 0; ++} ++ +// Simulate the complete chord before delivering any events or changing focus. +// This is compatibility checking, not layout translation: physical key positions +// remain unchanged. Unrelated remaps are harmless, requested remaps fail closed. +inline bool foreground_chord_compatible(xkb_keymap* physical, xkb_keymap* canonical, -+ std::uint32_t code, std::uint32_t mods) { ++ std::uint32_t code, std::uint32_t mods, ++ const std::array& modifiers) { + if (!physical || !canonical) return false; ++ if (foreground_key_modifier_failure(modifiers, foreground_numlock_mask(physical)) != ++ ForegroundFailureReason::none) return false; + using State = std::unique_ptr; + State actual{xkb_state_new(physical), xkb_state_unref}; + State expected{xkb_state_new(canonical), xkb_state_unref}; -+ if (!actual || !expected) return false; ++ // The client retains Num Lock, but wire keys still mean the neutral US ++ // chord. A third state rejects keypad/navigation changes caused by the lock. ++ State intended{xkb_state_new(canonical), xkb_state_unref}; ++ if (!actual || !expected || !intended) return false; ++ if (modifiers[2]) { ++ const auto canonical_lock = foreground_numlock_mask(canonical); ++ if (!canonical_lock) return false; ++ xkb_state_update_mask(actual.get(), 0, 0, modifiers[2], 0, 0, 0); ++ xkb_state_update_mask(expected.get(), 0, 0, canonical_lock, 0, 0, 0); ++ if (!same_modifier_state(actual.get(), expected.get())) return false; ++ } + const auto event = [&](std::uint32_t key, xkb_key_direction direction) { + // A client interprets the press using the preceding modifiers event. + // Stock both_capslock_cancel gives Shift a Caps_Lock symbol at its @@ -376,9 +516,12 @@ index 0000000..ab7defc + // keycode, but their lock/latch/group effects still must agree. + if (direction == XKB_KEY_DOWN && + (!same_key_symbols(actual.get(), expected.get(), key + 8) || -+ !same_consumed_modifiers(actual.get(), expected.get(), key + 8))) return false; ++ !same_consumed_modifiers(actual.get(), expected.get(), key + 8) || ++ !same_key_symbols(expected.get(), intended.get(), key + 8) || ++ !same_consumed_modifiers(expected.get(), intended.get(), key + 8))) return false; + xkb_state_update_key(actual.get(), key + 8, direction); + xkb_state_update_key(expected.get(), key + 8, direction); ++ xkb_state_update_key(intended.get(), key + 8, direction); + return same_modifier_state(actual.get(), expected.get()); + }; + constexpr std::array keys{42, 29, 56, 125}; @@ -391,7 +534,7 @@ index 0000000..ab7defc +} +} // namespace cua::hyprland diff --git a/src/plugin.cpp b/src/plugin.cpp -index 88b9900..2d24471 100644 +index 88b9900..ae7fc7c 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -218,6 +218,11 @@ std::string status_output(bool json) { @@ -401,7 +544,7 @@ index 88b9900..2d24471 100644 +#ifdef CUA_HYPRLAND_INPUT + // Installation checks compiled support before enabling input seats. + result.pop_back(); -+ result += ",\"keyboard_layout_independent\":true}"; ++ result += ",\"keyboard_layout_independent\":true,\"foreground_numlock_compatible\":true}"; +#endif #if defined(CUA_HYPRLAND_TEST_INPUT) || defined(CUA_HYPRLAND_INPUT) if (g_experiment) { @@ -583,12 +726,243 @@ index 68ca6c8..7a4d1b4 100644 return (ROOT / 'tests/desktop_fault_policy_fixture.cpp').read_text().replace( '// PRODUCTION_METHODS', methods) +diff --git a/tests/foreground_modifiers_test.py b/tests/foreground_modifiers_test.py +new file mode 100644 +index 0000000..013c9bf +--- /dev/null ++++ b/tests/foreground_modifiers_test.py +@@ -0,0 +1,225 @@ ++"""Exercise production foreground state admission, dispatch and unwind with XKB.""" ++import os ++from pathlib import Path ++import re ++import shlex ++import subprocess ++import tempfile ++import unittest ++ ++ROOT = Path(__file__).resolve().parents[1] ++ ++ ++class ForegroundModifiersTest(unittest.TestCase): ++ def test_production_modifiers(self): ++ source = (ROOT / 'src/input_experiment.cpp').read_text() ++ methods = [] ++ for name in ('capture_foreground_modifiers', 'require_foreground', 'finish_foreground', ++ 'start_foreground', 'foreground_key'): ++ body = re.search(r'^ \S[^\n]*\b' + name + r'\(.*?^ }', source, re.M | re.S) ++ self.assertIsNotNone(body, name) ++ methods.append(body.group()) ++ preflight = re.search(r' const auto modifiers = capture_foreground_modifiers\(command == "KEY"\);.*?' ++ r' start_foreground\([^\n]*;', source, re.S) ++ self.assertIsNotNone(preflight) ++ fixture = r''' ++#include "keyboard_layout.hpp" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++using namespace cua::hyprland; ++using Clock = std::chrono::steady_clock; ++void check(bool ok, const char* why) { if (!ok) { std::cerr << why; std::exit(1); } } ++struct Vector2D { double x, y; }; ++constexpr int WL_KEYBOARD_KEY_STATE_PRESSED=1, WL_KEYBOARD_KEY_STATE_RELEASED=0; ++constexpr int WL_POINTER_BUTTON_STATE_RELEASED=0; ++struct Root : std::enable_shared_from_this { ++ bool good() const { return true; } ++ int client() const { return 0; } ++ auto at(Vector2D, bool) { return std::pair{shared_from_this(), 0}; } ++}; ++struct Resource { ++ xkb_state* client = nullptr; ++ std::vector symbols; ++ std::array last{}; ++ std::vector> history; ++ bool good() const { return true; } ++ void sendKey(unsigned, unsigned code, unsigned down) { ++ if (down) symbols.push_back(xkb_state_key_get_one_sym(client, code + 8)); ++ } ++ void sendMods(unsigned d, unsigned l, unsigned k, unsigned g) { ++ last={d,l,k,g}; history.push_back(last); xkb_state_update_mask(client,d,l,k,0,0,g); ++ } ++ void sendButton(unsigned, unsigned, unsigned) {} ++ void sendFrame() {} ++}; ++struct Keyboard { ++ struct { unsigned depressed=0,latched=0,locked=0,group=0; } m_modifiersState; ++ xkb_keymap* m_xkbKeymap = nullptr; ++ bool m_enabled=true, shared=true, virt=false; ++ bool shareStates() const { return shared; } ++ bool isVirtual() const { return virt; } ++}; ++struct Seat { ++ std::vector> m_keyboards, m_pointers; ++ bool good() const { return true; } ++}; ++struct SeatManager { ++ std::weak_ptr m_keyboard; ++ bool m_mouse=true; ++ struct { std::shared_ptr keyboardFocus, pointerFocus; } m_state; ++ std::shared_ptr seat; ++ auto seatResourceForClient(int) { return seat; } ++ void setPointerFocus(std::shared_ptr root, Vector2D) { m_state.pointerFocus=root; } ++} manager, *g_pSeatManager=&manager; ++struct InputManager { ++ std::vector> m_keyboards; ++ bool shouldIgnoreVirtualKeyboard(const std::shared_ptr&) { return false; } ++} input, *g_pInputManager=&input; ++namespace Desktop { ++constexpr int FOCUS_REASON_OTHER=0; ++struct Focus { ++ std::shared_ptr root; ++ std::shared_ptr change_on_focus; ++ auto window() { return root; } ++ auto surface() { return root; } ++ void fullWindowFocus(std::shared_ptr, int, std::shared_ptr r) { ++ root=r; manager.m_state.keyboardFocus=r; ++ if (change_on_focus) change_on_focus->m_modifiersState.locked=0; ++ } ++} focus; ++auto focusState() { return &focus; } ++} ++namespace Pointer { struct Manager { void warpTo(Vector2D) {} } pointer; auto mgr(){ return &pointer; } } ++struct Client { ++ bool dead=false, foreground_attempted=false; ++ std::weak_ptr surface, window; ++ std::array geometry{}; ++}; ++struct Lane { ++ xkb_keymap* physical_keymap=nullptr; ++ xkb_keymap* keymap=nullptr; ++ xkb_state* physical_state=nullptr; ++ std::array foreground_modifiers{}; ++ std::vector> foreground_keyboards, foreground_pointers; ++ std::weak_ptr foreground_surface; ++ std::weak_ptr foreground_seat; ++ std::vector held_keys; ++ unsigned held_button=0; ++ bool foreground_started=false,foreground_activating=false,foreground_keyboard_used=false; ++ bool foreground_needs_pointer=false, layout_ready=true, physical_held=false; ++ Client* lease=nullptr; ++ Clock::time_point expires=Clock::now()+std::chrono::hours(1); ++ unsigned consumed=0, refused=0; ++ bool available() { return true; } ++ bool physical_layout_ready() { return layout_ready; } ++ bool point(Client&, double,double) { return true; } ++ unsigned event_ms() { return 0; } ++ void foreground_motion(Client&,double,double) {} ++ ForegroundGuard foreground_guard(Client&) { ++ return {.exact_root=true,.physical_keys=physical_held,.exact_keyboard_focus=true,.exact_pointer_focus=true}; ++ } ++ void revoke(const char*, bool) {} ++ auto refusal(const char*) { return std::string{}; } ++ void send(Client&, const std::string&) { ++refused; } ++ bool consume_grant(Client&, unsigned) { ++consumed; return true; } ++ // METHODS ++ void preflight(Client& c, unsigned code, unsigned mods) { ++ const std::string command="KEY"; ++ const unsigned cap=2; ++ const double x=0,y=0; ++ // PREFLIGHT ++ } ++ ~Lane() { if (physical_state) xkb_state_unref(physical_state); } ++}; ++int main() { ++ auto context=xkb_context_new(XKB_CONTEXT_NO_FLAGS); ++ const xkb_rule_names names{"evdev","pc105","us","","ctrl:nocaps"}; ++ auto physical=xkb_keymap_new_from_names(context,&names,XKB_KEYMAP_COMPILE_NO_FLAGS); ++ auto canonical=agent_keymap(context); ++ auto keyboard=std::make_shared(); keyboard->m_xkbKeymap=physical; ++ manager.m_keyboard=keyboard; input.m_keyboards={keyboard}; ++ auto root=std::make_shared(); ++ manager.m_state.keyboardFocus=root; manager.m_state.pointerFocus=root; Desktop::focus.root=root; ++ manager.seat=std::make_shared(); auto resource=std::make_shared(); ++ resource->client=xkb_state_new(physical); manager.seat->m_keyboards={resource}; ++ Client client; client.surface=root; client.window=root; ++ Lane lane; lane.physical_keymap=physical; lane.keymap=canonical; ++ lane.physical_state=xkb_state_new(physical); lane.lease=&client; ++ const auto num=foreground_numlock_mask(physical); ++ keyboard->m_modifiersState.locked=num; ++ lane.preflight(client,30,1); ++ check(lane.foreground_started && lane.foreground_modifiers[2]==num && resource->last[2]==num, ++ "actual Num Lock state was not captured and published before input"); ++ lane.foreground_key(client,42,true); lane.foreground_key(client,30,true); ++ lane.foreground_key(client,30,false); lane.foreground_key(client,42,false); ++ check(resource->symbols.back()==XKB_KEY_A,"client did not receive intended shifted text"); ++ for (const auto& state : resource->history) ++ check(state[2]==num,"dispatch transiently cleared Num Lock"); ++ lane.finish_foreground(); ++ check(resource->last==std::array{0,0,num,0} && keyboard->m_modifiersState.locked==num, ++ "completion changed real or client Num Lock state"); ++ const auto consumed=lane.consumed; ++ lane.preflight(client,79,0); ++ check(lane.refused==1 && lane.consumed==consumed && !lane.foreground_started, ++ "caller checked neutral state and admitted Num Lock keypad semantics"); ++ keyboard->m_modifiersState.locked=0; ++ lane.preflight(client,79,0); lane.foreground_key(client,79,true); lane.foreground_key(client,79,false); ++ check(resource->symbols.back()==XKB_KEY_KP_End,"neutral keypad contract changed"); lane.finish_foreground(); ++ keyboard->m_modifiersState.locked=num; lane.preflight(client,30,1); lane.foreground_key(client,42,true); ++ keyboard->m_modifiersState.locked=0; ++ try { lane.foreground_key(client,30,true); check(false,"ambient state change accepted"); } ++ catch (ForegroundFailure f) { check(f.reason==ForegroundFailureReason::keyboard_state,"wrong state change refusal"); } ++ lane.finish_foreground(); check(resource->last==std::array{},"cancellation restored stale Num Lock"); ++ keyboard->m_modifiersState.locked=num; lane.preflight(client,30,1); lane.foreground_key(client,42,true); ++ keyboard->m_modifiersState.locked=xkb_keymap_mod_get_mask(physical,XKB_MOD_NAME_CAPS); ++ keyboard->m_modifiersState.depressed=xkb_keymap_mod_get_mask(physical,XKB_MOD_NAME_CTRL); ++ lane.finish_foreground(); ++ check(resource->last[0]==keyboard->m_modifiersState.depressed && resource->last[2]==keyboard->m_modifiersState.locked, ++ "cancellation failed to restore current human Caps and held Control"); ++ keyboard->m_modifiersState.depressed=0; keyboard->m_modifiersState.locked=num; ++ lane.physical_held=true; ++ try { lane.preflight(client,30,0); check(false,"held physical key admitted"); } ++ catch (ForegroundFailure f) { check(f.reason==ForegroundFailureReason::physical_keys,"wrong held-key refusal"); } ++ lane.physical_held=false; ++ auto shared=std::make_shared(); shared->m_xkbKeymap=physical; ++ shared->m_modifiersState.locked=num; ++ keyboard->m_modifiersState.locked=0; ++ input.m_keyboards.push_back(shared); ++ lane.preflight(client,30,0); ++ check(lane.foreground_modifiers[2]==num && resource->last[2]==num,"shared Num Lock was ignored"); ++ lane.foreground_key(client,30,true); lane.foreground_key(client,30,false); lane.finish_foreground(); ++ check(resource->last[2]==num,"shared Num Lock not restored"); ++ shared->m_modifiersState.locked=xkb_keymap_mod_get_mask(physical,XKB_MOD_NAME_CAPS); ++ try { lane.preflight(client,30,0); check(false,"shared Caps state admitted"); } ++ catch (ForegroundFailure f) { check(f.reason==ForegroundFailureReason::keyboard_locked,"wrong shared lock refusal"); } ++ shared->shared=false; lane.preflight(client,30,0); lane.finish_foreground(); ++ // Focus callbacks can change real state between preflight and first event. ++ keyboard->m_modifiersState.locked=num; ++ Desktop::focus.root.reset(); Desktop::focus.change_on_focus=keyboard; ++ try { lane.preflight(client,30,0); check(false,"focus-time state change accepted"); } ++ catch (ForegroundFailure f) { check(f.reason==ForegroundFailureReason::keyboard_state,"wrong focus change refusal"); } ++ lane.finish_foreground(); ++ check(resource->last[2]==0,"focus-time cancellation restored stale lock"); ++ xkb_state_unref(resource->client); xkb_keymap_unref(physical); xkb_keymap_unref(canonical); xkb_context_unref(context); ++} ++'''.replace('// METHODS', '\n'.join(methods)).replace('// PREFLIGHT', preflight.group()) ++ compiler = shlex.split(os.environ.get('CXX', 'c++')) ++ flags = shlex.split(subprocess.check_output(['pkg-config', '--cflags', '--libs', 'xkbcommon'], text=True)) ++ with tempfile.TemporaryDirectory(prefix='cua-foreground-modifiers-') as directory: ++ cpp, binary = Path(directory) / 'fixture.cpp', Path(directory) / 'fixture' ++ cpp.write_text(fixture) ++ build = subprocess.run([*compiler, '-std=c++20', '-Wall', '-Wextra', '-Wpedantic', '-Werror', ++ '-I', str(ROOT / 'src'), str(cpp), '-o', str(binary), *flags], ++ capture_output=True, text=True, timeout=60) ++ self.assertEqual(build.returncode, 0, build.stdout + build.stderr) ++ result = subprocess.run([str(binary)], capture_output=True, text=True, timeout=10) ++ self.assertEqual(result.returncode, 0, result.stdout + result.stderr) ++ ++ ++if __name__ == '__main__': ++ unittest.main() diff --git a/tests/keyboard_layout_test.cpp b/tests/keyboard_layout_test.cpp new file mode 100644 -index 0000000..dd7c962 +index 0000000..6d57616 --- /dev/null +++ b/tests/keyboard_layout_test.cpp -@@ -0,0 +1,97 @@ +@@ -0,0 +1,130 @@ +#include "keyboard_layout.hpp" +#include +#include @@ -617,24 +991,53 @@ index 0000000..dd7c962 + auto german = map("de", ""); + check(stock && nocaps && swapctrl && swapalt && german, "test keymaps unavailable"); + for (auto* physical : {stock.get(), nocaps.get(), swapctrl.get(), swapalt.get(), german.get()}) { -+ check(foreground_chord_compatible(physical, agent.get(), 30, 0), "unrelated remap blocked A"); -+ check(foreground_chord_compatible(physical, agent.get(), 30, 1), "unrelated remap blocked Shift+A"); -+ check(foreground_chord_compatible(physical, agent.get(), 28, 0), "unrelated remap blocked Return"); ++ check(foreground_chord_compatible(physical, agent.get(), 30, 0, {}), "unrelated remap blocked A"); ++ check(foreground_chord_compatible(physical, agent.get(), 30, 1, {}), "unrelated remap blocked Shift+A"); ++ check(foreground_chord_compatible(physical, agent.get(), 28, 0, {}), "unrelated remap blocked Return"); + } -+ check(foreground_chord_compatible(stock.get(), agent.get(), 30, 2), "stock Omarchy blocked Ctrl+A"); -+ check(foreground_chord_compatible(nocaps.get(), agent.get(), 30, 2), "Caps to Ctrl blocked Ctrl+A"); -+ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 30, 2), "Ctrl/Caps swap sent wrong Ctrl+A"); -+ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 29, 0), "remapped modifier key accepted"); -+ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 4), "Alt/Super swap sent wrong Alt+A"); -+ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 8), "Alt/Super swap sent wrong Super+A"); -+ check(!foreground_chord_compatible(german.get(), agent.get(), 21, 0), "German Z accepted as US Y"); -+ check(!foreground_chord_compatible(german.get(), agent.get(), 3, 1), "German shifted punctuation accepted"); -+ check(!foreground_chord_compatible(nullptr, agent.get(), 30, 0), "missing physical map accepted"); ++ check(foreground_chord_compatible(stock.get(), agent.get(), 30, 2, {}), "stock Omarchy blocked Ctrl+A"); ++ check(foreground_chord_compatible(nocaps.get(), agent.get(), 30, 2, {}), "Caps to Ctrl blocked Ctrl+A"); ++ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 30, 2, {}), "Ctrl/Caps swap sent wrong Ctrl+A"); ++ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 29, 0, {}), "remapped modifier key accepted"); ++ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 4, {}), "Alt/Super swap sent wrong Alt+A"); ++ check(!foreground_chord_compatible(swapalt.get(), agent.get(), 30, 8, {}), "Alt/Super swap sent wrong Super+A"); ++ check(!foreground_chord_compatible(german.get(), agent.get(), 21, 0, {}), "German Z accepted as US Y"); ++ check(!foreground_chord_compatible(german.get(), agent.get(), 3, 1, {}), "German shifted punctuation accepted"); ++ check(!foreground_chord_compatible(nullptr, agent.get(), 30, 0, {}), "missing physical map accepted"); ++ for (auto* physical : {agent.get(), stock.get(), nocaps.get()}) { ++ const auto numlock = foreground_numlock_mask(physical); ++ check(numlock != 0, "Num Lock encoding missing"); ++ for (const auto locked : {0u, numlock}) { ++ const std::array ambient{0, 0, locked, 0}; ++ for (const auto key : {30u, 48u, 44u, 2u, 11u, 28u, 57u}) ++ for (const auto mods : {0u, 1u, 2u, 3u}) ++ check(foreground_chord_compatible(physical, agent.get(), key, mods, ambient), ++ "Num Lock blocked ordinary text or shortcut"); ++ for (const auto key : {71u, 72u, 75u, 79u, 82u, 83u}) ++ check(foreground_chord_compatible(physical, agent.get(), key, 0, ambient) == !locked, ++ "Num Lock keypad semantic change was ignored"); ++ } ++ const auto caps = xkb_keymap_mod_get_mask(physical, XKB_MOD_NAME_CAPS); ++ for (const auto locked : {caps, caps | numlock, 0x80000000u}) ++ check(!foreground_chord_compatible(physical, agent.get(), 30, 0, {0, 0, locked, 0}), ++ "unsupported lock accepted"); ++ check(!foreground_chord_compatible(physical, agent.get(), 30, 0, {numlock, 0, numlock, 0}), ++ "held modifier accepted with Num Lock"); ++ check(!foreground_chord_compatible(physical, agent.get(), 30, 0, {0, numlock, numlock, 0}), ++ "latched modifier accepted with Num Lock"); ++ check(!foreground_chord_compatible(physical, agent.get(), 30, 0, {0, 0, numlock, 1}), ++ "nonzero group accepted with Num Lock"); ++ } ++ const auto numlock = foreground_numlock_mask(agent.get()); ++ check(!foreground_chord_compatible(swapctrl.get(), agent.get(), 30, 2, {0, 0, numlock, 0}), ++ "Num Lock hid Ctrl remap"); ++ check(!foreground_chord_compatible(german.get(), agent.get(), 21, 0, {0, 0, numlock, 0}), ++ "Num Lock hid layout mismatch"); + // All supported wire chords remain compatible on the independent map. + for (unsigned code = 1; code <= 247; ++code) + if (code != 58 && code != 69 && code != 70) + for (unsigned mods = 0; mods < 16; ++mods) -+ check(foreground_chord_compatible(agent.get(), agent.get(), code, mods), "canonical chord rejected"); ++ check(foreground_chord_compatible(agent.get(), agent.get(), code, mods, {}), "canonical chord rejected"); + // Two lanes never share modifier state and never mutate the human state. + State first{xkb_state_new(agent.get()), xkb_state_unref}; + State other{xkb_state_new(second.get()), xkb_state_unref}; @@ -654,7 +1057,9 @@ index 0000000..dd7c962 + "key { type=\"ALPHABETIC\", symbols[Group1]=[a,A], actions[Group1]=[LockMods(modifiers=Mod3),LockMods(modifiers=Mod3)] };"); + Map lock{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; + check(bool(lock), "action fixture failed to compile"); -+ check(!foreground_chord_compatible(lock.get(), agent.get(), 30, 0), "hidden lock action accepted"); ++ check(!foreground_chord_compatible(lock.get(), agent.get(), 30, 0, {}), "hidden lock action accepted"); ++ check(!foreground_chord_compatible(lock.get(), agent.get(), 30, 0, {0, 0, numlock, 0}), ++ "Num Lock hid an unexpected lock action"); + // Equal symbols and modifier state can still alter toolkit shortcut matching. + serialized = xkb_keymap_get_as_string(agent.get(), XKB_KEYMAP_FORMAT_TEXT_V1); + changed = serialized; @@ -665,7 +1070,9 @@ index 0000000..dd7c962 + changed.insert(type_end, "preserve[Shift] = Shift;\n"); + Map preserved{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; + check(bool(preserved), "preserved modifier fixture failed to compile"); -+ check(!foreground_chord_compatible(preserved.get(), agent.get(), 30, 1), "consumed modifier mismatch accepted"); ++ check(!foreground_chord_compatible(preserved.get(), agent.get(), 30, 1, {}), "consumed modifier mismatch accepted"); ++ check(!foreground_chord_compatible(preserved.get(), agent.get(), 30, 1, {0, 0, numlock, 0}), ++ "Num Lock hid changed shortcut consumption"); + // A modifier that preserves Shift state but emits another symbol must fail. + serialized = xkb_keymap_get_as_string(agent.get(), XKB_KEYMAP_FORMAT_TEXT_V1); + changed = serialized; @@ -677,7 +1084,7 @@ index 0000000..dd7c962 + "key { symbols[Group1]=[Delete], actions[Group1]=[SetMods(modifiers=Shift)] };"); + Map badshift{xkb_keymap_new_from_string(context.get(), changed.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS), xkb_keymap_unref}; + check(bool(badshift), "shift fixture failed to compile"); -+ check(!foreground_chord_compatible(badshift.get(), agent.get(), 30, 1), "modifier press symbols not checked"); ++ check(!foreground_chord_compatible(badshift.get(), agent.get(), 30, 1, {}), "modifier press symbols not checked"); + for (auto route : {InputRoute::independent, InputRoute::primary_foreground}) { + for (uint64_t cap : {1, 4, 8, 16}) check(keyboard_layout_ready(route, cap, false, false), "pointer gated on layout"); + check(!keyboard_layout_ready(route, 2, false, false), "key accepted without map"); @@ -687,7 +1094,7 @@ index 0000000..dd7c962 + std::cout << "keyboard layout tests passed\n"; +} diff --git a/tests/plugin_input_lifetime_test.cpp b/tests/plugin_input_lifetime_test.cpp -index ff09451..b999925 100644 +index ff09451..456da44 100644 --- a/tests/plugin_input_lifetime_test.cpp +++ b/tests/plugin_input_lifetime_test.cpp @@ -51,12 +51,17 @@ int main() { @@ -703,17 +1110,18 @@ index ff09451..b999925 100644 }; +#ifdef CUA_HYPRLAND_INPUT + const auto initial_status = HyprlandAPI::registered_legacy_command->fn(FORMAT_JSON, {}); -+ check(created == 0 && initial_status.find("\"configured\":false") != std::string::npos && initial_status.find("\"keyboard_layout_independent\":true") != std::string::npos, ++ check(created == 0 && initial_status.find("\"configured\":false") != std::string::npos && initial_status.find("\"keyboard_layout_independent\":true") != std::string::npos && initial_status.find("\"foreground_numlock_compatible\":true") != std::string::npos, + "disabled production module advertises compiled keyboard support before enable"); +#endif for (unsigned i = 0; i < 20; ++i) { toggle(true); #ifdef CUA_HYPRLAND_INPUT -@@ -64,6 +69,7 @@ int main() { +@@ -64,6 +69,8 @@ int main() { check(status.find("\"state\":\"input_v3_candidate\"") != std::string::npos && status.find("trusted_local_per_action") != std::string::npos && status.find("\"input\":{}") != std::string::npos && + status.find("\"keyboard_layout_independent\":true") != std::string::npos && ++ status.find("\"foreground_numlock_compatible\":true") != std::string::npos && status.find("operator") == std::string::npos, "v3 status advertises its actual admission mode"); #endif From e95c6f37de9d1ffc149fcfef0ac2e987a24a0626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Wed, 16 Sep 2026 14:08:43 +0900 Subject: [PATCH 025/121] Update Linux kernel release to v7.2.5-4 for base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- pkgbuilds/linux-omarchy-bore/PKGBUILD | 2 +- pkgbuilds/linux-omarchy/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index df7c3cd..5fcf831 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy-bore pkgver=7.2.5 -pkgrel=3 +pkgrel=4 pkgdesc='Omarchy Linux (BORE CPU scheduler, ADIOS I/O scheduler)' url='https://omarchy.org' arch=( diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 9f63644..660c9e2 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy pkgver=7.2.5 -pkgrel=3 +pkgrel=4 pkgdesc='Omarchy Linux' url='https://omarchy.org' arch=( From 97871759bba15a3c5e71aae4f4c28a8bdc81e59c Mon Sep 17 00:00:00 2001 From: dhh <2741+dhh@users.noreply.github.com> Date: Wed, 16 Sep 2026 11:50:57 +0000 Subject: [PATCH 026/121] chore: sync upstream releases --- pkgbuilds/claude-code/PKGBUILD | 6 +++--- pkgbuilds/claude-desktop/PKGBUILD | 6 +++--- pkgbuilds/crush-bin/PKGBUILD | 10 +++++----- pkgbuilds/dropbox/PKGBUILD | 4 ++-- pkgbuilds/github-copilot-cli/PKGBUILD | 6 +++--- pkgbuilds/mise-bin/PKGBUILD | 6 +++--- pkgbuilds/strata/PKGBUILD | 4 ++-- pkgbuilds/t3code-bin/PKGBUILD | 4 ++-- pkgbuilds/visual-studio-code-bin/PKGBUILD | 8 ++++---- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pkgbuilds/claude-code/PKGBUILD b/pkgbuilds/claude-code/PKGBUILD index 700db29..4004045 100644 --- a/pkgbuilds/claude-code/PKGBUILD +++ b/pkgbuilds/claude-code/PKGBUILD @@ -4,7 +4,7 @@ # Automation repository: https://github.com/fabifont/claude-code-aur pkgname=claude-code -pkgver=2.1.272 +pkgver=2.1.273 pkgrel=1 pkgdesc="An agentic coding tool that lives in your terminal" arch=('x86_64' 'aarch64') @@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude") sha256sums=('SKIP') -sha256sums_x86_64=('d81396a668eb76fbddb49a2a5841f1b5d7af96b4c1f6500ced92f2c988f5bcd4') -sha256sums_aarch64=('214a90efdd16ee0ea81132ffecced588dba394d178cc494f285ba04b5288c8de') +sha256sums_x86_64=('6c752e2cc7c110c9df15f26d8d134d438c5ae95dbd610efc1a308bf7f9c5f6c1') +sha256sums_aarch64=('103cfab4d6ae898b6af692336fb662ffcc607075cc6408892bd350b3f549ebee') package() { install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude" diff --git a/pkgbuilds/claude-desktop/PKGBUILD b/pkgbuilds/claude-desktop/PKGBUILD index c7728fb..308d94a 100644 --- a/pkgbuilds/claude-desktop/PKGBUILD +++ b/pkgbuilds/claude-desktop/PKGBUILD @@ -6,7 +6,7 @@ # repository's package index. pkgname=claude-desktop -pkgver=1.52386.6 +pkgver=2.110.0 pkgrel=1 pkgdesc="Official Claude desktop app with Claude Code" arch=('x86_64' 'aarch64') @@ -63,8 +63,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('edfdbc63b65891ef7c481b07086c7e630fc102c042b6ed65331a52fcaf72b14a') -sha256sums_x86_64=('2e83a76c6ed9187671bfe80664fc6d59840171f4a2a81f408662c879a67f4e0a') -sha256sums_aarch64=('882f4a52a86b07ecff989d8db87c5ec292d43f21d0a6557d3e8b01e113b18190') +sha256sums_x86_64=('f44cb8b52f6e9171ac2e67cbcc8070c4974a2f0a9b9f141b430b32b4ff541109') +sha256sums_aarch64=('de9f24034f33dcadc53bedee92da6604e2c9268497ebff5447fedc092c884e71') package() { cd "${srcdir}" diff --git a/pkgbuilds/crush-bin/PKGBUILD b/pkgbuilds/crush-bin/PKGBUILD index 6c3d0ba..564caf8 100644 --- a/pkgbuilds/crush-bin/PKGBUILD +++ b/pkgbuilds/crush-bin/PKGBUILD @@ -3,7 +3,7 @@ # Maintainer: caarlos0 pkgname='crush-bin' -pkgver=0.94.2 +pkgver=0.95.0 pkgrel=1 pkgdesc='A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal.' url='https://charm.sh/crush' @@ -13,16 +13,16 @@ provides=('crush') conflicts=('crush') source_aarch64=("${pkgname}_${pkgver}_aarch64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_arm64.tar.gz") -sha256sums_aarch64=('3a9d00d135632b6b3f8821814ceb81512839d346d628ebac23a445b126e1f51c') +sha256sums_aarch64=('b42291307abe5572afb972fba9b8780f63a2058f37fb0dc61ab4c7b435314a8a') source_armv7h=("${pkgname}_${pkgver}_armv7h.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_armv7.tar.gz") -sha256sums_armv7h=('0c183c369af79a5e37e45cc98df2093e3381c1fd4c7fb3dc204d3c765f96f138') +sha256sums_armv7h=('756363804b6475ab6bf811f175a93766f47372beddb6e4a7b6e365ecba3f90ae') source_i686=("${pkgname}_${pkgver}_i686.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_i386.tar.gz") -sha256sums_i686=('d7b54a61bd112ba8c98b1ddb2229e93d53688d2bed8794cb9e3c6055489620ad') +sha256sums_i686=('ce7b0dec1f1d9aa5a6e339f04e835bc6b3a335caf816dcb6c83a2f808d9fcd3b') source_x86_64=("${pkgname}_${pkgver}_x86_64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_x86_64.tar.gz") -sha256sums_x86_64=('50df13841b617956690d3ca2881ed8601798e557ff187513ab7daff355621dc3') +sha256sums_x86_64=('edef832ff1fc03e420a0410b9653547feb816bda7e0458589434ea4164210f5e') package() { case "$CARCH" in diff --git a/pkgbuilds/dropbox/PKGBUILD b/pkgbuilds/dropbox/PKGBUILD index 0b081a1..5e052aa 100644 --- a/pkgbuilds/dropbox/PKGBUILD +++ b/pkgbuilds/dropbox/PKGBUILD @@ -4,7 +4,7 @@ # Contributor: David Manouchehri pkgname=dropbox -pkgver=268.4.4124 +pkgver=270.4.3312 pkgrel=1 pkgdesc="A free service that lets you bring your photos, docs, and videos anywhere and share them easily." arch=("x86_64") @@ -27,7 +27,7 @@ source=("DropboxGlyph_Blue.svg" "dropbox@.service" "https://edge.dropboxstatic.com/dbx-releng/client/dropbox-lnx.x86_64-$pkgver.tar.gz"{,.asc}) -sha256sums=('9ba76205ec5838db85d822f23cfd7e2112fd2757e8031d8374709f102143c548' '1610ff57e8b20ee7a37682c3cc505da4ddc9cec2bd7234c90c0f2073657521d2' '6c67a9c8c95c08fafafd2f1d828074b13e3347b05d2e4f4bf4e62746115d7477' '98581e65a91ae1f19ed42edcdaaa52e102298b5da0d71b50089393d364474d3d' 'fccaaa9fbe008e56729fafe13b581e2106f38a8b6f5d61de8bf546f349d5b155' 'SKIP') +sha256sums=('9ba76205ec5838db85d822f23cfd7e2112fd2757e8031d8374709f102143c548' '1610ff57e8b20ee7a37682c3cc505da4ddc9cec2bd7234c90c0f2073657521d2' '6c67a9c8c95c08fafafd2f1d828074b13e3347b05d2e4f4bf4e62746115d7477' '98581e65a91ae1f19ed42edcdaaa52e102298b5da0d71b50089393d364474d3d' '35404957d2a15dcac998d53cbec692d5236e197493f6c009accd91ea9aa8f34c' 'SKIP') # The PGP key fingerprint should match the one on https://www.dropbox.com/help/desktop-web/linux-commands validpgpkeys=( '1C61A2656FB57B7E4DE0F4C1FC918B335044912E' # Dropbox Automatic Signing Key diff --git a/pkgbuilds/github-copilot-cli/PKGBUILD b/pkgbuilds/github-copilot-cli/PKGBUILD index 917dca5..97bc32b 100644 --- a/pkgbuilds/github-copilot-cli/PKGBUILD +++ b/pkgbuilds/github-copilot-cli/PKGBUILD @@ -6,7 +6,7 @@ _npmmodule=@github/copilot pkgname=github-copilot-cli _pkgexec=copilot -pkgver=1.0.83 +pkgver=1.0.85 pkgrel=1 pkgdesc="GitHub Copilot CLI brings the power of Copilot coding agent directly to your terminal." @@ -31,8 +31,8 @@ source=("https://registry.npmjs.org/${_npmmodule}/-/copilot-${pkgver}.tgz" noextract=("copilot-${pkgver}.tgz") sha256sums=( - '135506fc2b13163ab55dbf76a06e2fbcbad04ecac76b4e9c6659f0ba309e6a86' - '0c0064a10effac8adf9ad97338bafaa0d7d7d5bf191cc1c0384e05ff4366d36c' + 'd26e3c15310bdcdcc910ed223285bed8d68aaebce0d344f97224b5cfdaeeee36' + '1b1a8fbd5562df73684b6e94865837ceffd6609d61822c39e6c8fcbd32d8ac41' ) # Document: https://wiki.archlinux.org/title/Node.js_package_guidelines diff --git a/pkgbuilds/mise-bin/PKGBUILD b/pkgbuilds/mise-bin/PKGBUILD index a7e07a6..1b8c274 100644 --- a/pkgbuilds/mise-bin/PKGBUILD +++ b/pkgbuilds/mise-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Jeff Dickey pkgname=mise-bin -pkgver=2026.9.7 +pkgver=2026.9.9 pkgrel=1 pkgdesc="dev tools, env vars, task runner" arch=('x86_64' 'aarch64') @@ -14,8 +14,8 @@ provides=('mise') conflicts=('mise') source_x86_64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-x64.tar.xz") source_aarch64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-arm64.tar.xz") -sha256sums_x86_64=('011e71834ef919c775f8d8ba7a985295a39a3ffe322b5f87a61cc0293eb6567f') -sha256sums_aarch64=('3c43ee044bb7d8bdaea800e1796a0b5d983276384f81d477c059a2b910042e16') +sha256sums_x86_64=('ed3ee9b7331182e57f77230cf6af64d90e6e1a01e2c3e4749568ea335837c0fb') +sha256sums_aarch64=('09d0489db27c173d1427b4248e3e1fbf18b00ccc1d887d8746f1d8b311903a50') package() { install -Dm755 "${srcdir}/mise/bin/mise" "${pkgdir}/usr/bin/mise" diff --git a/pkgbuilds/strata/PKGBUILD b/pkgbuilds/strata/PKGBUILD index 6672d2a..a94b4ed 100644 --- a/pkgbuilds/strata/PKGBUILD +++ b/pkgbuilds/strata/PKGBUILD @@ -1,5 +1,5 @@ pkgname=strata -pkgver=0.17.0 +pkgver=0.18.0 pkgrel=1 pkgdesc='Fast, keyboard-first file manager for modern Linux desktops' arch=('x86_64' 'aarch64') @@ -39,7 +39,7 @@ conflicts=('strata-git') options=('!debug' '!lto') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('d1f54c1a2d88b958f5d463c9c37fac73a982de7ae893b7c731820cf557d24f5f') +sha256sums=('82cfa5701f537e53d235b30e9450e1fcd5f2e7ccfea64ba317941e8e8766094b') prepare() { cd "$pkgname-$pkgver" diff --git a/pkgbuilds/t3code-bin/PKGBUILD b/pkgbuilds/t3code-bin/PKGBUILD index d848b90..fe90494 100644 --- a/pkgbuilds/t3code-bin/PKGBUILD +++ b/pkgbuilds/t3code-bin/PKGBUILD @@ -7,7 +7,7 @@ # from the release feed the app updates itself from. pkgname=t3code-bin -pkgver=0.0.40 +pkgver=0.0.42 pkgrel=1 pkgdesc="Open-source control plane for coding agents" arch=('x86_64') @@ -61,7 +61,7 @@ noextract=("${_appimage}") sha256sums=('cb905ff341372ef2ef6e402cf485959f8bd1df8f0efebee4cda1afdd5e6abc0a' 'c5b3f2a9f0b14b12cfd973b79319f0f018b7ae49a1d43d8ca346100c3f7de28f' '935d8f2af0c703f9c39517ee57cc4930b19d02d533be930b63f0e82f93614b43') -sha256sums_x86_64=('8bf5fd44cb7fad0c43191d54fefdf974a8227d50505ecb8abcf76326209f264a') +sha256sums_x86_64=('8dc1fccdabc2ed3a59a3944cc772ef11931b9351401c0963ed305d5f96e3cdf4') prepare() { chmod +x "${srcdir}/${_appimage}" diff --git a/pkgbuilds/visual-studio-code-bin/PKGBUILD b/pkgbuilds/visual-studio-code-bin/PKGBUILD index 08ad707..4d43a57 100644 --- a/pkgbuilds/visual-studio-code-bin/PKGBUILD +++ b/pkgbuilds/visual-studio-code-bin/PKGBUILD @@ -2,7 +2,7 @@ pkgname=visual-studio-code-bin _pkgname=visual-studio-code -pkgver=1.137.0 +pkgver=1.138.0 pkgrel=1 pkgdesc="Visual Studio Code (vscode): Editor for building and debugging modern web and cloud applications (official binary version)" arch=('x86_64' 'aarch64' 'armv7h') @@ -27,9 +27,9 @@ source_x86_64=(code_${pkgver}_amd64.deb::https://update.code.visualstudio.com/${ source_aarch64=(code_${pkgver}_arm64.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-arm64/stable) source_armv7h=(code_${pkgver}_armhf.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-armhf/stable) sha256sums=('bd0d9edf69283ebdf4e73e0a7b168d2fcf50acbd01f63674cad93ed4fe42fdad') -sha256sums_x86_64=('fd4dff72c44598d3acb885b448256f5d82cf53f59538d97fc7d3c8d8d9d574d3') -sha256sums_aarch64=('8bff558a659d351328f5a1e319802073b59dac42f95cc0f9b2ef1b0c27387431') -sha256sums_armv7h=('b86cdd666e972a5a555d34298c91239bcbaada69ee882c4a36fe1e74d1df2070') +sha256sums_x86_64=('73389cdcef7e66171a2039d1e49b9530e5ed02937e6159d3e6af93484e63cbad') +sha256sums_aarch64=('09760b73fb96ca19f8c6e483ec5b69123f34edd2c762cc9e0faf73fa3d400145') +sha256sums_armv7h=('bb74a3023aced544c71d4274d5942ce69c59a2ec0ffaf9094fa7c0fddb506366') package() { bsdtar -xf data.tar.xz -C "${pkgdir}/" From 10a451abc70c78172072c3fcf518483e929615d1 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Wed, 16 Sep 2026 11:10:50 -0500 Subject: [PATCH 027/121] Drop the .SRCINFO and .gitignore files the repository ignores The top-level .gitignore excludes pkgbuilds/*/.SRCINFO and pkgbuilds/*/.gitignore, and none of the packages under pkgbuilds/ tracks either. These four were added under the retired pkgbuilds/edge/ path, which that rule does not cover, and the move to pkgbuilds/ carried them along as already-tracked files. The per-package .gitignore negates the repository rule for its own directory and its leading * hides every future file there, so a patch or an .omarchy/upstream.sh dropped beside the PKGBUILD would never show up in git status. The build planner reads PKGBUILD and .omarchy/package.json; the only other reader, bin/package-worktree, takes .SRCINFO as a fallback while importing from the AUR and then removes both files as AUR-only. Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/omaspeak-bin/.SRCINFO | 27 --------------------------- pkgbuilds/omaspeak-bin/.gitignore | 7 ------- pkgbuilds/omawake-bin/.SRCINFO | 27 --------------------------- pkgbuilds/omawake-bin/.gitignore | 7 ------- 4 files changed, 68 deletions(-) delete mode 100644 pkgbuilds/omaspeak-bin/.SRCINFO delete mode 100644 pkgbuilds/omaspeak-bin/.gitignore delete mode 100644 pkgbuilds/omawake-bin/.SRCINFO delete mode 100644 pkgbuilds/omawake-bin/.gitignore diff --git a/pkgbuilds/omaspeak-bin/.SRCINFO b/pkgbuilds/omaspeak-bin/.SRCINFO deleted file mode 100644 index 674faf3..0000000 --- a/pkgbuilds/omaspeak-bin/.SRCINFO +++ /dev/null @@ -1,27 +0,0 @@ -pkgbase = omaspeak-bin - pkgdesc = Local-first text-to-speech application and daemon (pre-built binary) - pkgver = 0.0.1 - pkgrel = 1 - url = https://github.com/jacob-vincent-mink/omaspeak - install = omaspeak-bin.install - arch = x86_64 - arch = aarch64 - license = MIT - depends = alsa-utils - depends = gcc-libs - depends = glibc - optdepends = pipewire-audio: audio playback through pw-play - optdepends = openvino: Intel CPU acceleration runtime - optdepends = openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO - optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO - optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle - optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omaspeak=0.0.1 - conflicts = omaspeak - options = !strip - source_x86_64 = omaspeak-0.0.1-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1/omaspeak-0.0.1-linux-x86_64.tar.xz - sha256sums_x86_64 = 9e318960fb15fdf955efbb8dda9bc8eb2b9d0932a9acd9e31b85bf3492ca78ea - source_aarch64 = omaspeak-0.0.1-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omaspeak/releases/download/v0.0.1/omaspeak-0.0.1-linux-aarch64.tar.xz - sha256sums_aarch64 = 8a0d7728d0b6d3f447ab7a616389fc8c54a0617f14922b33593ca60b425deb8d - -pkgname = omaspeak-bin diff --git a/pkgbuilds/omaspeak-bin/.gitignore b/pkgbuilds/omaspeak-bin/.gitignore deleted file mode 100644 index cd3c2c4..0000000 --- a/pkgbuilds/omaspeak-bin/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -* -!.gitignore -!.SRCINFO -!PKGBUILD -!omaspeak-bin.install -!.omarchy/ -!.omarchy/package.json diff --git a/pkgbuilds/omawake-bin/.SRCINFO b/pkgbuilds/omawake-bin/.SRCINFO deleted file mode 100644 index 951ca45..0000000 --- a/pkgbuilds/omawake-bin/.SRCINFO +++ /dev/null @@ -1,27 +0,0 @@ -pkgbase = omawake-bin - pkgdesc = Configurable local wake-word daemon (pre-built binary) - pkgver = 0.0.2 - pkgrel = 1 - url = https://github.com/jacob-vincent-mink/omawake - install = omawake-bin.install - arch = x86_64 - arch = aarch64 - license = MIT - depends = alsa-lib - depends = gcc-libs - depends = glibc - optdepends = pipewire-audio: PipeWire audio support - optdepends = openvino: Intel runtime for an externally supplied OpenVINO provider bundle - optdepends = openvino-intel-gpu-plugin: Intel GPU device support for OpenVINO - optdepends = openvino-intel-npu-plugin: Intel NPU device support for OpenVINO - optdepends = cuda: NVIDIA CUDA libraries for an external CUDA runtime bundle - optdepends = cudnn: NVIDIA neural-network libraries for an external CUDA runtime bundle - provides = omawake=0.0.2 - conflicts = omawake - options = !strip - source_x86_64 = omawake-0.0.2-linux-x86_64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.2/omawake-0.0.2-linux-x86_64.tar.xz - sha256sums_x86_64 = 94f0677eb497babd351cb154e9adf057e4b796efe0241d809a7f7cf84742a515 - source_aarch64 = omawake-0.0.2-linux-aarch64.tar.xz::https://github.com/jacob-vincent-mink/omawake/releases/download/v0.0.2/omawake-0.0.2-linux-aarch64.tar.xz - sha256sums_aarch64 = acb359b21bbe4909b13c18a0de63f8106c6b254943074b57d8fd70af41421659 - -pkgname = omawake-bin diff --git a/pkgbuilds/omawake-bin/.gitignore b/pkgbuilds/omawake-bin/.gitignore deleted file mode 100644 index 1deba1d..0000000 --- a/pkgbuilds/omawake-bin/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -* -!.gitignore -!.SRCINFO -!PKGBUILD -!omawake-bin.install -!.omarchy/ -!.omarchy/package.json From 6ea162d2a4a86c90c4c4f12999292ef18b823490 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Wed, 16 Sep 2026 11:10:50 -0500 Subject: [PATCH 028/121] Turn off debug packaging alongside !strip The builder's makepkg.conf enables debug and emptydirs. With strip off, makepkg still takes the debug branch of tidy_strip, creates usr/src/debug/ inside the package to hold debug sources, finds none in a prebuilt tree, and emptydirs then ships the empty directory to every user. Seven of the ten -bin packages here that disable strip already disable debug with it. Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/omaspeak-bin/PKGBUILD | 2 +- pkgbuilds/omawake-bin/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index 26d4d91..d5fe10c 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -25,7 +25,7 @@ optdepends=( provides=("${_pkgname}=${pkgver}") conflicts=("${_pkgname}") install="${pkgname}.install" -options=('!strip') +options=('!strip' '!debug') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 42b3ca8..019eec9 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -25,7 +25,7 @@ optdepends=( provides=("${_pkgname}=${pkgver}") conflicts=("${_pkgname}") install="${pkgname}.install" -options=('!strip') +options=('!strip' '!debug') source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") From b836c23037e53d58f7693efc62d0524cab4e0b79 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Wed, 16 Sep 2026 11:10:50 -0500 Subject: [PATCH 029/121] Declare the licenses of the bundled audio.cpp provider Each package ships libaudiocpp, which upstream's own third-party notices describe as Apache-2.0 with BSD-3-Clause PocketFFT-derived code retained in it, and installs those texts under /usr/share/licenses. A license array of MIT alone describes only the project's own source, so pacman -Qi misreports what the package contains. Co-Authored-By: GPT-6 Astra XHigh Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/omaspeak-bin/PKGBUILD | 2 +- pkgbuilds/omawake-bin/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index d5fe10c..eb40b05 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -8,7 +8,7 @@ pkgrel=1 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omaspeak' -license=('MIT') +license=('MIT' 'Apache-2.0' 'BSD-3-Clause') depends=( 'alsa-utils' 'gcc-libs' diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 019eec9..55b3682 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -8,7 +8,7 @@ pkgrel=1 pkgdesc='Configurable local wake-word daemon (pre-built binary)' arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omawake' -license=('MIT') +license=('MIT' 'Apache-2.0' 'BSD-3-Clause') depends=( 'alsa-lib' 'gcc-libs' From 56eced522e5d39f636cecbdee77cd6a46639c21d Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Wed, 16 Sep 2026 13:04:49 -0500 Subject: [PATCH 030/121] Add elsewhen, the Omarchy shell world clock plugin --- pkgbuilds/elsewhen/.omarchy/README.md | 17 ++++++ pkgbuilds/elsewhen/.omarchy/package.json | 11 ++++ pkgbuilds/elsewhen/PKGBUILD | 70 ++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 pkgbuilds/elsewhen/.omarchy/README.md create mode 100644 pkgbuilds/elsewhen/.omarchy/package.json create mode 100644 pkgbuilds/elsewhen/PKGBUILD diff --git a/pkgbuilds/elsewhen/.omarchy/README.md b/pkgbuilds/elsewhen/.omarchy/README.md new file mode 100644 index 0000000..21b3341 --- /dev/null +++ b/pkgbuilds/elsewhen/.omarchy/README.md @@ -0,0 +1,17 @@ +# elsewhen + +Installs the Elsewhen world clock plugin from the `v{pkgver}` GitHub tag archive into `/usr/share/omarchy/plugins/omacom.elsewhen/` (the directory name is the plugin id the shell scans for, not the package name), plus `LICENSE` under `/usr/share/licenses/elsewhen/` and the upstream `README.md` under `/usr/share/doc/elsewhen/`. That directory is the packaged plugin root that omarchy PR [#12051](https://github.com/omacom/omarchy/pull/12051) teaches the shell to scan between its bundled plugins and `~/.config/omarchy/plugins`; on an Omarchy without it the package installs cleanly and the shell never looks, so it must ship alongside that change. `depends` carries no version floor for `omarchy` because no release carries #12051 yet; add one once it does. + +`package()` copies an explicit allow-list (`manifest.json`, every `*.qml` and `*.js`, `cities.json`, `world.json`, `worldclock-data.py`), so `tests/`, `.github/` and `.gitignore` never ship, and it fails the build if `manifest.json` is missing, does not declare `omacom.elsewhen`, or does not name a present `Panel.qml` as the entry point. An upstream release that adds a runtime file outside those patterns needs the allow-list extended here; the sync only moves versions and checksums. Every file is 0644: `Panel.qml` runs the script as `python3 /worldclock-data.py`, so it needs no execute bit. No install hook: Omarchy restarts the shell after `omarchy update`, and nothing here may write into a user home. The script's only writes go to `$XDG_CACHE_HOME/omacom-elsewhen/`, which it creates itself at runtime. + +Dependencies, cited as `file: tool` in the upstream tree: + +- `omarchy`: `ArcText.qml`, `Chip.qml`, `EarthRow.qml`, `Globe.qml`, `MiniGlobe.qml`, `MoonDot.qml`, `Panel.qml: import qs.Commons`; `EarthRow.qml`, `Globe.qml`, `Panel.qml: import qs.Ui`. Owns `/usr/share/omarchy` and the packaged plugin root the shell scans. +- `quickshell`: `Globe.qml`, `Panel.qml: import Quickshell`; `Globe.qml`, `MiniGlobe.qml`, `Panel.qml: import Quickshell.Io` (`Process`, `FileView`, `StdioCollector`). +- `python`: `Panel.qml: python3 /worldclock-data.py` (the facts process). `worldclock-data.py` imports only `json`, `os`, `sys`, `time`, `urllib`. +- Left implicit as members of `base`, per Arch convention: `bash` (`Panel.qml`, `Globe.qml: bash -c` wraps every probe), `coreutils` (`Panel.qml`, `Globe.qml: date`, one probe per refresh), `systemd` (`Panel.qml: timedatectl show`, `timedatectl list-timezones`, each with a fallback: `/etc/localtime` for the home zone and `find /usr/share/zoneinfo` for the catalog), `sed` and `grep` (`Panel.qml`: the symlink target of `/etc/localtime` and the zoneinfo catalog filter), `findutils` and `tzdata` (that fallback; `worldclock-data.py: /usr/share/zoneinfo/zone1970.tab`). `omarchy` cannot run without any of them either. +- Not a dependency: `iso-codes`. Only `tests/currency_check.py` reads `/usr/share/iso-codes/json`, to validate the currency table before a release; the runtime never touches it. + +Release tracking: `bin/sync-upstream` follows `omacom/elsewhen` through the `upstream.watch.github` provider, which reads the GitHub Releases feed (drafts and prereleases excluded; a tag with no published Release is not seen) and matches exactly `vX.Y.Z`, the grammar upstream's `scripts/set-version.sh` enforces. A newer release rewrites `pkgver`, resets `pkgrel` to 1, fetches `archive/refs/tags/v{pkgver}.tar.gz` again and rewrites `sha256sums` from the download. The Release's `published_at` is what lets `min_release_age: 24h` hold a fresh release for a day; `release_ring: fast` builds it straight to rc and stable as well as edge. + +The watch only moves on a version increase, so the first release's digest is filled in by hand (`curl -fsSL | sha256sum`), which is why the recipe carries a placeholder until the `v0.1.0` tag exists. Until upstream has published at least one Release, the watch finds nothing and fails the scheduled `sync-upstream` run for every package in the batch, so this recipe stays a draft until then. diff --git a/pkgbuilds/elsewhen/.omarchy/package.json b/pkgbuilds/elsewhen/.omarchy/package.json new file mode 100644 index 0000000..b1e7e71 --- /dev/null +++ b/pkgbuilds/elsewhen/.omarchy/package.json @@ -0,0 +1,11 @@ +{ + "source": "local", + "release_ring": "fast", + "min_release_age": "24h", + "upstream": { + "watch": { + "github": "omacom/elsewhen", + "pattern": "v(?P[0-9]+\\.[0-9]+\\.[0-9]+)" + } + } +} diff --git a/pkgbuilds/elsewhen/PKGBUILD b/pkgbuilds/elsewhen/PKGBUILD new file mode 100644 index 0000000..703a24c --- /dev/null +++ b/pkgbuilds/elsewhen/PKGBUILD @@ -0,0 +1,70 @@ +# Maintainer: Spencer Bull + +pkgname=elsewhen +pkgver=0.1.0 +pkgrel=1 +pkgdesc='World clock plugin for the Omarchy shell' +arch=('any') +url='https://github.com/omacom/elsewhen' +license=('MIT') + +# What the plugin needs to load and run. It also shells out to bash, date +# (coreutils) and timedatectl (systemd) and reads /usr/share/zoneinfo +# (tzdata); those are members of the base group and stay implicit, per Arch +# convention. The citations for each entry are in .omarchy/README.md. +depends=( + 'omarchy' + 'python' + 'quickshell' +) + +options=('!debug') + +source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") +# Fill once the v0.1.0 tag exists: +# curl -fsSL https://github.com/omacom/elsewhen/archive/refs/tags/v0.1.0.tar.gz | sha256sum +# bin/sync-upstream rewrites this array only when it moves pkgver forward, so +# the first release's digest has to be entered by hand. +sha256sums=('FILL_FROM_RELEASE_ARCHIVE') + +package() { + # The packaged plugin root, scanned by the shell between its bundled + # plugins and ~/.config/omarchy/plugins since omarchy PR #12051. An older + # shell never looks here, so on it this package installs cleanly and does + # nothing; there is no omarchy version to pin until a release carries #12051. + local plugin="$pkgdir/usr/share/omarchy/plugins/omacom.elsewhen" + cd "$srcdir/$pkgname-$pkgver" || return 1 + + # The shell loads the entry point each manifest declares. A tree without + # either would install cleanly and never load, so fail the build instead of + # shipping it. + [[ -f manifest.json ]] || { + echo "release tree is missing manifest.json" >&2 + return 1 + } + grep -Eq '"id"[[:space:]]*:[[:space:]]*"omacom\.elsewhen"' manifest.json || { + echo "manifest.json does not declare the plugin id omacom.elsewhen" >&2 + return 1 + } + grep -Eq '"barWidget"[[:space:]]*:[[:space:]]*"Panel\.qml"' manifest.json || { + echo "manifest.json does not name Panel.qml as the bar widget entry point" >&2 + return 1 + } + [[ -f Panel.qml ]] || { + echo "release tree is missing the entry point Panel.qml" >&2 + return 1 + } + + # An explicit allow-list of runtime files, so tests/, .github/ and the rest + # of the repository never reach the package. Directories end up 0755 and + # every file 0644: worldclock-data.py runs as `python3 ` and needs no + # execute bit. An unmatched glob is left literal and fails install, which + # is the right outcome for a release tree missing its QML or JS. + local file + for file in manifest.json cities.json world.json worldclock-data.py *.qml *.js; do + install -Dm644 "$file" "$plugin/$file" + done + + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md" +} From f5c944188869df3184ceb052641de7d412354e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Thu, 17 Sep 2026 08:52:45 +0900 Subject: [PATCH 031/121] Add fix for swapped-out TTM resources never leaving their bulk_move range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- ...tm-swapped-out-resource-leaves-bulk-move.patch | 12 ++++++++++++ ...wapped-out-resource-leaves-bulk-move.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy-bore/PKGBUILD | 5 +++++ ...tm-swapped-out-resource-leaves-bulk-move.patch | 12 ++++++++++++ ...wapped-out-resource-leaves-bulk-move.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/PKGBUILD | 5 +++++ 6 files changed, 34 insertions(+) create mode 100644 pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch create mode 100644 pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch create mode 100644 pkgbuilds/linux-omarchy/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig diff --git a/pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch b/pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch new file mode 100644 index 0000000..6977a84 --- /dev/null +++ b/pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch @@ -0,0 +1,12 @@ +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -1343,7 +1343,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) + + if (ttm_tt_is_populated(tt)) { + ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags); +- if (!ret) { ++ if (ret > 0) { + spin_lock(&bdev->lru_lock); + ttm_resource_del_bulk_move_unevictable(bo->resource, bo); + ttm_resource_move_to_lru_tail(bo->resource); diff --git a/pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig b/pkgbuilds/linux-omarchy-bore/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..bd99af47a4b81b26edc0c426ee3d6b1bfc9a1686 GIT binary patch literal 594 zcmV-Y0aDwlM0_EaL^LpfS!B+rD;gB+pSl(&-OS(1OOkvh%5N+-ImQJ|R}a$v?RPh@HRX;o6| zhA+~XYA2kKAVdb&Q}f)W#@axdJDdyrBs2kcrOh(6WQ+(u-cao9EI!k)L6)>X;2_dY zb%TVrvYLA`$xb5QvU%>bqr^u7hDuQ5lbn(&WK=v#{B*oik1Iyv!;zJfO`oGu6IH8l zEn2T&P06$1?bo5O)o()igxe>{aDB8Rk+EF~wBYG+YEEnAQT#6?^`P1%k8V?|`|%`_ z_v5r24b$DbB1Z8li1r?IdJSR*T&*1`VUp@b2w5SPGJ(TKzWUM^KTd!aLbC&1OB|D3 z=UK#}1Xei?j6*niL{U@Q{j~Ol-(TO|)?Uuxp3;pTrgfp_flags); +- if (!ret) { ++ if (ret > 0) { + spin_lock(&bdev->lru_lock); + ttm_resource_del_bulk_move_unevictable(bo->resource, bo); + ttm_resource_move_to_lru_tail(bo->resource); diff --git a/pkgbuilds/linux-omarchy/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig b/pkgbuilds/linux-omarchy/0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..8ca1431f4cc3105e2d1f56c1079456fac8471294 GIT binary patch literal 594 zcmV-Y0`A$C`ueNWIWhzeXL`nLBMG)wnDb&h_u6q2Ra1bZqB-5kLa3tp4#Re*0BryHtF zTIS<8^K|&WN}87XhKX_tEEvDoeote+iHs^(-azI)s_DhLa-eQwzwCFiuYRBqcd(yn z?Ex|e;g+r#rfgfVE;gz9J4stGo9BJ>?m4Gp2*_fL{){zt49mZAeD_tf`wvqn%91Op gA_wUlFV~6%tgbYt5j%EUaS@KrM{dYwm;86%C=fv#?*IS* literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 660c9e2..8a63277 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -82,6 +82,7 @@ source=( 0313-fuse-background-wakeup.patch{,.sig} 0350-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch{,.sig} 0360-gpu-mem-cgroup.patch{,.sig} + 0361-drm-ttm-swapped-out-resource-leaves-bulk-move.patch{,.sig} 0400-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch{,.sig} 0401-drm-i915-psr-exit-panel-replay-for-alpm-lag.patch{,.sig} 0402-psr2-early-transport-panels.patch{,.sig} @@ -216,6 +217,8 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' '1124c5c3fd5104c886c841ead1ae9afb42683388b640b1a86523dad9919c6bd59a1f78b07ee5a213e0dca77c636a29676af0592d4ed1735ea35f282f6f23e46f' 'SKIP' + '15855e9c28cb0abaab7ab606904dfc84d426ccab44edae59f0e1f092202b80525929f8d394d04ca1513d1d5dfc2cfc108a66a9c1cb42b9966c6417562ef20689' + 'SKIP' '505bf01a9d6b0926b557b673bb686d1a4ff73ee70539991e52272fbf58aad3ea25cf5ffc5c2d094a2d5e78b18a1a134f2ab530f595073a2d3eba9ff2c1418e1e' 'SKIP' 'b33b46c37f12f7650a67c3731b87ff84add1ac8623cc96b52223a1ef9946bcaa990ed7c7036674e228335f57ec9ed421ea4d6c1dd72d19b516215d9ac2c7c3ee' @@ -403,6 +406,8 @@ sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' 'SKIP' 'e303da14a3c8a15fd1cb45394138f03dd16e66d2ac0d1ebcd933977df937d771' 'SKIP' + '503eba8d7a80b978fccdaac798f57cbb6cd2b2b04fd04c46399daa004b6646dc' + 'SKIP' '1f0c958b64ba48b8dc8b5548e1ad1934b8d4903fc16fec15014759e3681ea275' 'SKIP' '47994d576008a377de612ed77e6b2e7bc6b24ad3a30a6d157646d380ae323142' From c2f2345f0d688670573f89c45c11f3b8f373e199 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Wed, 16 Sep 2026 23:47:49 -0500 Subject: [PATCH 032/121] Put Omawake and Omaspeak on the fast release ring A channels list of edge alone is the outer bound on where a package may build, so both packages were refused for rc and stable and could only ever reach edge users. The fast ring builds them natively for all three channels, each against its own base mirror, which is how the other prebuilt -bin applications here ship. The channels key has to go rather than sit beside the ring: package_builds_for_mirror checks it first, so an edge-only list would still block the rc and stable builds the ring asks for. Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/omaspeak-bin/.omarchy/package.json | 2 +- pkgbuilds/omawake-bin/.omarchy/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/omaspeak-bin/.omarchy/package.json b/pkgbuilds/omaspeak-bin/.omarchy/package.json index 2537ec0..db153c3 100644 --- a/pkgbuilds/omaspeak-bin/.omarchy/package.json +++ b/pkgbuilds/omaspeak-bin/.omarchy/package.json @@ -1,4 +1,4 @@ { "source": "local", - "channels": ["edge"] + "release_ring": "fast" } diff --git a/pkgbuilds/omawake-bin/.omarchy/package.json b/pkgbuilds/omawake-bin/.omarchy/package.json index 2537ec0..db153c3 100644 --- a/pkgbuilds/omawake-bin/.omarchy/package.json +++ b/pkgbuilds/omawake-bin/.omarchy/package.json @@ -1,4 +1,4 @@ { "source": "local", - "channels": ["edge"] + "release_ring": "fast" } From 1b8e0f38457d6a1531087ec93baafbfc1ec2d0af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Thu, 17 Sep 2026 18:25:22 +0900 Subject: [PATCH 033/121] Use -O3 build optimization flag for base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- ...1-kbuild-optimize-for-performance-o3.patch | 31 ++++++++++++++++++ ...uild-optimize-for-performance-o3.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy-bore/PKGBUILD | 7 +++- pkgbuilds/linux-omarchy-bore/config.x86_64 | 3 +- ...1-kbuild-optimize-for-performance-o3.patch | 31 ++++++++++++++++++ ...uild-optimize-for-performance-o3.patch.sig | Bin 0 -> 594 bytes pkgbuilds/linux-omarchy/PKGBUILD | 7 +++- pkgbuilds/linux-omarchy/config.x86_64 | 3 +- 8 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch create mode 100644 pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch create mode 100644 pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch.sig diff --git a/pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch b/pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch new file mode 100644 index 0000000..9506ee1 --- /dev/null +++ b/pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch @@ -0,0 +1,31 @@ +diff --git a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -935,6 +935,9 @@ KBUILD_RUSTFLAGS += -Copt-level=2 + else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE + KBUILD_CFLAGS += -Os + KBUILD_RUSTFLAGS += -Copt-level=s ++else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 ++KBUILD_CFLAGS += -O3 ++KBUILD_RUSTFLAGS += -Copt-level=3 + endif + + # Always set `debug-assertions` and `overflow-checks` because their default +diff --git a/init/Kconfig b/init/Kconfig +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1622,6 +1622,14 @@ config CC_OPTIMIZE_FOR_SIZE + Choosing this option will pass "-Os" to your compiler resulting + in a smaller kernel. + ++config CC_OPTIMIZE_FOR_PERFORMANCE_O3 ++ bool "Optimize harder for performance (-O3)" ++ help ++ Build with the "-O3" compiler flag: more inlining, loop ++ unrolling and vectorization than -O2, at the cost of a larger ++ kernel image and larger modules. Rust code is built at ++ opt-level 3. ++ + endchoice + + config HAVE_LD_DEAD_CODE_DATA_ELIMINATION diff --git a/pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch.sig b/pkgbuilds/linux-omarchy-bore/0011-kbuild-optimize-for-performance-o3.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..48ab131c7e9b3bda8c446ee9f1b9b5d16556b4f7 GIT binary patch literal 594 zcmV-Y000000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=V#Xs|4J-J%PExEAOHZN^Rj`WI-v#haX0Sx8v=ACq@eQ8Eo>N0*KAYP`fj8ZP znMpW#59>;1rj?`ph%d!|TBgR>pd@-~#*9wJKP!8mhte^qi5(zY@%Lt^0BUrR8*Kc! zEr7huoo`P|1yp`zIYP@bI8{mEQkFyiY1*uC6xpvkm$B8d0rmvE1ms zNfcHNR03z%@!<6W0d5xKb;r*f18gK@1s)4DiF+`CFQeQN@FH?+WR5a+{oRW+n?rA` zSvTH-NyD)T0J{^y zU)^*Ee&22F{4ycA0^H0WTemyJ^VXZV*n*8Kp)JUq!Kgr4o#s5G0K zP$V?eMy6LW?nYkd+}67!67c;RDkyo>U zKD=~wZ3(IZrvZQ}mIP1yybCy7Mnyu+cODTA* gOlA>QtQC?-aprw0>4USRn765kLzA8s`zWgH3Cc$o{r~^~ literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index 3f38f93..a7f01ac 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -49,6 +49,7 @@ source=( ${_rcpatch:+https://cdn.kernel.org/pub/linux/kernel/v${_major}.x/stable-review/${_rcpatch}.xz} ${_rcpatch:+https://cdn.kernel.org/pub/linux/kernel/v${_major}.x/stable-review/${_rcpatch}.sign} 0010-archlinux-base.patch{,.sig} + 0011-kbuild-optimize-for-performance-o3.patch{,.sig} 0110-bore-6.8.0.patch{,.sig} 0120-tlbpull.patch{,.sig} 0121-smp-preempt.patch{,.sig} @@ -152,6 +153,8 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' '6d92fb81077232b8cd1ae500b3aabc71434792e750ea6126dc095e50d4278d3e42b3cfdc3c8bc693ea14b109f6adfa3a1ed095187fc5501962fbe8f049f867bc' 'SKIP' + 'cc2a66a097b5567e80c59b7d6c492fef5e667fc71a0390908712c69512c4136dbaf3d150b62d04eff960c796f7a94e6d0915d3b92cb336318b49f5f516a3bba6' + 'SKIP' 'a32edb39b4ee9c0378239f4998f477fe5371e6931c188d660874b360ca6d3bdcfff71cf088bed071365627d87458eca0be625e154ca3d1e8150e5e0bdf64175c' 'SKIP' 'f6c00ac2400580dffe3605d2693809396e18185f0c59b21b86f1f22a1f8d6529c51e8cc2474bc40f74a96631f415da51521a8b35d5b096e9b9d164c2755fb091' @@ -336,13 +339,15 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' 'b69cf36cc5633e507866e67f59557646dda7d6ea436b145f3f3356c4b12e1300c94977a7d1214835f2476c94a30dd672076241b920d96d744fbc199539df506f' 'SKIP') -b2sums_x86_64=('54148fc55a2b611f84f62d0b1c19caf911e029cd29bda6f032b15cc2f3484a1cc648af63e101eb293b048b54df4a0efacdb39cbbaa5b13d8ea1dfc22b981ec6b') +b2sums_x86_64=('5abfe289c4487fd774890fbbe3989bb87e6b8d67e146c401ac6821b71be85a17816520b18eb874ff83e43ddece236273b2ac155943d2fdfabb1a444ba7162291') # https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' 'SKIP' '95f3e9209629044028373af987dc0e270a5a15acb8c8e49c5f05057220c75fe2' 'SKIP' + '6cf74fc3f28a751354187b6cf610c3e43cf9088b5f730b68dbb575828c3a7478' + 'SKIP' 'daf0aaebff3cf4679d0bb8137ace6c9a2de62f75aa4655a0a02ddf759f3c7f26' 'SKIP' 'a9171e731d08a454a50174889af8936fab962b33c37c67169b0cdf21b0b80821' diff --git a/pkgbuilds/linux-omarchy-bore/config.x86_64 b/pkgbuilds/linux-omarchy-bore/config.x86_64 index a4ddcba..4d90b02 100644 --- a/pkgbuilds/linux-omarchy-bore/config.x86_64 +++ b/pkgbuilds/linux-omarchy-bore/config.x86_64 @@ -278,8 +278,9 @@ CONFIG_BOOT_CONFIG=y # CONFIG_BOOT_CONFIG_EMBED is not set CONFIG_CMDLINE_LOG_WRAP_IDEAL_LEN=1021 CONFIG_INITRAMFS_PRESERVE_MTIME=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_LD_ORPHAN_WARN=y CONFIG_LD_ORPHAN_WARN_LEVEL="warn" CONFIG_SYSCTL=y diff --git a/pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch b/pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch new file mode 100644 index 0000000..9506ee1 --- /dev/null +++ b/pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch @@ -0,0 +1,31 @@ +diff --git a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -935,6 +935,9 @@ KBUILD_RUSTFLAGS += -Copt-level=2 + else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE + KBUILD_CFLAGS += -Os + KBUILD_RUSTFLAGS += -Copt-level=s ++else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 ++KBUILD_CFLAGS += -O3 ++KBUILD_RUSTFLAGS += -Copt-level=3 + endif + + # Always set `debug-assertions` and `overflow-checks` because their default +diff --git a/init/Kconfig b/init/Kconfig +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1622,6 +1622,14 @@ config CC_OPTIMIZE_FOR_SIZE + Choosing this option will pass "-Os" to your compiler resulting + in a smaller kernel. + ++config CC_OPTIMIZE_FOR_PERFORMANCE_O3 ++ bool "Optimize harder for performance (-O3)" ++ help ++ Build with the "-O3" compiler flag: more inlining, loop ++ unrolling and vectorization than -O2, at the cost of a larger ++ kernel image and larger modules. Rust code is built at ++ opt-level 3. ++ + endchoice + + config HAVE_LD_DEAD_CODE_DATA_ELIMINATION diff --git a/pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch.sig b/pkgbuilds/linux-omarchy/0011-kbuild-optimize-for-performance-o3.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..90d521977316a4c45664be6ebfc5b3d91ad8b3ee GIT binary patch literal 594 zcmV-Y0Dn?7-Mk#x&26gTWff&@xFV**qQYbnqh8H_v=T!UIj|aZmk&)IqKqw`-%aLj-ApWJkGM{rSBl(2O3 zJx=sQv+m$F9a|pq1>08#P5a6*8YtK?@hBkAwY3+bw@HjMg2|ON8@gV99dt`2#DsWU gn%;jfa-pCU8IdKB;87E;zlk6X#*c3VHCd|K6}X5Qo&W#< literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 8a63277..2e0bddf 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -49,6 +49,7 @@ source=( ${_rcpatch:+https://cdn.kernel.org/pub/linux/kernel/v${_major}.x/stable-review/${_rcpatch}.xz} ${_rcpatch:+https://cdn.kernel.org/pub/linux/kernel/v${_major}.x/stable-review/${_rcpatch}.sign} 0010-archlinux-base.patch{,.sig} + 0011-kbuild-optimize-for-performance-o3.patch{,.sig} 0120-tlbpull.patch{,.sig} 0121-smp-preempt.patch{,.sig} 0130-sched-detach-tasks.patch{,.sig} @@ -151,6 +152,8 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' '6d92fb81077232b8cd1ae500b3aabc71434792e750ea6126dc095e50d4278d3e42b3cfdc3c8bc693ea14b109f6adfa3a1ed095187fc5501962fbe8f049f867bc' 'SKIP' + 'cc2a66a097b5567e80c59b7d6c492fef5e667fc71a0390908712c69512c4136dbaf3d150b62d04eff960c796f7a94e6d0915d3b92cb336318b49f5f516a3bba6' + 'SKIP' 'f6c00ac2400580dffe3605d2693809396e18185f0c59b21b86f1f22a1f8d6529c51e8cc2474bc40f74a96631f415da51521a8b35d5b096e9b9d164c2755fb091' 'SKIP' '6aa6ea3690f3e4e145818650537cd110d33720d662af0b3660d95e15a3f91e48c993e31117c0a2fde852f55a77a83e3a50a1a95c0df78a33ae75d43d46a9fe15' @@ -333,13 +336,15 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' 'b69cf36cc5633e507866e67f59557646dda7d6ea436b145f3f3356c4b12e1300c94977a7d1214835f2476c94a30dd672076241b920d96d744fbc199539df506f' 'SKIP') -b2sums_x86_64=('11bfedf70dc9366a42b42573a3677e348fcd7b253ce13118036a75190e6c9372f9549589ff2dbfac5b976fc15d11a1b193baaee2135d331ca90f8a9a9a6e1462') +b2sums_x86_64=('459be66f895e5c75cadc2074965baa6261ba342b175eeb352157972be1940f1c6092001e8c0ab3cfbc92a35ee216ffb486f417b94df1a46ed217144257e3c7f2') # https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' 'SKIP' '95f3e9209629044028373af987dc0e270a5a15acb8c8e49c5f05057220c75fe2' 'SKIP' + '6cf74fc3f28a751354187b6cf610c3e43cf9088b5f730b68dbb575828c3a7478' + 'SKIP' 'a9171e731d08a454a50174889af8936fab962b33c37c67169b0cdf21b0b80821' 'SKIP' '6a27e1b363f1bb133b9905f84b00e4d01885cac84858db46bdbf764849c9984b' diff --git a/pkgbuilds/linux-omarchy/config.x86_64 b/pkgbuilds/linux-omarchy/config.x86_64 index 1a3eb2a..847db90 100644 --- a/pkgbuilds/linux-omarchy/config.x86_64 +++ b/pkgbuilds/linux-omarchy/config.x86_64 @@ -277,8 +277,9 @@ CONFIG_BOOT_CONFIG=y # CONFIG_BOOT_CONFIG_EMBED is not set CONFIG_CMDLINE_LOG_WRAP_IDEAL_LEN=1021 CONFIG_INITRAMFS_PRESERVE_MTIME=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_LD_ORPHAN_WARN=y CONFIG_LD_ORPHAN_WARN_LEVEL="warn" CONFIG_SYSCTL=y From d06bf4660a4a57a6fcb83753ff482a3264419d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Thu, 17 Sep 2026 18:29:09 +0900 Subject: [PATCH 034/121] Add small AMD Zen 5 TLB sizes display fix to base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- .../0220-x86-amd-zen5-tlb-sizes.patch | 95 +++++++++++++++++++ pkgbuilds/linux-omarchy-bore/PKGBUILD | 5 + .../0220-x86-amd-zen5-tlb-sizes.patch | 95 +++++++++++++++++++ pkgbuilds/linux-omarchy/PKGBUILD | 5 + 4 files changed, 200 insertions(+) create mode 100644 pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch create mode 100644 pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch diff --git a/pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch b/pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch new file mode 100644 index 0000000..1c5c5b3 --- /dev/null +++ b/pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch @@ -0,0 +1,95 @@ +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -471,6 +471,8 @@ + #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ + #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ + ++#define X86_FEATURE_L2_TLB_SIZE_X32 (20*32+14) /* L2 TLB sizes are encoded as multiples of 32 */ ++ + #define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */ + + #define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -1190,7 +1190,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) + + static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + { +- u32 ebx, eax, ecx, edx; ++ u32 ebx, eax, ecx, edx, shift, tmp; + u16 mask = 0xfff; + + if (c->x86 < 0xf) +@@ -1199,10 +1199,12 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + if (c->extended_cpuid_level < 0x80000006) + return; + ++ shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; ++ + cpuid(0x80000006, &eax, &ebx, &ecx, &edx); + +- tlb_lld_4k = (ebx >> 16) & mask; +- tlb_lli_4k = ebx & mask; ++ tlb_lld_4k = ((ebx >> 16) & mask) << shift; ++ tlb_lli_4k = (ebx & mask) << shift; + + /* + * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB +@@ -1214,16 +1216,18 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + } + + /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ +- if (!((eax >> 16) & mask)) ++ tmp = ((eax >> 16) & mask) << shift; ++ if (!tmp) + tlb_lld_2m = (cpuid_eax(0x80000005) >> 16) & 0xff; + else +- tlb_lld_2m = (eax >> 16) & mask; ++ tlb_lld_2m = tmp; + + /* a 4M entry uses two 2M entries */ + tlb_lld_4m = tlb_lld_2m >> 1; + + /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ +- if (!(eax & mask)) { ++ tmp = (eax & mask) << shift; ++ if (!tmp) { + /* Erratum 658 */ + if (c->x86 == 0x15 && c->x86_model <= 0x1f) { + tlb_lli_2m = 1024; +@@ -1231,8 +1235,9 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + cpuid(0x80000005, &eax, &ebx, &ecx, &edx); + tlb_lli_2m = eax & 0xff; + } +- } else +- tlb_lli_2m = eax & mask; ++ } else { ++ tlb_lli_2m = tmp; ++ } + + tlb_lli_4m = tlb_lli_2m >> 1; + +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -857,7 +857,7 @@ static void get_model_name(struct cpuinfo_x86 *c) + + void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) + { +- unsigned int n, dummy, ebx, ecx, edx, l2size; ++ unsigned int n, dummy, ebx, ecx, edx, l2size, shift __maybe_unused; + + n = c->extended_cpuid_level; + +@@ -877,7 +877,9 @@ void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) + l2size = ecx >> 16; + + #ifdef CONFIG_X86_64 ++ shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; + c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); ++ c->x86_tlbsize <<= shift; + #else + /* do processor-specific cache resizing */ + if (this_cpu->legacy_cache_size) diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index a7f01ac..68d19c1 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -65,6 +65,7 @@ source=( 0210-pstate.patch{,.sig} 0211-amd-pstate-fixes.patch{,.sig} 0212-amd-pstate-epp-cache.patch{,.sig} + 0220-x86-amd-zen5-tlb-sizes.patch{,.sig} 0250-zsmalloc.patch{,.sig} 0260-mglru-exec-protect.patch{,.sig} 0270-ksm-rmap-walk.patch{,.sig} @@ -185,6 +186,8 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' '2f24f88d8f960148046c36222fdaaadfed2ca88c60240fa1d111430898192ca45aeaa93a3afa24ad02b11c4dc8c3904a92f17c0284396f2f43352ad934a35056' 'SKIP' + 'e59c4da548b2ea4fd6144886e3e2e765b3e73972121e9e73dbc05c066834b2b35e6ef4c17617e77efc90260566bf7c0910d2138d8d5c1c3b6094eeac9de64cfe' + 'SKIP' '9809e258eb684b80d508fa2f2fa270683b62bd1412ed05a970114aaa7d84c37c0beaea51f9ff8c6ee1bc7318c4aee3725e9a1131fefb51ba700801de6ac414c5' 'SKIP' 'f115e8c80d723f7c24e6b1638b801cd664bef20acb1d2f6e6f5612744b916278693011782228cd3f4d0518654b8d53309bc5b06bbe8ed722fab9995f369bf548' @@ -378,6 +381,8 @@ sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' 'SKIP' '66eb2c49dbf708cc781d411d0e44ed613480f0ef66d522272929d9cb7bb21e93' 'SKIP' + '718b40e15350049e03c0ed281b9257fca5432b8dec2e0e145e8b26507ee8892d' + 'SKIP' 'b7ba949eea77e169aceb2c401d4eb83a7413aab6f15ee2a7ab1a96352f0aa12d' 'SKIP' '341424b925d506869793686e22ea8f095a34048595ebebec409c0a7bbd346ca2' diff --git a/pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch b/pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch new file mode 100644 index 0000000..1c5c5b3 --- /dev/null +++ b/pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch @@ -0,0 +1,95 @@ +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -471,6 +471,8 @@ + #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ + #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ + ++#define X86_FEATURE_L2_TLB_SIZE_X32 (20*32+14) /* L2 TLB sizes are encoded as multiples of 32 */ ++ + #define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */ + + #define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -1190,7 +1190,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) + + static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + { +- u32 ebx, eax, ecx, edx; ++ u32 ebx, eax, ecx, edx, shift, tmp; + u16 mask = 0xfff; + + if (c->x86 < 0xf) +@@ -1199,10 +1199,12 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + if (c->extended_cpuid_level < 0x80000006) + return; + ++ shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; ++ + cpuid(0x80000006, &eax, &ebx, &ecx, &edx); + +- tlb_lld_4k = (ebx >> 16) & mask; +- tlb_lli_4k = ebx & mask; ++ tlb_lld_4k = ((ebx >> 16) & mask) << shift; ++ tlb_lli_4k = (ebx & mask) << shift; + + /* + * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB +@@ -1214,16 +1216,18 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + } + + /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ +- if (!((eax >> 16) & mask)) ++ tmp = ((eax >> 16) & mask) << shift; ++ if (!tmp) + tlb_lld_2m = (cpuid_eax(0x80000005) >> 16) & 0xff; + else +- tlb_lld_2m = (eax >> 16) & mask; ++ tlb_lld_2m = tmp; + + /* a 4M entry uses two 2M entries */ + tlb_lld_4m = tlb_lld_2m >> 1; + + /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ +- if (!(eax & mask)) { ++ tmp = (eax & mask) << shift; ++ if (!tmp) { + /* Erratum 658 */ + if (c->x86 == 0x15 && c->x86_model <= 0x1f) { + tlb_lli_2m = 1024; +@@ -1231,8 +1235,9 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) + cpuid(0x80000005, &eax, &ebx, &ecx, &edx); + tlb_lli_2m = eax & 0xff; + } +- } else +- tlb_lli_2m = eax & mask; ++ } else { ++ tlb_lli_2m = tmp; ++ } + + tlb_lli_4m = tlb_lli_2m >> 1; + +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -857,7 +857,7 @@ static void get_model_name(struct cpuinfo_x86 *c) + + void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) + { +- unsigned int n, dummy, ebx, ecx, edx, l2size; ++ unsigned int n, dummy, ebx, ecx, edx, l2size, shift __maybe_unused; + + n = c->extended_cpuid_level; + +@@ -877,7 +877,9 @@ void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) + l2size = ecx >> 16; + + #ifdef CONFIG_X86_64 ++ shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; + c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); ++ c->x86_tlbsize <<= shift; + #else + /* do processor-specific cache resizing */ + if (this_cpu->legacy_cache_size) diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 2e0bddf..04293f9 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -64,6 +64,7 @@ source=( 0210-pstate.patch{,.sig} 0211-amd-pstate-fixes.patch{,.sig} 0212-amd-pstate-epp-cache.patch{,.sig} + 0220-x86-amd-zen5-tlb-sizes.patch{,.sig} 0250-zsmalloc.patch{,.sig} 0260-mglru-exec-protect.patch{,.sig} 0270-ksm-rmap-walk.patch{,.sig} @@ -182,6 +183,8 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' '2f24f88d8f960148046c36222fdaaadfed2ca88c60240fa1d111430898192ca45aeaa93a3afa24ad02b11c4dc8c3904a92f17c0284396f2f43352ad934a35056' 'SKIP' + 'e59c4da548b2ea4fd6144886e3e2e765b3e73972121e9e73dbc05c066834b2b35e6ef4c17617e77efc90260566bf7c0910d2138d8d5c1c3b6094eeac9de64cfe' + 'SKIP' '9809e258eb684b80d508fa2f2fa270683b62bd1412ed05a970114aaa7d84c37c0beaea51f9ff8c6ee1bc7318c4aee3725e9a1131fefb51ba700801de6ac414c5' 'SKIP' 'f115e8c80d723f7c24e6b1638b801cd664bef20acb1d2f6e6f5612744b916278693011782228cd3f4d0518654b8d53309bc5b06bbe8ed722fab9995f369bf548' @@ -373,6 +376,8 @@ sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' 'SKIP' '66eb2c49dbf708cc781d411d0e44ed613480f0ef66d522272929d9cb7bb21e93' 'SKIP' + '718b40e15350049e03c0ed281b9257fca5432b8dec2e0e145e8b26507ee8892d' + 'SKIP' 'b7ba949eea77e169aceb2c401d4eb83a7413aab6f15ee2a7ab1a96352f0aa12d' 'SKIP' '341424b925d506869793686e22ea8f095a34048595ebebec409c0a7bbd346ca2' From 99b8005e73bbc244ff9dcae4b1791ae504492daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Thu, 17 Sep 2026 09:02:23 +0900 Subject: [PATCH 035/121] Update Linux kernel release to v7.2.5-5 for base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- pkgbuilds/linux-omarchy-bore/PKGBUILD | 2 +- pkgbuilds/linux-omarchy/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index 68d19c1..c957e63 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy-bore pkgver=7.2.5 -pkgrel=4 +pkgrel=5 pkgdesc='Omarchy Linux (BORE CPU scheduler, ADIOS I/O scheduler)' url='https://omarchy.org' arch=( diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 04293f9..b02c163 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy pkgver=7.2.5 -pkgrel=4 +pkgrel=5 pkgdesc='Omarchy Linux' url='https://omarchy.org' arch=( From ce33f284140474c0ce579170fc49b6f02d6e726a Mon Sep 17 00:00:00 2001 From: Omarchybot Date: Thu, 17 Sep 2026 12:40:45 +0200 Subject: [PATCH 036/121] Match flea's O_NOFOLLOW fix by behaviour, not by spelling (#488) Upstream sync has failed on every run since flea v0.3.0 was published, with "Release v0.3.0 does not contain every required upstream security fix". Eight of the nine required fixes are present. The ninth is too: the check is wrong. The check pinned the literal call `regfile::open_if_regular(src, O_NOFOLLOW)`. v0.3.0 introduced directory-relative opens and the first argument became `src.at`. O_NOFOLLOW is still passed to the same function, on the same line, under the same comment, and the release hardened symlink handling further -- it added copy_symlink_at, opens directories with O_DIRECTORY | O_NOFOLLOW, and reaches every child through this process's own descriptor. The guard refused a release that is strictly safer than the one it accepted. The property worth asserting is that the copy opens its source with O_NOFOLLOW, so a symlink swapped in cannot redirect the read. Pinning the exact expression asserted the spelling instead, which is why a rename read as a removed fix. The check now matches the call and the flag together. Verified against the real archives rather than by inspection: v0.3.0 (src.at, O_NOFOLLOW) accepted v0.2.1 (src, O_NOFOLLOW) accepted, so the change is backwards compatible with what is packaged today first argument renamed accepted extra flag or argument added accepted O_NOFOLLOW dropped refused call replaced with File::open refused flag left only in a comment refused End to end with the real feed: the hook on master exits 1 with the refusal, and with this change exits 0 and reports 0.3.0 with its verified checksum. The other eight literals are untouched. Co-authored-by: Claude Opus 5 (1M context) --- pkgbuilds/flea/.omarchy/upstream.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkgbuilds/flea/.omarchy/upstream.sh b/pkgbuilds/flea/.omarchy/upstream.sh index 3acff3e..15c8853 100755 --- a/pkgbuilds/flea/.omarchy/upstream.sh +++ b/pkgbuilds/flea/.omarchy/upstream.sh @@ -85,6 +85,14 @@ sharelink_qml=$(tar -xOzf "$tarball" "$expected_root/ui/ShareLink.qml") copyfile_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/copyfile.rs") regfile_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/regfile.rs") +# Every check below pins a literal line except the O_NOFOLLOW one. That check +# guards a property -- the copy opens its source with O_NOFOLLOW, so a symlink +# swapped in cannot redirect the read -- and pinning the exact call expression +# made it assert the spelling instead. v0.3.0 moved the first argument from +# `src` to `src.at` when directory-relative opens landed, kept O_NOFOLLOW, and +# hardened symlink handling further; the literal still refused it. Match the +# call and the flag together so a rename cannot read as a removed fix, while +# dropping O_NOFOLLOW still fails. if ! grep -Fq 'a.push("--".to_string());' <<<"$archive_rs" || ! grep -Fq 'let input = std::fs::canonicalize(input)' <<<"$archiveops_rs" || ! grep -Fq 'if op != "compress" && op != "extract"' <<<"$run_rs$archivereq_rs" || @@ -92,7 +100,7 @@ if ! grep -Fq 'a.push("--".to_string());' <<<"$archive_rs" || ! grep -Fq 'if !sandbox::available()' <<<"$mediaprobe_rs" || ! grep -Fq 'if !sandbox::available()' <<<"$metareq_rs" || ! grep -Fq 'copyToClipboard.command = ["wl-copy", url]' <<<"$sharelink_qml" || - ! grep -Fq 'regfile::open_if_regular(src, O_NOFOLLOW)' <<<"$copyfile_rs" || + ! grep -Eq 'open_if_regular\(.*O_NOFOLLOW' <<<"$copyfile_rs" || ! grep -Fq '.custom_flags(O_NONBLOCK | extra_flags)' <<<"$regfile_rs"; then printf 'Release %s does not contain every required upstream security fix\n' "$best_tag" >&2 exit 1 From afcd481422c4f5a08252b775619287f5a0260566 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 13:20:13 +0200 Subject: [PATCH 037/121] chore: sync upstream releases (#481) Co-authored-by: dhh <2741+dhh@users.noreply.github.com> --- pkgbuilds/aether/PKGBUILD | 8 ++++---- pkgbuilds/claude-code/PKGBUILD | 6 +++--- pkgbuilds/cua-driver-bin/PKGBUILD | 6 +++--- pkgbuilds/cursor-cli/PKGBUILD | 6 +++--- pkgbuilds/heroic-games-launcher-bin/PKGBUILD | 4 ++-- pkgbuilds/omakade/PKGBUILD | 4 ++-- pkgbuilds/once-bin/PKGBUILD | 6 +++--- pkgbuilds/openai-codex-desktop/PKGBUILD | 6 +++--- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pkgbuilds/aether/PKGBUILD b/pkgbuilds/aether/PKGBUILD index 8927657..5456db6 100644 --- a/pkgbuilds/aether/PKGBUILD +++ b/pkgbuilds/aether/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Bjarne Øverli pkgname=aether -pkgver=4.29.8 +pkgver=4.29.9 pkgrel=1 pkgdesc='Desktop theming application - extract colors from wallpapers and apply cohesive themes' arch=('x86_64' 'aarch64') @@ -10,9 +10,9 @@ depends=('webkit2gtk-4.1' 'gtk3') source=("aether-${pkgver}.tar.gz::https://github.com/omacom/aether/archive/refs/tags/v${pkgver}.tar.gz") source_x86_64=("aether-linux-amd64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-amd64") source_aarch64=("aether-linux-arm64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-arm64") -sha256sums=('b83e0eeb1332b4ed655389a051d5b9b14a3e109968b7f278005e52c5e69a1e9c') -sha256sums_x86_64=('d3d2d07b32da7a495221ed271ee66f4a1e344c91dcec9b267ec0a74ab6e36462') -sha256sums_aarch64=('ffcfd23d0375a3f0c0ce014821cc5e1670f2e061c35e991340e75352dac9b731') +sha256sums=('d5f39da9f2566783f7be194efca41b20627e62e79f83c3ff944dd3d0511f0c15') +sha256sums_x86_64=('073784620a18931e8f1389e9e9e8a70dae1458eceda6fce608ae1290f77bee99') +sha256sums_aarch64=('5041c62b0638876d3ee907703bc95b5c2a0d3b1ab3f3a5257997a452cf60ca10') noextract=("aether-linux-amd64-${pkgver}" "aether-linux-arm64-${pkgver}") package() { diff --git a/pkgbuilds/claude-code/PKGBUILD b/pkgbuilds/claude-code/PKGBUILD index 4004045..3a179f8 100644 --- a/pkgbuilds/claude-code/PKGBUILD +++ b/pkgbuilds/claude-code/PKGBUILD @@ -4,7 +4,7 @@ # Automation repository: https://github.com/fabifont/claude-code-aur pkgname=claude-code -pkgver=2.1.273 +pkgver=2.1.274 pkgrel=1 pkgdesc="An agentic coding tool that lives in your terminal" arch=('x86_64' 'aarch64') @@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude") sha256sums=('SKIP') -sha256sums_x86_64=('6c752e2cc7c110c9df15f26d8d134d438c5ae95dbd610efc1a308bf7f9c5f6c1') -sha256sums_aarch64=('103cfab4d6ae898b6af692336fb662ffcc607075cc6408892bd350b3f549ebee') +sha256sums_x86_64=('15e2d05148f801b5774032faad87e624ecd172e9903288bda448b892eb58fa07') +sha256sums_aarch64=('2db904daea17addff9de557ba26a725916888aa7b546e2c5dd989c20d9d49ab3') package() { install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude" diff --git a/pkgbuilds/cua-driver-bin/PKGBUILD b/pkgbuilds/cua-driver-bin/PKGBUILD index 07ce954..f9679fb 100644 --- a/pkgbuilds/cua-driver-bin/PKGBUILD +++ b/pkgbuilds/cua-driver-bin/PKGBUILD @@ -18,7 +18,7 @@ # binary to point at pm.sh, a stand-in that declines and names pacman instead. pkgname=cua-driver-bin -pkgver=0.28.1 +pkgver=0.28.2 pkgrel=1 pkgdesc="Computer-use driver for native GUI apps: accessibility-tree snapshots and input injection" arch=('x86_64' 'aarch64') @@ -46,8 +46,8 @@ source_x86_64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v$ source_aarch64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v${pkgver}/cua-driver-rs-${pkgver}-linux-arm64.tar.gz") sha256sums=('c0779290c1d4783169aa3dbfb55feb505e563ef8a004bbf55298ceffcfbda8d9' 'c76e251c3ed424200eac52bec35ba534336307fabd83a175ab0b47e2084ab0d8') -sha256sums_x86_64=('a068b6e477893b77ced74bceccf7db7483cf140e8d54150ce5849b6252b90bcf') -sha256sums_aarch64=('a863951ef0699fd25091adb87bd114d69709b887fdfc059e795aca49ef8ac19c') +sha256sums_x86_64=('8f3e5b669e2bcd98d0eecc64f40640aac77f358b6332a06abc6ee79991620f7d') +sha256sums_aarch64=('cadd7e6b757c3ce50f2b5f6e273c154ea48450fb5fcaff744209b382915eddf5') case "${CARCH}" in x86_64) _platform="linux-x86_64" ;; diff --git a/pkgbuilds/cursor-cli/PKGBUILD b/pkgbuilds/cursor-cli/PKGBUILD index 14869ab..11205d0 100644 --- a/pkgbuilds/cursor-cli/PKGBUILD +++ b/pkgbuilds/cursor-cli/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ismet Togay # Contributor: Christopher Cooper pkgname=cursor-cli -pkgver=2026.09.10.1.fd3934a +pkgver=2026.09.15.1.d2fe57e # Upstream is YYYY.MM.DD-. pkgver cannot contain hyphens, and hashes are # not monotonically ordered, so pkgver is YYYY.MM.DD..: n resets to 1 # on a new date and increments when the same date gets a new hash. @@ -25,8 +25,8 @@ source_x86_64=("cursor-cli-${_upstream_ver}-x86_64.tar.gz::https://downloads.cur source_aarch64=("cursor-cli-${_upstream_ver}-aarch64.tar.gz::https://downloads.cursor.com/lab/${_upstream_ver}/linux/arm64/agent-cli-package.tar.gz") b2sums=('d241ee9895bdb1c17514438fde8528222a8f2326568bd7a033d7a1b11432ce6b4575ff1a50625764bfe6bc6f8a9dc060f7439c3be7e95f8fd02912cdd37a011d' '1928e04c713e13911ea607f84c3e4a2fed1f76af9795503811078f43d2b53c753e28b2233e553fc17e766831800fb0dbc272aad2a80b387f95ba6071d7d4116a') -b2sums_x86_64=('121c0128fd630565c7000b86ae53bf76e73fd72c1ab8ba2509fae7739b1c7f4bed0587a82137340303ac4704f3344cf63a10eab0e8bea262c8e48bbb21bcb742') -b2sums_aarch64=('bfc0f540190214396df3cbb93c411ab8055677bc1dd0b0e76d1b914d6c6d90af12519434227ba8b38a38249f1bfe0a8848f47e16dc048b4fa005d366815307be') +b2sums_x86_64=('ba078241313672770d91286f433b9f0e94aba6f3dd3f7b0e38b927a1dd9d2adc322ac54e8e04f6b87a42d020edbd8929070c330b23bc536a59ab998fdb6200cb') +b2sums_aarch64=('b3fb72843237b79b69b89c3d586bb4f56412bf26b444d08c174ffce8b8774c1be95452fcd84a4278ddcb9381a656d5b1e5dcd2e967d224c356ae31241e4044b2') prepare() { # Block cursor-agent auto-updates by making its versions directory diff --git a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD index ead38ab..6c18559 100755 --- a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD +++ b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD @@ -2,7 +2,7 @@ # Maintainer: CommandMC pkgname=heroic-games-launcher-bin -pkgver=2.22.2 +pkgver=2.22.3 pkgrel=1 pkgdesc="An Open source Launcher for Epic, Amazon and GOG Games" arch=('x86_64') @@ -11,7 +11,7 @@ license=('GPL-3.0-only') _filename=Heroic-${pkgver}-linux-x64.pacman source=("https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v${pkgver}/${_filename}") noextract=("${_filename}") -sha256sums=('4e4033ac70b8c407eaf70ce072e4e4d017200f07a3e88f7cfd4d3a597f3c09b8') +sha256sums=('ed17ce083a71dd7e49a89218052ab475edd5a654cedf443853f6baacbb0a00e9') options=(!strip) depends=( which diff --git a/pkgbuilds/omakade/PKGBUILD b/pkgbuilds/omakade/PKGBUILD index 72e502e..75a909f 100644 --- a/pkgbuilds/omakade/PKGBUILD +++ b/pkgbuilds/omakade/PKGBUILD @@ -1,5 +1,5 @@ pkgname=omakade -pkgver=1.9.2 +pkgver=1.10.0 pkgrel=1 pkgdesc='A beautiful, local-first game library for Omarchy' arch=('x86_64' 'aarch64') @@ -11,7 +11,7 @@ depends=('glib2' 'hicolor-icon-theme' 'libsecret' 'libzip' 'openssl' 'qt6-base' makedepends=('cmake' 'ninja' 'pkgconf' 'wayland-protocols') options=('!debug') source=("$pkgname-$pkgver.tar.gz::https://github.com/btsouth/omakade/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz") -sha256sums=('4c0ba7eecc036b959b34a8068f5923e8927e59b8ee2f0398d470cd933343c4fc') +sha256sums=('01a4c1aa35c51aba54f57fd0d4eab4a00a14ca2bd4d1b6163264b8ba6fed5b55') build() { cmake -S "$pkgname-$pkgver" -B build -G Ninja \ diff --git a/pkgbuilds/once-bin/PKGBUILD b/pkgbuilds/once-bin/PKGBUILD index 7784085..8b0f952 100644 --- a/pkgbuilds/once-bin/PKGBUILD +++ b/pkgbuilds/once-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Kevin McConnell pkgname=once-bin -pkgver=0.3.2 +pkgver=0.3.3 pkgrel=1 pkgdesc='CLI/TUI for installing and managing self-hosted web applications' arch=('x86_64' 'aarch64') @@ -22,8 +22,8 @@ source=("MIT-LICENSE-${pkgver}::https://raw.githubusercontent.com/basecamp/once/ sha256sums=('fa0d1454375cbc7701bc13d916c3ae71e613b8ae718321641e678e09409393c4' 'aa314fe79677eb5f120fcc3d4c42007a93ff7b1ef917382c0c1fdca5633ad46a') -sha256sums_x86_64=('e1da40a0952879580e43623d6fd6002a391ee469b642c98ecddbe00374facbb6') -sha256sums_aarch64=('9bd644e1557521b0b8cab93ba3841747cbee0390aa3aa020bd91bfa66ac51dec') +sha256sums_x86_64=('aef855da263721c6c1072ff5ebc4c17a52af8c8e80c46c5a9dd458e7ca3a7f35') +sha256sums_aarch64=('97e32ba0fdac0ad5e6010851b306e3cb2616285a9eeb2e869ff7e71f4b442bbb') package() { install -Dm755 "once-${pkgver}-${CARCH}" "${pkgdir}/usr/bin/once" diff --git a/pkgbuilds/openai-codex-desktop/PKGBUILD b/pkgbuilds/openai-codex-desktop/PKGBUILD index f875388..fa3f20d 100644 --- a/pkgbuilds/openai-codex-desktop/PKGBUILD +++ b/pkgbuilds/openai-codex-desktop/PKGBUILD @@ -5,7 +5,7 @@ # the version and checksums below from that repository's package index. pkgname=openai-codex-desktop -pkgver=26.908.70816 +pkgver=26.911.61220 pkgrel=1 pkgdesc="Official ChatGPT desktop app with Codex" arch=('x86_64' 'aarch64') @@ -71,8 +71,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c') -sha256sums_x86_64=('10ed0c1a880b9975d1f185bf7911a7f514e06b9863cd4ed9561d40063617c854') -sha256sums_aarch64=('d3ec8f1d73b92f203715c26dbf2e0e64375192d00ddaf26f7fbade7777124de8') +sha256sums_x86_64=('14e1d4aeed7fed22adbd2b8ec20fe57bfbdd9ee9902370b4e2726677ca68bbba') +sha256sums_aarch64=('8517ddd0582ba8aa9b7879a2c566b4e622b62e0aebc4830272492d4e123f358b') package() { cd "${srcdir}" From 1bce595733265e4c94db8a50cb3841e9d3e9b557 Mon Sep 17 00:00:00 2001 From: dhh <2741+dhh@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:54:13 +0000 Subject: [PATCH 038/121] chore: sync upstream releases --- pkgbuilds/claude-desktop/PKGBUILD | 6 +++--- pkgbuilds/flea/PKGBUILD | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgbuilds/claude-desktop/PKGBUILD b/pkgbuilds/claude-desktop/PKGBUILD index 308d94a..3de9345 100644 --- a/pkgbuilds/claude-desktop/PKGBUILD +++ b/pkgbuilds/claude-desktop/PKGBUILD @@ -6,7 +6,7 @@ # repository's package index. pkgname=claude-desktop -pkgver=2.110.0 +pkgver=2.110.1 pkgrel=1 pkgdesc="Official Claude desktop app with Claude Code" arch=('x86_64' 'aarch64') @@ -63,8 +63,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('edfdbc63b65891ef7c481b07086c7e630fc102c042b6ed65331a52fcaf72b14a') -sha256sums_x86_64=('f44cb8b52f6e9171ac2e67cbcc8070c4974a2f0a9b9f141b430b32b4ff541109') -sha256sums_aarch64=('de9f24034f33dcadc53bedee92da6604e2c9268497ebff5447fedc092c884e71') +sha256sums_x86_64=('0a9b0ac5456451637d8068ed757db0335cb6c0f24375479e740f572dbf886466') +sha256sums_aarch64=('2bbcd7bd9807417335290621d950f0b8a7b884e19724122bd4a6e40a63a81495') package() { cd "${srcdir}" diff --git a/pkgbuilds/flea/PKGBUILD b/pkgbuilds/flea/PKGBUILD index a525033..337aa95 100644 --- a/pkgbuilds/flea/PKGBUILD +++ b/pkgbuilds/flea/PKGBUILD @@ -1,8 +1,8 @@ # Maintainer: GM pkgname=flea -pkgver=0.2.1 -pkgrel=3 +pkgver=0.3.0 +pkgrel=1 pkgdesc='Fast, keyboard-first file manager for Omarchy' arch=('x86_64' 'aarch64') url='https://github.com/thisisgm/flea' @@ -48,7 +48,7 @@ options=('!debug') source=( "$url/releases/download/v$pkgver/$pkgname-v$pkgver.tar.gz" ) -sha256sums=('75f9ac0274a09a0d55cf7d9187943983c1b78a9e443465738b3ac8af8f2a77e9') +sha256sums=('975fe4c3d6ee91470be9fe8835e247ec3054e74b1682a8315e19c3aedbef8d05') build() { cd "$pkgname-$pkgver" From 1beee4695b7d2513384a22a8d7931e0d68c988c7 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Thu, 17 Sep 2026 09:34:56 -0400 Subject: [PATCH 039/121] Package Flea 0.3.0 phone backends and shelf --- pkgbuilds/flea/PKGBUILD | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgbuilds/flea/PKGBUILD b/pkgbuilds/flea/PKGBUILD index 337aa95..1c15737 100644 --- a/pkgbuilds/flea/PKGBUILD +++ b/pkgbuilds/flea/PKGBUILD @@ -15,7 +15,10 @@ depends=( 'glib2' 'glibc' 'gvfs' + 'gvfs-afc' 'gvfs-dnssd' + 'gvfs-gphoto2' + 'gvfs-mtp' 'gvfs-nfs' 'gvfs-smb' 'hicolor-icon-theme' @@ -28,6 +31,7 @@ depends=( 'qt6-multimedia' 'qt6-webengine' 'shared-mime-info' + 'usbmuxd' 'util-linux' 'wl-clipboard' 'xdg-terminal-exec' @@ -158,6 +162,9 @@ package() { install -Dm644 ui/qmldir ui/*.qml -t "$pkgdir/usr/share/flea/ui" install -Dm644 ui/js/*.js -t "$pkgdir/usr/share/flea/ui/js" + # Flea's Shelf setting installs this plugin into the user's plugin directory. + install -Dm644 shelf/manifest.json shelf/README.md shelf/*.qml shelf/*.js \ + -t "$pkgdir/usr/share/flea/shelf" ln -s /usr/share/omarchy/shell/Commons "$pkgdir/usr/share/flea/ui/Commons" ln -s /usr/share/omarchy/shell/Ui "$pkgdir/usr/share/flea/ui/Ui" } From 750eb611f50c47fcbd51dc396e29175b9667e12e Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 17 Sep 2026 09:54:55 -0400 Subject: [PATCH 040/121] Update herdr to 0.9.1 with Zig 0.16.0 for the vendored libghostty-vt (#493) Upstream 0.9.1 bumps vendored libghostty-vt's minimum_zig_version to 0.16.0, so the pinned Zig tarballs move from 0.15.2 to 0.16.0 with checksums taken from ziglang.org's download index. Co-authored-by: Claude Fable 5.1 --- pkgbuilds/herdr/PKGBUILD | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgbuilds/herdr/PKGBUILD b/pkgbuilds/herdr/PKGBUILD index 02cc4d3..94e5e31 100644 --- a/pkgbuilds/herdr/PKGBUILD +++ b/pkgbuilds/herdr/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=herdr -pkgver=0.9.0 +pkgver=0.9.1 pkgrel=1 pkgdesc="Herdr terminal workspace manager for AI coding agents" arch=('x86_64' 'aarch64') @@ -13,13 +13,13 @@ replaces=('omarchy-herdr') conflicts=('omarchy-herdr') options=('!debug' '!lto') -_zigver=0.15.2 +_zigver=0.16.0 source=("herdr-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") source_x86_64=("zig-x86_64-linux-$_zigver.tar.xz::https://ziglang.org/download/$_zigver/zig-x86_64-linux-$_zigver.tar.xz") source_aarch64=("zig-aarch64-linux-$_zigver.tar.xz::https://ziglang.org/download/$_zigver/zig-aarch64-linux-$_zigver.tar.xz") -sha256sums=('1e83bff4b05834ed8281e16f1680e8f3e58375a94b2e3f2b3d021e28e293ef9a') -sha256sums_x86_64=('02aa270f183da276e5b5920b1dac44a63f1a49e55050ebde3aecc9eb82f93239') -sha256sums_aarch64=('958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f') +sha256sums=('03403d3ef80dcf2b954dd5d27eb636e6c4f5279d240b48de272b7f53e4b73093') +sha256sums_x86_64=('70e49664a74374b48b51e6f3fdfbf437f6395d42509050588bd49abe52ba3d00') +sha256sums_aarch64=('ea4b09bfb22ec6f6c6ceac57ab63efb6b46e17ab08d21f69f3a48b38e1534f17') prepare() { cd "herdr-$pkgver" From 259aa68129eba0e56c8768e0649c095e41d226d6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 17 Sep 2026 11:36:14 -0400 Subject: [PATCH 041/121] Add Monologue webcam recorder package (#495) * Add Monologue webcam recorder package * Update Monologue to latest published source --- pkgbuilds/monologue/.omarchy/package.json | 3 ++ pkgbuilds/monologue/PKGBUILD | 40 +++++++++++++++++++++++ pkgbuilds/monologue/monologue.install | 12 +++++++ 3 files changed, 55 insertions(+) create mode 100644 pkgbuilds/monologue/.omarchy/package.json create mode 100644 pkgbuilds/monologue/PKGBUILD create mode 100644 pkgbuilds/monologue/monologue.install diff --git a/pkgbuilds/monologue/.omarchy/package.json b/pkgbuilds/monologue/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/monologue/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/monologue/PKGBUILD b/pkgbuilds/monologue/PKGBUILD new file mode 100644 index 0000000..9b9e14e --- /dev/null +++ b/pkgbuilds/monologue/PKGBUILD @@ -0,0 +1,40 @@ +# Maintainer: David Heinemeier Hansson + +pkgname=monologue +pkgver=0.1.0 +pkgrel=3 +pkgdesc='A simple, theme-synced webcam recorder for Omarchy' +arch=('x86_64' 'aarch64') +url='https://github.com/omacom/monologue' +license=('MIT') +install='monologue.install' +options=('!debug') +depends=( + 'ffmpeg' + 'hicolor-icon-theme' + 'libpulse' + 'qt6-base' + 'qt6-declarative' + 'qt6-multimedia>=6.8' + 'xdg-desktop-portal' +) +makedepends=('gcc' 'make' 'pkgconf') +optdepends=('omacut: trim recordings directly from Monologue') +# Pin the published source until a tagged release is available. +_commit=23e0844f60feef2f9d2cf2c9d89f13eb0bf5adef +source=("$pkgname-$_commit.tar.gz::$url/archive/$_commit.tar.gz") +sha256sums=('1a04b9e47b29846e9135d110978f7f35c0274f7361729f0b6ac03796499c0ad6') + +build() { + cd "$srcdir/$pkgname-$_commit" + ./bin/build +} + +package() { + cd "$srcdir/$pkgname-$_commit" + + install -Dm755 build/monologue "$pkgdir/usr/bin/monologue" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 pkgbuild/monologue.svg "$pkgdir/usr/share/icons/hicolor/scalable/apps/monologue.svg" + install -Dm644 pkgbuild/monologue.desktop "$pkgdir/usr/share/applications/monologue.desktop" +} diff --git a/pkgbuilds/monologue/monologue.install b/pkgbuilds/monologue/monologue.install new file mode 100644 index 0000000..5357602 --- /dev/null +++ b/pkgbuilds/monologue/monologue.install @@ -0,0 +1,12 @@ +post_install() { + command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database -q + command -v gtk-update-icon-cache >/dev/null 2>&1 && gtk-update-icon-cache -q -t -f usr/share/icons/hicolor +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} From afd75bc571e397d56be04d5b4219e17a8b3c5196 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Thu, 17 Sep 2026 10:58:46 -0500 Subject: [PATCH 042/121] Add linux-firmware-cirrus stable-snapshot shim for the Dell XPS 13 DX13260 The Panther Lake XPS 13 (audio subsystem 1028:0e54) drives all of its speakers through two CS35L56 amplifiers behind the CS42L43 codec. Their DSP firmware aliases (cs35l56-b2-dsp1-misc-10280e54-spkid{1,2,3}) were added to linux-firmware on 2026-08-18 and ship in Arch's linux-firmware-cirrus 20260910-2, but the stable channel's Arch snapshot is still on 20260810-2. Without them the amps run ROM firmware and the machine is completely silent; upstream 7.2 already selects the sidecar amplifier path for this SSID, so no kernel change is involved. Ship the 20260910-2 payload to stable as a self-retiring shim: - fast ring, no upstream watch (sync: false): the version is deliberately 20260810-3, above the snapshot's 20260810-2 and below Arch's real 20260910-2, so the genuine package supersedes it in the same transaction that upgrades linux-firmware-other once the snapshot advances. Bumping pkgver would defeat that. - the signed Arch package is verified against the Arch packager key in keys/pgp/ and reinstalled as-is, minus the cs42l45 SDCA tree that Arch moved out of linux-firmware-other in 20260910: on the stable snapshot those 190 files are still owned by -other 20260810-2 and would conflict. The nine 10280e54 links and the 39 new SDCA files are kept. Verified on a DX13260: cold boot loads 10280e54-spkid1 v4.5.9 on both amps with "Calibration applied", and a 440 Hz tone measured through the internal microphones peaks 238x over the noise floor on the stock UCM bridge route. Delete this recipe once stable's snapshot carries linux-firmware >= 20260910. Co-Authored-By: Claude Fable 5.1 --- docs/upstream-sources.md | 2 + .../.omarchy/package.json | 5 ++ pkgbuilds/linux-firmware-cirrus/PKGBUILD | 63 +++++++++++++++++++ ...BC8889351B5DEBBB68416EB8AC08600F108CDF.asc | 60 ++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 pkgbuilds/linux-firmware-cirrus/.omarchy/package.json create mode 100644 pkgbuilds/linux-firmware-cirrus/PKGBUILD create mode 100644 pkgbuilds/linux-firmware-cirrus/keys/pgp/83BC8889351B5DEBBB68416EB8AC08600F108CDF.asc diff --git a/docs/upstream-sources.md b/docs/upstream-sources.md index 9276bd2..e57f546 100644 --- a/docs/upstream-sources.md +++ b/docs/upstream-sources.md @@ -168,6 +168,8 @@ in `origin` and has no effect on release selection. These packages were already excluded from automatic AUR updates. The migration preserves that policy. +`linux-firmware-cirrus` is a deliberate hold: a self-retiring shim that ships Arch's linux-firmware-cirrus 20260910-2 payload to stable while stable's Arch snapshot is on 20260810-2 (Dell XPS 13 DX13260 / 1028:0e54 speaker firmware). It is versioned 20260810-3 so the genuine Arch package supersedes it as soon as the snapshot advances; bumping it to the Arch version would defeat that. Delete the recipe once stable's snapshot carries linux-firmware >= 20260910. + ## Package-specific boundaries - NVIDIA watches remain on the 580 driver branch. diff --git a/pkgbuilds/linux-firmware-cirrus/.omarchy/package.json b/pkgbuilds/linux-firmware-cirrus/.omarchy/package.json new file mode 100644 index 0000000..ba6af6c --- /dev/null +++ b/pkgbuilds/linux-firmware-cirrus/.omarchy/package.json @@ -0,0 +1,5 @@ +{ + "source": "local", + "release_ring": "fast", + "sync": false +} diff --git a/pkgbuilds/linux-firmware-cirrus/PKGBUILD b/pkgbuilds/linux-firmware-cirrus/PKGBUILD new file mode 100644 index 0000000..0c46f9b --- /dev/null +++ b/pkgbuilds/linux-firmware-cirrus/PKGBUILD @@ -0,0 +1,63 @@ +# Maintainer: Spencer Bull +# +# Self-retiring shim: ships Arch's linux-firmware-cirrus 20260910-2 payload to +# the stable channel while stable's pinned Arch snapshot is still on +# linux-firmware 20260810-2 (which lacks the Dell XPS 13 DX13260 / 1028:0e54 +# CS35L56 amplifier firmware aliases, leaving that machine's speakers silent). +# +# Nothing is rebuilt. The signed Arch package is verified against the Arch +# packager key and its payload reinstalled as-is, minus the files that Arch +# moved out of linux-firmware-other in 20260910 (the cs42l45 SDCA tree): on +# the stable snapshot those are still owned by linux-firmware-other 20260810-2 +# and would conflict, so they are left to that package. +# +# Versioning is deliberate: 20260810-3 orders above the snapshot's 20260810-2 +# and BELOW Arch's real 20260910-2, so as soon as the stable snapshot advances +# pacman replaces this shim with the genuine package in the same transaction +# that upgrades linux-firmware-other, and nothing is lost. Delete this recipe +# once stable's snapshot is at linux-firmware >= 20260910. + +pkgname=linux-firmware-cirrus +pkgver=20260810 +pkgrel=3 +_fwver=20260910 +_fwrel=2 +_basever=20260810 +_baserel=2 +pkgdesc="Firmware files for Linux - Firmware for Cirrus Logic audio devices (Arch - payload, stable-snapshot shim)" +arch=('any') +url="https://gitlab.com/kernel-firmware/linux-firmware" +license=('LicenseRef-WHENCE' 'LicenseRef-cirrus') +depends=('linux-firmware-whence') +options=('!strip' '!debug') +_cirrus="linux-firmware-cirrus-${_fwver}-${_fwrel}-any.pkg.tar.zst" +_other="linux-firmware-other-${_basever}-${_baserel}-any.pkg.tar.zst" +source=( + "https://archive.archlinux.org/packages/l/linux-firmware-cirrus/${_cirrus}" + "https://archive.archlinux.org/packages/l/linux-firmware-cirrus/${_cirrus}.sig" + "https://archive.archlinux.org/packages/l/linux-firmware-other/${_other}" + "https://archive.archlinux.org/packages/l/linux-firmware-other/${_other}.sig" +) +noextract=("${_cirrus}" "${_other}") +sha256sums=('70100c551b079bd8abec3d9c96a16defd04766b2a4afc6d7be9128d37e9840f7' + 'SKIP' + 'b0f016ee0d0532b977211b0cbb630bca75184f68a9ace82675eb3cf9acce4f6c' + 'SKIP') +# Jan Alexander Steffens (heftig) , Arch Linux packager +validpgpkeys=('83BC8889351B5DEBBB68416EB8AC08600F108CDF') + +package() { + # Payload only; makepkg regenerates .PKGINFO/.MTREE/.BUILDINFO. + bsdtar -xf "${srcdir}/${_cirrus}" -C "${pkgdir}" \ + --exclude='.PKGINFO' --exclude='.MTREE' --exclude='.BUILDINFO' \ + --exclude='.INSTALL' --exclude='.CHANGELOG' + + # Drop every file the snapshot's linux-firmware-other still owns. + local f + while IFS= read -r f; do + [[ -e "${pkgdir}/${f}" || -L "${pkgdir}/${f}" ]] && rm -f "${pkgdir}/${f}" + done < <(bsdtar -tf "${srcdir}/${_other}" | grep -v '^\.' | grep -v '/$') + + # Remove directories emptied by the step above. + find "${pkgdir}/usr/lib/firmware" -depth -type d -empty -delete +} diff --git a/pkgbuilds/linux-firmware-cirrus/keys/pgp/83BC8889351B5DEBBB68416EB8AC08600F108CDF.asc b/pkgbuilds/linux-firmware-cirrus/keys/pgp/83BC8889351B5DEBBB68416EB8AC08600F108CDF.asc new file mode 100644 index 0000000..e6ae5d8 --- /dev/null +++ b/pkgbuilds/linux-firmware-cirrus/keys/pgp/83BC8889351B5DEBBB68416EB8AC08600F108CDF.asc @@ -0,0 +1,60 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZXeS9hYJKwYBBAHaRw8BAQdAT04Na8ee0UltkhyNi2RGHYdjZDgg+X/K8Jix +dSSQ+Ni0NkphbiBBbGV4YW5kZXIgU3RlZmZlbnMgKGhlZnRpZykgPGhlZnRpZ0Bh +cmNobGludXgub3JnPoiQBBMWCgA4AhsDAheAFiEEg7yIiTUbXeu7aEFuuKwIYA8Q +jN8FAmWq/kcFCwkIBwMFFQoJCAsFFgIDAQACHgUACgkQuKwIYA8QjN+2qAEAh/RL +Zq7Hmqv/z09yq0m6IEb0kbXaW50POi/V+2VcJ9wBAN5Ik/fFgnGMlvZF7Rugu37o +2fk7jnUVsWJca9QmytgGiHUEEBYKAB0WIQSZtmGEcqOzuBQYW67X09gjuIvbmwUC +aYWy0QAKCRDX09gjuIvbm7vJAP9xqmmI8jNGEUQNidh9yZCmVOr3vT5/sUcHGo0J +08o/TgD/Wix2/4DHfnk6fu+onERrK5uF9BAacERnCsG5lMWQ2wSJAjMEEAEKAB0W +IQSR/+BwDoBhnOtzI1yojiPjd1FOAAUCZa0cywAKCRCojiPjd1FOAIKbEACipPSS +sA2G7ntHRGEHSWKgqEKseGGr7kflVdsmJn1tjKI8/VGKa77NkCRgqIJRwmE9m9+F +Cx+a3ILmMOxsjj5RCVFce9NJuscVGHaphZcp7Z0MVoR9hhtnsyjWk/CYOAv+JLKq +NTYhdmat+ixY4fwPzjdV6sxCDL/s6Fci0zPLUam7QVr9LIS4U3UH7smkKj6jM+G/ +sEn0QM02EKy2iJLlbPNN3pppYWqZ5p9xXeB6EJ89JvZMI3k92xy456JjkCgLN860 +NPmdmnLLtlrGWJRgNK6+iaFjLt/BL9gU8aGe+K3ONXES2k7iZnh+oLAEV8Z07dgv +Gd0o+OFEPrC8kETbQK45r1yAjZVO+tp4dSxvV/BD+7KhUXAZnOKWLaOMomfsG17E +KKa894cBLJG7LWN/d/Uk9fjfjd4ZYbSpIALJiEoKrm1ytj2KgnxKveTtY69i63/N +0BpNVrkYIJffWR6zSosC8geAWfqm7pR6JARUAZrw0YtJbluDrRgOO0XFn8hDqRUm +FPWgXuvqNdR2JyD4aB87LKGhzVFzQvbHa+S4sG7+w5nWQB0Eca+hiVpJDpMYjoU+ +f+L3yUb6POwvUJe7VT/2PYOwidnV3guTevnn9a4erKoW/6wKAr13cW+KTKTR0bdC +S0UTOWbJnbi2Hfhyr7NZgs4T4OcpH3kj+R4WPIkCMwQQAQoAHRYhBNiv3aB6W27f +p9jM2tbQVfknhD8cBQJlg4C5AAoJENbQVfknhD8cpPQP/19uAVMaG1lQNaAK9XWT +Z1/lAr6sxYT6B2+MqnRtbkr4Gh3ts7Ey5BI39HxNWRIUGUt7pq4FjCQxWeJC9mfp +/hqj9rl1s32lbBzevbkjESro+cHPfrv0vsVlwJA2W3rURQlQzbEq3fvDzc/wz4sN +vgQDiUlxH5JYXZ5OexsDATLyfHNpJh+4NxqB24axjDe/1ZK8hoYl+eX46dP9JKWB +F8GA3Ebwst3de/81oNngBjDgNPju6cvgykoT2jCBn4asp1xKekZh5ZbRG40jAeoQ +QAvEgTxIbwNf4HBVhvGjQ6G5lCNO6gQonq1X4UbHgH8tRGSSgnz2yDAdcxtaj1eC +e5BMhjuoHuxS4DCtR97Dtn7YjrYoVus5eMkhEZGuWKK4hkggsLbyUx5llxZxLXPD +mBAYLkqgZsHgiqLeHAdrEmAFaRfskVg0MzfCcEE9StWnWf0ixk3thuwQAaPI4GCB +nNLnmqCcOyCN1Qa3iXjdOzp5bU0qwFi/qFQagq0nu8sJim7q0g0Bk7J+iGRht3no +L5iT9d+8CQaN1it+L+elSYfrr/LamghRvh9epOtGUVH3GQYS4Bgo2rgktGXKtcX+ +P/jR/aM034g8VPlbV+Kas/c6mIk9JzKOvJJ4+Lpvr0ZzRG32ez9dAlDogE3xASi6 +sMWbY+t4unGs+nY3SqIOyHLTiHUEEBYKAB0WIQRp5kceOuBlKXUpgy5roPWiA39P +QQUCZX7ZYAAKCRBroPWiA39PQadvAQD7F/N3xuyWogrJV7TMZk2PFteviEW2Dv9d +dSUGasK3dQEAxf3HxRDvrv3yJLhgNKa+ksr4bBBmruvilpWS+X4InwKIdQQQFgoA +HRYhBDVy+iobBn8ixYrxVfi4IbQqb9zXBQJlfKbrAAoJEPi4IbQqb9zXe7MBAIzF +QqdV8CJXYIcZJtUUIQ7a/AN2enHBpoa/qXEre5bAAP4uNEUMKiDZRpHAh/KmqarM +vF+c1BOpEJbQsPqv0L5hDIh1BBAWCgAdFiEEKsCkLvsLXLx6BALtTclbbXvpiS4F +AmV8nsgACgkQTclbbXvpiS6bpwD/W0sMOH4lmR4t9Sc8hJB+uBLGYxzoNIgaNa5x +vbdm5hwBAIPYr1SVl0+yghsxg5k75jStRL2S5MZW2iSV3ynNLTkFiHkEEBYKACEW +IQSi/zo2qqVmVBCQZKsZgC+LDXD8MAUCZXe6yAMFAngACgkQGYAviw1w/DCmCAD8 +Cfvn8O+N/AJTOKY8lZzk+OSX3tSTQTOUiLHKRl+RX6IA/1Bku44c1YJVZ+RhWkGQ +n0C8ZN/DYzHh9JInl3blLcIMtDhKYW4gQWxleGFuZGVyIFN0ZWZmZW5zIChoZWZ0 +aWcpIDxqYW4uc3RlZmZlbnNAZ21haWwuY29tPoiTBBMWCgA7AhsDAheAAhkBFiEE +g7yIiTUbXeu7aEFuuKwIYA8QjN8FAmWq/kIFCwkIBwMFFQoJCAsFFgIDAQACHgUA +CgkQuKwIYA8QjN+ySAD+PI99JJsFWz2CaS3enxjUMCWJZJvSV9G1FqmeTKtH95oA +/ismVRjBbwbCrDDEsZVIK3NeRyRyhiWIVFXWix/KnH4CiHkEEBYKACEWIQSi/zo2 +qqVmVBCQZKsZgC+LDXD8MAUCZXe6xQMFAngACgkQGYAviw1w/DDnzAD6AwROKYI8 +7DZ6a1onZeR5wOV50bt2LCB4XxNiupHcpLMA/i4dmwa4Bkzyh/h+v0kN2PSssueX +7kFPNcnyhe3KbUUDuDMEZXeUSxYJKwYBBAHaRw8BAQdAkvIbYwde3OFqoAy6QOO9 +BPwFNCll8tgQ6iAmQMkOjtWIeAQYFgoAIBYhBIO8iIk1G13ru2hBbrisCGAPEIzf +BQJld5RLAhsgAAoJELisCGAPEIzfhU8A/3NZzIEk3dmCAL0XLtylcFp/HExnN+5Q +RGmT0+SzzuGaAP9ozoMlSjtcGLAZMglLk8/mYzKveR89RJlB0cZtUU6UArg4BGV3 +kvYSCisGAQQBl1UBBQEBB0Dh/7CubQh/MabODq3IcoqeGUzEGUPU8GXCVrDmPHih +WQMBCAeIeAQYFgoAIBYhBIO8iIk1G13ru2hBbrisCGAPEIzfBQJld5L2AhsMAAoJ +ELisCGAPEIzfao0A/AiJPB4igiyHjPgR8OpKh4Nz+pwmFrD/j5l2YC0Xi2dOAP4j +LDEa1VCNNhq7vWA8SqUjareBzHpwlG2ObUwYxORjBQ== +=OXp6 +-----END PGP PUBLIC KEY BLOCK----- From 1f025695d571e9bb848262bff5ac74afcc2dbd95 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Thu, 17 Sep 2026 13:35:33 -0400 Subject: [PATCH 043/121] Build t3code-bin for aarch64 --- pkgbuilds/t3code-bin/.omarchy/upstream.sh | 24 ++++++--- pkgbuilds/t3code-bin/PKGBUILD | 30 +++++++---- tests/upstream-watch.py | 66 +++++++++++++++++++++++ 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/pkgbuilds/t3code-bin/.omarchy/upstream.sh b/pkgbuilds/t3code-bin/.omarchy/upstream.sh index 6bc010c..63c436d 100755 --- a/pkgbuilds/t3code-bin/.omarchy/upstream.sh +++ b/pkgbuilds/t3code-bin/.omarchy/upstream.sh @@ -1,8 +1,9 @@ #!/bin/bash # T3 Code publishes electron-builder's update feed beside every release, so the -# newest version costs one small request. The feed's checksum is a base64 +# newest version costs one small request. Each feed's checksum is a base64 # SHA-512 and makepkg wants hex SHA-256, so a release that is actually new still -# has to be downloaded once to hash -- hence the version check before the fetch. +# has to be downloaded once per architecture to hash -- hence the version check +# before the fetch. set -euo pipefail FEED_URL="https://github.com/pingdotgg/t3code/releases/latest/download/latest-linux.yml" @@ -23,7 +24,7 @@ if [[ -n "$current" ]] && [[ "$(vercmp "$version" "$current")" -le 0 ]]; then exit 0 fi -# The PKGBUILD builds one fixed asset name, so a feed naming anything else -- +# The PKGBUILD builds fixed asset names, so a feed naming anything else -- # a rename, or an arm64 build reaching the Linux feed first -- has to stop the # sync rather than pin that file's checksum to a URL nobody will fetch. expected="T3-Code-${version}-x86_64.AppImage" @@ -32,7 +33,18 @@ if [[ "$asset" != "$expected" ]]; then exit 1 fi -sha256=$(curl -fsSL "$RELEASE_URL/v${version}/${asset}" | sha256sum | cut -d' ' -f1) +# Pin the ARM feed to the same release, so a partially published release or a +# latest-release change cannot mix versions between architectures. +arm_feed=$(curl -fsSL "$RELEASE_URL/v${version}/latest-linux-arm64.yml") +arm_version=$(awk '/^version:/ { print $2; exit }' <<<"$arm_feed" | tr -d '"'\''') +arm_asset=$(awk '/^path:/ { print $2; exit }' <<<"$arm_feed" | tr -d '"'\''') +if [[ "$arm_version" != "$version" || "$arm_asset" != "T3-Code-${version}-arm64.AppImage" ]]; then + echo "Upstream ARM feed does not match T3-Code-${version}-arm64.AppImage" >&2 + exit 1 +fi -jq -n --arg pkgver "$version" --arg sha256 "$sha256" \ - '{pkgver: $pkgver, sha256sums: {x86_64: [$sha256]}}' +sha256=$(curl -fsSL "$RELEASE_URL/v${version}/${asset}" | sha256sum | cut -d' ' -f1) +arm_sha256=$(curl -fsSL "$RELEASE_URL/v${version}/${arm_asset}" | sha256sum | cut -d' ' -f1) + +jq -n --arg pkgver "$version" --arg sha256 "$sha256" --arg arm_sha256 "$arm_sha256" \ + '{pkgver: $pkgver, sha256sums: {x86_64: [$sha256], aarch64: [$arm_sha256]}}' diff --git a/pkgbuilds/t3code-bin/PKGBUILD b/pkgbuilds/t3code-bin/PKGBUILD index fe90494..235022d 100644 --- a/pkgbuilds/t3code-bin/PKGBUILD +++ b/pkgbuilds/t3code-bin/PKGBUILD @@ -1,18 +1,19 @@ # Maintainer: David Heinemeier Hansson -# T3 Code ships Linux as an AppImage and nothing else, so Omarchy unpacks it and +# T3 Code ships its Linux desktop as an AppImage, so Omarchy unpacks it and # keeps only the Electron tree. AppRun, the compatibility libraries bundled for # distributions that do not ship their own, and the AppImage's icon shims are all -# dead weight here. .omarchy/upstream.sh rewrites the version and checksum below -# from the release feed the app updates itself from. +# dead weight here. .omarchy/upstream.sh rewrites the version and checksums below +# from the release feeds the app updates itself from. pkgname=t3code-bin pkgver=0.0.42 -pkgrel=1 +pkgrel=2 pkgdesc="Open-source control plane for coding agents" -arch=('x86_64') +arch=('x86_64' 'aarch64') url="https://t3.codes" license=('MIT') +makedepends=('7zip') depends=( 'alsa-lib' @@ -54,19 +55,28 @@ provides=("t3code=${pkgver}") conflicts=('t3code') options=('!debug' '!strip') -_appimage="T3-Code-${pkgver}-x86_64.AppImage" +_appimage_x86_64="T3-Code-${pkgver}-x86_64.AppImage" +_appimage_aarch64="T3-Code-${pkgver}-arm64.AppImage" source=('t3code-launcher.sh' 't3-launcher.sh' 'LICENSE') -source_x86_64=("${_appimage}::https://github.com/pingdotgg/t3code/releases/download/v${pkgver}/${_appimage}") -noextract=("${_appimage}") +source_x86_64=("https://github.com/pingdotgg/t3code/releases/download/v${pkgver}/${_appimage_x86_64}") +source_aarch64=("https://github.com/pingdotgg/t3code/releases/download/v${pkgver}/${_appimage_aarch64}") +noextract=("${_appimage_x86_64}" "${_appimage_aarch64}") sha256sums=('cb905ff341372ef2ef6e402cf485959f8bd1df8f0efebee4cda1afdd5e6abc0a' 'c5b3f2a9f0b14b12cfd973b79319f0f018b7ae49a1d43d8ca346100c3f7de28f' '935d8f2af0c703f9c39517ee57cc4930b19d02d533be930b63f0e82f93614b43') sha256sums_x86_64=('8dc1fccdabc2ed3a59a3944cc772ef11931b9351401c0963ed305d5f96e3cdf4') +sha256sums_aarch64=('c256d872d358e9f2c91328b0154c6311fa2eb16386ef6f788fcda12d73cf2836') prepare() { - chmod +x "${srcdir}/${_appimage}" + local _appimage + case "$CARCH" in + x86_64) _appimage="${_appimage_x86_64}" ;; + aarch64) _appimage="${_appimage_aarch64}" ;; + esac rm -rf "${srcdir}/squashfs-root" - "${srcdir}/${_appimage}" --appimage-extract >/dev/null + # Extract without executing the runtime: AppImage's ELF magic does not match + # QEMU's binfmt registration when building ARM packages on an x86_64 host. + 7z x "${srcdir}/${_appimage}" -o"${srcdir}/squashfs-root" >/dev/null } package() { diff --git a/tests/upstream-watch.py b/tests/upstream-watch.py index 856a928..bb9c8dc 100644 --- a/tests/upstream-watch.py +++ b/tests/upstream-watch.py @@ -330,5 +330,71 @@ os.execv(os.environ['REAL_GIT'], ['git', *args]) self.assertEqual(metadata_file.read_bytes(), original) +class T3CodeHookTest(unittest.TestCase): + """Keep both desktop architectures on the same complete upstream release.""" + + def setUp(self): + work = tempfile.TemporaryDirectory() + self.addCleanup(work.cleanup) + self.root = Path(work.name) + self.recipe = self.root / "PKGBUILD" + self.recipe.write_text("pkgver=0.0.41\n") + self.feed = self.root / "latest-linux.yml" + self.feed.write_text("version: 0.0.42\npath: T3-Code-0.0.42-x86_64.AppImage\n") + self.arm_feed = self.root / "latest-linux-arm64.yml" + self.arm_feed.write_text("version: 0.0.42\npath: T3-Code-0.0.42-arm64.AppImage\n") + for arch in ("x86_64", "arm64"): + (self.root / f"T3-Code-0.0.42-{arch}.AppImage").write_text(arch) + # Serve only fixture assets, and record the requested release URLs. + curl = self.root / "curl" + curl.write_text('#!/bin/bash\nurl="${@: -1}"\nprintf "%s\\n" "$url" >> requests\ncat "${url##*/}"\n') + curl.chmod(0o755) + self.env = dict(os.environ, PATH=f"{self.root}:{os.environ['PATH']}") + + def run_hook(self): + return subprocess.run( + ['bash', str(ROOT / 'pkgbuilds/t3code-bin/.omarchy/upstream.sh')], + cwd=self.root, env=self.env, text=True, capture_output=True, + ) + + def test_hashes_both_architectures_from_one_release(self): + result = self.run_hook() + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(json.loads(result.stdout), { + 'pkgver': '0.0.42', + 'sha256sums': { + arch: [w.hash_file(self.root / f'T3-Code-0.0.42-{asset_arch}.AppImage', 'sha256')] + for arch, asset_arch in [('x86_64', 'x86_64'), ('aarch64', 'arm64')] + }, + }) + self.assertIn('/download/v0.0.42/latest-linux-arm64.yml', (self.root / 'requests').read_text()) + + def test_current_version_does_not_download_assets(self): + self.recipe.write_text('pkgver=0.0.42\n') + result = self.run_hook() + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(json.loads(result.stdout), {}) + self.assertEqual(len((self.root / 'requests').read_text().splitlines()), 1) + + def test_incomplete_or_mismatched_arm_release_reports_no_update(self): + for bad_feed in ('', 'version: 0.0.43\npath: T3-Code-0.0.42-arm64.AppImage\n', + 'version: 0.0.42\npath: renamed.AppImage\n'): + with self.subTest(feed=bad_feed): + self.arm_feed.write_text(bad_feed) + result = self.run_hook() + self.assertNotEqual(result.returncode, 0) + self.assertEqual(result.stdout, '') + self.arm_feed.unlink() + result = self.run_hook() + self.assertNotEqual(result.returncode, 0) + self.assertEqual(result.stdout, '') + + def test_missing_arm_asset_reports_no_update(self): + (self.root / 'T3-Code-0.0.42-arm64.AppImage').unlink() + result = self.run_hook() + self.assertNotEqual(result.returncode, 0) + self.assertEqual(result.stdout, '') + + if __name__ == '__main__': unittest.main(verbosity=2) From 3e0cba033ae570a26cc58f18c99e2d0dc9c3b225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Fri, 18 Sep 2026 03:15:43 +0900 Subject: [PATCH 044/121] Add missing patch signature files to the base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- .../0220-x86-amd-zen5-tlb-sizes.patch.sig | Bin 0 -> 594 bytes .../0220-x86-amd-zen5-tlb-sizes.patch.sig | Bin 0 -> 594 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch.sig create mode 100644 pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch.sig diff --git a/pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch.sig b/pkgbuilds/linux-omarchy-bore/0220-x86-amd-zen5-tlb-sizes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..33230cf470ebcca7be5a6e6ff82dfae191332adc GIT binary patch literal 594 zcmV-Y000000 z1ON_gVQzIYEHW-ND={uHGAuAGG5`t*5PW2IjXmQu=hDs)0Fr?da&gc9s_7jbW@}Wn zAp?B22psmn;a5==e`&LjuSypf7ao?}uN(a%MpDMJ$XfyhB@FycbeK&yQM|XiLHi_8R|x4SvsD?c z-6B^g=YOtx74o(1kJU^|C}!c7P7^We!;lgpvt$EV>A|TnmHs2Ym;8hcu;C@R9%mFu zxMttw)1qV9kK)+2bao;#-)NKtBJ=08IP8dDh^5yK2wxOl#dA#}e9i+796$QXV5g g$1F@I_;0_PMhT%et%K7%6m%P5uS=&LDOR3EEh145r~m)} literal 0 HcmV?d00001 diff --git a/pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch.sig b/pkgbuilds/linux-omarchy/0220-x86-amd-zen5-tlb-sizes.patch.sig new file mode 100644 index 0000000000000000000000000000000000000000..aa440e0b4a3cb0ac7e4f8b90495ec0ba15d24f98 GIT binary patch literal 594 zcmV-Y0*W?+oyfq=l}(DpY=4;cWz zoIWj#pmd;t4vT4?B617o>6DJ4oA20vz=S3>|4;DQ@j4pUF!f?JmCr>*401Tb+Eiq1 zf5QY+$Mr8-%C`+dta%6M>b6bVK=msWNM;6xCbdY|1D;t3~2}8 zqHvaLRZ?Q+3H9JA0FVaRtyPBYOIeYMZ8XaD>;(?0v;R^s8a+y%!BYXTCp;u`j3Plk zWImi+2MJ&Pg*LU={7K~1&{ik~?oiN5=#!3!amr*;ANvi6RJ#iWKIaDq*~ZIOB*{6xPadRzQu-kZqfL&VO6 Date: Fri, 18 Sep 2026 03:32:34 +0900 Subject: [PATCH 045/121] Disable register zeroing on function exit for base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unset CONFIG_ZERO_CALL_USED_REGS to disable the kernel hardening feature, allowing for older NVIDIA drivers to build successfully against the new kernel. Signed-off-by: Krzysztof Wilczyński --- pkgbuilds/linux-omarchy-bore/PKGBUILD | 2 +- pkgbuilds/linux-omarchy-bore/config.x86_64 | 2 +- pkgbuilds/linux-omarchy/PKGBUILD | 2 +- pkgbuilds/linux-omarchy/config.x86_64 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index c957e63..a8c9126 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -342,7 +342,7 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' 'b69cf36cc5633e507866e67f59557646dda7d6ea436b145f3f3356c4b12e1300c94977a7d1214835f2476c94a30dd672076241b920d96d744fbc199539df506f' 'SKIP') -b2sums_x86_64=('5abfe289c4487fd774890fbbe3989bb87e6b8d67e146c401ac6821b71be85a17816520b18eb874ff83e43ddece236273b2ac155943d2fdfabb1a444ba7162291') +b2sums_x86_64=('f69a306213a769710e3429817239746406e115af29f34f37514119eb49f973c86953379b68d3df89700bef7f86e3ec43eb91d5f5821f2a8eae7f28dba589d265') # https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' diff --git a/pkgbuilds/linux-omarchy-bore/config.x86_64 b/pkgbuilds/linux-omarchy-bore/config.x86_64 index 4d90b02..27b8b44 100644 --- a/pkgbuilds/linux-omarchy-bore/config.x86_64 +++ b/pkgbuilds/linux-omarchy-bore/config.x86_64 @@ -11873,7 +11873,7 @@ CONFIG_INIT_STACK_ALL_ZERO=y CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y -CONFIG_ZERO_CALL_USED_REGS=y +# CONFIG_ZERO_CALL_USED_REGS is not set # end of Memory initialization # diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index b02c163..6ae400c 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -339,7 +339,7 @@ b2sums=('48551bee71cd02815136fb8abe7da4464c2e17c89ef35cb0c0530c8b969fe12127ca97a 'SKIP' 'b69cf36cc5633e507866e67f59557646dda7d6ea436b145f3f3356c4b12e1300c94977a7d1214835f2476c94a30dd672076241b920d96d744fbc199539df506f' 'SKIP') -b2sums_x86_64=('459be66f895e5c75cadc2074965baa6261ba342b175eeb352157972be1940f1c6092001e8c0ab3cfbc92a35ee216ffb486f417b94df1a46ed217144257e3c7f2') +b2sums_x86_64=('5cbc3cba5e3abe4c77a54aeb2015b04e39dc80351accaa7c268da3e67577c0ad47109b8693bf2dee8d5366d0a0df3e6439c32d18fcf5ea07345bfcf517e5036d') # https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc sha256sums=('55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78' diff --git a/pkgbuilds/linux-omarchy/config.x86_64 b/pkgbuilds/linux-omarchy/config.x86_64 index 847db90..283d023 100644 --- a/pkgbuilds/linux-omarchy/config.x86_64 +++ b/pkgbuilds/linux-omarchy/config.x86_64 @@ -11870,7 +11870,7 @@ CONFIG_INIT_STACK_ALL_ZERO=y CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y -CONFIG_ZERO_CALL_USED_REGS=y +# CONFIG_ZERO_CALL_USED_REGS is not set # end of Memory initialization # From 18433c2499ba60c826c4d040320405c5672e53bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Fri, 18 Sep 2026 04:18:47 +0900 Subject: [PATCH 046/121] Update Linux kernel release to v7.2.5-6 for base and BORE kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Wilczyński --- pkgbuilds/linux-omarchy-bore/PKGBUILD | 2 +- pkgbuilds/linux-omarchy/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/linux-omarchy-bore/PKGBUILD b/pkgbuilds/linux-omarchy-bore/PKGBUILD index a8c9126..d9c5b41 100644 --- a/pkgbuilds/linux-omarchy-bore/PKGBUILD +++ b/pkgbuilds/linux-omarchy-bore/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy-bore pkgver=7.2.5 -pkgrel=5 +pkgrel=6 pkgdesc='Omarchy Linux (BORE CPU scheduler, ADIOS I/O scheduler)' url='https://omarchy.org' arch=( diff --git a/pkgbuilds/linux-omarchy/PKGBUILD b/pkgbuilds/linux-omarchy/PKGBUILD index 6ae400c..cc70049 100644 --- a/pkgbuilds/linux-omarchy/PKGBUILD +++ b/pkgbuilds/linux-omarchy/PKGBUILD @@ -3,7 +3,7 @@ pkgbase=linux-omarchy pkgver=7.2.5 -pkgrel=5 +pkgrel=6 pkgdesc='Omarchy Linux' url='https://omarchy.org' arch=( From f7577b59a6d8e6285e0753f64638928a5779b56d Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Fri, 18 Sep 2026 01:34:01 -0500 Subject: [PATCH 047/121] Refresh Cua plugin profile for Aquamarine 0.15.1 Derive an exact Aquamarine 0.15.1-1 profile from the verified upstream kit so edge installations resolve without weakening native compatibility checks. Co-Authored-By: Codex GPT-6 Astra xhigh --- pkgbuilds/cua-hyprland-plugin/PKGBUILD | 35 +++++++++++----------- pkgbuilds/cua-hyprland-plugin/PROFILE.json | 6 ++-- pkgbuilds/cua-hyprland-plugin/README.md | 23 +++++++------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/pkgbuilds/cua-hyprland-plugin/PKGBUILD b/pkgbuilds/cua-hyprland-plugin/PKGBUILD index 9fba2d2..9e0f9b0 100644 --- a/pkgbuilds/cua-hyprland-plugin/PKGBUILD +++ b/pkgbuilds/cua-hyprland-plugin/PKGBUILD @@ -4,18 +4,18 @@ # shellcheck shell=bash disable=SC2034,SC2154 pkgname=cua-hyprland-plugin pkgver=0.26.1 -pkgrel=5 -pkgdesc='Cua input candidate for reviewed profile omarchy-hyprland-0562r3-remaps' +pkgrel=6 +pkgdesc='Cua input candidate for reviewed profile omarchy-hypr0562r3-aq0151-remaps' arch=('x86_64') url='https://github.com/trycua/cua' license=('MIT') -depends=('hyprland=0.56.2-3' 'aquamarine=0.15.0-2' 'glibc=2.44+r24+g16be1518495f-1' 'hyprcursor=0.1.13-7' 'hyprgraphics=0.5.1-4' 'hyprlang=0.6.8-5' 'hyprutils=0.14.2-1' 'libgcc=16.2.1+r23+gd564253eb6c8-1' 'libstdc++=16.2.1+r23+gd564253eb6c8-1' 'libxkbcommon=1.13.2-1' 'wayland=1.26.0-1' 'python>=3.11' 'binutils') +depends=('hyprland=0.56.2-3' 'aquamarine=0.15.1-1' 'glibc=2.44+r24+g16be1518495f-1' 'hyprcursor=0.1.13-7' 'hyprgraphics=0.5.1-4' 'hyprlang=0.6.8-5' 'hyprutils=0.14.2-1' 'libgcc=16.2.1+r23+gd564253eb6c8-1' 'libstdc++=16.2.1+r23+gd564253eb6c8-1' 'libxkbcommon=1.13.2-1' 'wayland=1.26.0-1' 'python>=3.11' 'binutils') makedepends=('cmake>=3.30' 'ninja' 'pkgconf' 'gcc' 'patch') options=('!strip' '!debug' '!lto') _stem='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7' _archive_sha256='47bca9e018f32f4fcfe683f91c7475c60368f3b65d318cc35c1f2de88a4ee9ab' -_kit_sha256='089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9' -_profile_sha256='fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b' +_kit_sha256='819779b93655d603d9ebb0d33ea052326c3374674a1d473886106af25e0fffdd' +_profile_sha256='a2eade8b8195036be2c666788a1d28ac722403285a35987d92b3344e095f9a5e' _verifier_sha256='480f649cbd35a0ddc7f49dc0a3a44785402c9e0ec9653b0f8ea4965d52d7f900' _cxx="${CUA_RELEASE_CXX:-/usr/bin/g++}" _download_name='cua-hyprland-plugin-0.26.1-cc54254464c0c9aebfd6547fe7e4a0ceaf0456d7-profile-omarchy-stable-20260910-kit-1.1.0-5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a-67f89ceb47edd973aa748820eadd02ddbfb3d3e4.tar.gz' @@ -24,7 +24,7 @@ source=('https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0 'PROFILE.json') noextract=("$_download_name") sha256sums=('a89bfa7f6490f598719dfabdd2a5badc137e27b0764fd25e6a05e1f969433520' - 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b') + 'a2eade8b8195036be2c666788a1d28ac722403285a35987d92b3344e095f9a5e') # Downstream inputs are also checked explicitly when makepkg integrity is skipped. declare -gA _downstream_sha256=( @@ -71,33 +71,34 @@ with tarfile.open(fileobj=io.BytesIO(data), mode='r:gz') as contents: require(digest(content) == expected[member.name], 'outer kit member checksum mismatch') payload[member.name] = content require(payload.keys() == expected.keys(), 'outer kit inventory mismatch') -# Arch's -3 package has the same compositor and all 498 headers/pkg-config -# files as -2. Derive a version-only profile with the original source/tooling -# and byte checks intact; record its own profile and kit provenance digests. +# Derive the reviewed Hyprland -3/Aquamarine 0.15.1 profile while preserving +# upstream source/tooling and compiler, compositor, header and runtime hashes. profile_data = Path(profile_path).read_bytes() -require(digest(profile_data) == 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b', +require(digest(profile_data) == 'a2eade8b8195036be2c666788a1d28ac722403285a35987d92b3344e095f9a5e', 'local profile checksum mismatch') profile = json.loads(payload['PROFILE.json']) -profile.update(profile_id='omarchy-hyprland-0562r3-remaps', package_release=5) +profile.update(profile_id='omarchy-hypr0562r3-aq0151-remaps', package_release=6) profile['hyprland']['package_version'] = '0.56.2-3' -require(json.loads(profile_data) == profile, 'local profile changes more than the reviewed package revision') +profile['runtime']['packages']['aquamarine'] = '0.15.1-1' +require(json.loads(profile_data) == profile, 'local profile changes more than the reviewed package versions') payload['PROFILE.json'] = profile_data provenance = json.loads(payload['KIT-PROVENANCE.json']) provenance['profile_sha256'] = digest(profile_data) payload['KIT-PROVENANCE.json'] = (json.dumps(provenance, sort_keys=True, indent=2) + '\n').encode() recipe = payload['PKGBUILD'].decode() -for old, new in [('pkgrel=2\n', 'pkgrel=5\n'), ('omarchy-stable-20260910', profile['profile_id']), +for old, new in [('pkgrel=2\n', 'pkgrel=6\n'), ('omarchy-stable-20260910', profile['profile_id']), ('hyprland=0.56.2-2', 'hyprland=0.56.2-3'), + ('aquamarine=0.15.0-2', 'aquamarine=0.15.1-1'), ('5dacea79a6a5927e59fca7b51e6c04e94fa45133ac1b8fb7f4e1f442d113eb9a', digest(profile_data)), ('7beb736adfd334eed52e84070177634269e3a09f8bb25971b38606933ff4c997', digest(payload['KIT-PROVENANCE.json']))]: recipe = recipe.replace(old, new) payload['PKGBUILD'] = recipe.encode() payload['SHA256SUMS'] = ''.join(f'{digest(body)} {name}\n' for name, body in sorted(payload.items()) if name != 'SHA256SUMS').encode() -expected.update({'PROFILE.json': 'fc3034649af98f7f81178ef575660143c249664b9ff5d0e1ccaf79d7580df17b', - 'KIT-PROVENANCE.json': '089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9', - 'PKGBUILD': '0cbf2cd34c3c5038a5ed51e6bf84acd81844e4c2bb08ad7203959201bba61da9', - 'SHA256SUMS': 'd01b9e0be4c5bcf84cc2ecef9f11f44cedfc1ca5b31afbfcf52aa2efbd636a09'}) +expected.update({'PROFILE.json': 'a2eade8b8195036be2c666788a1d28ac722403285a35987d92b3344e095f9a5e', + 'KIT-PROVENANCE.json': '819779b93655d603d9ebb0d33ea052326c3374674a1d473886106af25e0fffdd', + 'PKGBUILD': 'c3e4149eba3f7def10ef700b30b9d0abcea994e3dd32fb169014874a0b75687c', + 'SHA256SUMS': 'd9057a9534f7a820ee04cbf5d60db567c5072fa96d1f71030a6a85b4bb7ce881'}) for name, content in payload.items(): require(digest(content) == expected[name], 'derived kit checksum mismatch: ' + name) require(srcdir.is_dir() and not srcdir.is_symlink(), 'srcdir must be a real directory') diff --git a/pkgbuilds/cua-hyprland-plugin/PROFILE.json b/pkgbuilds/cua-hyprland-plugin/PROFILE.json index fe5eff2..c24dc2d 100644 --- a/pkgbuilds/cua-hyprland-plugin/PROFILE.json +++ b/pkgbuilds/cua-hyprland-plugin/PROFILE.json @@ -12,12 +12,12 @@ "sha256": "da8fcacf347bcbed83edc40108c6e2298da095e22246bd764e9bb382786cebb2" }, "kit_version": "1.1.0", - "package_release": 5, - "profile_id": "omarchy-hyprland-0562r3-remaps", + "package_release": 6, + "profile_id": "omarchy-hypr0562r3-aq0151-remaps", "runtime": { "basename": "libstdc++.so.6.0.36", "packages": { - "aquamarine": "0.15.0-2", + "aquamarine": "0.15.1-1", "glibc": "2.44+r24+g16be1518495f-1", "hyprcursor": "0.1.13-7", "hyprgraphics": "0.5.1-4", diff --git a/pkgbuilds/cua-hyprland-plugin/README.md b/pkgbuilds/cua-hyprland-plugin/README.md index 61946b4..c6c85fc 100644 --- a/pkgbuilds/cua-hyprland-plugin/README.md +++ b/pkgbuilds/cua-hyprland-plugin/README.md @@ -1,8 +1,8 @@ # Optional Cua Hyprland plugin -This package targets **Omarchy stable x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Package release `5` includes the Omarchy patch for independent agent keymaps, operation-specific foreground checks, and compatible Num Lock state; the upstream native qualification below covers the unpatched source, not this change. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. +This package targets **Omarchy x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Release `6` is an edge candidate for Aquamarine `0.15.1-1`; it retains the keyboard-remap patch introduced in release `5`, which includes the Omarchy patch for independent agent keymaps, operation-specific foreground checks, and compatible Num Lock state; the upstream native qualification below covers the unpatched source, not this change. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target. -The plugin is optional. Cua Driver works independently, and installation does not load the plugin or enable input. The package follows the normal edge-to-RC-to-stable promotion path instead of the fast release ring. Its PKGBUILD limits builds to x86_64; only stable x86_64 is a qualified target. +The plugin is optional. Cua Driver works independently, and installation does not load the plugin or enable input. The package follows the normal edge-to-RC-to-stable promotion path instead of the fast release ring. Its PKGBUILD limits builds to x86_64. The upstream qualification covers the original stable profile; the updated Aquamarine profile needs its own Omabot validation before promotion. ## Source and build profile @@ -12,26 +12,23 @@ It is not a repackaging of the unmodified 0.24.0 plugin. The qualified upstream Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with the upstream module; its production plugin source is the base for the downstream patch used here. Discovery protocol v2 is separate. A newer Driver release is a changed pairing and requires affected replay before promotion. -Profile `omarchy-hyprland-0562r3-remaps`, kit tooling `1.1.0`, and package release `5` pin: +Profile `omarchy-hypr0562r3-aq0151-remaps`, kit tooling `1.1.0`, and package release `6` pin: - Hyprland `0.56.2-3`, headers `0.56.2`, and measured executable/header hashes. - GCC `16.2.1 20260810`, including compiler bytes and emitted ELF identity. -- Shared runtime `libstdc++.so.6.0.36`, its bytes, and exact ABI package versions. +- Shared runtime `libstdc++.so.6.0.36`, its bytes, and exact ABI package versions, including Aquamarine `0.15.1-1`. This profile derives from Cua's `omarchy-stable-20260910` profile. Arch's Hyprland `-3` package splits out `hyprpm` and changes package dependencies; its compositor executable and all 498 header/pkg-config files are byte-identical to `-2`. Both executables have SHA-256 `da8fcacf347bcbed83edc40108c6e2298da095e22246bd764e9bb382786cebb2`. -The checked-in `PROFILE.json` changes only the profile name, package release, -and exact Hyprland package version. Compiler, runtime, upstream source, executable, -and header identities remain unchanged; the separately recorded patch changes the build source. The download wrapper verifies the +The checked-in `PROFILE.json` changes only the profile name, package release, and exact Hyprland and Aquamarine package versions. Compiler, libstdc++ runtime, upstream source, compositor executable, and header identities remain unchanged; the separately recorded patch changes the build source. The download wrapper verifies the original kit before deriving the updated profile, recipe, and provenance, then verifies every derived member against its recorded digest. The native qualification below was recorded with package release `2` and -Hyprland `-2`. The downstream keymap change needs its own application and Driver replay before promotion. The `-3` dependency must reach a destination channel before -this artifact can be installed there; publication still follows edge → RC → stable. +Hyprland `-2`. The downstream keymap change and Aquamarine update need their own application and Driver replay before promotion. Hyprland `0.56.2-3` and Aquamarine `0.15.1-1` must both reach a destination channel before this artifact can be installed there; publication still follows edge → RC → stable. The generated `PKGBUILD` identifies the immutable kit download, outer checksum, and member checksums. The kit records the full source and tooling revisions, @@ -48,6 +45,12 @@ Production input is built in; experimental signed input and tracing are off. The pristine upstream archive, manifest, and verifier remain unchanged. `independent-keymaps.patch` is applied to a separate source tree, and `DOWNSTREAM-PROVENANCE.json` pins the patch and every resulting source file. Build, check, and package revalidate both trees, including when makepkg integrity checks are skipped. `BUILD-PROVENANCE.json` records the upstream base under `source`, the applied change under `downstream`, and the final module digest; the downstream manifest and patch are installed beside it. This preserves the existing compiler, headers, runtime, and consumer checks without representing the modified module as an unmodified upstream build. +## Aquamarine dependency refresh + +Release `5` required Aquamarine `0.15.0-2`. When the edge mirror moved to `0.15.1-1`, pacman could no longer resolve that dependency, even after a full database refresh. Release `6` derives a new profile from the same verified upstream kit and pins `0.15.1-1` in both the package dependencies and the installed compatibility verifier. Source, patch, compiler, compositor, headers, and libstdc++ hashes remain pinned; the original upstream qualification does not establish compatibility with the changed Aquamarine package. + +A package release bump alone cannot repair future dependency drift: the checked-in profile and derived kit checksums must agree with the new environment, and affected native checks must pass before publication. Do not remove exact dependencies or selectively downgrade a library to bypass a mismatch. + ## Keyboard behavior Each background lane owns a canonical US keymap and independent modifier state. The physical keyboard keeps its layout, Compose key, and remaps. No installation or activation step edits `input:kb_*`. Existing Driver keycodes are interpreted by the agent keyboard, so this does not add Unicode, IME, or new Driver text routes. @@ -142,7 +145,7 @@ kit-provenance digest: ```sh python3 /usr/share/cua-hyprland-plugin/profile_verify.py \ --kit /usr/share/cua-hyprland-plugin \ - --kit-sha256 089f447e11cacd8c2d3d6cd56528776417c51d353b9677c47c42bba1ef79c9f9 \ + --kit-sha256 819779b93655d603d9ebb0d33ea052326c3374674a1d473886106af25e0fffdd \ --consumer /usr/lib/cua/hyprland/cua-hyprland-plugin.so ``` From d7fe983681a99f1cf1572b9b9b932bf9ead64522 Mon Sep 17 00:00:00 2001 From: dhh <2741+dhh@users.noreply.github.com> Date: Fri, 18 Sep 2026 11:30:05 +0000 Subject: [PATCH 048/121] chore: sync upstream releases --- pkgbuilds/claude-code/PKGBUILD | 6 +++--- pkgbuilds/claude-desktop/PKGBUILD | 6 +++--- pkgbuilds/cursor-bin/PKGBUILD | 8 ++++---- pkgbuilds/github-copilot-cli/PKGBUILD | 6 +++--- pkgbuilds/mise-bin/PKGBUILD | 6 +++--- pkgbuilds/openai-codex-desktop/PKGBUILD | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pkgbuilds/claude-code/PKGBUILD b/pkgbuilds/claude-code/PKGBUILD index 3a179f8..b8da20f 100644 --- a/pkgbuilds/claude-code/PKGBUILD +++ b/pkgbuilds/claude-code/PKGBUILD @@ -4,7 +4,7 @@ # Automation repository: https://github.com/fabifont/claude-code-aur pkgname=claude-code -pkgver=2.1.274 +pkgver=2.1.276 pkgrel=1 pkgdesc="An agentic coding tool that lives in your terminal" arch=('x86_64' 'aarch64') @@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude") sha256sums=('SKIP') -sha256sums_x86_64=('15e2d05148f801b5774032faad87e624ecd172e9903288bda448b892eb58fa07') -sha256sums_aarch64=('2db904daea17addff9de557ba26a725916888aa7b546e2c5dd989c20d9d49ab3') +sha256sums_x86_64=('8a56c8a14bd3cb246e2bdb7e60aefe0f609bff78c8bbcc5ea6b1817c111c6145') +sha256sums_aarch64=('e9ac3df956083645578a382ad64ec304468666e362c33bfdefd803cd6ff596b0') package() { install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude" diff --git a/pkgbuilds/claude-desktop/PKGBUILD b/pkgbuilds/claude-desktop/PKGBUILD index 3de9345..919b043 100644 --- a/pkgbuilds/claude-desktop/PKGBUILD +++ b/pkgbuilds/claude-desktop/PKGBUILD @@ -6,7 +6,7 @@ # repository's package index. pkgname=claude-desktop -pkgver=2.110.1 +pkgver=2.2553.1 pkgrel=1 pkgdesc="Official Claude desktop app with Claude Code" arch=('x86_64' 'aarch64') @@ -63,8 +63,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('edfdbc63b65891ef7c481b07086c7e630fc102c042b6ed65331a52fcaf72b14a') -sha256sums_x86_64=('0a9b0ac5456451637d8068ed757db0335cb6c0f24375479e740f572dbf886466') -sha256sums_aarch64=('2bbcd7bd9807417335290621d950f0b8a7b884e19724122bd4a6e40a63a81495') +sha256sums_x86_64=('6700fdd84e77a6b8c93912c2f69eb5d1e40fa99bcd9d37f438f809ef2a6fe6f8') +sha256sums_aarch64=('0003a6f9605a210f03c38670d62cd59c71153c2702aa4427e4cabe2e2e5f3390') package() { cd "${srcdir}" diff --git a/pkgbuilds/cursor-bin/PKGBUILD b/pkgbuilds/cursor-bin/PKGBUILD index d0a3e32..573c3e8 100644 --- a/pkgbuilds/cursor-bin/PKGBUILD +++ b/pkgbuilds/cursor-bin/PKGBUILD @@ -1,8 +1,8 @@ # Maintainer: Gunther Schulz pkgname=cursor-bin -pkgver=3.20.21 -pkgrel=2 +pkgver=3.21.9 +pkgrel=1 pkgdesc='AI-first coding environment' arch=('x86_64') url="https://www.cursor.com" @@ -12,11 +12,11 @@ _electron=electron42 depends=(xdg-utils ripgrep $_electron nodejs 'gcc-libs' 'hicolor-icon-theme' 'libxkbfile') options=(!strip !debug) # Don't break ext of VSCode -_commit=f09fca384ceca23f7bf21f9c23655b162641d747 +_commit=9998796a6096ce83d83a9332bfe7473b985db750 source=("https://downloads.cursor.com/production/${_commit}/linux/x64/deb/amd64/deb/cursor_${pkgver}_amd64.deb" "https://gitlab.archlinux.org/archlinux/packaging/packages/code/-/raw/main/code."{sh,mjs} rg.sh) -sha512sums=('8329138d207309d16410f1cb58da18eea1a034a35f2bdd022ef9b373bb8f1b3d80e489e65256b7283c40e10da77962d158bfa3a64e742337a942633810d80dbe' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') +sha512sums=('a1c26cc9add2bb593068f11bbb18165a5934ccaebe380019b84a552641aad41c942357c600d55998e47cbcd86f0a1d862a295b3502d269f06167cd6891043d71' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') noextract=(cursor_${pkgver}_amd64.deb) # avoid double tarball _app=usr/share/cursor/resources/app package() { diff --git a/pkgbuilds/github-copilot-cli/PKGBUILD b/pkgbuilds/github-copilot-cli/PKGBUILD index 97bc32b..71f4f52 100644 --- a/pkgbuilds/github-copilot-cli/PKGBUILD +++ b/pkgbuilds/github-copilot-cli/PKGBUILD @@ -6,7 +6,7 @@ _npmmodule=@github/copilot pkgname=github-copilot-cli _pkgexec=copilot -pkgver=1.0.85 +pkgver=1.0.86 pkgrel=1 pkgdesc="GitHub Copilot CLI brings the power of Copilot coding agent directly to your terminal." @@ -31,8 +31,8 @@ source=("https://registry.npmjs.org/${_npmmodule}/-/copilot-${pkgver}.tgz" noextract=("copilot-${pkgver}.tgz") sha256sums=( - 'd26e3c15310bdcdcc910ed223285bed8d68aaebce0d344f97224b5cfdaeeee36' - '1b1a8fbd5562df73684b6e94865837ceffd6609d61822c39e6c8fcbd32d8ac41' + '4c6433345f08199e96dcf8db1c3e46a337dfab96cea32132d6127ffcd63a6200' + 'b94d2aab574cf3e0c8d950e72430186cdd918261a1376146de971fa90ba0a672' ) # Document: https://wiki.archlinux.org/title/Node.js_package_guidelines diff --git a/pkgbuilds/mise-bin/PKGBUILD b/pkgbuilds/mise-bin/PKGBUILD index 1b8c274..7162891 100644 --- a/pkgbuilds/mise-bin/PKGBUILD +++ b/pkgbuilds/mise-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Jeff Dickey pkgname=mise-bin -pkgver=2026.9.9 +pkgver=2026.9.10 pkgrel=1 pkgdesc="dev tools, env vars, task runner" arch=('x86_64' 'aarch64') @@ -14,8 +14,8 @@ provides=('mise') conflicts=('mise') source_x86_64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-x64.tar.xz") source_aarch64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-arm64.tar.xz") -sha256sums_x86_64=('ed3ee9b7331182e57f77230cf6af64d90e6e1a01e2c3e4749568ea335837c0fb') -sha256sums_aarch64=('09d0489db27c173d1427b4248e3e1fbf18b00ccc1d887d8746f1d8b311903a50') +sha256sums_x86_64=('c5e4b03cb8266d3114e1c9322924608652fbb5bbcc3347928dbe86cd8b2fa654') +sha256sums_aarch64=('21697d5388315a5271cd7e3b56e12b1a3603796640f8f5760b3e7698d18a49f8') package() { install -Dm755 "${srcdir}/mise/bin/mise" "${pkgdir}/usr/bin/mise" diff --git a/pkgbuilds/openai-codex-desktop/PKGBUILD b/pkgbuilds/openai-codex-desktop/PKGBUILD index fa3f20d..5f72989 100644 --- a/pkgbuilds/openai-codex-desktop/PKGBUILD +++ b/pkgbuilds/openai-codex-desktop/PKGBUILD @@ -5,7 +5,7 @@ # the version and checksums below from that repository's package index. pkgname=openai-codex-desktop -pkgver=26.911.61220 +pkgver=26.915.31029 pkgrel=1 pkgdesc="Official ChatGPT desktop app with Codex" arch=('x86_64' 'aarch64') @@ -71,8 +71,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c') -sha256sums_x86_64=('14e1d4aeed7fed22adbd2b8ec20fe57bfbdd9ee9902370b4e2726677ca68bbba') -sha256sums_aarch64=('8517ddd0582ba8aa9b7879a2c566b4e622b62e0aebc4830272492d4e123f358b') +sha256sums_x86_64=('932825b76a41e80643204a9aa9ccfd1cb2471ffbfcbe1d314994360fcaaffb35') +sha256sums_aarch64=('5c01ce35eccea9e95d16de052c74f16deed381408931e82b106d7dbeeed8de4a') package() { cd "${srcdir}" From b422d37fa25ed76e8f9ade1cc61438e098bb7118 Mon Sep 17 00:00:00 2001 From: Basti <233381911+bastidotnet@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:24:41 +0200 Subject: [PATCH 049/121] Drop privileges when seeding Dell haptic config (#497) The root-run package hook changed ownership of paths below a user-controlled home directory. A config symlink could redirect chown to an arbitrary root-owned file during installation or upgrade. Run the config writer as the target desktop user and remove the privileged ownership changes. This also prevents the missing-config path from writing through a user-controlled pathname as root. Add regression coverage and bump the package release. Reported-by: piratemoo (Esther) <22439214+piratemoo@users.noreply.github.com> Link: https://github.com/piratemoo/Arbitrary-File-Ownership-Change-via-Symlink-LPE --- .github/workflows/test.yml | 1 + pkgbuilds/dell-xps-touchpad-haptics/PKGBUILD | 2 +- .../dell-xps-touchpad-haptics.install | 10 ++-- tests/dell-xps-touchpad-haptics-install.sh | 53 +++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100755 tests/dell-xps-touchpad-haptics-install.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6e48346..2ac36ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,6 +45,7 @@ jobs: ./bin/sync-rebuilds --self-test ./bin/omarchy-pkgs self-test ./bin/omarchy-release self-test + ./tests/dell-xps-touchpad-haptics-install.sh ./tests/partial-release.sh ./tests/published-build-plan.sh ' diff --git a/pkgbuilds/dell-xps-touchpad-haptics/PKGBUILD b/pkgbuilds/dell-xps-touchpad-haptics/PKGBUILD index 68d9967..9d35b3a 100644 --- a/pkgbuilds/dell-xps-touchpad-haptics/PKGBUILD +++ b/pkgbuilds/dell-xps-touchpad-haptics/PKGBUILD @@ -2,7 +2,7 @@ pkgname=dell-xps-touchpad-haptics pkgver=1.0.0 -pkgrel=3 +pkgrel=4 pkgdesc="Synaptics haptic touchpad presets for Dell XPS on Omarchy" arch=('x86_64') url="https://github.com/omacom-io/omarchy-pkgs" diff --git a/pkgbuilds/dell-xps-touchpad-haptics/dell-xps-touchpad-haptics.install b/pkgbuilds/dell-xps-touchpad-haptics/dell-xps-touchpad-haptics.install index 587f96c..25ddfa4 100644 --- a/pkgbuilds/dell-xps-touchpad-haptics/dell-xps-touchpad-haptics.install +++ b/pkgbuilds/dell-xps-touchpad-haptics/dell-xps-touchpad-haptics.install @@ -3,6 +3,7 @@ _default_level="high" _env_path="/etc/dell-xps-touchpad-haptics.env" _legacy_env_path="/etc/omarchy-dell-haptic-touchpad.env" _legacy_override_dir="/etc/systemd/system/dell-xps-haptic-touchpad.service.d" +_runuser_path="/usr/bin/runuser" _existing_home() { local line value @@ -124,18 +125,13 @@ _ensure_user_config() { local config_dir="$home/.config/omarchy" local config_path="$config_dir/dell-haptic.conf" - if [[ ! -f $config_path ]] && ! env HOME="$home" USER="$user" LOGNAME="$user" \ + if [[ ! -f $config_path ]] && ! "$_runuser_path" --user "$user" -- \ + /usr/bin/env HOME="$home" USER="$user" LOGNAME="$user" \ /usr/bin/dell-xps-touchpad-haptics set "$_default_level"; then echo ":: Failed to create ${config_path} for user '$user'." >&2 return 1 fi - if [[ -f $config_path ]]; then - chown "$user:$user" "$home/.config" 2>/dev/null || true - chown "$user:$user" "$config_dir" 2>/dev/null || true - chown "$user:$user" "$config_path" 2>/dev/null || true - fi - return 0 } diff --git a/tests/dell-xps-touchpad-haptics-install.sh b/tests/dell-xps-touchpad-haptics-install.sh new file mode 100755 index 0000000..2a5583c --- /dev/null +++ b/tests/dell-xps-touchpad-haptics-install.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -euo pipefail + +REPO_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +INSTALL_SCRIPT="$REPO_ROOT/pkgbuilds/dell-xps-touchpad-haptics/dell-xps-touchpad-haptics.install" +TEST_ROOT=$(mktemp -d) +trap 'rm -rf "$TEST_ROOT"' EXIT + +# shellcheck source=/dev/null +source "$INSTALL_SCRIPT" + +home="$TEST_ROOT/home" +config_dir="$home/.config/omarchy" +config_path="$config_dir/dell-haptic.conf" +protected_file="$TEST_ROOT/protected" +runuser_call="$TEST_ROOT/runuser-call" +chown_call="$TEST_ROOT/chown-call" +runuser_stub="$TEST_ROOT/runuser" +mkdir -p "$config_dir" +printf 'must remain unchanged\n' >"$protected_file" +ln -s "$protected_file" "$config_path" + +chown() { + printf '%s\n' "$*" >>"$chown_call" +} + +_ensure_user_config test-user "$home" +[[ ! -e $chown_call ]] +[[ ! -e $runuser_call ]] +[[ $(cat "$protected_file") == 'must remain unchanged' ]] + +rm "$config_path" +printf '%s\n' \ + '#!/bin/bash' \ + 'set -euo pipefail' \ + '[[ $1 == --user && $2 == test-user && $3 == -- && $4 == /usr/bin/env ]]' \ + '[[ $5 == "HOME=$EXPECTED_HOME" && $6 == USER=test-user && $7 == LOGNAME=test-user ]]' \ + '[[ $8 == /usr/bin/dell-xps-touchpad-haptics && $9 == set && ${10} == high ]]' \ + 'printf "%s\n" "$*" >>"$RUNUSER_CALL"' \ + 'printf "INTENSITY=100\n" >"$EXPECTED_CONFIG"' >"$runuser_stub" +chmod +x "$runuser_stub" +export EXPECTED_HOME="$home" +export EXPECTED_CONFIG="$config_path" +export RUNUSER_CALL="$runuser_call" +_runuser_path="$runuser_stub" + +_ensure_user_config test-user "$home" +[[ ! -e $chown_call ]] +[[ -f $config_path && ! -L $config_path ]] +[[ $(cat "$config_path") == 'INTENSITY=100' ]] +grep -q '^--user test-user -- /usr/bin/env ' "$runuser_call" + +echo 'PASS: user config creation drops privileges and never chowns symlink targets' From 537c377fa535ef945d4f89ed465b6941568296fa Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 11:25:32 -0400 Subject: [PATCH 050/121] Build PRs on ephemeral droplets; publish merged packages from CI Every pull request now builds the package directories it touches on ephemeral DigitalOcean droplets, and every merge to master publishes the resulting artifacts into the channels each package belongs to. The repository host's timers become the fallback rather than the pipeline. Build (.github/workflows/build-pr.yml) One job per package per architecture, always against edge. The artifact is labelled with the package directory's git tree hash. Tooling (bin/, helpers/, build/) is checked out from the base branch; the PR supplies only pkgbuilds/, so a PR can change what is built, never how. Builds run only for trusted authors: collaborators, .github/VOUCHED.td, or a PR carrying the build-approved label. A single required check, result, aggregates the matrix. Publish (.github/workflows/publish.yml, bin/publish-artifact) One job per merge. It collects the PR artifacts for the merged tree, builds anything that has none, then walks each channel/architecture slot once: pull that database, repo-add every package that belongs in it, upload packages, signatures, then the database. A published filename is immutable; identical bytes under an existing name only gain a database entry, different bytes are refused. Fast-ring packages reach edge, rc and stable in the same run from the same file. Matrix (bin/build-matrix) Package x architecture, with the channels the artifact ships to, decided by package_builds_for_mirror so CI and the host agree. arch=any packages build once and land in every architecture database. Builder (build/build.sh, bin/build, build/Dockerfile) With no local published tree, plan against and resolve from the public channel over HTTPS. PACKAGER is set to Omarchy. rclone is in the image. Runners (ci/) A controller droplet polls GitHub with curl and creates one g5 droplet per queued job from cloud-init, deleting them when off or over-age. Builders carry QEMU with credential support for aarch64. Operator SSH keys come from GitHub. tests/controller.sh and tests/publish-artifact.sh cover the decisions against fixtures and real makepkg output. Tests run on pull requests only; branch protection requires result, self-tests and build-isolation with up-to-date branches. --- .github/VOUCHED.td | 15 ++ .github/workflows/build-pr.yml | 166 +++++++++++++++++ .github/workflows/publish.yml | 179 +++++++++++++++++++ .github/workflows/test.yml | 9 +- bin/build | 3 + bin/build-matrix | 54 ++++++ bin/publish-artifact | 118 ++++++++++++ build/Dockerfile | 4 +- build/build.sh | 34 +++- ci/README.md | 79 ++++++++ ci/controller-box/cloud-init.yaml | 45 +++++ ci/controller-box/controller.env.example | 15 ++ ci/controller-box/create.sh | 41 +++++ ci/controller-box/omarchy-controller.service | 12 ++ ci/controller-box/omarchy-controller.timer | 10 ++ ci/controller.sh | 125 +++++++++++++ ci/runner-cloud-init.yaml | 77 ++++++++ tests/controller.sh | 66 +++++++ tests/publish-artifact.sh | 74 ++++++++ 19 files changed, 1119 insertions(+), 7 deletions(-) create mode 100644 .github/VOUCHED.td create mode 100644 .github/workflows/build-pr.yml create mode 100644 .github/workflows/publish.yml create mode 100755 bin/build-matrix create mode 100755 bin/publish-artifact create mode 100644 ci/README.md create mode 100644 ci/controller-box/cloud-init.yaml create mode 100644 ci/controller-box/controller.env.example create mode 100755 ci/controller-box/create.sh create mode 100644 ci/controller-box/omarchy-controller.service create mode 100644 ci/controller-box/omarchy-controller.timer create mode 100755 ci/controller.sh create mode 100644 ci/runner-cloud-init.yaml create mode 100755 tests/controller.sh create mode 100755 tests/publish-artifact.sh diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td new file mode 100644 index 0000000..2aec3ae --- /dev/null +++ b/.github/VOUCHED.td @@ -0,0 +1,15 @@ +# Trust list for PR builds. +# +# A pull request only builds packages (and spins up builder droplets) when +# its author is trusted: repository collaborators are trusted automatically +# and do not need listing; external contributors listed here are trusted +# too. Anyone else gets the plan only, until a maintainer either adds them +# here or applies the "build-approved" label to that one PR. +# +# Syntax: +# github:username +# -github:username reason for denouncement +# +# Keep entries sorted alphabetically. +github:f-trycua +github:scottjones diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml new file mode 100644 index 0000000..8d68dbb --- /dev/null +++ b/.github/workflows/build-pr.yml @@ -0,0 +1,166 @@ +name: Build changed packages + +# Build every package directory a PR touches, one job per package per arch, on +# the self-hosted droplet pool. Artifacts are unsigned; publish.yml signs and +# publishes them on merge. +# +# Tooling runs from the base branch; a PR supplies only pkgbuilds/. The +# vouch gate limits who may spend compute; this limits what their PR can run. + +# No paths filter: `result` is the required status check, so it has to be +# reported on every PR. A PR that touches no package directory gets an empty +# matrix and a passing result in seconds. +on: + pull_request: + types: [opened, synchronize, reopened, labeled] + workflow_dispatch: + inputs: + packages: + description: "Space-separated package directories to build" + required: true + +concurrency: + group: build-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + +jobs: + # Builds cost real machines, so they run only for trusted authors: + # collaborators, anyone in .github/VOUCHED.td (read from the default + # branch, so a PR cannot vouch for itself), or a PR a maintainer has + # labelled "build-approved". Everyone else gets this job's plan output + # and a passing `result`, which is enough for a maintainer to review + # before deciding to spend the compute. + changes: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.list.outputs.matrix }} + count: ${{ steps.gate.outputs.count }} + trusted: ${{ steps.gate.outputs.trusted }} + steps: + # Same rule as the build job: bin/build-matrix comes from base, the + # package directories from the PR head. + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.sha || github.sha }} + fetch-depth: 0 + persist-credentials: false + - if: github.event_name == 'pull_request' + run: | + git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.head.sha }}" + git checkout "${{ github.event.pull_request.head.sha }}" -- pkgbuilds/ + - id: vouch + if: github.event_name == 'pull_request' + uses: mitchellh/vouch/action/check-user@f23dbb5e745334f97414ec70463ce7301071a661 # v1 + with: + user: ${{ github.event.pull_request.user.login }} + allow-fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # One matrix entry per package per architecture. Every package builds + # once, against edge; the channels it ships to on merge are carried + # along for information. A filename means one set of bytes. + - id: list + run: | + if [[ -n "${{ github.event.inputs.packages }}" ]]; then + names="${{ github.event.inputs.packages }}" + else + names=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" -- pkgbuilds \ + | awk -F/ '$1=="pkgbuilds" && NF>2 {print $2}' | sort -u) + fi + matrix=$(printf '%s\n' $names | bin/build-matrix) + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + echo "planned=$(jq '.include | length' <<<"$matrix")" >> "$GITHUB_OUTPUT" + jq -r '.include[] | "\(.package) \(.arch) -> \(.channels)"' <<<"$matrix" + - id: gate + env: + STATUS: ${{ steps.vouch.outputs.status || 'dispatch' }} + AUTHOR: ${{ github.event.pull_request.user.login }} + APPROVED: ${{ contains(github.event.pull_request.labels.*.name, 'build-approved') }} + PLANNED: ${{ steps.list.outputs.planned }} + run: | + case "$STATUS" in + bot|collaborator|vouched|dispatch) trusted=true ;; + # A denouncement is absolute: the label cannot override it. + denounced) trusted=false ;; + *) trusted=$APPROVED ;; + esac + echo "trusted=$trusted" >> "$GITHUB_OUTPUT" + if [[ $trusted == true ]]; then + echo "count=$PLANNED" >> "$GITHUB_OUTPUT" + echo "Author $AUTHOR is trusted ($STATUS); building $PLANNED package(s)." + else + echo "count=0" >> "$GITHUB_OUTPUT" + echo "::warning::Author $AUTHOR is not trusted ($STATUS). $PLANNED package build(s) planned but not run." + if [[ $STATUS == denounced ]]; then + echo "::warning::The author is denounced in .github/VOUCHED.td; the build-approved label does not apply." + else + echo "::warning::A maintainer can add the author to .github/VOUCHED.td, or apply the 'build-approved' label to build this PR." + fi + fi + + build: + needs: changes + if: needs.changes.outputs.count != '0' + runs-on: [self-hosted, omarchy-builder] + timeout-minutes: 180 + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.changes.outputs.matrix) }} + steps: + # Tooling from base: everything that executes on this droplet's host + # (bin/, helpers/, build/) comes from the base branch. Only the PR's + # package directories are overlaid. A PR can therefore change what + # gets built, never how the runner builds it. A PR that changes both + # tooling and a package builds the package with the OLD tooling; land + # the tooling first. workflow_dispatch has no PR and runs as checked out. + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.sha || github.sha }} + persist-credentials: false + - name: Overlay the PR's package directories onto base tooling + if: github.event_name == 'pull_request' + run: | + set -euo pipefail + git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.head.sha }}" + git checkout "${{ github.event.pull_request.head.sha }}" -- pkgbuilds/ + echo "tooling: $(git rev-parse --short HEAD) (base) packages: ${{ github.event.pull_request.head.sha }} (PR head)" + git status --short | head + - name: Build ${{ matrix.package }} (${{ matrix.arch }}, ships to ${{ matrix.channels }}) + env: + CONTAINER_ENGINE: docker + run: bin/build --mirror edge --arch ${{ matrix.arch }} --package ${{ matrix.package }} + # The artifact label carries the package directory's git tree hash so + # the publish step can find the build for exactly the tree that merged. + # The package file inside keeps makepkg's standard name untouched. + # The artifact label uses the PR head's tree for this package: that is + # the tree that merges, and what publish looks up. + - name: Tree hash + id: tree + run: echo "hash=$(git rev-parse "${{ github.event.pull_request.head.sha || github.sha }}:pkgbuilds/${{ matrix.package }}")" >> "$GITHUB_OUTPUT" + - name: Upload artifact + if: always() + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.package }}-${{ matrix.arch }}-${{ steps.tree.outputs.hash }} + path: build-output/edge/${{ matrix.arch }}/*.pkg.tar.zst + if-no-files-found: error + retention-days: 7 + + # The one required status check. Matrix job names carry the package name, so + # they cannot be listed in branch protection; this job's name is stable and + # it fails if any package failed. It also runs (and passes) when no package + # changed, so tooling-only PRs are not stuck waiting for a status. + result: + needs: [changes, build] + if: always() + runs-on: ubuntu-latest + steps: + - run: | + echo "trusted=${{ needs.changes.outputs.trusted }} build=${{ needs.build.result }}" + # An untrusted author's PR is held, not failed: the required check + # stays pending until a maintainer vouches or labels it. + if [[ "${{ needs.changes.outputs.trusted }}" != "true" ]]; then + echo "::error::Builds were not run: author is not vouched. Add to .github/VOUCHED.td or apply the 'build-approved' label." + exit 1 + fi + [[ "${{ needs.build.result }}" == "success" || "${{ needs.build.result }}" == "skipped" ]] diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9eb969c --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,179 @@ +name: Publish merged packages + +# On every push to master: for each package directory the push touched and +# each architecture it supports, find the PR build artifact for exactly that +# tree (label = --), or build it now when there is +# none, then publish that one artifact into every channel the package ships +# to. One build, one file, several databases: a filename means one set of +# bytes everywhere, and channels are views over a shared pool. +# +# Secrets live in the "publish" environment, restricted to master: +# GPG_PRIVATE_KEY, GPG_PASSPHRASE the channel signing key +# R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ENDPOINT +# OMARCHY_PUBLISH_PREFIX (environment variable, not secret) points a proof +# run at a scratch prefix inside the live bucket; empty means the real +# channel paths. + +on: + push: + branches: [master] + paths: ["pkgbuilds/**"] + workflow_dispatch: + inputs: + packages: + description: "Space-separated package directories to publish from master" + required: true + +# Merges serialize. Two publishes into one channel at once would race on +# the database; queued is fine, cancelled is not. +concurrency: + group: publish + cancel-in-progress: false + +jobs: + changes: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.list.outputs.matrix }} + count: ${{ steps.list.outputs.count }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + - id: list + run: | + if [[ -n "${{ github.event.inputs.packages }}" ]]; then + names="${{ github.event.inputs.packages }}" + else + names=$(git diff --name-only "${{ github.event.before }}..${{ github.sha }}" -- pkgbuilds \ + | awk -F/ '$1=="pkgbuilds" && NF>2 {print $2}' | sort -u) + fi + matrix=$(printf '%s\n' $names | bin/build-matrix) + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + echo "count=$(jq '.include | length' <<<"$matrix")" >> "$GITHUB_OUTPUT" + jq -r '.include[] | "\(.package) \(.arch) -> \(.channels)"' <<<"$matrix" + + # One job for the whole merge. It collects every PR artifact for the + # merged tree (building only what has none), then walks each channel and + # architecture slot exactly once: pull that database, add every package + # that belongs in it, upload. Six slots, six round trips, however many + # packages the merge carried. One process is the only writer, so there + # is no race between packages; the run-level concurrency group above + # keeps one merge from overlapping the next. + publish: + needs: changes + if: needs.changes.outputs.count != '0' + runs-on: [self-hosted, omarchy-builder] + environment: publish + timeout-minutes: 240 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + # Every matrix entry, as a file the shell steps can loop over: + # package arch channels publish_arches + - name: Plan + run: | + jq -r '.include[] | "\(.package) \(.arch) \(.channels|gsub(" ";",")) \(.publish_arches|gsub(" ";","))"' \ + <<'EOF_MATRIX' > plan.txt + ${{ needs.changes.outputs.matrix }} + EOF_MATRIX + cat plan.txt + + # Fetch each package's PR artifact into build-output/edge//, or + # build it when no artifact exists for exactly this tree. + - name: Collect artifacts + env: + GH_TOKEN: ${{ github.token }} + CONTAINER_ENGINE: docker + run: | + set -euo pipefail + while read -r package arch channels publish_arches; do + hash=$(git rev-parse "HEAD:pkgbuilds/$package") + label="$package-$arch-$hash" + found=$(curl -fsS -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/${{ github.repository }}/actions/artifacts?name=$label&per_page=5" \ + | jq -r '[.artifacts[] | select(.expired|not)] | sort_by(.created_at) | last | .archive_download_url // empty') + mkdir -p "build-output/edge/$arch" + if [[ -n "$found" ]]; then + echo "==> $label: PR artifact" + curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" + unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch" + else + echo "==> $label: no artifact for this tree, building" + OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package" + fi + done < plan.txt + ls -1 build-output/edge/*/*.pkg.tar.zst + + - name: Publish + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + RCLONE_CONFIG_R2_TYPE: s3 + RCLONE_CONFIG_R2_PROVIDER: Cloudflare + # The token is scoped to the bucket; it may not CreateBucket, and + # rclone's existence check is a CreateBucket in disguise. + RCLONE_CONFIG_R2_NO_CHECK_BUCKET: "true" + RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} + OMARCHY_PUBLISH_PREFIX: ${{ vars.OMARCHY_PUBLISH_PREFIX }} + # repo-add, gpg and bsdtar are Arch tools; run the publish inside the + # builder image (host-native, edge) with the workspace mounted. + run: | + set -euo pipefail + docker image inspect omarchy-pkg-builder:latest-x86_64-edge >/dev/null 2>&1 \ + || docker buildx build --load -t omarchy-pkg-builder:latest-x86_64-edge --build-arg MIRROR=edge build + + # Group the merge's files by the (channel, architecture) slot each + # belongs to. A package's files live under build-output/edge// and are named --.pkg.tar.zst; a + # split package's outputs share the pkgbase's directory, so match + # on the artifact list rather than the name. + # pkgbase is read inside the builder image: the Ubuntu host has no + # bsdtar. One container call maps every file to its pkgbase. + docker run --rm -v "$PWD:/w:ro" -w /w omarchy-pkg-builder:latest-x86_64-edge bash -c ' + for f in build-output/edge/*/*.pkg.tar.zst; do + printf "%s %s\n" "$f" "$(bsdtar -xOf "$f" .PKGINFO | awk -F" = " "\$1==\"pkgbase\"{print \$2}")" + done' > pkgbase.txt + declare -A slot_files=() + while read -r package arch channels publish_arches; do + for f in build-output/edge/"$arch"/*.pkg.tar.zst; do + # Only files this package produced (its PKGINFO pkgbase). + [[ $(awk -v f="$f" '$1==f{print $2}' pkgbase.txt) == "$package" ]] || continue + for mirror in ${channels//,/ }; do + for parch in ${publish_arches//,/ }; do + slot_files["$mirror/$parch"]+="$f " + done + done + done + done < plan.txt + + # Deterministic slot order: edge before rc before stable, x86_64 + # before aarch64, so a failure leaves the earlier rings consistent. + for mirror in edge rc stable; do + for parch in x86_64 aarch64; do + files=${slot_files["$mirror/$parch"]:-} + [[ -n "$files" ]] || continue + echo "==> $mirror/$parch: $files" + docker run --rm \ + -e GPG_PRIVATE_KEY -e GPG_PASSPHRASE -e OMARCHY_PUBLISH_PREFIX \ + -e RCLONE_CONFIG_R2_TYPE -e RCLONE_CONFIG_R2_PROVIDER -e RCLONE_CONFIG_R2_ENDPOINT -e RCLONE_CONFIG_R2_NO_CHECK_BUCKET \ + -e RCLONE_CONFIG_R2_ACCESS_KEY_ID -e RCLONE_CONFIG_R2_SECRET_ACCESS_KEY \ + -v "$PWD:/w:ro" -w /w \ + omarchy-pkg-builder:latest-x86_64-edge \ + bin/publish-artifact --remote R2:omarchy-pkgs --mirror "$mirror" --arch "$parch" $files + done + done + + result: + needs: [changes, publish] + if: always() + runs-on: ubuntu-latest + steps: + - run: | + echo "publish result: ${{ needs.publish.result }}" + [[ "${{ needs.publish.result }}" == "success" || "${{ needs.publish.result }}" == "skipped" ]] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ac36ec..3ff7ea7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,9 +1,10 @@ name: Tests +# PR-only. Branch protection requires PRs to be up to date with master, so +# the PR run already tested the exact tree that merges; a second run on the +# merge commit would only repeat it. Publishing on push has its own workflow. on: pull_request: - push: - branches: [master] workflow_dispatch: jobs: @@ -45,7 +46,9 @@ jobs: ./bin/sync-rebuilds --self-test ./bin/omarchy-pkgs self-test ./bin/omarchy-release self-test - ./tests/dell-xps-touchpad-haptics-install.sh ./tests/partial-release.sh ./tests/published-build-plan.sh + ./tests/controller.sh + pacman -S --noconfirm --quiet rclone >/dev/null + ./tests/publish-artifact.sh ' diff --git a/bin/build b/bin/build index 728852b..765e071 100755 --- a/bin/build +++ b/bin/build @@ -92,6 +92,8 @@ while [[ $# -gt 0 ]]; do echo " OMARCHY_KEEP_BUILD_WORKSPACE=1 keep build-output and reuse packages already there" echo " OMARCHY_SKIP_BUILDER_IMAGE=1 use the existing builder image instead of building it" echo " OMARCHY_DEFER_RUNTIME_DEPS=true build the omarchy pair with --nodeps (transaction verified later)" + echo " OMARCHY_PUBLISHED_REPO_URL= channel to plan and resolve against when no local tree exists" + echo " (default https://pkgs.omarchy.org; empty disables the fallback)" echo "" exit 0 ;; @@ -256,6 +258,7 @@ DOCKER_ARGS=( -e MIRROR="$MIRROR" -e PACKAGES="$PACKAGES" -e OMARCHY_RC_PINS="${OMARCHY_RC_PINS:-}" + -e OMARCHY_PUBLISHED_REPO_URL="${OMARCHY_PUBLISHED_REPO_URL-https://pkgs.omarchy.org}" -e DEFER_RUNTIME_DEPS="$DEFER_RUNTIME_DEPS" -e BUILD_PLAN_DIR=/build-plan -v "$PLAN_DIR:/build-plan" diff --git a/bin/build-matrix b/bin/build-matrix new file mode 100755 index 0000000..e772349 --- /dev/null +++ b/bin/build-matrix @@ -0,0 +1,54 @@ +#!/bin/bash +# Print the PR build matrix for a set of package directories as JSON: one +# entry per package per supported architecture. Every package builds exactly +# once, against edge, and that one artifact is what every channel ships: +# channels are databases over a shared pool of files, and a filename must +# mean one set of bytes. "channels" lists where the artifact is published on +# merge: edge for everything, plus rc and stable immediately for the fast +# ring. Eligibility comes from package_builds_for_mirror, the rule the +# release host uses, so CI and the host cannot disagree. +# +# Usage: build-matrix [--arch |all] ... +# Reads package names on stdin when none are given. With no --arch, every +# architecture in CI_ARCHES (default "x86_64 aarch64") the package supports. +# Output: {"include":[{"package":"x","arch":"x86_64","channels":"edge rc stable","publish_arches":"x86_64"},...]} +# arch is where it builds; publish_arches lists every architecture +# database the file goes into (all of them for arch=any). +set -euo pipefail +BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +source "$BUILD_ROOT/helpers/paths.sh" +source "$BUILD_ROOT/helpers/package-metadata.sh" + +ARCHES=${CI_ARCHES:-x86_64 aarch64} +if [[ "${1:-}" == --arch ]]; then [[ $2 == all ]] || ARCHES=$2; shift 2; fi +for a in $ARCHES; do require_valid_arch "$a"; done + +if (( $# )); then names=("$@"); else mapfile -t names; fi + +entries=() +for name in "${names[@]}"; do + [[ -n "$name" ]] || continue + pkgdir="$PKGBUILDS_DIR/$name" + [[ -d "$pkgdir" ]] || continue + # skip_build packages still build on their own PR (explicit --package + # semantics); the host's unscoped runs are what skip them. + channels="" + for mirror in $VALID_MIRRORS; do + package_builds_for_mirror "$pkgdir" "$mirror" && channels="$channels $mirror" + done + channels=${channels# } + [[ -n "$channels" ]] || continue + # An arch=any package produces one architecture-independent file, so it + # builds once, on the first architecture, and that file serves every + # channel database of every architecture. + if [[ " $(package_arches "$pkgdir" "${ARCHES%% *}") " == *" any "* ]]; then + entries+=("$(jq -nc --arg p "$name" --arg a "${ARCHES%% *}" --arg c "$channels" --arg pa "$ARCHES" '{package:$p, arch:$a, channels:$c, publish_arches:$pa}')") + continue + fi + for arch in $ARCHES; do + package_supports_arch "$pkgdir" "$arch" || continue + entries+=("$(jq -nc --arg p "$name" --arg a "$arch" --arg c "$channels" '{package:$p, arch:$a, channels:$c, publish_arches:$a}')") + done +done + +printf '%s\n' "${entries[@]}" | jq -sc '{include: .}' diff --git a/bin/publish-artifact b/bin/publish-artifact new file mode 100755 index 0000000..32a4909 --- /dev/null +++ b/bin/publish-artifact @@ -0,0 +1,118 @@ +#!/bin/bash +# Publish built packages into one channel of the remote repository, +# incrementally and immutably. +# +# publish-artifact --mirror --arch +# +# What it does, in order: +# 1. pull the channel's current database from the remote +# 2. refuse if any package filename already exists on the remote +# 3. sign each package (GPG_PRIVATE_KEY / GPG_PASSPHRASE) +# 4. repo-add the packages into the pulled database (replaces the entry +# for that name; nothing else in the channel is touched) +# 5. upload packages, then signatures, then the database last +# +# Never overwrites: uploads use --ignore-existing for packages and the +# pre-check in step 2 makes a same-name collision a hard failure rather than +# a silent skip. The database is the only object rewritten, and it is +# uploaded only after every file it references is present. +# +# The remote is an rclone remote (REMOTE, default the production one); +# OMARCHY_PUBLISH_PREFIX can point a proof run at a scratch prefix. +set -euo pipefail +BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +source "$BUILD_ROOT/helpers/message-helpers.sh" +source "$BUILD_ROOT/helpers/paths.sh" + +REMOTE=${REMOTE:-pkgs.omarchy.org:omarchy-pkgs} +PREFIX=${OMARCHY_PUBLISH_PREFIX:-} +FILES=() +while [[ $# -gt 0 ]]; do + case $1 in + --mirror) MIRROR=$2; require_valid_mirror "$MIRROR"; shift 2 ;; + --arch) ARCH=$2; require_valid_arch "$ARCH"; shift 2 ;; + --remote) REMOTE=$2; shift 2 ;; + -h|--help) sed -n '2,22p' "$0"; exit 0 ;; + -*) print_error "Unknown option: $1"; exit 1 ;; + *) FILES+=("$1"); shift ;; + esac +done +(( ${#FILES[@]} )) || { print_error "No package files given"; exit 1; } +: "${GPG_PRIVATE_KEY:?}"; GPG_PASSPHRASE=${GPG_PASSPHRASE-} + +DEST="$REMOTE/${PREFIX:+$PREFIX/}$MIRROR/$ARCH" +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT +print_header "Publish to $DEST" + +# --- 0. sanity: every file is a package, named as makepkg names it --------- +for f in "${FILES[@]}"; do + [[ -f "$f" && "$f" == *.pkg.tar.* && "$f" != *.sig ]] || { print_error "Not a package file: $f"; exit 1; } + name=$(bsdtar -xOf "$f" .PKGINFO | awk -F' = ' '$1=="pkgname"{print $2}') + ver=$(bsdtar -xOf "$f" .PKGINFO | awk -F' = ' '$1=="pkgver"{print $2}') + pkgarch=$(bsdtar -xOf "$f" .PKGINFO | awk -F' = ' '$1=="arch"{print $2}') + [[ "$(basename "$f")" == "$name-$ver-$pkgarch.pkg.tar."* ]] || { + print_error "Filename does not match PKGINFO ($name-$ver-$pkgarch): $(basename "$f")"; exit 1; } + [[ "$pkgarch" == any || "$pkgarch" == "$ARCH" ]] || { print_error "$f is $pkgarch, publishing to $ARCH"; exit 1; } +done + +# --- 1. pull the current database ----------------------------------------- +mkdir -p "$WORK/repo" +listing=$(rclone lsf "$DEST/" --s3-no-head 2>/dev/null || true) +if grep -q '^omarchy.db.tar.zst$' <<<"$listing"; then + rclone copy "$DEST/omarchy.db.tar.zst" "$WORK/repo" --s3-no-head + rclone copy "$DEST/omarchy.files.tar.zst" "$WORK/repo" --s3-no-head 2>/dev/null || true + print_info "Pulled current database ($(tar -tf "$WORK/repo/omarchy.db.tar.zst" | grep -c '/$') entries)" +else + print_warning "No database at $DEST — creating a new one" +fi + +# --- 2. same-name collisions ---------------------------------------------- +# A filename must mean one set of bytes across every channel. The same file +# reaching a channel that already holds it (a fast-ring publish after edge, +# a re-run, a later promotion) is fine: it is skipped on upload and only the +# database entry is added. Different bytes under a name the channel already +# has is the one thing this must never do. +for f in "${FILES[@]}"; do + b=$(basename "$f") + grep -qxF "$b" <<<"$listing" || continue + remote_sum=$(rclone hashsum md5 "$DEST/$b" --s3-no-head 2>/dev/null | awk '{print $1}') + local_sum=$(md5sum "$f" | awk '{print $1}') + if [[ -n "$remote_sum" && "$remote_sum" == "$local_sum" ]]; then + print_info "Already published with identical bytes, adding to the database only: $b" + else + print_error "Already published with DIFFERENT bytes, refusing to overwrite: $b" + echo " Bump pkgrel; published filenames are immutable." + exit 1 + fi +done + +# --- 3. sign --------------------------------------------------------------- +export GNUPGHOME="$WORK/gnupg"; mkdir -m 700 "$GNUPGHOME" +echo "$GPG_PRIVATE_KEY" | gpg --batch --quiet --import +KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '$1=="sec"{print $5; exit}') +[[ -n "$KEY_ID" ]] || { print_error "No secret key imported"; exit 1; } +for f in "${FILES[@]}"; do + cp "$f" "$WORK/repo/" + gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ + --detach-sign --no-armor --local-user "$KEY_ID" "$WORK/repo/$(basename "$f")" + print_step "signed $(basename "$f")" +done + +# --- 4. repo-add (replaces the entry for each pkgname) --------------------- +( cd "$WORK/repo" && repo-add --quiet omarchy.db.tar.zst "${FILES[@]/#*\//}" ) +ln -sf omarchy.db.tar.zst "$WORK/repo/omarchy.db" +ln -sf omarchy.files.tar.zst "$WORK/repo/omarchy.files" +print_info "Database now has $(tar -tf "$WORK/repo/omarchy.db.tar.zst" | grep -c '/$') entries" + +# --- 5. upload: packages, signatures, database last ----------------------- +rclone copy "$WORK/repo" "$DEST" --s3-no-head --ignore-existing --filter '- *.sig' --filter '+ *.pkg.tar.*' --filter '- *' +rclone copy "$WORK/repo" "$DEST" --s3-no-head --ignore-existing --filter '+ *.pkg.tar.*.sig' --filter '- *' +# Re-verify every referenced file is really there before the db goes up. +listing=$(rclone lsf "$DEST/" --s3-no-head) +for f in "${FILES[@]}"; do + b=$(basename "$f") + grep -qxF "$b" <<<"$listing" && grep -qxF "$b.sig" <<<"$listing" || { print_error "Upload incomplete: $b"; exit 1; } +done +rclone copy "$WORK/repo" "$DEST" --s3-no-head --checksum --copy-links --filter '+ omarchy.db*' --filter '+ omarchy.files*' --filter '- *' +print_success "Published ${#FILES[@]} package(s) to $DEST" diff --git a/build/Dockerfile b/build/Dockerfile index af1bb5e..2a81a62 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -129,6 +129,7 @@ RUN pacman -Syu --noconfirm && \ wget \ curl \ jq \ + rclone \ gnupg && \ pacman -Scc --noconfirm && \ rm -rf /var/cache/pacman/pkg/* @@ -146,7 +147,8 @@ RUN useradd -m -G wheel -s /bin/bash builder && \ # be skipped at signing. Pin the extension so both architectures match. RUN sed -i 's/^#MAKEFLAGS=.*/MAKEFLAGS="-j$(nproc)"/' /etc/makepkg.conf && \ sed -i 's/^COMPRESSZST=.*/COMPRESSZST=(zstd -c -z -q --threads=0 -)/' /etc/makepkg.conf && \ - sed -i "s|^PKGEXT=.*|PKGEXT='.pkg.tar.zst'|" /etc/makepkg.conf + sed -i "s|^PKGEXT=.*|PKGEXT='.pkg.tar.zst'|" /etc/makepkg.conf && \ + sed -i 's|^#\?PACKAGER=.*|PACKAGER="Omarchy "|' /etc/makepkg.conf # Pacman wrapper that auto-resolves package conflicts (e.g. rustup vs rust). # makepkg only passes --noconfirm to pacman, which defaults to 'N' on conflict diff --git a/build/build.sh b/build/build.sh index 4c39147..65d6017 100755 --- a/build/build.sh +++ b/build/build.sh @@ -26,6 +26,29 @@ DEFER_RUNTIME_DEPS=${DEFER_RUNTIME_DEPS:-false} source "$HELPERS_DIR/package-metadata.sh" +# Where the channel's published database is read from for planning. On the +# repository host it is the published tree itself. Anywhere else (a CI runner, +# a fresh clone) that tree is absent, so the database is fetched from the +# public channel and the same URL serves as pacman's dependency repository. +# Set OMARCHY_PUBLISHED_REPO_URL= (empty) to disable the remote fallback. +PUBLISHED_REPO_URL=${OMARCHY_PUBLISHED_REPO_URL-https://pkgs.omarchy.org} +PUBLISHED_DB_DIR="$FINAL_OUTPUT_DIR" +PUBLISHED_REPO_SERVER="" +if [[ ! -f "$FINAL_OUTPUT_DIR/omarchy.db.tar.zst" && ! -f "$FINAL_OUTPUT_DIR/omarchy.db" && -n "$PUBLISHED_REPO_URL" ]]; then + remote_channel="$PUBLISHED_REPO_URL/$MIRROR/$ARCH" + remote_db_dir=$(mktemp -d /tmp/omarchy-published.XXXXXX) || exit 1 + # Cache-bust: the channel sits behind a CDN that serves a stale database + # for a while after a sync. + if curl -fsSL "$remote_channel/omarchy.db.tar.zst?$(date +%s)" -o "$remote_db_dir/omarchy.db.tar.zst"; then + PUBLISHED_DB_DIR="$remote_db_dir" + PUBLISHED_REPO_SERVER="$remote_channel" + echo "==> No local published tree; planning against $remote_channel" + else + rm -rf "$remote_db_dir" + echo "==> No local published tree and $remote_channel is unavailable; treating the channel as empty" + fi +fi + if [[ $DEFER_RUNTIME_DEPS != "false" && $DEFER_RUNTIME_DEPS != "true" ]]; then echo "DEFER_RUNTIME_DEPS must be true or false" >&2 exit 1 @@ -118,10 +141,15 @@ if [[ "$DRY_RUN" != true ]]; then fi touch "$BUILD_PLAN_DIR/repository-initialized" || exit 1 - # Add omarchy repo if it has a database (stable packages) + # Add omarchy repo if it has a database (stable packages). The local tree + # is trusted as-is; the public channel is verified against the omarchy + # keyring the image already carries. if [[ -f "$FINAL_OUTPUT_DIR/omarchy.db.tar.zst" ]] || [[ -f "$FINAL_OUTPUT_DIR/omarchy.db" ]]; then sudo sed -i "/^\[core\]$/i [omarchy]\nSigLevel = Optional TrustAll\nServer = file://$FINAL_OUTPUT_DIR\n" /etc/pacman.conf echo " -> omarchy (priority 2): $FINAL_OUTPUT_DIR" + elif [[ -n "$PUBLISHED_REPO_SERVER" ]]; then + sudo sed -i "/^\[core\]$/i [omarchy]\nSigLevel = Required DatabaseOptional\nServer = $PUBLISHED_REPO_SERVER\n" /etc/pacman.conf + echo " -> omarchy (priority 2): $PUBLISHED_REPO_SERVER" fi # Sync pacman database @@ -159,10 +187,10 @@ LOCAL_VERSION_CACHE_LOADED=false LOCAL_VERSION_CACHE_DB="" load_local_versions() { - local db="$FINAL_OUTPUT_DIR/omarchy.db.tar.zst" + local db="$PUBLISHED_DB_DIR/omarchy.db.tar.zst" if [[ ! -f "$db" ]]; then - db="$FINAL_OUTPUT_DIR/omarchy.db" + db="$PUBLISHED_DB_DIR/omarchy.db" fi [[ -f "$db" ]] || return 0 diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 0000000..0e53988 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,79 @@ +# CI spike: build PRs on ephemeral DigitalOcean droplets + +Status: spike. Nothing here publishes. The repository host keeps building and +signing on merge exactly as before. + +## Pieces + +- `.github/workflows/build-pr.yml` — on a PR touching `pkgbuilds/**`, one job + per changed package on runners labelled `omarchy-builder`. Uploads the + unsigned `.pkg.tar.zst` as a workflow artifact (7 days). +- `runner-cloud-init.yaml` — Ubuntu 24.04 user-data: docker + buildx, the + GitHub runner registered `--ephemeral`, runs one job, powers off. +- `controller.sh` — systemd timer every minute on a small always-on droplet. + Polls for queued jobs with our label, creates one g5-32vcpu-64gb-50gb droplet (ric1) per job up + to `MAX_DROPLETS`, deletes droplets that are powered off or older than + `MAX_AGE_MINUTES`. No inbound endpoint. Plain curl against both APIs, no + doctl and no gh: a token in the environment cannot pick the wrong account + the way a saved doctl context can. Needs curl and jq. + `tests/controller.sh` exercises every decision against canned responses. +- `controller-box/` — the always-on droplet: unit, timer, env template, + cloud-init, and `create.sh` to stand it up with one API call. + +## Standing up the controller box + + DIGITALOCEAN_TOKEN= GITHUB_TOKEN= \ + REPO=omacom/omarchy-pkgs ci/controller-box/create.sh + +The GitHub PAT is fine-grained, scoped to the one repo: Actions read, +Administration read+write (registration tokens). The DO token is baked into +the box's env file, so it is the account that pays for builder droplets. +Watch it with `journalctl -u omarchy-controller -f` on the box. + +## What the spike proved (2026-09-17, fork ryanrhughes/omarchy-pkgs) + +- `bin/build` works from a bare clone: with no local published tree it + plans against and resolves from `https://pkgs.omarchy.org//`. +- Droplet create → runner registered: ~70 s. omarchy-fish PR job: 2 min + including the builder image build. Droplet powers off after the job. +- linux-omarchy on a c-32 droplet: 30 min wall clock for the build job + (23:39 → 00:09), 254 MB artifact. Cold start ~90 s before the job began. +- A PR whose PKGBUILD fails to build turns the required check red and GitHub + refuses the merge (`mergeStateStatus=BLOCKED`, `gh pr merge` refuses + without `--admin`). +- Controller: one queued job + one busy droplet ⇒ creates exactly one more; + reaps powered-off droplets on the next tick. + +## Not done (required before this touches the real repo) + +- Tooling from base: check out master's `bin/ helpers/ build/` and overlay + only the PR's `pkgbuilds/`; today a PR can edit the build script + and it runs on the droplet. The vouch gate limits who can do that, not + what they can do. +- DigitalOcean cloud firewall on the `omarchy-builder` tag: no inbound, no + egress to private ranges or the metadata address. +- A fine-grained GitHub token for the real repository (the one on the + controller box is scoped to the fork), and the publish environment's + secrets set there. +- Disable the host's auto-release timers for any channel CI publishes to, + so two writers never touch one database. + +## Done since the spike README was first written + +- Controller as a systemd timer on its own droplet, plain curl, self-test. +- Build once against edge; one artifact per package per architecture, + published into every channel it belongs to (fast ring: all three at + once). arch=any builds once for every architecture database. +- Publish is incremental and immutable: pull the channel db, refuse + different bytes under an existing name, accept identical bytes, upload + packages then signatures then the db. +- aarch64 under QEMU with credential-preserving binfmt. +- Vouch gate: collaborators, `.github/VOUCHED.td`, or the `build-approved` + label; denounced authors cannot be overridden by the label. +- Tests run on PRs only; `result`, `self-tests`, `build-isolation` are the + required checks with strict up-to-date branches. + +## Cleanup + + doctl compute droplet list --tag-name omarchy-builder + doctl compute droplet delete -f diff --git a/ci/controller-box/cloud-init.yaml b/ci/controller-box/cloud-init.yaml new file mode 100644 index 0000000..fda8c43 --- /dev/null +++ b/ci/controller-box/cloud-init.yaml @@ -0,0 +1,45 @@ +#cloud-config +# The always-on controller droplet (smallest size is fine). Clones the repo +# for ci/controller.sh, installs the unit and timer, and starts polling. +# +# Substitute before use: +# __REPO_URL__ https://github.com/omacom/omarchy-pkgs.git +# __BRANCH__ branch carrying ci/ (master once merged) +# __ENV_B64__ base64 of a filled-in controller.env.example +# __SSH_KEYS_JSON__ JSON array of public keys authorized for root +package_update: true +packages: [curl, jq, git] + +# Root stays reachable by key so the journal can be read. Two things stand +# in the way on DO images: disable_root rewrites root's keys into a stub, and +# with no account ssh key attached DO expires root's password, which makes +# sshd refuse every non-interactive session with "password change required". +disable_root: false +chpasswd: + expire: false +ssh_authorized_keys: __SSH_KEYS_JSON__ + +users: + - name: controller + shell: /bin/bash + +write_files: + # defer: write after the users module has created the controller group, + # otherwise chown to root:controller fails and the unit cannot read this. + - path: /etc/omarchy-controller.env + permissions: "0640" + owner: root:controller + encoding: b64 + defer: true + content: __ENV_B64__ + +runcmd: + - chage -d "$(date +%F)" -M -1 root + - chown root:controller /etc/omarchy-controller.env && chmod 0640 /etc/omarchy-controller.env + - git clone --depth 1 --branch __BRANCH__ __REPO_URL__ /opt/omarchy-pkgs + - mkdir -p /run/omarchy-controller && chown controller:controller /run/omarchy-controller + - echo "d /run/omarchy-controller 0755 controller controller -" > /etc/tmpfiles.d/omarchy-controller.conf + # runcmd is executed by /bin/sh: no brace expansion. + - cp /opt/omarchy-pkgs/ci/controller-box/omarchy-controller.service /opt/omarchy-pkgs/ci/controller-box/omarchy-controller.timer /etc/systemd/system/ + - systemctl daemon-reload + - systemctl enable --now omarchy-controller.timer diff --git a/ci/controller-box/controller.env.example b/ci/controller-box/controller.env.example new file mode 100644 index 0000000..37ae372 --- /dev/null +++ b/ci/controller-box/controller.env.example @@ -0,0 +1,15 @@ +# /etc/omarchy-controller.env — mode 0600, owned by root, read by systemd. +DIGITALOCEAN_TOKEN=dop_v1_... +# Fine-grained PAT scoped to the repo: Actions: read, Administration: read+write +GITHUB_TOKEN=github_pat_... +REPO=omacom/omarchy-pkgs +LABEL=omarchy-builder +TAG=omarchy-builder +REGION=ric1 +SIZE=g5-32vcpu-64gb-50gb +MAX_DROPLETS=6 +MAX_AGE_MINUTES=200 +LOCK=/run/omarchy-controller/lock +# Operator public keys for root on every builder droplet (JSON array). +# create.sh fills this from the operators' GitHub keys. +SSH_KEYS_JSON=[] diff --git a/ci/controller-box/create.sh b/ci/controller-box/create.sh new file mode 100755 index 0000000..9ec4c3d --- /dev/null +++ b/ci/controller-box/create.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Create the controller droplet with plain curl. Run from a laptop, once. +# +# DIGITALOCEAN_TOKEN=... GITHUB_TOKEN=... ci/controller-box/create.sh [branch] +# +# The DO token given here is baked into the box's env file, so it must be the +# token for the account that should pay for builder droplets. +set -euo pipefail +here=$(dirname "$0") +: "${DIGITALOCEAN_TOKEN:?}" "${GITHUB_TOKEN:?}" +REPO=${REPO:-omacom/omarchy-pkgs} +BRANCH=${1:-master} +REGION=${REGION:-ric1} +NAME=${NAME:-omarchy-controller} +# Optional DO ssh key ids as a JSON array, e.g. SSH_KEYS='[123]', for reading +# the journal while bringing the box up. Not needed once it works. +SSH_KEYS=${SSH_KEYS:-[]} +# Public keys authorized for root: the operators' GitHub keys, fetched at +# creation so the box never depends on an ssh_key API scope. Override with +# ADMIN_GITHUB_USERS. +ADMIN_GITHUB_USERS=${ADMIN_GITHUB_USERS:-ryanrhughes dhh} +ssh_keys_json=$(for u in $ADMIN_GITHUB_USERS; do curl -fsS "https://github.com/$u.keys"; done | jq -R . | jq -sc .) +[[ $(jq length <<<"$ssh_keys_json") -gt 0 ]] || { echo "no ssh keys fetched for $ADMIN_GITHUB_USERS" >&2; exit 1; } + +env_file=$(sed -e "s|^DIGITALOCEAN_TOKEN=.*|DIGITALOCEAN_TOKEN=$DIGITALOCEAN_TOKEN|" \ + -e "s|^GITHUB_TOKEN=.*|GITHUB_TOKEN=$GITHUB_TOKEN|" \ + -e "s|^REPO=.*|REPO=$REPO|" \ + -e "s|^SSH_KEYS_JSON=.*|SSH_KEYS_JSON=$ssh_keys_json|" "$here/controller.env.example") +userdata=$(sed -e "s|__REPO_URL__|https://github.com/$REPO.git|" -e "s|__BRANCH__|$BRANCH|" \ + -e "s|__ENV_B64__|$(printf '%s\n' "$env_file" | base64 -w0)|" \ + -e "s|__SSH_KEYS_JSON__|$ssh_keys_json|" "$here/cloud-init.yaml") +body=$(jq -n --arg name "$NAME" --arg region "$REGION" --arg ud "$userdata" --argjson keys "$SSH_KEYS" \ + '{name:$name, region:$region, size:"s-1vcpu-1gb", image:"ubuntu-24-04-x64", tags:["omarchy-controller"], user_data:$ud, ssh_keys:$keys}') + +# Refuse to create a second one. +existing=$(curl -fsS -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v2/droplets?tag_name=omarchy-controller" | jq '.droplets | length') +if (( existing > 0 )); then echo "a controller droplet already exists" >&2; exit 1; fi + +curl -fsS -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" -H "Content-Type: application/json" \ + -X POST -d "$body" https://api.digitalocean.com/v2/droplets | jq -r '"created \(.droplet.name) id=\(.droplet.id)"' diff --git a/ci/controller-box/omarchy-controller.service b/ci/controller-box/omarchy-controller.service new file mode 100644 index 0000000..12d2e9c --- /dev/null +++ b/ci/controller-box/omarchy-controller.service @@ -0,0 +1,12 @@ +[Unit] +Description=Provision ephemeral omarchy-builder runner droplets for queued jobs +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +User=controller +EnvironmentFile=/etc/omarchy-controller.env +ExecStart=/opt/omarchy-pkgs/ci/controller.sh +# The reaper's safety net is time, not state; a hung tick must not hold the lock. +TimeoutStartSec=240 diff --git a/ci/controller-box/omarchy-controller.timer b/ci/controller-box/omarchy-controller.timer new file mode 100644 index 0000000..0534b68 --- /dev/null +++ b/ci/controller-box/omarchy-controller.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Run the omarchy-builder controller every minute + +[Timer] +OnBootSec=1min +OnUnitActiveSec=1min +AccuracySec=5s + +[Install] +WantedBy=timers.target diff --git a/ci/controller.sh b/ci/controller.sh new file mode 100755 index 0000000..cc60950 --- /dev/null +++ b/ci/controller.sh @@ -0,0 +1,125 @@ +#!/bin/bash +# Droplet-per-job controller for the omarchy-builder runner pool. +# +# Run from a systemd timer every minute on a small always-on droplet. No +# inbound endpoint: it polls GitHub for queued jobs wanting our label, creates +# one ephemeral droplet per job (up to MAX_DROPLETS), and deletes droplets +# that have powered off or exceeded MAX_AGE_MINUTES. The reaper does not +# trust its own bookkeeping: it lists by tag and acts on what DigitalOcean +# reports. +# +# Talks to both APIs with curl. No doctl: its saved contexts silently choose +# an account; a token in the environment cannot. Needs curl and jq. +# +# Environment: +# DIGITALOCEAN_TOKEN DO API token for the account that pays for droplets +# GITHUB_TOKEN fine-grained PAT: Actions read, Administration write +# REPO owner/name +set -euo pipefail + +REPO=${REPO:?owner/name} +: "${DIGITALOCEAN_TOKEN:?}" "${GITHUB_TOKEN:?}" +LABEL=${LABEL:-omarchy-builder} +TAG=${TAG:-omarchy-builder} +REGION=${REGION:-ric1} +SIZE=${SIZE:-g5-32vcpu-64gb-50gb} +IMAGE=${IMAGE:-ubuntu-24-04-x64} +MAX_DROPLETS=${MAX_DROPLETS:-4} +MAX_AGE_MINUTES=${MAX_AGE_MINUTES:-200} +RUNNER_VERSION=${RUNNER_VERSION:-2.337.0} +CLOUD_INIT=${CLOUD_INIT:-$(dirname "$0")/runner-cloud-init.yaml} +# Operator public keys authorized on every builder (JSON array of strings). +# The box's env file carries them; empty means no root login. +SSH_KEYS_JSON=${SSH_KEYS_JSON:-[]} +LOCK=${LOCK:-/tmp/omarchy-controller.lock} + +log() { echo "$(date '+%F %T') $*"; } + +# The only two places the outside world is touched. The self-test overrides +# both, so every decision below is exercised against canned responses. +do_api() { # do_api [curl args...] + local path=$1; shift + curl -fsS -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -H "Content-Type: application/json" "https://api.digitalocean.com/v2/$path" "$@" +} +gh_api() { # gh_api [curl args...] + local path=$1; shift + curl -fsS -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github+json" "https://api.github.com/$path" "$@" +} + +# --- reap ------------------------------------------------------------------ +reap() { + local now id status created age + now=$(date +%s) + while read -r id status created; do + [[ -n "$id" ]] || continue + age=$(( (now - $(date -d "$created" +%s)) / 60 )) + if [[ $status == off ]] || (( age > MAX_AGE_MINUTES )); then + log "deleting droplet $id (status=$status age=${age}m)" + do_api "droplets/$id" -X DELETE + fi + done < <(do_api "droplets?tag_name=$TAG&per_page=200" | + jq -r '.droplets[] | "\(.id) \(.status) \(.created_at)"') +} + +# --- demand ---------------------------------------------------------------- +queued_jobs() { + local run + gh_api "repos/$REPO/actions/runs?status=queued&per_page=50" --get \ + | jq -r '.workflow_runs[].id' | + while read -r run; do + gh_api "repos/$REPO/actions/runs/$run/jobs" \ + | jq -r --arg l "$LABEL" '.jobs[] | select(.status=="queued") | select(.labels | index($l)) | .id' + done | wc -l +} + +live_droplets() { + do_api "droplets?tag_name=$TAG&per_page=200" | jq '[.droplets[] | select(.status != "off")] | length' +} + +busy_runners() { + gh_api "repos/$REPO/actions/runners?per_page=100" \ + | jq --arg l "$LABEL" '[.runners[] | select(.busy) | select(any(.labels[]; .name == $l))] | length' +} + +# --- create ---------------------------------------------------------------- +create_droplet() { + local token userdata name body + token=$(gh_api "repos/$REPO/actions/runners/registration-token" -X POST | jq -r .token) + userdata=$(sed -e "s|__REPO__|$REPO|g" -e "s|__RUNNER_TOKEN__|$token|g" \ + -e "s|__RUNNER_LABELS__|$LABEL|g" -e "s|__RUNNER_VERSION__|$RUNNER_VERSION|g" \ + -e "s|__SSH_KEYS_JSON__|$SSH_KEYS_JSON|" "$CLOUD_INIT") + name="$TAG-$(date +%s)-$RANDOM" + body=$(jq -n --arg name "$name" --arg region "$REGION" --arg size "$SIZE" --arg image "$IMAGE" \ + --arg tag "$TAG" --arg ud "$userdata" \ + '{name:$name, region:$region, size:$size, image:$image, tags:[$tag], user_data:$ud, monitoring:false}') + log "creating $name ($SIZE)" + do_api droplets -X POST -d "$body" | jq -r '"created droplet \(.droplet.id)"' +} + +controller_tick() { + reap + local queued live busy available need room + queued=$(queued_jobs) + live=$(live_droplets) + busy=$(busy_runners) + # A live droplet whose runner is busy is spoken for. Only droplets still + # booting or listening can absorb a queued job. + available=$(( live - busy )); (( available < 0 )) && available=0 + need=$(( queued - available )) + (( need > 0 )) || return 0 + room=$(( MAX_DROPLETS - live )) + (( need > room )) && need=$room + if (( need <= 0 )); then + log "at cap ($live/$MAX_DROPLETS, $busy busy) with $queued queued" + return 0 + fi + local i + for (( i = 0; i < need; i++ )); do create_droplet; done +} + +if [[ "${CONTROLLER_LIBRARY_ONLY:-}" != 1 ]]; then + exec 9>"$LOCK"; flock -n 9 || exit 0 + controller_tick +fi diff --git a/ci/runner-cloud-init.yaml b/ci/runner-cloud-init.yaml new file mode 100644 index 0000000..c2db181 --- /dev/null +++ b/ci/runner-cloud-init.yaml @@ -0,0 +1,77 @@ +#cloud-config +# Ephemeral GitHub Actions runner for omarchy-pkgs package builds. +# +# Boots an Ubuntu droplet, installs docker and the runner, registers ONCE with +# --ephemeral, runs exactly one job, then powers off. The controller (or the +# reaper) deletes the powered-off droplet. Nothing here holds a long-lived +# credential: the registration token is single-use and expires in an hour. +# +# Substitute before use: +# __REPO__ owner/name +# __RUNNER_TOKEN__ registration token (gh api -X POST repos/O/R/actions/runners/registration-token) +# __RUNNER_LABELS__ e.g. omarchy-builder +# __RUNNER_VERSION__ e.g. 2.329.0 + +# Operators can reach a builder by key while it lives; it powers off after +# one job anyway. Keys are substituted by the controller (__SSH_KEYS_JSON__). +disable_root: false +chpasswd: + expire: false +ssh_authorized_keys: __SSH_KEYS_JSON__ + +package_update: true +packages: + - docker.io + - docker-buildx + - unzip + - git + - curl + - jq + - rsync + +users: + - name: runner + groups: [docker] + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + +write_files: + # defer: write after users/groups exist, so /home/runner is created by + # useradd (owned by runner) rather than by this module as root. + - path: /home/runner/start.sh + permissions: "0755" + owner: runner:runner + defer: true + content: | + #!/bin/bash + set -euo pipefail + cd /home/runner + mkdir -p actions-runner && cd actions-runner + arch=$(uname -m); [[ $arch == x86_64 ]] && arch=x64 + curl -fsSL -o runner.tgz \ + "https://github.com/actions/runner/releases/download/v__RUNNER_VERSION__/actions-runner-linux-${arch}-__RUNNER_VERSION__.tar.gz" + tar xzf runner.tgz && rm runner.tgz + ./config.sh --unattended --ephemeral \ + --url "https://github.com/__REPO__" \ + --token "__RUNNER_TOKEN__" \ + --name "do-$(hostname)" \ + --labels "__RUNNER_LABELS__" \ + --replace + ./run.sh + # One job done. Power off; the controller deletes powered-off droplets. + sudo poweroff + +runcmd: + # With no account ssh key attached, DO expires root's password, and sshd + # then refuses every non-interactive session. Clear it first so operators + # can read the logs of a builder that never registers. + - chage -d "$(date +%F)" -M -1 root + - systemctl enable --now docker + # aarch64 builds run under user-mode emulation (DO has no arm droplets). + # Register QEMU with the F and C flags via the multiarch image, exactly as + # helpers/docker-helpers.sh setup_qemu does: Ubuntu's qemu-user-static + # package registers without C, so sudo inside the emulated container fails + # with "effective uid is not 0". Best-effort: an x86-only job never needs it. + - docker run --rm --privileged docker.io/multiarch/qemu-user-static --reset -p yes --credential yes || true + - chown -R runner:runner /home/runner + - sudo -u runner /home/runner/start.sh > /home/runner/runner.log 2>&1 diff --git a/tests/controller.sh b/tests/controller.sh new file mode 100755 index 0000000..d777fc5 --- /dev/null +++ b/tests/controller.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Self-test for ci/controller.sh: every decision, no cloud. +# +# The controller's two API functions are overridden with canned responses and +# a recorder, then each scenario asserts which creates and deletes it issued. +set -euo pipefail +ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") + +export REPO=o/r DIGITALOCEAN_TOKEN=x GITHUB_TOKEN=x +export CLOUD_INIT="$ROOT/ci/runner-cloud-init.yaml" LOCK=/tmp/controller-test.lock +CONTROLLER_LIBRARY_ONLY=1 source "$ROOT/ci/controller.sh" + +# Calls are recorded to a file: the controller invokes the API functions +# inside command substitutions, and a subshell cannot append to an array. +CALLS_FILE=$(mktemp); trap 'rm -f "$CALLS_FILE"' EXIT +NOW=$(date -u +%FT%TZ) +OLD=$(date -u -d '5 hours ago' +%FT%TZ) + +# Scenario state: DROPLETS is "id status created" lines, QUEUED a count, +# BUSY a count. +do_api() { + local path=$1; shift + echo "do $path $*" >>"$CALLS_FILE" + case "$path" in + droplets\?*) printf '%s\n' "$DROPLETS" | jq -Rs '{droplets: [split("\n")[] | select(length>0) | split(" ") | {id: .[0]|tonumber, status: .[1], created_at: .[2]}]}' ;; + droplets) echo '{"droplet":{"id":999}}' ;; + droplets/*) echo '{}' ;; + esac +} +gh_api() { + local path=$1; shift + echo "gh $path $*" >>"$CALLS_FILE" + case "$path" in + */actions/runs\?*) jq -nc --argjson n "$QUEUED" '{workflow_runs: [range($n) | {id: .}]}' ;; + */actions/runs/*/jobs) echo '{"jobs":[{"id":1,"status":"queued","labels":["self-hosted","omarchy-builder"]}]}' ;; + */actions/runners\?*) jq -nc --argjson n "$BUSY" '{runners: [range($n) | {busy: true, labels: [{name: "omarchy-builder"}]}]}' ;; + */registration-token) echo '{"token":"T"}' ;; + esac +} + +creates() { grep -c '^do droplets -X POST' "$CALLS_FILE" || true; } +deletes() { grep -c '^do droplets/.* -X DELETE' "$CALLS_FILE" || true; } +run() { : >"$CALLS_FILE"; controller_tick >/dev/null; } +check() { # check + local c d; c=$(creates); d=$(deletes) + if [[ "$c" == "$2" && "$d" == "$3" ]]; then echo "PASS: $1"; else echo "FAIL: $1 (creates=$c want $2, deletes=$d want $3)"; cat "$CALLS_FILE"; exit 1; fi +} + +DROPLETS="" QUEUED=0 BUSY=0; run; check "idle: nothing queued, nothing to reap" 0 0 +DROPLETS="" QUEUED=2 BUSY=0; run; check "two queued, none live: create two" 2 0 +DROPLETS="1 active $NOW" QUEUED=1 BUSY=1; run; check "one queued, one live but busy: create one" 1 0 +DROPLETS="1 active $NOW" QUEUED=1 BUSY=0; run; check "one queued, one live and idle: it will take it" 0 0 +DROPLETS="1 off $NOW" QUEUED=0 BUSY=0; run; check "powered-off droplet reaped" 0 1 +DROPLETS="1 active $OLD" QUEUED=0 BUSY=0; run; check "over-age droplet reaped even if active" 0 1 +DROPLETS=$'1 active '"$NOW"$'\n2 active '"$NOW"$'\n3 active '"$NOW"$'\n4 active '"$NOW" QUEUED=3 BUSY=4; MAX_DROPLETS=4; run; check "at cap: no creates" 0 0 +DROPLETS=$'1 active '"$NOW"$'\n2 active '"$NOW" QUEUED=5 BUSY=2; MAX_DROPLETS=3; run; check "cap limits creates to remaining room" 1 0 +DROPLETS="1 off $NOW" QUEUED=1 BUSY=0; MAX_DROPLETS=4; run; check "off droplet is not capacity: reaped and replaced" 1 1 + +# The create body must carry the tag (reaper scope) and substituted user-data. +BODY_FILE=$(mktemp); trap 'rm -f "$CALLS_FILE" "$BODY_FILE"' EXIT +do_api() { if [[ $1 == droplets ]]; then printf '%s' "${*: -1}" >"$BODY_FILE"; echo '{"droplet":{"id":1}}'; else echo '{"droplets":[]}'; fi; } +gh_api() { echo '{"token":"TOK"}'; } +create_droplet >/dev/null +jq -e '.tags == ["omarchy-builder"] and .size == "g5-32vcpu-64gb-50gb" and (.user_data | test("--token \"TOK\"")) and (.user_data | test("__") | not)' "$BODY_FILE" >/dev/null \ + && echo "PASS: create body carries tag, size, substituted user-data" \ + || { echo "FAIL: create body"; jq . "$BODY_FILE" | head -20; exit 1; } diff --git a/tests/publish-artifact.sh b/tests/publish-artifact.sh new file mode 100755 index 0000000..2c5269c --- /dev/null +++ b/tests/publish-artifact.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Self-test for bin/publish-artifact against a local directory as the remote. +# Needs repo-add, gpg, rclone, bsdtar (run in the Arch builder/test container). +set -euo pipefail +ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +T=$(mktemp -d); chmod 755 "$T"; trap 'rm -rf "$T"' EXIT +REMOTE="$T/r2"; mkdir -p "$REMOTE" + +# throwaway signing key +export GNUPGHOME="$T/g"; mkdir -m700 "$GNUPGHOME" +gpg --batch --quiet --passphrase '' --quick-gen-key 'Test ' ed25519 sign 0 2>/dev/null +export GPG_PRIVATE_KEY=$(gpg --batch --armor --export-secret-keys 'Test ') GPG_PASSPHRASE='' +unset GNUPGHOME + +# minimal real packages via makepkg +mkpkg() { # mkpkg [payload] + local d="$T/src/$1-$2${4:+-$4}"; mkdir -p "$d"; cd "$d" + printf 'pkgname=%s\npkgver=1.0\npkgrel=%s\narch=(%s)\npackage(){ install -Dm644 /dev/null "$pkgdir/usr/share/%s-%s"; echo "%s" > "$pkgdir/usr/share/%s-%s"; }\n' "$1" "$2" "$3" "$1" "$2" "${4:-payload}" "$1" "$2" > PKGBUILD + # CARCH so the PKGINFO records the requested arch (--ignorearch would + # stamp the host's). + # makepkg refuses to run as root (the CI test container does); build the + # fixture as an unprivileged user in that case. + if (( EUID == 0 )); then + id -u fixture >/dev/null 2>&1 || useradd -m fixture + chmod 755 "$T/src"; chown -R fixture "$d" + runuser -u fixture -- env CARCH=$3 makepkg -f --nodeps --ignorearch >/dev/null 2>&1 + else + CARCH=$3 makepkg -f --nodeps --ignorearch >/dev/null 2>&1 + fi + ls "$d"/*.pkg.tar.zst +} +A1=$(mkpkg alpha 1 any); A2=$(mkpkg alpha 2 any); B1=$(mkpkg beta 1 x86_64); C1=$(mkpkg gamma 1 aarch64) + +pub() { "$ROOT/bin/publish-artifact" --remote "$REMOTE" --mirror edge --arch x86_64 "$@" >"$T/out" 2>&1; } +entries() { tar -tf "$REMOTE/edge/x86_64/omarchy.db.tar.zst" | grep '/$' | sort | tr '\n' ' '; } +pass() { echo "PASS: $1"; } +fail() { echo "FAIL: $1"; cat "$T/out"; exit 1; } + +pub "$A1" && [[ "$(entries)" == "alpha-1.0-1/ " ]] && [[ -f "$REMOTE/edge/x86_64/$(basename "$A1").sig" ]] \ + && pass "first publish creates db with one entry and a signature" || fail "first publish" + +sum_before=$(sha256sum "$REMOTE/edge/x86_64/$(basename "$A1")") +pub "$B1" && [[ "$(entries)" == "alpha-1.0-1/ beta-1.0-1/ " ]] && [[ "$(sha256sum "$REMOTE/edge/x86_64/$(basename "$A1")")" == "$sum_before" ]] \ + && pass "second package added incrementally; first file untouched" || fail "incremental add" + +pub "$A2" && [[ "$(entries)" == "alpha-1.0-2/ beta-1.0-1/ " ]] && [[ -f "$REMOTE/edge/x86_64/$(basename "$A1")" ]] \ + && pass "new pkgrel replaces the db entry, old file remains on remote" || fail "replace entry" + +# Same bytes again: allowed, idempotent (this is how a fast-ring artifact +# reaches rc and stable after edge, and how a re-run recovers). +pub "$A2" && grep -q 'identical bytes' "$T/out" && [[ "$(entries)" == "alpha-1.0-2/ beta-1.0-1/ " ]] \ + && pass "identical bytes under an existing name: accepted, db unchanged" || fail "identical republish" + +# Orphan repair: a file that reached the remote but whose db entry was lost +# (a concurrent publish overwrote the db) is fixed by publishing it again. +( cd "$REMOTE/edge/x86_64" && repo-remove --quiet omarchy.db.tar.zst alpha >/dev/null 2>&1 ) +[[ "$(entries)" == "beta-1.0-1/ " ]] || fail "fixture: could not drop alpha from the db" +pub "$A2" && [[ "$(entries)" == "alpha-1.0-2/ beta-1.0-1/ " ]] \ + && pass "orphaned file regains its db entry on republish" || fail "orphan repair" + +# Different bytes under an existing name: refused. Build alpha-2 again with +# a different payload (makepkg is reproducible, so the content must change). +A2b=$(mkpkg alpha 2 any different-payload) +[[ "$(md5sum < "$A2")" != "$(md5sum < "$A2b")" ]] || { echo "fixture: rebuilt package is byte-identical, cannot test"; exit 1; } +if pub "$A2b"; then fail "different bytes under same filename should refuse"; else grep -q 'DIFFERENT bytes' "$T/out" && pass "different bytes under an existing name refused" || fail "wrong refusal reason"; fi + +if pub "$C1"; then fail "aarch64 package into x86_64 should refuse"; else grep -q 'publishing to x86_64' "$T/out" && pass "wrong-arch package refused" || fail "wrong-arch reason"; fi + +cp "$B1" "$T/renamed-1.0-1-x86_64.pkg.tar.zst" +if pub "$T/renamed-1.0-1-x86_64.pkg.tar.zst"; then fail "filename/PKGINFO mismatch should refuse"; else grep -q 'does not match PKGINFO' "$T/out" && pass "filename must match PKGINFO" || fail "mismatch reason"; fi + +# db must verify: pacman can read it and each package's signature checks +gpg --batch --quiet --import <<<"$GPG_PRIVATE_KEY" 2>/dev/null || true +( cd "$REMOTE/edge/x86_64" && for f in *.pkg.tar.zst; do gpg --batch --quiet --verify "$f.sig" "$f" 2>/dev/null || { echo "FAIL: signature $f"; exit 1; }; done ) && pass "all signatures verify" From 5a701be9d14e469662d862d338d66d0a2df6a3ca Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 11:46:50 -0400 Subject: [PATCH 051/121] PR plan job: bootstrap when the base branch has no bin/build-matrix yet --- .github/workflows/build-pr.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 8d68dbb..59d12bf 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -48,6 +48,13 @@ jobs: run: | git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.head.sha }}" git checkout "${{ github.event.pull_request.head.sha }}" -- pkgbuilds/ + # Bootstrap: the PR that introduces this tooling has a base without + # it. Take the plan helper from the PR head in that one case; it + # runs on a hosted runner and only prints a plan. + if [[ ! -x bin/build-matrix ]]; then + git checkout "${{ github.event.pull_request.head.sha }}" -- bin/build-matrix helpers/ + echo "::notice::base branch has no bin/build-matrix; using the PR's copy for planning" + fi - id: vouch if: github.event_name == 'pull_request' uses: mitchellh/vouch/action/check-user@f23dbb5e745334f97414ec70463ce7301071a661 # v1 From 902f6d3da9015ae6c75c6de393631ea0cd6d19d8 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 12:42:47 -0400 Subject: [PATCH 052/121] Report each publish: comment on the merged PR, append to a JSON log in the bucket The publish job now writes publish-record.json describing every channel/architecture slot it touched: the packages, whether the slot was published or failed, the target (live or a proof prefix), the commit and the run. A report job renders that as a comment on the PR the merge commit came from (looked up by commit, so squash and rebase merges work) and appends the record as one line to publish-log.jsonl in the bucket, served next to the packages at https://pkgs.omarchy.org/publish-log.jsonl. Failures are reported too, with the slots that landed before the failure, which is when a human most needs to know. --- .github/workflows/publish.yml | 91 ++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9eb969c..c34449e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -154,20 +154,107 @@ jobs: # Deterministic slot order: edge before rc before stable, x86_64 # before aarch64, so a failure leaves the earlier rings consistent. + # Every slot's outcome goes into publish-record.json for the report + # job: what was published, where, from which artifact, and whether + # the slot succeeded. A failing slot stops the loop (set -e) but the + # record still shows everything before it landed. + : > slots.jsonl + record_slot() { jq -nc --arg m "$1" --arg a "$2" --arg st "$3" --arg files "$4" \ + '{mirror:$m, arch:$a, status:$st, packages:[$files | split(" ") | .[] | select(length>0) | sub(".*/";"") | sub("\\.pkg\\.tar\\.zst$";"")]}' >> slots.jsonl; } + status=0 for mirror in edge rc stable; do for parch in x86_64 aarch64; do files=${slot_files["$mirror/$parch"]:-} [[ -n "$files" ]] || continue echo "==> $mirror/$parch: $files" - docker run --rm \ + if docker run --rm \ -e GPG_PRIVATE_KEY -e GPG_PASSPHRASE -e OMARCHY_PUBLISH_PREFIX \ -e RCLONE_CONFIG_R2_TYPE -e RCLONE_CONFIG_R2_PROVIDER -e RCLONE_CONFIG_R2_ENDPOINT -e RCLONE_CONFIG_R2_NO_CHECK_BUCKET \ -e RCLONE_CONFIG_R2_ACCESS_KEY_ID -e RCLONE_CONFIG_R2_SECRET_ACCESS_KEY \ -v "$PWD:/w:ro" -w /w \ omarchy-pkg-builder:latest-x86_64-edge \ - bin/publish-artifact --remote R2:omarchy-pkgs --mirror "$mirror" --arch "$parch" $files + bin/publish-artifact --remote R2:omarchy-pkgs --mirror "$mirror" --arch "$parch" $files; then + record_slot "$mirror" "$parch" published "$files" + else + record_slot "$mirror" "$parch" failed "$files" + status=1 + break 2 + fi done done + jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ + --slurpfile slots slots.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], slots:$slots}' \ + > publish-record.json + cat publish-record.json + exit $status + + - name: Keep the publish record + if: always() + uses: actions/upload-artifact@v4 + with: + name: publish-record-${{ github.run_id }} + path: publish-record.json + retention-days: 90 + + # Tell people what happened. A comment on the merged PR (found by the + # merge commit, so squash and rebase merges work too) and a line appended + # to a running JSON log in the bucket, next to the packages it describes, + # so the history is public and can be rendered later. + report: + needs: [changes, publish] + if: always() && needs.publish.result != 'skipped' + runs-on: ubuntu-latest + environment: publish + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/download-artifact@v4 + with: + name: publish-record-${{ github.run_id }} + - name: Render + id: render + run: | + jq -r --arg outcome "${{ needs.publish.result }}" ' + def pkgs: [.packages[] | select(test("-debug-")|not)] | join(", "); + "### Publish " + (if $outcome=="success" then "succeeded" else "FAILED" end) + + " → **" + .target + "**" + (if .target!="live" then " (proof prefix, not live)" else "" end), + "", + (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs), + "", + (if (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), + "Commit " + .commit[0:7] + " · [run](" + .run + ")" + ' publish-record.json > comment.md + cat comment.md + - name: Comment on the merged PR + env: + GH_TOKEN: ${{ github.token }} + run: | + pr=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}/pulls" --jq '.[0].number // empty') + if [[ -n "$pr" ]]; then + gh pr comment "$pr" -R "${{ github.repository }}" --body-file comment.md + echo "commented on #$pr" + else + echo "no PR for ${{ github.sha }} (manual dispatch?); skipping PR comment" + fi + - name: Append to the publish log in the bucket + env: + RCLONE_CONFIG_R2_TYPE: s3 + RCLONE_CONFIG_R2_PROVIDER: Cloudflare + RCLONE_CONFIG_R2_NO_CHECK_BUCKET: "true" + RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} + run: | + curl -fsSL https://downloads.rclone.org/rclone-current-linux-amd64.zip -o rclone.zip && unzip -jq rclone.zip '*/rclone' && chmod +x rclone + # One JSON object per line, newest last. Served at + # https://pkgs.omarchy.org/publish-log.jsonl + ./rclone copy R2:omarchy-pkgs/publish-log.jsonl . --s3-no-head 2>/dev/null || : > publish-log.jsonl + jq -c . publish-record.json >> publish-log.jsonl + ./rclone copyto publish-log.jsonl R2:omarchy-pkgs/publish-log.jsonl --s3-no-head + echo "log now has $(wc -l < publish-log.jsonl) entries" result: needs: [changes, publish] From 54685a55a175016424737cc22d055bff049a1582 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 12:55:18 -0400 Subject: [PATCH 053/121] PR check fails when the PR changes no files relative to its base A PR whose diff against its base is empty has already landed some other way, typically a sync PR carrying the same bump or a merge from master that swallowed it. Merging it records a change that isn't one and could mask a real mistake. result now fails with a message saying to close it. --- .github/workflows/build-pr.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 59d12bf..c80927a 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -36,6 +36,7 @@ jobs: matrix: ${{ steps.list.outputs.matrix }} count: ${{ steps.gate.outputs.count }} trusted: ${{ steps.gate.outputs.trusted }} + empty: ${{ steps.list.outputs.empty }} steps: # Same rule as the build job: bin/build-matrix comes from base, the # package directories from the PR head. @@ -78,6 +79,17 @@ jobs: echo "matrix=$matrix" >> "$GITHUB_OUTPUT" echo "planned=$(jq '.include | length' <<<"$matrix")" >> "$GITHUB_OUTPUT" jq -r '.include[] | "\(.package) \(.arch) -> \(.channels)"' <<<"$matrix" + # A PR whose diff against its base is empty changes nothing: its + # content already landed some other way (a sync PR beat it, or a + # merge from master swallowed it). Merging it would record a change + # that isn't one. Flag it so `result` fails rather than passes. + if [[ "${{ github.event_name }}" == pull_request ]]; then + total=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" | wc -l) + echo "empty=$([[ $total -eq 0 ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "files changed vs base: $total" + else + echo "empty=false" >> "$GITHUB_OUTPUT" + fi - id: gate env: STATUS: ${{ steps.vouch.outputs.status || 'dispatch' }} @@ -170,4 +182,10 @@ jobs: echo "::error::Builds were not run: author is not vouched. Add to .github/VOUCHED.td or apply the 'build-approved' label." exit 1 fi + # Nothing to merge: the PR's diff against its base is empty. Its + # change already landed elsewhere. Close it rather than merge it. + if [[ "${{ needs.changes.outputs.empty }}" == "true" ]]; then + echo "::error::This PR changes no files relative to its base. Its content is already on the target branch; close it instead of merging." + exit 1 + fi [[ "${{ needs.build.result }}" == "success" || "${{ needs.build.result }}" == "skipped" ]] From 4717cfec4e1feef9d277ab890787b0053dcadc8c Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 13:39:56 -0400 Subject: [PATCH 054/121] Publish record covers build failures, and says where each package came from When a package had no PR artifact and its build failed, the publish step never ran, no record was written, and the report job failed looking for it. The collect step now records each package's source (PR artifact, built here, or build-failed) and writes the record itself when a build fails, so the report can say plainly that nothing was published and why. --- .github/workflows/publish.yml | 44 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c34449e..dea7370 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -89,7 +89,12 @@ jobs: GH_TOKEN: ${{ github.token }} CONTAINER_ENGINE: docker run: | - set -euo pipefail + set -uo pipefail + # sources.jsonl: where each package's files came from, or that the + # build failed. A failed build ends the run before any publish, and + # the record says so instead of the report job finding nothing. + : > sources.jsonl + failed=0 while read -r package arch channels publish_arches; do hash=$(git rev-parse "HEAD:pkgbuilds/$package") label="$package-$arch-$hash" @@ -99,14 +104,31 @@ jobs: mkdir -p "build-output/edge/$arch" if [[ -n "$found" ]]; then echo "==> $label: PR artifact" - curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" - unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch" + if curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" && unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch"; then + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"pr-artifact"}' >> sources.jsonl + else + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"artifact-download-failed"}' >> sources.jsonl; failed=1; break + fi else echo "==> $label: no artifact for this tree, building" - OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package" + if OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package"; then + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"built"}' >> sources.jsonl + else + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"build-failed"}' >> sources.jsonl; failed=1; break + fi fi done < plan.txt - ls -1 build-output/edge/*/*.pkg.tar.zst + ls -1 build-output/edge/*/*.pkg.tar.zst 2>/dev/null || true + if (( failed )); then + # Write the record now; the publish step will not run. + jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ + --slurpfile sources sources.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], sources:$sources, slots:[]}' \ + > publish-record.json + cat publish-record.json + exit 1 + fi - name: Publish env: @@ -184,8 +206,8 @@ jobs: done jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ - --slurpfile slots slots.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ - '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], slots:$slots}' \ + --slurpfile slots slots.jsonl --slurpfile sources sources.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], sources:$sources, slots:$slots}' \ > publish-record.json cat publish-record.json exit $status @@ -219,12 +241,16 @@ jobs: run: | jq -r --arg outcome "${{ needs.publish.result }}" ' def pkgs: [.packages[] | select(test("-debug-")|not)] | join(", "); + def src: if .source=="pr-artifact" then "PR artifact" elif .source=="built" then "built here" else "**" + .source + "**" end; "### Publish " + (if $outcome=="success" then "succeeded" else "FAILED" end) + " → **" + .target + "**" + (if .target!="live" then " (proof prefix, not live)" else "" end), "", - (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs), + "Packages: " + ([.sources[] | .package + " (" + .arch + ", " + src + ")"] | join("; ")), "", - (if (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), + (if (.slots|length) > 0 then (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs) else "_Nothing was published._" end), + "", + (if ([.sources[] | select(.source|test("failed"))] | length) > 0 then "_A build failed, so no channel was touched._\n" + elif (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), "Commit " + .commit[0:7] + " · [run](" + .run + ")" ' publish-record.json > comment.md cat comment.md From a24c56cd523f9e673b5e89d60da9fb1024a7b42f Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 14:01:07 -0400 Subject: [PATCH 055/121] Dispatch: a package already published at master's version is a no-op, not a failure Re-running publish for a package that is already live (a dispatch for something that turned out fine, or a retry after a partial failure) made bin/build report nothing to build and exit 2, which the publish step treated as an error. The collect step now dry-runs first: if the channel already holds master's version the package is recorded as already-published and skipped, and a run where every package is in that state exits cleanly with a record saying so. --- .github/workflows/publish.yml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dea7370..2028b7a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -110,6 +110,17 @@ jobs: jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"artifact-download-failed"}' >> sources.jsonl; failed=1; break fi else + # bin/build plans against the public channel first. If the + # channel already holds master's version there is nothing to + # build and nothing to publish: a re-run for a package that + # turned out to be fine. Record it and move on. + plan=$(CONTAINER_ENGINE=docker bin/build --dry-run --mirror edge --arch "$arch" --package "$package" 2>&1 | grep -E '^==> Plan complete' || true) + # "Packages that would build:" followed by nothing means none. + if [[ -n "$plan" && -z "$(sed -E 's/.*would build: *//' <<<"$plan" | tr -d '[:space:]')" ]]; then + echo "==> $label: already published at master's version, nothing to do" + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"already-published"}' >> sources.jsonl + continue + fi echo "==> $label: no artifact for this tree, building" if OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package"; then jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"built"}' >> sources.jsonl @@ -147,6 +158,16 @@ jobs: # builder image (host-native, edge) with the workspace mounted. run: | set -euo pipefail + if ! compgen -G "build-output/edge/*/*.pkg.tar.zst" >/dev/null; then + echo "Nothing to publish: every requested package is already published at master's version." + jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ + --slurpfile sources sources.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], sources:$sources, slots:[]}' \ + > publish-record.json + cat publish-record.json + exit 0 + fi docker image inspect omarchy-pkg-builder:latest-x86_64-edge >/dev/null 2>&1 \ || docker buildx build --load -t omarchy-pkg-builder:latest-x86_64-edge --build-arg MIRROR=edge build @@ -241,13 +262,15 @@ jobs: run: | jq -r --arg outcome "${{ needs.publish.result }}" ' def pkgs: [.packages[] | select(test("-debug-")|not)] | join(", "); - def src: if .source=="pr-artifact" then "PR artifact" elif .source=="built" then "built here" else "**" + .source + "**" end; + def src: if .source=="pr-artifact" then "PR artifact" elif .source=="built" then "built here" elif .source=="already-published" then "already published, skipped" else "**" + .source + "**" end; "### Publish " + (if $outcome=="success" then "succeeded" else "FAILED" end) + " → **" + .target + "**" + (if .target!="live" then " (proof prefix, not live)" else "" end), "", "Packages: " + ([.sources[] | .package + " (" + .arch + ", " + src + ")"] | join("; ")), "", - (if (.slots|length) > 0 then (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs) else "_Nothing was published._" end), + (if (.slots|length) > 0 then (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs) + elif ([.sources[] | select(.source=="already-published")] | length) == (.sources|length) then "_Nothing to publish: already at master'"'"'s version everywhere._" + else "_Nothing was published._" end), "", (if ([.sources[] | select(.source|test("failed"))] | length) > 0 then "_A build failed, so no channel was touched._\n" elif (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), From 8411b99fc4d7ff4399b8fc13568e728e31234584 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 18 Sep 2026 19:22:47 +0200 Subject: [PATCH 056/121] Add Hype presentation editor package --- pkgbuilds/hype/.omarchy/package.json | 3 ++ pkgbuilds/hype/PKGBUILD | 42 ++++++++++++++++++++++++++++ pkgbuilds/hype/hype.install | 12 ++++++++ 3 files changed, 57 insertions(+) create mode 100644 pkgbuilds/hype/.omarchy/package.json create mode 100644 pkgbuilds/hype/PKGBUILD create mode 100644 pkgbuilds/hype/hype.install diff --git a/pkgbuilds/hype/.omarchy/package.json b/pkgbuilds/hype/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/hype/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD new file mode 100644 index 0000000..ed8f051 --- /dev/null +++ b/pkgbuilds/hype/PKGBUILD @@ -0,0 +1,42 @@ +# Maintainer: David Heinemeier Hansson + +pkgname=hype +pkgver=0.1.0 +pkgrel=1 +pkgdesc='Simple Markdown presentations with a visual slide editor' +arch=('x86_64' 'aarch64') +url='https://github.com/omacom/hype' +license=('MIT') +install='hype.install' +options=('!debug') +depends=( + 'ffmpeg' + 'hicolor-icon-theme' + 'qt6-base>=6.8' + 'qt6-declarative>=6.8' + 'qt6-multimedia' + 'qt6-svg' + 'source-highlight' + 'zlib' + 'xdg-desktop-portal' +) +makedepends=('gcc' 'git' 'make') +# Pin the source until a tagged release is available. +_commit=34475b239d0dacb6918f43734bb5557b624555e2 +source=("git+$url.git#commit=$_commit") +sha256sums=('SKIP') + +build() { + cd "$srcdir/$pkgname" + ./bin/build +} + +package() { + cd "$srcdir/$pkgname" + + install -Dm755 build/hype "$pkgdir/usr/bin/hype" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 pkgbuild/hype.svg "$pkgdir/usr/share/icons/hicolor/scalable/apps/hype.svg" + install -Dm644 pkgbuild/hype.desktop "$pkgdir/usr/share/applications/hype.desktop" + install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md" +} diff --git a/pkgbuilds/hype/hype.install b/pkgbuilds/hype/hype.install new file mode 100644 index 0000000..5357602 --- /dev/null +++ b/pkgbuilds/hype/hype.install @@ -0,0 +1,12 @@ +post_install() { + command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database -q + command -v gtk-update-icon-cache >/dev/null 2>&1 && gtk-update-icon-cache -q -t -f usr/share/icons/hicolor +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} From 5cdaca6048f11d5e7c53f516b7abe276b65962d1 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 18 Sep 2026 20:18:08 +0200 Subject: [PATCH 057/121] Include animated WebP support in Hype package --- pkgbuilds/hype/PKGBUILD | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index ed8f051..107143c 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -15,6 +15,7 @@ depends=( 'qt6-base>=6.8' 'qt6-declarative>=6.8' 'qt6-multimedia' + 'qt6-imageformats' 'qt6-svg' 'source-highlight' 'zlib' @@ -22,7 +23,7 @@ depends=( ) makedepends=('gcc' 'git' 'make') # Pin the source until a tagged release is available. -_commit=34475b239d0dacb6918f43734bb5557b624555e2 +_commit=204d22c39deaeeeda75d8c90ee011bb53053f524 source=("git+$url.git#commit=$_commit") sha256sums=('SKIP') From efff828746b17854ddc74b6cbb5fe7cebc40d924 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 14:56:03 -0400 Subject: [PATCH 058/121] Builders emulate aarch64 with QEMU 10.2.3 instead of the abandoned 7.2 image multiarch/qemu-user-static stopped at QEMU 7.2 (January 2023). Under it, qmake's compiler probe (`g++ -E -v` in toolchain.prf) returns nothing on the current gcc 16 toolchain, so every qmake package fails on aarch64 with "failed to parse default include paths from compiler output" (hype, PR #517). The same PKGBUILD builds under QEMU 10.2.3 and 11.1. Register through tonistiigi/binfmt at a pinned tag, on both the ephemeral builder droplets and the rootful-Docker path of setup_qemu, uninstalling any existing entry first because the tool keeps an older registration in place. The tag is now the one place that decides what every emulated build runs under. Flags stay F and C, which rootless sudo inside the builder needs. --- ci/runner-cloud-init.yaml | 14 +++++++++----- helpers/docker-helpers.sh | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ci/runner-cloud-init.yaml b/ci/runner-cloud-init.yaml index c2db181..c05e32e 100644 --- a/ci/runner-cloud-init.yaml +++ b/ci/runner-cloud-init.yaml @@ -68,10 +68,14 @@ runcmd: - chage -d "$(date +%F)" -M -1 root - systemctl enable --now docker # aarch64 builds run under user-mode emulation (DO has no arm droplets). - # Register QEMU with the F and C flags via the multiarch image, exactly as - # helpers/docker-helpers.sh setup_qemu does: Ubuntu's qemu-user-static - # package registers without C, so sudo inside the emulated container fails - # with "effective uid is not 0". Best-effort: an x86-only job never needs it. - - docker run --rm --privileged docker.io/multiarch/qemu-user-static --reset -p yes --credential yes || true + # Register QEMU with the F and C flags via tonistiigi/binfmt, exactly as + # helpers/docker-helpers.sh setup_qemu does. Ubuntu's qemu-user-static + # registers without C, so sudo inside the emulated container fails with + # "effective uid is not 0"; multiarch/qemu-user-static is abandoned at QEMU + # 7.2, under which qmake's compiler probe returns nothing on current gcc + # ("failed to parse default include paths", PR #517). Pin the emulator + # version: the tag is the only thing that decides what every aarch64 build + # runs under. Best-effort: an x86-only job never needs it. + - docker run --rm --privileged docker.io/tonistiigi/binfmt:qemu-v10.2.3-68 --uninstall qemu-aarch64 --install arm64 || true - chown -R runner:runner /home/runner - sudo -u runner /home/runner/start.sh > /home/runner/runner.log 2>&1 diff --git a/helpers/docker-helpers.sh b/helpers/docker-helpers.sh index cc18222..22c8004 100644 --- a/helpers/docker-helpers.sh +++ b/helpers/docker-helpers.sh @@ -91,8 +91,19 @@ setup_qemu() { exit 1 fi - # Register emulators for builds whose target differs from the host. - if ! "$CONTAINER_ENGINE" run --rm --privileged docker.io/multiarch/qemu-user-static --reset -p yes --credential yes >/dev/null 2>&1; then + # Register emulators for builds whose target differs from the host, with + # the F and C flags (tonistiigi/binfmt always sets both). The image tag pins + # the QEMU version every emulated build runs under; multiarch/qemu-user-static + # stopped at QEMU 7.2, which breaks qmake's compiler probe on current gcc. + # Keep ci/runner-cloud-init.yaml on the same tag. Uninstall first: install + # leaves an existing registration (an older emulator) in place and exits 0. + local platform_arch + case "$target_arch" in + aarch64) platform_arch=arm64 ;; + x86_64) platform_arch=amd64 ;; + *) platform_arch="$target_arch" ;; + esac + if ! "$CONTAINER_ENGINE" run --rm --privileged docker.io/tonistiigi/binfmt:qemu-v10.2.3-68 --uninstall "qemu-$target_arch" --install "$platform_arch" >/dev/null 2>&1; then print_error "Failed to set up QEMU emulation" exit 1 fi From 16087f19b48ee21de3b3239bf10930d1e1383e90 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 18 Sep 2026 20:57:38 +0200 Subject: [PATCH 059/121] Verify Hype Git source with makepkg checksum --- pkgbuilds/hype/PKGBUILD | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 107143c..2eebb3f 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -2,7 +2,7 @@ pkgname=hype pkgver=0.1.0 -pkgrel=1 +pkgrel=2 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') url='https://github.com/omacom/hype' @@ -25,7 +25,8 @@ makedepends=('gcc' 'git' 'make') # Pin the source until a tagged release is available. _commit=204d22c39deaeeeda75d8c90ee011bb53053f524 source=("git+$url.git#commit=$_commit") -sha256sums=('SKIP') +# makepkg hashes git archive --format tar of the pinned commit. +sha256sums=('c99441b1494f313b3912a3098c5fab5ff339488f0ed68df15447c87aa450374f') build() { cd "$srcdir/$pkgname" From ae0e7407e340e1af4bdf8d5373f17ce855e512be Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 18 Sep 2026 21:04:53 +0200 Subject: [PATCH 060/121] Package animated-image PowerPoint export support --- pkgbuilds/hype/PKGBUILD | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 2eebb3f..44fd19c 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -2,7 +2,7 @@ pkgname=hype pkgver=0.1.0 -pkgrel=2 +pkgrel=3 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') url='https://github.com/omacom/hype' @@ -19,14 +19,15 @@ depends=( 'qt6-svg' 'source-highlight' 'zlib' + 'libwebp' 'xdg-desktop-portal' ) makedepends=('gcc' 'git' 'make') # Pin the source until a tagged release is available. -_commit=204d22c39deaeeeda75d8c90ee011bb53053f524 +_commit=f54cec61f5932f0ebb7659273b9a7de0fed64054 source=("git+$url.git#commit=$_commit") # makepkg hashes git archive --format tar of the pinned commit. -sha256sums=('c99441b1494f313b3912a3098c5fab5ff339488f0ed68df15447c87aa450374f') +sha256sums=('017d08f590bf835d94ea95a3856d6c73d64ea72f7eeb6c21d417a8bd23c990a1') build() { cd "$srcdir/$pkgname" From 9013b97fcc7c8d0a9ccbb81100757b853e817a1d Mon Sep 17 00:00:00 2001 From: Bjarne Oeverli <1419214+bjarneo@users.noreply.github.com> Date: Fri, 18 Sep 2026 21:26:58 +0200 Subject: [PATCH 061/121] Add owe, the wallpaper engine for video backgrounds The OWE engine owns desktop video backgrounds in omarchy#12429. This recipe is imported from the owe AUR package and watches the vX.Y.Z tags on omacom/owe. It builds for x86_64 and aarch64. 0.1.1 is the first release that plays the wallpaper audio track. --- pkgbuilds/owe/.omarchy/package.json | 14 ++++++++++++ pkgbuilds/owe/PKGBUILD | 34 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 pkgbuilds/owe/.omarchy/package.json create mode 100644 pkgbuilds/owe/PKGBUILD diff --git a/pkgbuilds/owe/.omarchy/package.json b/pkgbuilds/owe/.omarchy/package.json new file mode 100644 index 0000000..4f7a928 --- /dev/null +++ b/pkgbuilds/owe/.omarchy/package.json @@ -0,0 +1,14 @@ +{ + "source": "local", + "release_ring": "fast", + "upstream": { + "watch": { + "github": "omacom/owe", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "owe", + "commit": "884100f82cf2940e4c1ef50dff39a99e37e9895e" + } +} diff --git a/pkgbuilds/owe/PKGBUILD b/pkgbuilds/owe/PKGBUILD new file mode 100644 index 0000000..5f64eb9 --- /dev/null +++ b/pkgbuilds/owe/PKGBUILD @@ -0,0 +1,34 @@ +# Maintainer: owe contributors +pkgname=owe +pkgver=0.1.1 +pkgrel=1 +pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)" +arch=('x86_64' 'aarch64') +url="https://github.com/omacom/owe" +license=('MIT') +depends=('mpv' 'ffmpeg' 'wayland' 'libglvnd' 'libepoxy' 'systemd-libs' 'socat') +makedepends=('meson' 'ninja' 'gcc' 'pkgconf' 'wayland-protocols') +checkdepends=('python') +optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs' + 'libva-mesa-driver: VAAPI hardware decode on AMD GPUs') +source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") +sha256sums=('64dc47e510973983bcbe37234ce2cf72ce1abbf3265aa54d3bc1c22da3ffa8c5') + +build() { + meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr + ninja -C build +} + +check() { + meson test -C build +} + +package() { + DESTDIR="$pkgdir" ninja -C build install + install -d "$pkgdir/usr/lib/systemd/user" + sed 's|%h/.local/bin/owed|/usr/bin/owed|' "$srcdir/owe-$pkgver/systemd/owed.service" \ + >"$pkgdir/usr/lib/systemd/user/owed.service" + install -Dm755 "$srcdir/owe-$pkgver/hooks/owe-idle" "$pkgdir/usr/bin/owe-idle" + install -Dm644 "$srcdir/owe-$pkgver/hooks/theme-set.d/10-owe-sync" "$pkgdir/usr/share/owe/10-owe-sync" + install -Dm644 "$srcdir/owe-$pkgver/config/config.toml" "$pkgdir/usr/share/doc/$pkgname/config.toml.example" +} From 4fb4dafa1dacbfbcddc34e1a03a288ab4f70aa21 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 18 Sep 2026 21:29:00 +0200 Subject: [PATCH 062/121] Package 4K PowerPoint export rendering --- pkgbuilds/hype/PKGBUILD | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 44fd19c..66ce55c 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -2,7 +2,7 @@ pkgname=hype pkgver=0.1.0 -pkgrel=3 +pkgrel=4 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') url='https://github.com/omacom/hype' @@ -24,10 +24,10 @@ depends=( ) makedepends=('gcc' 'git' 'make') # Pin the source until a tagged release is available. -_commit=f54cec61f5932f0ebb7659273b9a7de0fed64054 +_commit=fc9b3baaad0d6ef357e1bd6a97c67d58e733024e source=("git+$url.git#commit=$_commit") # makepkg hashes git archive --format tar of the pinned commit. -sha256sums=('017d08f590bf835d94ea95a3856d6c73d64ea72f7eeb6c21d417a8bd23c990a1') +sha256sums=('f15ac30a3e42ebebbc9d64eac1f1fe6231a5e7366ba25c211bef5e193a912b07') build() { cd "$srcdir/$pkgname" From e751da36fd8722376055c928a506c595fb5772ed Mon Sep 17 00:00:00 2001 From: Bjarne Oeverli <1419214+bjarneo@users.noreply.github.com> Date: Fri, 18 Sep 2026 22:54:51 +0200 Subject: [PATCH 063/121] Update owe to 0.2.0 The release brings the lock feed: the daemon hands the locked session's video to the shell as shared memory frames. --- pkgbuilds/owe/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/owe/PKGBUILD b/pkgbuilds/owe/PKGBUILD index 5f64eb9..4cb2cc4 100644 --- a/pkgbuilds/owe/PKGBUILD +++ b/pkgbuilds/owe/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe -pkgver=0.1.1 +pkgver=0.2.0 pkgrel=1 pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)" arch=('x86_64' 'aarch64') @@ -12,7 +12,7 @@ checkdepends=('python') optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs' 'libva-mesa-driver: VAAPI hardware decode on AMD GPUs') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('64dc47e510973983bcbe37234ce2cf72ce1abbf3265aa54d3bc1c22da3ffa8c5') +sha256sums=('d667048b0096bbcbb508c0cedd460bf5fb669fafffdcefc432f2886e284295c8') build() { meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr From 0db615342090783aa8de8a99e12f2f9b6f3aa168 Mon Sep 17 00:00:00 2001 From: Bjarne Oeverli <1419214+bjarneo@users.noreply.github.com> Date: Fri, 18 Sep 2026 22:54:51 +0200 Subject: [PATCH 064/121] Add owe-lockfeed, the lock screen video module The lock screen draws video through Owe.LockFeed in omarchy#12429. The module maps the frame slots the OWE renderer publishes, with no media pipeline of its own. It builds from the qml-plugin directory of the owe release and installs to the Qt QML module path. --- pkgbuilds/owe-lockfeed/.omarchy/package.json | 10 ++++++++ pkgbuilds/owe-lockfeed/PKGBUILD | 24 ++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 pkgbuilds/owe-lockfeed/.omarchy/package.json create mode 100644 pkgbuilds/owe-lockfeed/PKGBUILD diff --git a/pkgbuilds/owe-lockfeed/.omarchy/package.json b/pkgbuilds/owe-lockfeed/.omarchy/package.json new file mode 100644 index 0000000..bc11813 --- /dev/null +++ b/pkgbuilds/owe-lockfeed/.omarchy/package.json @@ -0,0 +1,10 @@ +{ + "source": "local", + "release_ring": "fast", + "upstream": { + "watch": { + "github": "omacom/owe", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + } +} diff --git a/pkgbuilds/owe-lockfeed/PKGBUILD b/pkgbuilds/owe-lockfeed/PKGBUILD new file mode 100644 index 0000000..137329f --- /dev/null +++ b/pkgbuilds/owe-lockfeed/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: owe contributors +pkgname=owe-lockfeed +pkgver=0.2.0 +pkgrel=1 +pkgdesc="Lock screen video feed module for the OWE wallpaper engine" +arch=('x86_64' 'aarch64') +url="https://github.com/omacom/owe" +license=('MIT') +depends=('qt6-declarative') +makedepends=('cmake' 'qt6-declarative') +source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") +sha256sums=('d667048b0096bbcbb508c0cedd460bf5fb669fafffdcefc432f2886e284295c8') + +build() { + cmake -S "$srcdir/owe-$pkgver/qml-plugin" -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib + cmake --build build +} + +package() { + DESTDIR="$pkgdir" cmake --install build +} From da4e1b55a823ce6ebaccb48c293f94ab90335bba Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 18:07:43 -0400 Subject: [PATCH 065/121] Publish report: no PR comment on dispatch runs; append the log before commenting A workflow_dispatch runs from master's head. That commit's PR merged something unrelated, so looking the PR up by commit attached a failed elsewhen report to #515, whose merge had nothing to do with elsewhen. Dispatch runs now go to the log only. The log append also moves ahead of the PR comment so the record exists by the time anyone follows the comment to it. --- .github/workflows/publish.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2028b7a..75f236f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -277,17 +277,6 @@ jobs: "Commit " + .commit[0:7] + " · [run](" + .run + ")" ' publish-record.json > comment.md cat comment.md - - name: Comment on the merged PR - env: - GH_TOKEN: ${{ github.token }} - run: | - pr=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}/pulls" --jq '.[0].number // empty') - if [[ -n "$pr" ]]; then - gh pr comment "$pr" -R "${{ github.repository }}" --body-file comment.md - echo "commented on #$pr" - else - echo "no PR for ${{ github.sha }} (manual dispatch?); skipping PR comment" - fi - name: Append to the publish log in the bucket env: RCLONE_CONFIG_R2_TYPE: s3 @@ -305,6 +294,21 @@ jobs: ./rclone copyto publish-log.jsonl R2:omarchy-pkgs/publish-log.jsonl --s3-no-head echo "log now has $(wc -l < publish-log.jsonl) entries" + - name: Comment on the merged PR + # Only for a push: the merge commit names its PR. A dispatch runs + # from master's head, whose PR merged something else entirely, so + # commenting there would attach this run's report to the wrong PR. + if: github.event_name == 'push' + env: + GH_TOKEN: ${{ github.token }} + run: | + pr=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}/pulls" --jq '.[0].number // empty') + if [[ -n "$pr" ]]; then + gh pr comment "$pr" -R "${{ github.repository }}" --body-file comment.md + echo "commented on #$pr" + else + echo "no PR for ${{ github.sha }} (manual dispatch?); skipping PR comment" + fi result: needs: [changes, publish] if: always() From fae6eaec1bd0a06c70839bdea5fa64772906ec64 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 18:11:35 -0400 Subject: [PATCH 066/121] elsewhen: 1.0.0, the only tag upstream has The package was added pointing at v0.1.0 with a placeholder checksum, but that tag was never cut; upstream went straight to v1.0.0. The package has never built anywhere. Point at the real tag and fill the digest. The upstream watch keeps it current from here. --- pkgbuilds/elsewhen/PKGBUILD | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkgbuilds/elsewhen/PKGBUILD b/pkgbuilds/elsewhen/PKGBUILD index 703a24c..902a5e5 100644 --- a/pkgbuilds/elsewhen/PKGBUILD +++ b/pkgbuilds/elsewhen/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Spencer Bull pkgname=elsewhen -pkgver=0.1.0 +pkgver=1.0.0 pkgrel=1 pkgdesc='World clock plugin for the Omarchy shell' arch=('any') @@ -21,11 +21,7 @@ depends=( options=('!debug') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -# Fill once the v0.1.0 tag exists: -# curl -fsSL https://github.com/omacom/elsewhen/archive/refs/tags/v0.1.0.tar.gz | sha256sum -# bin/sync-upstream rewrites this array only when it moves pkgver forward, so -# the first release's digest has to be entered by hand. -sha256sums=('FILL_FROM_RELEASE_ARCHIVE') +sha256sums=('3124f0c0a19ebc1b158bcf04151cddd6c733ceeead88052186b6a54c46bee263') package() { # The packaged plugin root, scanned by the shell between its bundled From 868f2a1e18c25bccf672b0dc5843fad67e91ae5b Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 18:46:54 -0400 Subject: [PATCH 067/121] Tests: note that publish, not strict protection, guards the merged tree --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ff7ea7..ae8f470 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,9 @@ name: Tests -# PR-only. Branch protection requires PRs to be up to date with master, so -# the PR run already tested the exact tree that merges; a second run on the -# merge commit would only repeat it. Publishing on push has its own workflow. +# PR-only. Publishing on push has its own workflow and is what verifies the +# merged tree: it resolves every package against the live channel and refuses +# a filename that already exists with different bytes, so two PRs cannot land +# the same version twice. A post-merge test run would only repeat the PR's. on: pull_request: workflow_dispatch: From fbfbda4eca0b82e6105dec42989b475001e39d9a Mon Sep 17 00:00:00 2001 From: Jacob Mink <152457076+jacob-vincent-mink@users.noreply.github.com> Date: Fri, 18 Sep 2026 20:32:11 -0500 Subject: [PATCH 068/121] Package Omawake 0.0.3 and Omaspeak 0.0.3 with service-removal cleanup hooks (#503) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Package Omawake 0.0.3 and Omaspeak 0.0.2 Bump both -bin packages to the model-support roadmap delivery: Omawake 0.0.3: - W02-W05 setup/activation/cache gates audited and closed - W07 pinned catalog URL health checks and import diagnostics - W08 Moonshine Small/Medium benchmarked; both deferred (Tiny default) - W09 Spanish wake profile (multilingual Whisper Base INT8, es) - W10 connection-owned playback pauses (HoldPause) Omaspeak 0.0.2: - S09 Kokoro 82M: Kokoro-capable packaged provider (supertonic;kokoro_tts) with espeak-ng-data.bin shipped beside the executable, 54 named voices - S10 catalog URL checks, Spanish speech profile, consistent status shape - S07 streaming deferred at the current pin Upstream: omawake v0.0.3, omaspeak v0.0.2 (aarch64 + x86_64 verified on promaxgb10-d666 CUDA and local NPU installs). * omaspeak-bin: install espeak-ng-data.bin beside the packaged library * omaspeak-bin: bump to 0.0.3-rc.1 (catalog-managed eSpeak data) - The tarball no longer ships espeak-ng-data.bin: the Kokoro catalog row pins the data package as a model asset (downloaded/verified/installed into the model directory with the GGUF), so the core package ships no model data at all. - Both arch checksums taken from the v0.0.3-rc.1 SHA256SUMS.txt. * omaspeak-bin: finalize at 0.0.3 * Stop setup-created Oma services before pacman removes their binaries * Drop stale release-verification fixtures from the branch These were swept in by git add -A during the version bumps: packaged copies of old releases (0.0.1 tarballs and extracted trees, ~80 MB) belong to the local verification workflow, not to the package repo. The consolidated upstream PR should carry only the package changes, hooks and the removal regression suite. * Update removal-test fixture versions to the packaged finals * Ask systemd to reset only an Oma unit that actually failed The removal helper reset the failed state of every unit it stopped, but systemd accepts ResetFailed for a unit that is in the failed state alone. For any other state it answers that the unit is not loaded and exits non-zero, and because the helper runs under errexit while the hook aborts on failure, a healthy unit then aborted the whole transaction: (2/2) Stop and remove omaspeak user services before package removal Failed to reset failed state of unit omaspeak.service: Unit omaspeak.service not loaded. :: Could not clean up omaspeak for jacob; removal aborted. That is the ordinary case, as the packaged service ships disabled and an enabled one is commonly stopped rather than failed. Read the active state after the stop and ask for the reset only where it applies, so a failed unit still loses its failed state along with its rate and restart counters while a clean unit no longer fails the removal. A reset that a reachable manager still refuses stays fatal. Model the rule in the removal suite, where reset-failed now follows the active state the way a real manager does, and cover both outcomes: an inactive unit must not be asked for, a failed one must be reset between the stop and the disable, and a refused reset must still fail the hook. * Keep removal cleanup faithful to how systemd reads configuration Both defects from the review of e025111 sat in the shared package-remove helper, so both packages were affected the same way. An offline user's drop-in was recognised by grep '^ExecStart=', while the configuration parser throws away the whitespace around an assignment (parse_line() strips the line and both halves of the assignment). A drop-in naming a development build as ExecStart = ExecStart = /home/alice/build/omawake daemon therefore went unmatched, and the helper cleared away the generated base unit beside with its enablement links, right behind a service that was never meant to be the package's. Match an assignment the way the parser accepts one. The gate that decides whether a unit file is the generated one stays strict on purpose: only the exact generated shape is ever deleted. systemctl show-environment also prints every value the way a shell would read it, through shell_maybe_quote(SHELL_ESCAPE_POSIX), so an XDG_CONFIG_HOME with a space arrives as $'/home/alice/custom config'. The XDG_CONFIG_HOME=/* case saw neither form and kept the home's .config directory quietly, leaving the unit in the directory the manager really reads pointing at the removed binary. Decode that quoting character by character, without letting the text become shell syntax, and refuse a value that is neither a plain path nor a closed $'...' quote rather than delete what would have to be guessed at. A value that is not an absolute path stays the fallback it is in systemd itself. The fixtures now hand the helper the very text a manager prints, quoted by a mirror of that printer, and cover a quoted path with a space, an apostrophe and a backslash, an unreadable quoted value, a relative one, and each spacing of an offline override. Verified with the removal suite, 15 tests; the eight new assertions fail against the helper as it was. The other suites were not run here, as they reach for the network. pkgrel 3 -> 4 and the helper's checksum, in both recipes. Reported-by: spencerbull * Decode systemd control escapes during service removal systemctl C-escapes control bytes in show-environment output. Rejecting those valid values aborted package removal for every user, even when the affected account had no Oma service. Decode the printer’s named and octal escapes without evaluating shell syntax or stripping trailing newlines, and cover the real printer format in the fixtures. Co-Authored-By: GPT-6 XHigh --------- Co-authored-by: Spencer Bull Co-authored-by: GPT-6 XHigh --- .github/workflows/test.yml | 1 + .gitignore | 1 + pkgbuilds/omaspeak-bin/PKGBUILD | 18 +- pkgbuilds/omaspeak-bin/package-remove | 150 ++++++++ .../omaspeak-bin/remove-user-services.hook | 10 + pkgbuilds/omawake-bin/PKGBUILD | 18 +- pkgbuilds/omawake-bin/package-remove | 150 ++++++++ .../omawake-bin/remove-user-services.hook | 10 + tests/oma-service-removal.py | 347 ++++++++++++++++++ 9 files changed, 695 insertions(+), 10 deletions(-) create mode 100644 pkgbuilds/omaspeak-bin/package-remove create mode 100644 pkgbuilds/omaspeak-bin/remove-user-services.hook create mode 100644 pkgbuilds/omawake-bin/package-remove create mode 100644 pkgbuilds/omawake-bin/remove-user-services.hook create mode 100644 tests/oma-service-removal.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ae8f470..9ced3ea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,6 +42,7 @@ jobs: archlinux:base-devel bash -lc ' set -euo pipefail pacman -Syu --noconfirm git jq python libarchive + python tests/oma-service-removal.py python tests/upstream-watch.py ./bin/sync-upstream self-test ./bin/sync-rebuilds --self-test diff --git a/.gitignore b/.gitignore index 7b1f63b..65cb4ad 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ pkgbuilds/yay/yay/ # Python helpers and offline tests __pycache__/ +.release-verification/ diff --git a/pkgbuilds/omaspeak-bin/PKGBUILD b/pkgbuilds/omaspeak-bin/PKGBUILD index eb40b05..c60ac9e 100644 --- a/pkgbuilds/omaspeak-bin/PKGBUILD +++ b/pkgbuilds/omaspeak-bin/PKGBUILD @@ -2,9 +2,9 @@ pkgname=omaspeak-bin _pkgname=${pkgname%-bin} -pkgver=0.0.1 -_upstream_ver=0.0.1 -pkgrel=1 +pkgver=0.0.3 +_upstream_ver=0.0.3 +pkgrel=4 pkgdesc='Local-first text-to-speech application and daemon (pre-built binary)' arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omaspeak' @@ -27,13 +27,21 @@ conflicts=("${_pkgname}") install="${pkgname}.install" options=('!strip' '!debug') +source=('package-remove' 'remove-user-services.hook') +sha256sums=('f1b527448529b45fee2f96b4c0a19b11087377c0ac9f43842bab0d04fcfd3b9f' + '9f1a0c2f5031fcd5905de77643a8727b792e07c582c09c2ba179f0714f118b20') + source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('9e318960fb15fdf955efbb8dda9bc8eb2b9d0932a9acd9e31b85bf3492ca78ea') -sha256sums_aarch64=('8a0d7728d0b6d3f447ab7a616389fc8c54a0617f14922b33593ca60b425deb8d') +sha256sums_x86_64=('c72428bf6989582b5aa802f39e9390e4cacf26f7fbfacf76645118286c7d1ab2') +sha256sums_aarch64=('88fc4ea8c275b9d5b9d41602d32dbca77ee30de0fc7dcbc06ad0e819fd41545a') package() { + install -Dm755 "${srcdir}/package-remove" "${pkgdir}/usr/lib/${_pkgname}/package-remove" + install -Dm644 "${srcdir}/remove-user-services.hook" \ + "${pkgdir}/usr/share/libalpm/hooks/30-${_pkgname}-remove-user-services.hook" + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" diff --git a/pkgbuilds/omaspeak-bin/package-remove b/pkgbuilds/omaspeak-bin/package-remove new file mode 100644 index 0000000..1b45b95 --- /dev/null +++ b/pkgbuilds/omaspeak-bin/package-remove @@ -0,0 +1,150 @@ +#!/bin/bash +# Invoked only by the package's Remove/PreTransaction ALPM hook. +set -eu + +# systemd's configuration parser throws the whitespace around an assignment away +# (parse_line() runs both halves through strstrip()), so a drop-in written as +# ExecStart = /home/alice/build/omawake daemon +# picks the executable just as surely as the unspaced form does. +readonly execstart_assignment='^[[:space:]]*ExecStart[[:space:]]*=' + +owned_unit() { + local commands + [[ -f $1 && ! -L $1 ]] || return 1 + # Only a unit in the very shape the application generates is ever deleted; + # anything else, however it is spaced, stays somebody's own file. + commands=$(grep '^ExecStart=' "$1") || return 1 + [[ $commands != *$'\n'* ]] || return 1 + grep -Eq "^ExecStart=\"?/usr/bin/$2\"?([[:space:]]|$)" <<< "$commands" +} + +# Decode systemd's shell_maybe_quote() output, including cescape_char() escapes. +# Never evaluate manager-controlled values as shell syntax. +unquote_manager_value() { + local text=$1 decoded= character octal + if [[ $text != '$'* ]]; then + unquoted_value=$text + return 0 + fi + [[ $text == \$\'*\' ]] || return 1 + text=${text:2:${#text}-3} + while [[ -n $text ]]; do + if [[ ${text:0:1} != \\ ]]; then + decoded+=${text:0:1} + text=${text:1} + continue + fi + case ${text:1:1} in + \\ | "'") decoded+=${text:1:1} ;; + a | b | f | n | r | t | v) + printf -v character '%b' "\\${text:1:1}" + decoded+=$character + ;; + [0-3]) + octal=${text:1:3} + [[ $octal =~ ^[0-3][0-7]{2}$ && $octal != 000 ]] || return 1 + printf -v character '%b' "\\0$octal" + decoded+=$character + text=${text:4} + continue + ;; + *) return 1 ;; + esac + text=${text:2} + done + unquoted_value=$decoded +} + +remove_for_user() { + local app=$1 user_home=$2 runtime=$3 config="$2/.config" unit="$1.service" + local online=false effective path target manager_environment load_state + if [[ -S $runtime/bus || -S $runtime/systemd/private ]]; then + online=true + # Do not evaluate shell syntax from a user manager's environment. + manager_environment=$(systemctl --user show-environment) || return 1 + while IFS= read -r line; do + case $line in + XDG_CONFIG_HOME=*) + if ! unquote_manager_value "${line#XDG_CONFIG_HOME=}"; then + echo ":: Cannot tell which directory $user_home's manager reads $unit from; removal aborted." >&2 + return 1 + fi + # An XDG_CONFIG_HOME that is not an absolute path is no setting at all: + # the manager itself falls back to the home's .config directory then. + if [[ $unquoted_value == /* ]]; then config=$unquoted_value; fi + ;; + esac + done <<< "$manager_environment" + effective=$(systemctl --user show "$unit" --property=ExecStart --value) || return 1 + if [[ -n $effective && $effective != *"path=/usr/bin/$app ;"* ]]; then + echo ":: Preserving $unit for $user_home: it uses another executable." + return 0 + fi + fi + path="$config/systemd/user/$unit" + if ! $online && grep -qs "$execstart_assignment" "$path.d/"*.conf; then + echo ":: Preserving offline service with an executable override: $path." + return 0 + fi + if [[ -e $path || -L $path ]]; then + if ! owned_unit "$path" "$app"; then + echo ":: Preserving custom or masked unit $path." + return 0 + fi + fi + if $online; then + # Stop first, and fail the package transaction if stopping fails. + load_state=$(systemctl --user show "$unit" --property=LoadState --value) || return 1 + if [[ $load_state != not-found ]]; then + systemctl --user stop "$unit" || return 1 + # A unit that had failed stays failed once it is stopped, which is the one + # state systemd will reset. For every other state it answers that the unit + # is not loaded and exits non-zero, so the reset is asked for only where it + # applies: a healthy unit leaving the transaction never aborts a removal. + if [[ $(systemctl --user show "$unit" --property=ActiveState --value) == failed ]]; then + systemctl --user reset-failed "$unit" || return 1 + fi + # Disabling also removes enablement links outside the normal target. + systemctl --user disable "$unit" || return 1 + fi + fi + # Offline users have no bus. Remove only exact enablement links for this unit. + # All filesystem operations run as the owning user, never as pacman's root. + for target in "$config/systemd/user/"*.wants/"$unit" "$config/systemd/user/"*.requires/"$unit"; do + [[ -L $target ]] || continue + case $(realpath -m -- "$target") in + "$path"|"/usr/lib/systemd/user/$unit") rm -- "$target" ;; + esac + done + if owned_unit "$path" "$app"; then rm -- "$path"; fi + if $online; then systemctl --user daemon-reload || return 1; fi +} + +if [[ ${1-} == --user ]]; then + shift + case ${1-} in omawake|omaspeak) ;; *) exit 2 ;; esac + [[ $# == 3 ]] || exit 2 + remove_for_user "$@" + exit +fi + +[[ $# == 1 ]] || exit 2 +case $1 in omawake|omaspeak) ;; *) exit 2 ;; esac +app=$1 +result=0 +# Include logged-out users as well as active/lingering user managers. +accounts=$(getent passwd) || exit 1 +while IFS=: read -r account _ user_id _ _ user_home _; do + [[ $user_home == /* ]] || continue + runtime="/run/user/$user_id" + if [[ ! -d $user_home/.config/systemd/user && ! -S $runtime/bus && ! -S $runtime/systemd/private ]]; then + continue + fi + if ! runuser -u "$account" -- env -u XDG_CONFIG_HOME \ + XDG_RUNTIME_DIR="$runtime" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime/bus" \ + "$0" --user "$app" "$user_home" "$runtime"; then + echo ":: Could not clean up $app for $account; removal aborted. Stop/remove the user service and retry." >&2 + result=1 + fi +done <<< "$accounts" +exit "$result" diff --git a/pkgbuilds/omaspeak-bin/remove-user-services.hook b/pkgbuilds/omaspeak-bin/remove-user-services.hook new file mode 100644 index 0000000..f3eec8c --- /dev/null +++ b/pkgbuilds/omaspeak-bin/remove-user-services.hook @@ -0,0 +1,10 @@ +[Trigger] +Operation = Remove +Type = Package +Target = omaspeak-bin + +[Action] +Description = Stop and remove omaspeak user services before package removal +When = PreTransaction +Exec = /usr/lib/omaspeak/package-remove omaspeak +AbortOnFail diff --git a/pkgbuilds/omawake-bin/PKGBUILD b/pkgbuilds/omawake-bin/PKGBUILD index 55b3682..2ee1d54 100644 --- a/pkgbuilds/omawake-bin/PKGBUILD +++ b/pkgbuilds/omawake-bin/PKGBUILD @@ -2,9 +2,9 @@ pkgname=omawake-bin _pkgname=${pkgname%-bin} -pkgver=0.0.2 -_upstream_ver=0.0.2 -pkgrel=1 +pkgver=0.0.3 +_upstream_ver=0.0.3 +pkgrel=4 pkgdesc='Configurable local wake-word daemon (pre-built binary)' arch=('x86_64' 'aarch64') url='https://github.com/jacob-vincent-mink/omawake' @@ -27,13 +27,21 @@ conflicts=("${_pkgname}") install="${pkgname}.install" options=('!strip' '!debug') +source=('package-remove' 'remove-user-services.hook') +sha256sums=('f1b527448529b45fee2f96b4c0a19b11087377c0ac9f43842bab0d04fcfd3b9f' + 'a0bb2e9de807bdb2cc8d0076eac3c21555c910eb8baa06acfba18fea716b9014') + source_x86_64=("${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-x86_64.tar.xz") source_aarch64=("${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz::${url}/releases/download/v${_upstream_ver}/${_pkgname}-${_upstream_ver}-linux-aarch64.tar.xz") -sha256sums_x86_64=('94f0677eb497babd351cb154e9adf057e4b796efe0241d809a7f7cf84742a515') -sha256sums_aarch64=('acb359b21bbe4909b13c18a0de63f8106c6b254943074b57d8fd70af41421659') +sha256sums_x86_64=('fa374341f60760b04c9a97d76f7ad2679463f5b2b673ee6d9c1ceee97d3f0669') +sha256sums_aarch64=('384eb11872c873a33332acf51f567dc4d4e327e57563b61056e4d0aa7fe470eb') package() { + install -Dm755 "${srcdir}/package-remove" "${pkgdir}/usr/lib/${_pkgname}/package-remove" + install -Dm644 "${srcdir}/remove-user-services.hook" \ + "${pkgdir}/usr/share/libalpm/hooks/30-${_pkgname}-remove-user-services.hook" + local release_root="${srcdir}/${_pkgname}-${_upstream_ver}-linux-${CARCH}" install -Dm755 "${release_root}/${_pkgname}" "${pkgdir}/usr/bin/${_pkgname}" diff --git a/pkgbuilds/omawake-bin/package-remove b/pkgbuilds/omawake-bin/package-remove new file mode 100644 index 0000000..1b45b95 --- /dev/null +++ b/pkgbuilds/omawake-bin/package-remove @@ -0,0 +1,150 @@ +#!/bin/bash +# Invoked only by the package's Remove/PreTransaction ALPM hook. +set -eu + +# systemd's configuration parser throws the whitespace around an assignment away +# (parse_line() runs both halves through strstrip()), so a drop-in written as +# ExecStart = /home/alice/build/omawake daemon +# picks the executable just as surely as the unspaced form does. +readonly execstart_assignment='^[[:space:]]*ExecStart[[:space:]]*=' + +owned_unit() { + local commands + [[ -f $1 && ! -L $1 ]] || return 1 + # Only a unit in the very shape the application generates is ever deleted; + # anything else, however it is spaced, stays somebody's own file. + commands=$(grep '^ExecStart=' "$1") || return 1 + [[ $commands != *$'\n'* ]] || return 1 + grep -Eq "^ExecStart=\"?/usr/bin/$2\"?([[:space:]]|$)" <<< "$commands" +} + +# Decode systemd's shell_maybe_quote() output, including cescape_char() escapes. +# Never evaluate manager-controlled values as shell syntax. +unquote_manager_value() { + local text=$1 decoded= character octal + if [[ $text != '$'* ]]; then + unquoted_value=$text + return 0 + fi + [[ $text == \$\'*\' ]] || return 1 + text=${text:2:${#text}-3} + while [[ -n $text ]]; do + if [[ ${text:0:1} != \\ ]]; then + decoded+=${text:0:1} + text=${text:1} + continue + fi + case ${text:1:1} in + \\ | "'") decoded+=${text:1:1} ;; + a | b | f | n | r | t | v) + printf -v character '%b' "\\${text:1:1}" + decoded+=$character + ;; + [0-3]) + octal=${text:1:3} + [[ $octal =~ ^[0-3][0-7]{2}$ && $octal != 000 ]] || return 1 + printf -v character '%b' "\\0$octal" + decoded+=$character + text=${text:4} + continue + ;; + *) return 1 ;; + esac + text=${text:2} + done + unquoted_value=$decoded +} + +remove_for_user() { + local app=$1 user_home=$2 runtime=$3 config="$2/.config" unit="$1.service" + local online=false effective path target manager_environment load_state + if [[ -S $runtime/bus || -S $runtime/systemd/private ]]; then + online=true + # Do not evaluate shell syntax from a user manager's environment. + manager_environment=$(systemctl --user show-environment) || return 1 + while IFS= read -r line; do + case $line in + XDG_CONFIG_HOME=*) + if ! unquote_manager_value "${line#XDG_CONFIG_HOME=}"; then + echo ":: Cannot tell which directory $user_home's manager reads $unit from; removal aborted." >&2 + return 1 + fi + # An XDG_CONFIG_HOME that is not an absolute path is no setting at all: + # the manager itself falls back to the home's .config directory then. + if [[ $unquoted_value == /* ]]; then config=$unquoted_value; fi + ;; + esac + done <<< "$manager_environment" + effective=$(systemctl --user show "$unit" --property=ExecStart --value) || return 1 + if [[ -n $effective && $effective != *"path=/usr/bin/$app ;"* ]]; then + echo ":: Preserving $unit for $user_home: it uses another executable." + return 0 + fi + fi + path="$config/systemd/user/$unit" + if ! $online && grep -qs "$execstart_assignment" "$path.d/"*.conf; then + echo ":: Preserving offline service with an executable override: $path." + return 0 + fi + if [[ -e $path || -L $path ]]; then + if ! owned_unit "$path" "$app"; then + echo ":: Preserving custom or masked unit $path." + return 0 + fi + fi + if $online; then + # Stop first, and fail the package transaction if stopping fails. + load_state=$(systemctl --user show "$unit" --property=LoadState --value) || return 1 + if [[ $load_state != not-found ]]; then + systemctl --user stop "$unit" || return 1 + # A unit that had failed stays failed once it is stopped, which is the one + # state systemd will reset. For every other state it answers that the unit + # is not loaded and exits non-zero, so the reset is asked for only where it + # applies: a healthy unit leaving the transaction never aborts a removal. + if [[ $(systemctl --user show "$unit" --property=ActiveState --value) == failed ]]; then + systemctl --user reset-failed "$unit" || return 1 + fi + # Disabling also removes enablement links outside the normal target. + systemctl --user disable "$unit" || return 1 + fi + fi + # Offline users have no bus. Remove only exact enablement links for this unit. + # All filesystem operations run as the owning user, never as pacman's root. + for target in "$config/systemd/user/"*.wants/"$unit" "$config/systemd/user/"*.requires/"$unit"; do + [[ -L $target ]] || continue + case $(realpath -m -- "$target") in + "$path"|"/usr/lib/systemd/user/$unit") rm -- "$target" ;; + esac + done + if owned_unit "$path" "$app"; then rm -- "$path"; fi + if $online; then systemctl --user daemon-reload || return 1; fi +} + +if [[ ${1-} == --user ]]; then + shift + case ${1-} in omawake|omaspeak) ;; *) exit 2 ;; esac + [[ $# == 3 ]] || exit 2 + remove_for_user "$@" + exit +fi + +[[ $# == 1 ]] || exit 2 +case $1 in omawake|omaspeak) ;; *) exit 2 ;; esac +app=$1 +result=0 +# Include logged-out users as well as active/lingering user managers. +accounts=$(getent passwd) || exit 1 +while IFS=: read -r account _ user_id _ _ user_home _; do + [[ $user_home == /* ]] || continue + runtime="/run/user/$user_id" + if [[ ! -d $user_home/.config/systemd/user && ! -S $runtime/bus && ! -S $runtime/systemd/private ]]; then + continue + fi + if ! runuser -u "$account" -- env -u XDG_CONFIG_HOME \ + XDG_RUNTIME_DIR="$runtime" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime/bus" \ + "$0" --user "$app" "$user_home" "$runtime"; then + echo ":: Could not clean up $app for $account; removal aborted. Stop/remove the user service and retry." >&2 + result=1 + fi +done <<< "$accounts" +exit "$result" diff --git a/pkgbuilds/omawake-bin/remove-user-services.hook b/pkgbuilds/omawake-bin/remove-user-services.hook new file mode 100644 index 0000000..4bac03f --- /dev/null +++ b/pkgbuilds/omawake-bin/remove-user-services.hook @@ -0,0 +1,10 @@ +[Trigger] +Operation = Remove +Type = Package +Target = omawake-bin + +[Action] +Description = Stop and remove omawake user services before package removal +When = PreTransaction +Exec = /usr/lib/omawake/package-remove omawake +AbortOnFail diff --git a/tests/oma-service-removal.py b/tests/oma-service-removal.py new file mode 100644 index 0000000..5686144 --- /dev/null +++ b/tests/oma-service-removal.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python3 +"""Removal regression fixtures. No real systemd manager, user home or package is touched.""" +import os +from pathlib import Path +import socket +import subprocess +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[1] + +# Characters that make systemd's shell_maybe_quote() quote a value, a copy of +# SHELL_NEED_ESCAPE, GLOB_CHARS and the rest of SHELL_NEED_QUOTES in escape.h. +SHELL_NEED_QUOTES = '"\\`$*?[]' + "'()<>|&;!" + + +def systemd_environment_value(value): + r"""Return VALUE as ``systemctl show-environment`` would print it. + + print_variable() in systemctl-set-environment.c hands every value to + shell_maybe_quote(SHELL_ESCAPE_POSIX) quotes special values and uses + cescape_char() for control bytes. + """ + if not any(c in SHELL_NEED_QUOTES or c.isspace() or ord(c) < 0x20 or c == "\x7f" + for c in value): + return value + escapes = dict(zip("\a\b\f\n\r\t\v\\'", (r"\a", r"\b", r"\f", r"\n", r"\r", r"\t", r"\v", r"\\", r"\'"))) + return "$'" + "".join(escapes.get(c, f"\\{ord(c):03o}" if ord(c) < 0x20 or c == "\x7f" else c) + for c in value) + "'" + + +class Removal(unittest.TestCase): + def setUp(self): + self.temp = tempfile.TemporaryDirectory(prefix="oma-removal-") + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.home = self.root / "home" + self.runtime = self.root / "runtime" + self.units = self.home / ".config/systemd/user" + self.units.mkdir(parents=True) + self.runtime.mkdir() + self.bin = self.root / "bin" + self.bin.mkdir() + self.log = self.root / "calls" + self.env = dict(os.environ, PATH=f"{self.bin}:{os.environ['PATH']}", CALLS=str(self.log)) + self.executable("systemctl", '''#!/bin/bash +printf '%s\\n' "$*" >> "$CALLS" +case "$*" in + *show-environment*) [[ -z ${MANAGER_FAIL-} ]] || exit 1 + # print_variable() prints every value the way a shell would read it, so the + # fixture, not this stub, decides how the value is quoted. + echo "XDG_CONFIG_HOME=${CONFIG_HOME_RAW-${CONFIG_HOME-}}" ;; + *property=ExecStart*) echo "${EFFECTIVE-}" ;; + *property=LoadState*) echo "${LOAD_STATE-loaded}" ;; + # A unit that failed stays failed after it is stopped, and systemd refuses + # reset-failed for every other state, reporting the unit as not loaded. + *property=ActiveState*) echo "${ACTIVE_STATE-inactive}" ;; + *" reset-failed "*) [[ ${ACTIVE_STATE-inactive} == failed && -z ${RESET_FAIL-} ]] || { + printf 'Failed to reset failed state of unit: Unit is not loaded.\n' >&2; exit 1; } ;; + *" stop "*) [[ -z ${STOP_FAIL-} ]] || exit 1 ;; +esac +''') + + def executable(self, name, source): + path = self.bin / name + path.write_text(source) + path.chmod(0o755) + + def online(self): + sock = socket.socket(socket.AF_UNIX) + sock.bind(str(self.runtime / "bus")) + self.addCleanup(sock.close) + + def install(self, app, binary=None): + unit = self.units / f"{app}.service" + unit.write_text(f'[Service]\nExecStart="{binary or "/usr/bin/" + app}" --config "{self.home}/config.toml" daemon\n') + target = self.units / "graphical-session.target.wants" + target.mkdir(exist_ok=True) + link = target / unit.name + link.symlink_to(f"../{unit.name}") + return unit, link + + def run_remove(self, app): + self.log.unlink(missing_ok=True) # Every run is judged on its own calls. + return subprocess.run(["bash", str(ROOT / f"pkgbuilds/{app}-bin/package-remove"), + "--user", app, str(self.home), str(self.runtime)], + env=self.env, text=True, capture_output=True) + + def test_logged_out_users_and_data_preservation(self): + for app in ("omawake", "omaspeak"): + unit, link = self.install(app) + config = self.home / f"{app}.toml" + config.write_text("keep settings and models") + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + self.assertEqual(config.read_text(), "keep settings and models") + self.assertFalse(self.log.exists(), "offline cleanup contacted systemd") + + def test_active_unit_is_stopped_before_removing_it(self): + self.online() + for app in ("omawake", "omaspeak"): + unit, link = self.install(app) + self.env["EFFECTIVE"] = f"{{ path=/usr/bin/{app} ; argv[]=/usr/bin/{app} daemon ; }}" + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + calls = self.log.read_text().splitlines() + self.assertLess(calls.index(f"--user stop {app}.service"), calls.index(f"--user disable {app}.service")) + self.assertEqual(calls[-1], "--user daemon-reload") + + def test_failed_stop_prevents_unit_deletion_and_fails_hook(self): + self.online() + unit, link = self.install("omawake") + self.env.update(STOP_FAIL="1", EFFECTIVE="{ path=/usr/bin/omawake ; }") + result = self.run_remove("omawake") + self.assertNotEqual(result.returncode, 0) + self.assertTrue(unit.exists()) + self.assertTrue(link.is_symlink()) + self.assertNotIn("disable", self.log.read_text()) + + def test_reset_failed_is_requested_only_for_a_unit_that_failed(self): + self.online() + for app in ("omawake", "omaspeak"): + unit, link = self.install(app) + self.env["EFFECTIVE"] = f"{{ path=/usr/bin/{app} ; argv[]=/usr/bin/{app} daemon ; }}" + # A loaded unit that never failed is not failed, and asking systemd to + # reset it fails with "Unit is not loaded": that must not abort removal. + self.env["ACTIVE_STATE"] = "active" + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + calls = [call for call in self.log.read_text().splitlines() if call.startswith("--user")] + self.assertNotIn(f"--user reset-failed {app}.service", calls) + # Reading the manager's state is welcome; the only changes asked for + # are the stop, the disable and the reload that follow them. + self.assertEqual([call for call in calls + if "show-environment" not in call and "--property=" not in call], + [f"--user stop {app}.service", + f"--user disable {app}.service", "--user daemon-reload"]) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + + # A unit that failed does keep that state once stopped, and there the + # reset belongs between stopping the service and disabling the unit. + unit, link = self.install(app) + self.env["ACTIVE_STATE"] = "failed" + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + calls = self.log.read_text().splitlines() + reset = f"--user reset-failed {app}.service" + self.assertIn(reset, calls) + self.assertLess(calls.index(f"--user stop {app}.service"), calls.index(reset)) + self.assertLess(calls.index(reset), calls.index(f"--user disable {app}.service")) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + del self.env["ACTIVE_STATE"] + + def test_reset_refused_by_a_healthy_manager_still_fails_the_transaction(self): + self.online() + unit, link = self.install("omaspeak") + self.env.update(EFFECTIVE="{ path=/usr/bin/omaspeak ; }", + ACTIVE_STATE="failed", RESET_FAIL="1") + result = self.run_remove("omaspeak") + self.assertNotEqual(result.returncode, 0) + self.assertTrue(unit.exists()) + self.assertTrue(link.is_symlink()) + + def test_custom_build_and_mask_are_preserved(self): + unit, link = self.install("omawake", "/home/user/dev/omawake") + self.assertEqual(self.run_remove("omawake").returncode, 0) + self.assertTrue(unit.exists()) + self.assertTrue(link.is_symlink()) + unit.unlink() + unit.symlink_to("/dev/null") + self.assertEqual(self.run_remove("omawake").returncode, 0) + self.assertTrue(unit.is_symlink()) + self.assertFalse(self.log.exists()) + + def test_effective_override_and_missing_online_unit(self): + self.online() + unit, _ = self.install("omaspeak") + self.env["EFFECTIVE"] = "{ path=/home/user/development/omaspeak ; }" + self.assertEqual(self.run_remove("omaspeak").returncode, 0) + self.assertTrue(unit.exists()) + self.assertNotIn(" stop ", self.log.read_text()) + unit.unlink() + self.env.update(EFFECTIVE="", LOAD_STATE="not-found") + self.assertEqual(self.run_remove("omaspeak").returncode, 0) + self.assertNotIn(" stop ", self.log.read_text()) + + def test_manager_config_home_and_unavailable_manager(self): + self.online() + default = self.units + self.units = self.home / "custom-config/systemd/user" + self.units.mkdir(parents=True) + unit, link = self.install("omawake") + self.env.update(CONFIG_HOME=str(self.home / "custom-config"), MANAGER_FAIL="1") + self.assertNotEqual(self.run_remove("omawake").returncode, 0) + self.assertTrue(unit.exists()) + del self.env["MANAGER_FAIL"] + self.assertEqual(self.run_remove("omawake").returncode, 0) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + self.assertTrue(default.exists()) + + def test_root_dispatch_drops_privileges_and_propagates_failure(self): + passwd = f"fixture:x:12345:12345::{self.home}:/bin/bash" + self.executable("getent", f"#!/bin/sh\nprintf '%s\\n' '{passwd}'\n") + self.executable("runuser", '#!/bin/sh\nprintf "%s\\n" "$*" >> "$CALLS"\nexit 1\n') + result = subprocess.run(["bash", str(ROOT / "pkgbuilds/omawake-bin/package-remove"), "omawake"], env=self.env, capture_output=True) + self.assertNotEqual(result.returncode, 0) + self.assertIn("-u fixture -- env", self.log.read_text()) + self.assertIn("--user omawake", self.log.read_text()) + + def test_offline_executable_overrides_are_preserved(self): + for app in ("omawake", "omaspeak"): + for spacing in ("ExecStart=\nExecStart={command}", + # systemd's parser throws the whitespace around an + # assignment away, so both of these spellings still + # name a development build, exactly as the first does. + "ExecStart =\nExecStart = {command}", + "\tExecStart\t=\t{command}"): + unit, link = self.install(app) + dropins = Path(str(unit) + ".d") + dropins.mkdir(exist_ok=True) + (dropins / "override.conf").write_text("[Service]\n" + spacing.format( + command=f"/home/user/build/{app} daemon") + "\n") + try: + with self.subTest(app=app, spacing=spacing): + self.assertEqual(self.run_remove(app).returncode, 0) + self.assertTrue(unit.exists(), "removed a service with an override") + self.assertTrue(link.is_symlink(), "unlinked a service with an override") + finally: + unit.unlink(missing_ok=True) + link.unlink(missing_ok=True) + self.assertFalse(self.log.exists(), "offline cleanup contacted systemd") + + def test_shell_quoted_manager_config_home_is_resolved(self): + self.online() + default_units = self.units + for app in ("omawake", "omaspeak"): + config_home = self.home / f"{app} custom's \\ config" + self.units = config_home / "systemd/user" + self.units.mkdir(parents=True) + unit, link = self.install(app) + # A unit in the directory the manager reads nothing from is no unit of + # the manager's, and the helper has no business reaching for it. + stray = default_units / f"{app}.service" + stray.write_text(f'[Service]\nExecStart="/usr/bin/{app}" daemon\n') + printed = self.env["CONFIG_HOME_RAW"] = systemd_environment_value(str(config_home)) + with self.subTest(app=app, printed=printed): + self.assertTrue(printed.startswith("$'") and printed.endswith("'"), + "a path of spaces is not what a plain value looks like") + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + self.assertTrue(stray.is_file(), "guessed at a directory no manager reads") + del self.env["CONFIG_HOME_RAW"] + + def test_control_character_manager_config_home_is_resolved(self): + self.online() + for app in ("omawake", "omaspeak"): + for suffix in ("tab\tpath", "newline\npath\n", "\a\b\f\r\v", "\x01\x1b\x7f"): + config_home = self.home / (app + suffix) + self.units = config_home / "systemd/user" + self.units.mkdir(parents=True) + unit, link = self.install(app) + self.env["CONFIG_HOME_RAW"] = systemd_environment_value(str(config_home)) + with self.subTest(app=app, suffix=suffix): + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + + def test_unreadable_manager_config_home_aborts_the_cleanup(self): + self.online() + for app in ("omawake", "omaspeak"): + unit, link = self.install(app) + # Truncated output must not make cleanup guess at a directory. + self.env["CONFIG_HOME_RAW"] = "$'" + str(self.home / f"broken {app} config") + with self.subTest(app=app): + result = self.run_remove(app) + self.assertNotEqual(result.returncode, 0) + self.assertTrue(unit.exists()) + self.assertTrue(link.is_symlink()) + self.assertNotIn(" stop ", self.log.read_text()) + del self.env["CONFIG_HOME_RAW"] + + def test_relative_manager_config_home_keeps_the_default_directory(self): + self.online() + for app in ("omawake", "omaspeak"): + unit, link = self.install(app) + # An XDG_CONFIG_HOME that is not absolute is no setting at all: the + # manager itself reads the home's .config directory then. + self.env["CONFIG_HOME_RAW"] = systemd_environment_value(f"relative {app} config") + with self.subTest(app=app): + result = self.run_remove(app) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(unit.exists()) + self.assertFalse(link.is_symlink()) + del self.env["CONFIG_HOME_RAW"] + + def test_packaging_installs_hooks_and_helpers(self): + import shutil + for app, version in (("omawake", "0.0.3"), ("omaspeak", "0.0.3")): + source = self.root / app / "src" + package = self.root / app / "pkg" + release = source / f"{app}-{version}-linux-x86_64" + release.mkdir(parents=True) + for path in [app, "lib/libaudiocpp.so.0.1.0", f"packaging/systemd/{app}.service", + "README.md", "INSTALL.md", "ACCELERATOR_SETUP.md", "CHANGELOG.md", + "RELEASE_NOTES.md", "DEMO.md", "RUNTIME.md", "config.example.toml", + "licenses/LICENSE", "assets/fixture", "benchmarks/fixture"]: + target = release / path + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text("fixture") + directory = ROOT / f"pkgbuilds/{app}-bin" + for name in ("package-remove", "remove-user-services.hook"): + shutil.copyfile(directory / name, source / name) + env = dict(self.env, srcdir=str(source), pkgdir=str(package), CARCH="x86_64") + result = subprocess.run(["bash", "-c", 'source "$1"; package', "package-fixture", str(directory / "PKGBUILD")], env=env, capture_output=True, text=True) + self.assertEqual(result.returncode, 0, result.stderr) + helper = package / f"usr/lib/{app}/package-remove" + self.assertEqual(helper.read_bytes(), (directory / "package-remove").read_bytes()) + self.assertEqual(helper.stat().st_mode & 0o777, 0o755) + self.assertTrue((package / f"usr/share/libalpm/hooks/30-{app}-remove-user-services.hook").exists()) + + def test_hook_contract_and_package_release(self): + scripts = [] + for app in ("omawake", "omaspeak"): + directory = ROOT / f"pkgbuilds/{app}-bin" + hook = (directory / "remove-user-services.hook").read_text() + self.assertIn("Operation = Remove", hook) + self.assertNotIn("Operation = Upgrade", hook) + self.assertIn("When = PreTransaction", hook) + self.assertIn("AbortOnFail", hook) + self.assertIn(f"Exec = /usr/lib/{app}/package-remove {app}", hook) + self.assertIn("pkgrel=4", (directory / "PKGBUILD").read_text()) + scripts.append((directory / "package-remove").read_bytes()) + self.assertEqual(*scripts) + + +if __name__ == "__main__": + unittest.main() From 29c9561a3f668b7bf05aeb7f424c0d934a0051e8 Mon Sep 17 00:00:00 2001 From: Josh Owen Date: Thu, 10 Sep 2026 22:36:08 -0700 Subject: [PATCH 069/121] Add bambustudio-bin, Bambu Studio, to the fast ring Bambu Studio is the official slicer for Bambu Lab printers. Linux builds are GitHub AppImages with a changing timestamp in the filename, so this tracks the AUR bambustudio-bin package that already resolves those assets, and puts it on the fast ring so stable users get updates with omarchy update. Two small Omarchy patches: skip stripping the extracted AppImage, and clear the AppImage ELF magic byte so --appimage-extract works in the build container. The desktop entry is labeled Bambu Studio and grouped under Graphics. Validation: bin/add-package + bin/sync-aur reapply the patches; AUR + .omarchy reproduces the checked-in tree. Built and launched the 2.8.2.61 AppImage on Omarchy 4.0.3 (x86_64); bambu-studio --help reports BambuStudio-02.08.02.61. AUR is currently 02.08.02.60; the next AUR bump will sync through. --- .../bambustudio-bin/.omarchy/package.json | 5 +++ .../.omarchy/patches/appimage-extract.patch | 17 +++++++ .../.omarchy/patches/desktop-entry.patch | 17 +++++++ pkgbuilds/bambustudio-bin/BambuStudio.desktop | 12 +++++ pkgbuilds/bambustudio-bin/PKGBUILD | 45 +++++++++++++++++++ pkgbuilds/bambustudio-bin/bambu-studio | 2 + 6 files changed, 98 insertions(+) create mode 100644 pkgbuilds/bambustudio-bin/.omarchy/package.json create mode 100644 pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch create mode 100644 pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch create mode 100644 pkgbuilds/bambustudio-bin/BambuStudio.desktop create mode 100644 pkgbuilds/bambustudio-bin/PKGBUILD create mode 100755 pkgbuilds/bambustudio-bin/bambu-studio diff --git a/pkgbuilds/bambustudio-bin/.omarchy/package.json b/pkgbuilds/bambustudio-bin/.omarchy/package.json new file mode 100644 index 0000000..d36a6a6 --- /dev/null +++ b/pkgbuilds/bambustudio-bin/.omarchy/package.json @@ -0,0 +1,5 @@ +{ + "source": "aur", + "release_ring": "fast", + "upstream_commit": "b962c12d14873f94669e0e256a444f957b1843cd" +} diff --git a/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch b/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch new file mode 100644 index 0000000..2f1bb39 --- /dev/null +++ b/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch @@ -0,0 +1,17 @@ +--- a/PKGBUILD ++++ b/PKGBUILD +@@ -10,6 +10,7 @@ + conflicts=('bambustudio' 'bambustudio-git' 'squashfuse') + depends=('mesa' 'glu' 'cairo' 'gtk3' 'libsoup3' 'gstreamer' 'openvdb' 'wayland' 'wayland-protocols' 'libxkbcommon' 'gst-libav' 'webkit2gtk-4.1') + makedepends=('fuse2' 'patchelf') ++options=('!strip') + # Thanks so much for generating random image names Bambu, much appreciated, keeps you on your toes or something I guess... + source=("bambustudio-${pkgver}.AppImage::https://github.com/bambulab/BambuStudio/releases/download/v${pkgver}/BambuStudio_ubuntu24.04-v${pkgver/%/-20260814171356}.AppImage" + "BambuStudio.desktop" +@@ -21,4 +22,6 @@ + package() { + cd "$srcdir" + chmod +x ./bambustudio-${pkgver}.AppImage ++ # AppImage ELF interpreter can fail in build containers; clear the magic byte. ++ printf '\x00' | dd of="./bambustudio-${pkgver}.AppImage" bs=1 seek=8 conv=notrunc status=none + ./bambustudio-${pkgver}.AppImage --appimage-extract diff --git a/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch b/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch new file mode 100644 index 0000000..f16dc57 --- /dev/null +++ b/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch @@ -0,0 +1,17 @@ +--- a/BambuStudio.desktop ++++ b/BambuStudio.desktop +@@ -1,7 +1,12 @@ + [Desktop Entry] +-Name=BambuStudio ++Name=Bambu Studio ++GenericName=3D Printing Software ++Comment=Slicer for Bambu Lab and other 3D printers + Exec=/usr/bin/bambu-studio %U + Icon=BambuStudio ++Terminal=false + Type=Application +-Categories=Utility; ++Categories=Graphics;3DGraphics;Engineering; + MimeType=x-scheme-handler/bambustudio;model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; ++Keywords=3D;Printing;Slicer;gcode;stl;3mf ++StartupWMClass=bambu-studio diff --git a/pkgbuilds/bambustudio-bin/BambuStudio.desktop b/pkgbuilds/bambustudio-bin/BambuStudio.desktop new file mode 100644 index 0000000..5a8fd45 --- /dev/null +++ b/pkgbuilds/bambustudio-bin/BambuStudio.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Name=Bambu Studio +GenericName=3D Printing Software +Comment=Slicer for Bambu Lab and other 3D printers +Exec=/usr/bin/bambu-studio %U +Icon=BambuStudio +Terminal=false +Type=Application +Categories=Graphics;3DGraphics;Engineering; +MimeType=x-scheme-handler/bambustudio;model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; +Keywords=3D;Printing;Slicer;gcode;stl;3mf +StartupWMClass=bambu-studio diff --git a/pkgbuilds/bambustudio-bin/PKGBUILD b/pkgbuilds/bambustudio-bin/PKGBUILD new file mode 100644 index 0000000..21eee3d --- /dev/null +++ b/pkgbuilds/bambustudio-bin/PKGBUILD @@ -0,0 +1,45 @@ +# Maintainer: goll +# Contributor: George Woodall +pkgname=bambustudio-bin +pkgver=02.08.02.60 +pkgrel=1.1 +pkgdesc="PC Software for BambuLab's 3D printers" +arch=("x86_64") +url="https://github.com/bambulab/BambuStudio" +license=('AGPL3') +conflicts=('bambustudio' 'bambustudio-git' 'squashfuse') +depends=('mesa' 'glu' 'cairo' 'gtk3' 'libsoup3' 'gstreamer' 'openvdb' 'wayland' 'wayland-protocols' 'libxkbcommon' 'gst-libav' 'webkit2gtk-4.1') +makedepends=('fuse2' 'patchelf') +options=('!strip') +# Thanks so much for generating random image names Bambu, much appreciated, keeps you on your toes or something I guess... +source=("bambustudio-${pkgver}.AppImage::https://github.com/bambulab/BambuStudio/releases/download/v${pkgver}/BambuStudio_ubuntu24.04-v${pkgver/%/-20260814171356}.AppImage" + "BambuStudio.desktop" + "bambu-studio") +sha256sums=('b78d2527a20ee9fbcf70ee82138c3b3ca707aa9c6625881629db29627252acc3' + 'SKIP' + 'SKIP') + +package() { + cd "$srcdir" + chmod +x ./bambustudio-${pkgver}.AppImage + # AppImage ELF interpreter can fail in build containers; clear the magic byte. + printf '\x00' | dd of="./bambustudio-${pkgver}.AppImage" bs=1 seek=8 conv=notrunc status=none + ./bambustudio-${pkgver}.AppImage --appimage-extract + + cd squashfs-root + mkdir -p $pkgdir/opt/bambustudio-bin + cp -r ./usr "$pkgdir/" + cp -r ./* "$pkgdir/opt/bambustudio-bin/" + patchelf --remove-needed libOSMesa.so.8 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" + patchelf --replace-needed libwebkit2gtk-4.0.so.37 libwebkit2gtk-4.1.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" + patchelf --replace-needed libjavascriptcoregtk-4.0.so.18 libjavascriptcoregtk-4.1.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" + patchelf --replace-needed libsoup-2.4.so.1 libsoup-3.0.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" + + cd "$srcdir" + mkdir "$pkgdir/usr/bin/" + chmod +x ./bambu-studio + cp ./bambu-studio "$pkgdir/usr/bin/" + + mkdir "$pkgdir/usr/share/applications/" + cp ./BambuStudio.desktop "$pkgdir/usr/share/applications/BambuStudio.desktop" +} diff --git a/pkgbuilds/bambustudio-bin/bambu-studio b/pkgbuilds/bambustudio-bin/bambu-studio new file mode 100755 index 0000000..d1d3fb9 --- /dev/null +++ b/pkgbuilds/bambustudio-bin/bambu-studio @@ -0,0 +1,2 @@ +#!/bin/bash +exec "/opt/bambustudio-bin/AppRun" "$@" From 02f63ae1f2975aa606310f8fb26651a49be8ab9a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Sep 2026 12:17:23 +0200 Subject: [PATCH 070/121] Add omarchy-billboard-generator, the animated domain video maker Packages llstrk/omarchy-billboard-generator from its GitHub release archive: the runtime tree plus locked production npm dependencies under /usr/lib, entry-point symlinks in /usr/bin, a desktop entry whose WM class matches the Chromium app-mode window, and the fonts and provenance notices the project bundles. Chromium and ffmpeg are runtime dependencies found on PATH rather than downloaded, which is how the project itself works. The desktop entry is written from the PKGBUILD rather than shipped as a second source because sync-upstream rewrites the checksum array wholesale from the release manifest. The catalog checks pin the data directories to empty scratch paths so the build reads bundled data rather than a synced snapshot in the builder's home. Co-Authored-By: Claude Fable 5.1 Co-Authored-By: Codex XHigh --- .../.omarchy/package.json | 12 +++ .../omarchy-billboard-generator/PKGBUILD | 82 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 pkgbuilds/omarchy-billboard-generator/.omarchy/package.json create mode 100644 pkgbuilds/omarchy-billboard-generator/PKGBUILD diff --git a/pkgbuilds/omarchy-billboard-generator/.omarchy/package.json b/pkgbuilds/omarchy-billboard-generator/.omarchy/package.json new file mode 100644 index 0000000..d9c0d05 --- /dev/null +++ b/pkgbuilds/omarchy-billboard-generator/.omarchy/package.json @@ -0,0 +1,12 @@ +{ + "source": "local", + "release_ring": "fast", + "min_release_age": "24h", + "upstream": { + "github": "llstrk/omarchy-billboard-generator", + "checksums": "SHA256SUMS", + "assets": { + "any": "omarchy-billboard-generator.tar.gz" + } + } +} diff --git a/pkgbuilds/omarchy-billboard-generator/PKGBUILD b/pkgbuilds/omarchy-billboard-generator/PKGBUILD new file mode 100644 index 0000000..11e8fc7 --- /dev/null +++ b/pkgbuilds/omarchy-billboard-generator/PKGBUILD @@ -0,0 +1,82 @@ +# Maintainer: David Heinemeier Hansson + +# Upstream ships a release archive plus a SHA256SUMS manifest, which is what +# the upstream feed in .omarchy/package.json follows. Chromium and ffmpeg are +# runtime dependencies found on PATH, never downloaded. + +pkgname=omarchy-billboard-generator +pkgver=0.1.1 +pkgrel=1 +pkgdesc='Desktop app and CLI that renders animated OMARCHY domain videos' +arch=('any') +url='https://github.com/llstrk/omarchy-billboard-generator' +# MIT covers the project's own code and Apache-2.0 and 0BSD the vendored npm +# dependencies. The Omarchy wordmark, website palettes, taglines and the ttfx +# animation runtime are Omarchy's own material carried over from omarchy-site, +# and PROVENANCE.md says which file is which. +license=('MIT' 'Apache-2.0' '0BSD' 'OFL-1.1' 'LicenseRef-Omarchy') +depends=('nodejs>=22' 'chromium' 'ffmpeg' 'xdg-utils') +makedepends=('npm') +source=("${pkgname}-${pkgver}.tar.gz::${url}/releases/download/v${pkgver}/${pkgname}.tar.gz") +sha256sums=('b5edb7f975c46d29a7b492a009cf826a04dc19daf4962a7b2ae4774643555df6') +# Pure JavaScript and WebAssembly; nothing here is an ELF to strip. +options=('!strip' '!debug') + +_appdir="/usr/lib/${pkgname}" + +build() { + cd "${srcdir}/${pkgname}" + # The same install the upstream release installer performs: locked production + # dependencies, no lifecycle scripts. + npm ci --omit=dev --ignore-scripts --cache "${srcdir}/npm-cache" +} + +check() { + cd "${srcdir}/${pkgname}" + # The catalogs prefer a synced snapshot in the user data directory, so point + # them at an empty one: the build must read the bundled data, not whatever + # the builder's home happens to hold. + export BILLBOARD_DATA_DIR="${srcdir}/data-home" BILLBOARD_CACHE_DIR="${srcdir}/cache-home" + # Upstream's own startup check, plus the catalogs that load the bundled data. + node bin/omarchy-billboard --help >/dev/null + node bin/omarchy-billboard --list-themes >/dev/null + node bin/omarchy-billboard --list-languages >/dev/null + node bin/omarchy-billboard --list-animations >/dev/null + node bin/omarchy-billboard-app --help >/dev/null +} + +package() { + cd "${srcdir}/${pkgname}" + + install -dm755 "${pkgdir}${_appdir}" + # Only what runs: no tests, release scripts, CI, or the curl|bash installer. + cp -a bin src app web assets data examples node_modules package.json "${pkgdir}${_appdir}/" + + # The entry points resolve their sources through the real path of the + # script, so a symlink is enough and keeps the launcher's node on PATH. + install -dm755 "${pkgdir}/usr/bin" + ln -s "${_appdir}/bin/omarchy-billboard" "${pkgdir}/usr/bin/omarchy-billboard" + ln -s "${_appdir}/bin/omarchy-billboard-app" "${pkgdir}/usr/bin/omarchy-billboard-app" + + # Written here rather than shipped as a second source: sync-upstream rewrites + # sha256sums wholesale from the release manifest, so a local file's checksum + # would not survive the first version bump. The WM class is what Chromium + # derives for this app-mode window, so the launcher's icon follows it. + install -dm755 "${pkgdir}/usr/share/applications" + cat > "${pkgdir}/usr/share/applications/${pkgname}.desktop" <<'DESKTOP' +[Desktop Entry] +Version=1.0 +Type=Application +Name=Omarchy Billboard Generator +Comment=Create animated Omarchy domain videos locally +Exec=omarchy-billboard-app +Icon=omarchy-billboard-generator +Terminal=false +Categories=AudioVideo;Video; +StartupWMClass=chrome-127.0.0.1__omarchy-billboard-Default +DESKTOP + install -Dm644 app/icon.svg "${pkgdir}/usr/share/icons/hicolor/scalable/apps/${pkgname}.svg" + + install -Dm644 -t "${pkgdir}/usr/share/doc/${pkgname}" README.md THEMES.md PROVENANCE.md + install -Dm644 -t "${pkgdir}/usr/share/licenses/${pkgname}" LICENSE PROVENANCE.md assets/fonts/*-OFL.txt +} From 00685ab3e7606898fdbff895ff9c290716604795 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Sep 2026 15:16:42 +0200 Subject: [PATCH 071/121] Package v0.1.2, the release carrying the reviewed fixes Upstream merged the installer rollback, renderer Host check, contrast warning and playback fixes and cut v0.1.2 with them, plus a fullscreen intro that is canvas geometry only: no new dependencies, files or runtime paths. The checksum is the one its SHA256SUMS manifest publishes. Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/omarchy-billboard-generator/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/omarchy-billboard-generator/PKGBUILD b/pkgbuilds/omarchy-billboard-generator/PKGBUILD index 11e8fc7..0cce74c 100644 --- a/pkgbuilds/omarchy-billboard-generator/PKGBUILD +++ b/pkgbuilds/omarchy-billboard-generator/PKGBUILD @@ -5,7 +5,7 @@ # runtime dependencies found on PATH, never downloaded. pkgname=omarchy-billboard-generator -pkgver=0.1.1 +pkgver=0.1.2 pkgrel=1 pkgdesc='Desktop app and CLI that renders animated OMARCHY domain videos' arch=('any') @@ -18,7 +18,7 @@ license=('MIT' 'Apache-2.0' '0BSD' 'OFL-1.1' 'LicenseRef-Omarchy') depends=('nodejs>=22' 'chromium' 'ffmpeg' 'xdg-utils') makedepends=('npm') source=("${pkgname}-${pkgver}.tar.gz::${url}/releases/download/v${pkgver}/${pkgname}.tar.gz") -sha256sums=('b5edb7f975c46d29a7b492a009cf826a04dc19daf4962a7b2ae4774643555df6') +sha256sums=('e457d061f6714d4c032c980ce00aad1cb57d5753b42dc174a55c31c329a8d641') # Pure JavaScript and WebAssembly; nothing here is an ELF to strip. options=('!strip' '!debug') From b7f44e4744119676dea62dcad55a8c32071478b4 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Sat, 22 Aug 2026 15:47:31 -0500 Subject: [PATCH 072/121] Add OpenVINO GenAI runtime package --- .../openvino-genai/.omarchy/package.json | 3 + pkgbuilds/openvino-genai/PKGBUILD | 78 +++++++++++++++++++ pkgbuilds/openvino-genai/gcc-16-char8_t.patch | 7 ++ 3 files changed, 88 insertions(+) create mode 100644 pkgbuilds/openvino-genai/.omarchy/package.json create mode 100644 pkgbuilds/openvino-genai/PKGBUILD create mode 100644 pkgbuilds/openvino-genai/gcc-16-char8_t.patch diff --git a/pkgbuilds/openvino-genai/.omarchy/package.json b/pkgbuilds/openvino-genai/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/openvino-genai/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/openvino-genai/PKGBUILD b/pkgbuilds/openvino-genai/PKGBUILD new file mode 100644 index 0000000..212a977 --- /dev/null +++ b/pkgbuilds/openvino-genai/PKGBUILD @@ -0,0 +1,78 @@ +# Maintainer: Spencer Bull + +pkgname=openvino-genai +pkgver=2026.3.0.0 +pkgrel=1 +pkgdesc="OpenVINO GenAI C and C++ runtime libraries" +arch=('x86_64') +url="https://github.com/openvinotoolkit/openvino.genai" +license=('Apache-2.0') +options=('!debug' '!lto') +depends=( + 'gcc-libs' + 'glibc' + 'onetbb' + 'openvino=2026.3.0' +) +makedepends=( + 'cmake' + 'git' + 'ninja' + 'python' +) +optdepends=( + 'openvino-intel-gpu-plugin: inference on Intel GPUs' + 'openvino-intel-npu-plugin: inference on Intel NPUs' +) + +_commit=bd8d6542e3ca1ac30042d5d8d4202ce00b5f4af0 +source=( + "openvino.genai::git+$url.git#commit=$_commit" + 'gcc-16-char8_t.patch' +) +sha256sums=( + 'SKIP' + '6e685c1e45d4b2314fd55e2f791846cc9086413ba62a6bb5e31be5a5878a243c' +) + +prepare() { + cd openvino.genai + patch -Np1 -i "$srcdir/gcc-16-char8_t.patch" + git submodule update --init --recursive +} + +build() { + CFLAGS+=" -ffile-prefix-map=$srcdir=/usr/src/$pkgname" + CXXFLAGS+=" -ffile-prefix-map=$srcdir=/usr/src/$pkgname" + + cmake -S openvino.genai -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_SKIP_RPATH=ON \ + -DENABLE_JS=OFF \ + -DENABLE_MISAKI_CPP=OFF \ + -DENABLE_PYTHON=OFF \ + -DENABLE_SAMPLES=OFF \ + -DENABLE_TESTS=OFF \ + -DENABLE_TOOLS=OFF \ + -DENABLE_XGRAMMAR=OFF + + cmake --build build +} + +package() { + install -d "$pkgdir/usr/lib" "$pkgdir/usr/share/licenses/$pkgname" + + cp -a build/openvino_genai/libopenvino_genai.so* "$pkgdir/usr/lib/" + cp -a build/openvino_genai/libopenvino_tokenizers.so* "$pkgdir/usr/lib/" + cp -a build/src/c/libopenvino_genai_c.so* "$pkgdir/usr/lib/" + + install -Dm644 openvino.genai/LICENSE \ + "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 openvino.genai/third-party-programs.txt \ + "$pkgdir/usr/share/licenses/$pkgname/third-party-programs.txt" + install -Dm644 openvino.genai/thirdparty/openvino_tokenizers/LICENSE \ + "$pkgdir/usr/share/licenses/$pkgname/openvino-tokenizers-LICENSE" + install -Dm644 openvino.genai/thirdparty/openvino_tokenizers/third-party-programs.txt \ + "$pkgdir/usr/share/licenses/$pkgname/openvino-tokenizers-third-party-programs.txt" +} diff --git a/pkgbuilds/openvino-genai/gcc-16-char8_t.patch b/pkgbuilds/openvino-genai/gcc-16-char8_t.patch new file mode 100644 index 0000000..c94559d --- /dev/null +++ b/pkgbuilds/openvino-genai/gcc-16-char8_t.patch @@ -0,0 +1,7 @@ +diff --git a/src/cpp/src/whisper/word_level_timestamps.cpp b/src/cpp/src/whisper/word_level_timestamps.cpp +index 7b3da124..d1f9212f 100644 +--- a/src/cpp/src/whisper/word_level_timestamps.cpp ++++ b/src/cpp/src/whisper/word_level_timestamps.cpp +@@ -327 +327 @@ std::pair, std::vector>> split_toke +- const std::string replacement_char = u8"\uFFFD"; ++ const std::string replacement_char = "\xEF\xBF\xBD"; From 2294bfa19cbedde49c33a45eef9af538ff1b7220 Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Fri, 4 Sep 2026 11:04:09 -0500 Subject: [PATCH 073/121] Update OpenVINO GenAI for Voxtype NPU support --- pkgbuilds/openvino-genai/PKGBUILD | 6 +++--- pkgbuilds/voxtype-bin/PKGBUILD | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/openvino-genai/PKGBUILD b/pkgbuilds/openvino-genai/PKGBUILD index 212a977..1d449fb 100644 --- a/pkgbuilds/openvino-genai/PKGBUILD +++ b/pkgbuilds/openvino-genai/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Spencer Bull pkgname=openvino-genai -pkgver=2026.3.0.0 +pkgver=2026.3.1.0 pkgrel=1 pkgdesc="OpenVINO GenAI C and C++ runtime libraries" arch=('x86_64') @@ -12,7 +12,7 @@ depends=( 'gcc-libs' 'glibc' 'onetbb' - 'openvino=2026.3.0' + 'openvino=2026.3.1' ) makedepends=( 'cmake' @@ -25,7 +25,7 @@ optdepends=( 'openvino-intel-npu-plugin: inference on Intel NPUs' ) -_commit=bd8d6542e3ca1ac30042d5d8d4202ce00b5f4af0 +_commit=56d9685302da2fc5cc7c9689cfab500fd0660a02 source=( "openvino.genai::git+$url.git#commit=$_commit" 'gcc-16-char8_t.patch' diff --git a/pkgbuilds/voxtype-bin/PKGBUILD b/pkgbuilds/voxtype-bin/PKGBUILD index 5333cd2..69e5391 100644 --- a/pkgbuilds/voxtype-bin/PKGBUILD +++ b/pkgbuilds/voxtype-bin/PKGBUILD @@ -29,6 +29,8 @@ optdepends=( 'ollama: local AI summarization for meeting mode' 'gtk4-layer-shell: runtime for the GTK4 on-screen mic visualizer (voxtype-osd-gtk4)' 'quickshell: Quickshell-based OSD frontend (opt in via [osd] frontend = "quickshell")' + 'openvino-genai: OpenVINO GenAI C runtime for the OpenVINO Whisper engine (Voxtype 1.1+)' + 'openvino-intel-npu-plugin: Intel NPU acceleration for the OpenVINO Whisper engine (Voxtype 1.1+)' ) provides=('voxtype') conflicts=('voxtype') From c7799557149c387fb4b4353810864c3c0e227d9c Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Fri, 4 Sep 2026 11:37:34 -0500 Subject: [PATCH 074/121] Fix OpenVINO GenAI C runtime loading --- pkgbuilds/openvino-genai/PKGBUILD | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkgbuilds/openvino-genai/PKGBUILD b/pkgbuilds/openvino-genai/PKGBUILD index 1d449fb..bd3f5bf 100644 --- a/pkgbuilds/openvino-genai/PKGBUILD +++ b/pkgbuilds/openvino-genai/PKGBUILD @@ -2,7 +2,7 @@ pkgname=openvino-genai pkgver=2026.3.1.0 -pkgrel=1 +pkgrel=2 pkgdesc="OpenVINO GenAI C and C++ runtime libraries" arch=('x86_64') url="https://github.com/openvinotoolkit/openvino.genai" @@ -29,15 +29,20 @@ _commit=56d9685302da2fc5cc7c9689cfab500fd0660a02 source=( "openvino.genai::git+$url.git#commit=$_commit" 'gcc-16-char8_t.patch' + 'format-template-linkage.patch::https://github.com/openvinotoolkit/openvino.genai/commit/398fbc1450f7485368edf52dd82f45eba215d6c9.patch' ) sha256sums=( 'SKIP' '6e685c1e45d4b2314fd55e2f791846cc9086413ba62a6bb5e31be5a5878a243c' + '8c2a3e4bf1d33e00b780da7bec2d5e40b6fd26a4e518359d6ff7c59ca7f649e3' ) prepare() { cd openvino.genai patch -Np1 -i "$srcdir/gcc-16-char8_t.patch" + # Backport upstream 398fbc14: GCC -O3 can otherwise leave format + # unresolved in libopenvino_genai.so. + patch -Np1 -i "$srcdir/format-template-linkage.patch" git submodule update --init --recursive } @@ -60,6 +65,11 @@ build() { cmake --build build } +check() { + LD_LIBRARY_PATH="$srcdir/build/openvino_genai:$srcdir/build/src/c${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \ + python -c 'import ctypes; ctypes.CDLL("libopenvino_genai_c.so")' +} + package() { install -d "$pkgdir/usr/lib" "$pkgdir/usr/share/licenses/$pkgname" From 302430272531cfe7c9b6bb8cfd6d814af1a46b4f Mon Sep 17 00:00:00 2001 From: Jacob Mink Date: Tue, 15 Sep 2026 15:14:08 -0500 Subject: [PATCH 075/121] Ensure OpenVINO GenAI package includes both C bindings --- pkgbuilds/openvino-genai/PKGBUILD | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/openvino-genai/PKGBUILD b/pkgbuilds/openvino-genai/PKGBUILD index bd3f5bf..2340166 100644 --- a/pkgbuilds/openvino-genai/PKGBUILD +++ b/pkgbuilds/openvino-genai/PKGBUILD @@ -2,7 +2,7 @@ pkgname=openvino-genai pkgver=2026.3.1.0 -pkgrel=2 +pkgrel=3 pkgdesc="OpenVINO GenAI C and C++ runtime libraries" arch=('x86_64') url="https://github.com/openvinotoolkit/openvino.genai" @@ -12,7 +12,7 @@ depends=( 'gcc-libs' 'glibc' 'onetbb' - 'openvino=2026.3.1' + 'openvino=2026.3.1' # Includes libopenvino_c.so. ) makedepends=( 'cmake' @@ -67,7 +67,7 @@ build() { check() { LD_LIBRARY_PATH="$srcdir/build/openvino_genai:$srcdir/build/src/c${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \ - python -c 'import ctypes; ctypes.CDLL("libopenvino_genai_c.so")' + python -c 'import ctypes; ctypes.CDLL("libopenvino_c.so"); ctypes.CDLL("libopenvino_genai_c.so")' } package() { @@ -77,6 +77,13 @@ package() { cp -a build/openvino_genai/libopenvino_tokenizers.so* "$pkgdir/usr/lib/" cp -a build/src/c/libopenvino_genai_c.so* "$pkgdir/usr/lib/" + # Consumers such as omawake load the unversioned name dynamically. + # Reject a missing/empty library or a broken symlink before publishing. + if [[ ! -s "$pkgdir/usr/lib/libopenvino_genai_c.so" ]]; then + error 'Required C binding is missing or empty: libopenvino_genai_c.so' + return 1 + fi + install -Dm644 openvino.genai/LICENSE \ "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm644 openvino.genai/third-party-programs.txt \ From 7bd8f5de1c43b00b3cece5adda346165f06bb17e Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Fri, 18 Sep 2026 21:58:04 -0500 Subject: [PATCH 076/121] Ship Voxtype OpenVINO metadata in a new package release Bump pkgrel so the builder produces an artifact and installed packages receive the optional dependency metadata. Restrict the Intel/OpenVINO recommendations to x86_64, where these packages are available. Co-Authored-By: GPT-6 (Codex) Co-Authored-By: GPT-6 Astra XHigh (Codex) --- pkgbuilds/voxtype-bin/PKGBUILD | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgbuilds/voxtype-bin/PKGBUILD b/pkgbuilds/voxtype-bin/PKGBUILD index 69e5391..636de44 100644 --- a/pkgbuilds/voxtype-bin/PKGBUILD +++ b/pkgbuilds/voxtype-bin/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Peter Jackson pkgname=voxtype-bin pkgver=1.0.1 -pkgrel=1 +pkgrel=2 pkgdesc="Push-to-talk voice-to-text for Linux (pre-built binaries)" arch=('x86_64' 'aarch64') url="https://voxtype.io" @@ -29,6 +29,8 @@ optdepends=( 'ollama: local AI summarization for meeting mode' 'gtk4-layer-shell: runtime for the GTK4 on-screen mic visualizer (voxtype-osd-gtk4)' 'quickshell: Quickshell-based OSD frontend (opt in via [osd] frontend = "quickshell")' +) +optdepends_x86_64=( 'openvino-genai: OpenVINO GenAI C runtime for the OpenVINO Whisper engine (Voxtype 1.1+)' 'openvino-intel-npu-plugin: Intel NPU acceleration for the OpenVINO Whisper engine (Voxtype 1.1+)' ) From f2805a5a3909365110d1f06427fb0edffc2f0055 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Fri, 18 Sep 2026 22:45:23 -0500 Subject: [PATCH 077/121] Keep the GenAI runtime PR independent of Voxtype 1.1 Move the Voxtype optional dependency metadata and release bump to a separate draft pending upstream 1.1. The GenAI runtime package can ship independently. Co-Authored-By: GPT-6 (Codex) --- pkgbuilds/voxtype-bin/PKGBUILD | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgbuilds/voxtype-bin/PKGBUILD b/pkgbuilds/voxtype-bin/PKGBUILD index 636de44..5333cd2 100644 --- a/pkgbuilds/voxtype-bin/PKGBUILD +++ b/pkgbuilds/voxtype-bin/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Peter Jackson pkgname=voxtype-bin pkgver=1.0.1 -pkgrel=2 +pkgrel=1 pkgdesc="Push-to-talk voice-to-text for Linux (pre-built binaries)" arch=('x86_64' 'aarch64') url="https://voxtype.io" @@ -30,10 +30,6 @@ optdepends=( 'gtk4-layer-shell: runtime for the GTK4 on-screen mic visualizer (voxtype-osd-gtk4)' 'quickshell: Quickshell-based OSD frontend (opt in via [osd] frontend = "quickshell")' ) -optdepends_x86_64=( - 'openvino-genai: OpenVINO GenAI C runtime for the OpenVINO Whisper engine (Voxtype 1.1+)' - 'openvino-intel-npu-plugin: Intel NPU acceleration for the OpenVINO Whisper engine (Voxtype 1.1+)' -) provides=('voxtype') conflicts=('voxtype') backup=('etc/voxtype/config.toml') From 34257e0820db334646af96f8f739e0b8ce0e3ff7 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Fri, 18 Sep 2026 22:51:46 -0500 Subject: [PATCH 078/121] Update OpenVINO GenAI maintainer email Co-Authored-By: GPT-6 (Codex) --- pkgbuilds/openvino-genai/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgbuilds/openvino-genai/PKGBUILD b/pkgbuilds/openvino-genai/PKGBUILD index 2340166..41f52cd 100644 --- a/pkgbuilds/openvino-genai/PKGBUILD +++ b/pkgbuilds/openvino-genai/PKGBUILD @@ -1,4 +1,4 @@ -# Maintainer: Spencer Bull +# Maintainer: Spencer Bull pkgname=openvino-genai pkgver=2026.3.1.0 From 0a1ae34275fb9d1839aaa775d83ab3bc9aa11c20 Mon Sep 17 00:00:00 2001 From: Jim Martin Date: Sat, 19 Sep 2026 00:45:52 -0500 Subject: [PATCH 079/121] nvidia-utils: carry missing ARM EGL library fix --- pkgbuilds/nvidia-utils/.omarchy/package.json | 6 + pkgbuilds/nvidia-utils/LICENSE | 12 + pkgbuilds/nvidia-utils/PKGBUILD | 240 ++++++++++++++++++ pkgbuilds/nvidia-utils/README.package.md | 36 +++ .../nvidia-utils/nvidia-drm-outputclass.conf | 8 + pkgbuilds/nvidia-utils/nvidia-utils.conf | 15 ++ pkgbuilds/nvidia-utils/nvidia-utils.install | 21 ++ pkgbuilds/nvidia-utils/nvidia-utils.sysusers | 1 + pkgbuilds/nvidia-utils/nvidia.rules | 7 + .../nvidia-utils/systemd-homed-override.conf | 2 + .../systemd-suspend-override.conf | 2 + 11 files changed, 350 insertions(+) create mode 100644 pkgbuilds/nvidia-utils/.omarchy/package.json create mode 100644 pkgbuilds/nvidia-utils/LICENSE create mode 100644 pkgbuilds/nvidia-utils/PKGBUILD create mode 100644 pkgbuilds/nvidia-utils/README.package.md create mode 100644 pkgbuilds/nvidia-utils/nvidia-drm-outputclass.conf create mode 100644 pkgbuilds/nvidia-utils/nvidia-utils.conf create mode 100644 pkgbuilds/nvidia-utils/nvidia-utils.install create mode 100644 pkgbuilds/nvidia-utils/nvidia-utils.sysusers create mode 100644 pkgbuilds/nvidia-utils/nvidia.rules create mode 100644 pkgbuilds/nvidia-utils/systemd-homed-override.conf create mode 100644 pkgbuilds/nvidia-utils/systemd-suspend-override.conf diff --git a/pkgbuilds/nvidia-utils/.omarchy/package.json b/pkgbuilds/nvidia-utils/.omarchy/package.json new file mode 100644 index 0000000..7ddd330 --- /dev/null +++ b/pkgbuilds/nvidia-utils/.omarchy/package.json @@ -0,0 +1,6 @@ +{ + "source": "local", + "channels": [ + "edge" + ] +} diff --git a/pkgbuilds/nvidia-utils/LICENSE b/pkgbuilds/nvidia-utils/LICENSE new file mode 100644 index 0000000..b87c5e4 --- /dev/null +++ b/pkgbuilds/nvidia-utils/LICENSE @@ -0,0 +1,12 @@ +Copyright Arch Linux Contributors + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/pkgbuilds/nvidia-utils/PKGBUILD b/pkgbuilds/nvidia-utils/PKGBUILD new file mode 100644 index 0000000..105281e --- /dev/null +++ b/pkgbuilds/nvidia-utils/PKGBUILD @@ -0,0 +1,240 @@ +# Maintainer: Sven-Hendrik Haase +# Maintainer: Peter Jung +# Contributor: James Rayner +# Contributor: Vasiliy Stelmachenok +# Contributor: Thomas Baechler + +pkgbase=nvidia-utils +pkgname=('nvidia-utils') +pkgver=615.71.09 +pkgrel=1.1 +arch=('aarch64') +url="https://www.nvidia.com/" +license=('LicenseRef-NVIDIA-Driver-License-Agreement') +options=('!strip') +source_aarch64=("https://download.nvidia.com/XFree86/Linux-aarch64/${pkgver}/NVIDIA-Linux-aarch64-${pkgver}.run") +source=('nvidia-drm-outputclass.conf' + 'nvidia-utils.sysusers' + 'nvidia.rules' + 'systemd-homed-override.conf' + 'systemd-suspend-override.conf' + 'nvidia-utils.conf') +sha512sums=('de7116c09f282a27920a1382df84aa86f559e537664bb30689605177ce37dc5067748acf9afd66a3269a6e323461356592fdfc624c86523bf105ff8fe47d3770' + '1bcf2c6ee71686c0d32625e746ec8c0f7cf42fc63c76c3076ff2526b2661e8b9e9f76eaa2c4b213c7cc437a6f06006cc07672c4974d7f4515b2de2fd7c47a891' + '7f1457dc454144fdece5abf795744c4c948a13feb8d49c20e2a1b8b8973e86f980233b521485d73eb039c396688f287a3a5b3de8cb1fb20ed70cc62e4ba91250' + 'a0183adce78e40853edf7e6b73867e7a8ea5dabac8e8164e42781f64d5232fbe869f850ab0697c3718ebced5cde760d0e807c05da50a982071dfe1157c31d6b8' + '55def6319f6abb1a4ccd28a89cd60f1933d155c10ba775b8dfa60a2dc5696b4b472c14b252dc0891f956e70264be87c3d5d4271e929a4fc4b1a68a6902814cee' + 'a380e5faeb19293c90f613cd92bcd1cef7597ee52f79f03ffdffe5d37d2badc05b6bdb4c26a9d610868ae4c16eafd56e7d16f769e849dc0335d0d248c6235fe9') +sha512sums_aarch64=('316f90d5e0ba74db3a79a91464955240aa2c14e986653067fe902c132c771898d2866afc4e6498069b33665596e17b1b5282980936e1e6e31cabb53787e70196') + +_pkg=NVIDIA-Linux-${CARCH}-${pkgver} + +create_links() { + # create soname links + find "$pkgdir" -type f -name '*.so*' ! -path '*xorg/*' -print0 | while read -d $'\0' _lib; do + _soname=$(dirname "${_lib}")/$(readelf -d "${_lib}" | grep -Po 'SONAME.*: \[\K[^]]*' || true) + _base=$(echo ${_soname} | sed -r 's/(.*)\.so.*/\1.so/') + [[ -e "${_soname}" ]] || ln -s $(basename "${_lib}") "${_soname}" + [[ -e "${_base}" ]] || ln -s $(basename "${_soname}") "${_base}" + done +} + +prepare() { + sh ${_pkg}.run --extract-only + cd ${_pkg} + bsdtar -xf nvidia-persistenced-init.tar.bz2 + +} + +package_nvidia-utils() { + pkgdesc="NVIDIA drivers utilities" + depends=('libglvnd' 'egl-wayland' 'egl-wayland2' 'egl-gbm' 'egl-x11') + optdepends=('nvidia-settings: configuration tool' + 'xorg-server: Xorg support' + 'xorg-server-devel: nvidia-xconfig' + 'opencl-nvidia: OpenCL support') + conflicts=('nvidia-libgl') + provides=('vulkan-driver' 'opengl-driver' 'nvidia-libgl') + replaces=('nvidia-libgl') + install="${pkgname}.install" + + cd "${_pkg}" + + # Check http://us.download.nvidia.com/XFree86/Linux-x86_64/${pkgver}/README/installedcomponents.html + # for hints on what needs to be installed where. + + # X driver + install -Dm755 nvidia_drv.so "${pkgdir}/usr/lib/xorg/modules/drivers/nvidia_drv.so" + + # Wayland/GBM + mkdir -p "${pkgdir}/usr/lib/gbm" + ln -sr "${pkgdir}/usr/lib/libnvidia-allocator.so.${pkgver}" "${pkgdir}/usr/lib/gbm/nvidia-drm_gbm.so" + + # firmware + install -Dm644 -t "${pkgdir}/usr/lib/firmware/nvidia/${pkgver}/" firmware/*.bin + + # GLX extension module for X + install -Dm755 "libglxserver_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/nvidia/xorg/libglxserver_nvidia.so.${pkgver}" + # Ensure that X finds glx + ln -s "libglxserver_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/nvidia/xorg/libglxserver_nvidia.so.1" + ln -s "libglxserver_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/nvidia/xorg/libglxserver_nvidia.so" + + install -Dm755 "libGLX_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/libGLX_nvidia.so.${pkgver}" + + # OpenGL libraries + install -Dm755 "libEGL_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/libEGL_nvidia.so.${pkgver}" + install -Dm755 "libGLESv1_CM_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/libGLESv1_CM_nvidia.so.${pkgver}" + install -Dm755 "libGLESv2_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/libGLESv2_nvidia.so.${pkgver}" + install -Dm644 "10_nvidia.json" "${pkgdir}/usr/share/glvnd/egl_vendor.d/10_nvidia.json" + + # OpenGL core library + install -Dm755 "libnvidia-glcore.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-glcore.so.${pkgver}" + install -Dm755 "libnvidia-eglcore.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-eglcore.so.${pkgver}" + install -Dm755 "libnvidia-glsi.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-glsi.so.${pkgver}" + if [[ $CARCH == aarch64 ]]; then + # Required by the ARM EGL/GLX libraries. + install -Dm755 "libnvidia-rmapi-tegra.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-rmapi-tegra.so.${pkgver}" + fi + + # misc + install -Dm755 "libnvidia-api.so.1" "${pkgdir}/usr/lib/libnvidia-api.so.1" + install -Dm755 "libnvidia-fbc.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-fbc.so.${pkgver}" + install -Dm755 "libnvidia-encode.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-encode.so.${pkgver}" + install -Dm755 "libnvidia-cfg.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-cfg.so.${pkgver}" + install -Dm755 "libnvidia-ml.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-ml.so.${pkgver}" + install -Dm755 "libnvidia-fmdrv.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-fmdrv.so.${pkgver}" + install -Dm755 "libnvidia-imex.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-imex.so.${pkgver}" + install -Dm755 "libnvidia-glvkspirv.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-glvkspirv.so.${pkgver}" + install -Dm755 "libnvidia-allocator.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-allocator.so.${pkgver}" + install -Dm755 "libnvidia-gpucomp.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-gpucomp.so.${pkgver}" + + # Vulkan ICD + install -Dm644 "nvidia_icd.json" "${pkgdir}/usr/share/vulkan/icd.d/nvidia_icd.json" + install -Dm644 "nvidia_layers.json" "${pkgdir}/usr/share/vulkan/implicit_layer.d/nvidia_layers.json" + + if [[ $CARCH = x86_64 ]]; then + # VulkanSC + install -D -m755 nvidia-pcc -t "${pkgdir}/usr/bin" + install -D -m755 "libnvidia-vksc-core.so.${pkgver}" -t "${pkgdir}/usr/lib" + install -D -m644 nvidia_icd_vksc.json -t "${pkgdir}/usr/share/vulkansc/icd.d" + fi + + # VDPAU + install -Dm755 "libvdpau_nvidia.so.${pkgver}" "${pkgdir}/usr/lib/vdpau/libvdpau_nvidia.so.${pkgver}" + + # nvidia-tls library + install -Dm755 "libnvidia-tls.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-tls.so.${pkgver}" + + # CUDA + install -Dm755 "libcuda.so.${pkgver}" "${pkgdir}/usr/lib/libcuda.so.${pkgver}" + install -Dm755 "libnvcuvid.so.${pkgver}" "${pkgdir}/usr/lib/libnvcuvid.so.${pkgver}" + install -Dm755 "libcudadebugger.so.${pkgver}" "${pkgdir}/usr/lib/libcudadebugger.so.${pkgver}" + + # NVVM Compiler library loaded by the CUDA driver to do JIT link-time-optimization + install -Dm644 "libnvidia-nvvm.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-nvvm.so.${pkgver}" + install -Dm755 "libnvidia-nvvm70.so.4" "${pkgdir}/usr/lib/libnvidia-nvvm70.so.4" + + # PTX JIT Compiler (Parallel Thread Execution (PTX) is a pseudo-assembly language for CUDA) + install -Dm755 "libnvidia-ptxjitcompiler.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-ptxjitcompiler.so.${pkgver}" + + # raytracing + install -Dm755 "nvoptix.bin" "${pkgdir}/usr/share/nvidia/nvoptix.bin" + install -Dm755 "libnvoptix.so.${pkgver}" "${pkgdir}/usr/lib/libnvoptix.so.${pkgver}" + install -Dm755 "libnvidia-rtcore.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-rtcore.so.${pkgver}" + + # NGX + install -Dm755 nvidia-ngx-updater "${pkgdir}/usr/bin/nvidia-ngx-updater" + install -Dm755 "libnvidia-ngx.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-ngx.so.${pkgver}" + if [[ $CARCH = x86_64 ]]; then + install -Dm755 _nvngx.dll "${pkgdir}/usr/lib/nvidia/wine/_nvngx.dll" + install -Dm755 nvngx.dll "${pkgdir}/usr/lib/nvidia/wine/nvngx.dll" + install -Dm755 nvngx_dlssg.dll "${pkgdir}/usr/lib/nvidia/wine/nvngx_dlssg.dll" + fi + + # Optical flow + install -Dm755 "libnvidia-opticalflow.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-opticalflow.so.${pkgver}" + + if [[ $CARCH = x86_64 ]]; then + # Cryptography library wrapper + install -Dm755 "libnvidia-pkcs11.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-pkcs11.so.${pkgver}" + install -Dm755 "libnvidia-pkcs11-openssl3.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-pkcs11-openssl3.so.${pkgver}" + fi + + # Sandboxhelper + install -Dm755 "libnvidia-sandboxutils.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-sandboxutils.so.${pkgver}" + + # Present Helper + install -Dm755 "libnvidia-present.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-present.so.${pkgver}" + + # https://github.com/microsoft/TileIR + install -Dm755 "libnvidia-tileiras.so.${pkgver}" "${pkgdir}/usr/lib/libnvidia-tileiras.so.${pkgver}" + + # Debug + install -Dm755 nvidia-debugdump "${pkgdir}/usr/bin/nvidia-debugdump" + + # nvidia-xconfig + install -Dm755 nvidia-xconfig "${pkgdir}/usr/bin/nvidia-xconfig" + install -Dm644 nvidia-xconfig.1.gz "${pkgdir}/usr/share/man/man1/nvidia-xconfig.1.gz" + + # nvidia-bug-report + install -Dm755 nvidia-bug-report.sh "${pkgdir}/usr/bin/nvidia-bug-report.sh" + + # nvidia-smi + install -Dm755 nvidia-smi "${pkgdir}/usr/bin/nvidia-smi" + install -Dm644 nvidia-smi.1.gz "${pkgdir}/usr/share/man/man1/nvidia-smi.1.gz" + + # nvidia-cuda-mps + install -Dm755 nvidia-cuda-mps-server "${pkgdir}/usr/bin/nvidia-cuda-mps-server" + install -Dm755 nvidia-cuda-mps-control "${pkgdir}/usr/bin/nvidia-cuda-mps-control" + install -Dm644 nvidia-cuda-mps-control.1.gz "${pkgdir}/usr/share/man/man1/nvidia-cuda-mps-control.1.gz" + + # nvidia-modprobe + # This should be removed if nvidia fixed their uvm module! + install -Dm4755 nvidia-modprobe "${pkgdir}/usr/bin/nvidia-modprobe" + install -Dm644 nvidia-modprobe.1.gz "${pkgdir}/usr/share/man/man1/nvidia-modprobe.1.gz" + + # nvidia-persistenced + install -Dm755 nvidia-persistenced "${pkgdir}/usr/bin/nvidia-persistenced" + install -Dm644 nvidia-persistenced.1.gz "${pkgdir}/usr/share/man/man1/nvidia-persistenced.1.gz" + install -Dm644 nvidia-persistenced-init/systemd/nvidia-persistenced.service.template "${pkgdir}/usr/lib/systemd/system/nvidia-persistenced.service" + sed -i 's/__USER__/nvidia-persistenced/' "${pkgdir}/usr/lib/systemd/system/nvidia-persistenced.service" + + # application profiles + install -Dm644 "nvidia-application-profiles-${pkgver}-rc" "${pkgdir}/usr/share/nvidia/nvidia-application-profiles-${pkgver}-rc" + install -Dm644 "nvidia-application-profiles-${pkgver}-key-documentation" "${pkgdir}/usr/share/nvidia/nvidia-application-profiles-${pkgver}-key-documentation" + + install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/nvidia-utils/LICENSE" + install -Dm644 README.txt "${pkgdir}/usr/share/doc/nvidia/README" + install -Dm644 NVIDIA_Changelog "${pkgdir}/usr/share/doc/nvidia/NVIDIA_Changelog" + cp -r html "${pkgdir}/usr/share/doc/nvidia/" + ln -s nvidia "${pkgdir}/usr/share/doc/nvidia-utils" + + # new power management support + install -Dm644 systemd/system/*.service -t "${pkgdir}/usr/lib/systemd/system" + install -Dm755 systemd/system-sleep/nvidia "${pkgdir}/usr/lib/systemd/system-sleep/nvidia" + install -Dm755 systemd/nvidia-sleep.sh "${pkgdir}/usr/bin/nvidia-sleep.sh" + install -Dm755 nvidia-powerd "${pkgdir}/usr/bin/nvidia-powerd" + install -Dm644 dlsnetparams.csv "${pkgdir}/usr/share/nvidia/nvidia-powerd/dlsnetparams.csv" + install -Dm644 nvidia-dbus.conf "${pkgdir}/usr/share/dbus-1/system.d/nvidia-dbus.conf" + install -Dm644 "${srcdir}/systemd-homed-override.conf" "${pkgdir}/usr/lib/systemd/system/systemd-homed.service.d/10-nvidia-no-freeze-session.conf" + install -Dm644 "${srcdir}/systemd-suspend-override.conf" "${pkgdir}/usr/lib/systemd/system/systemd-suspend.service.d/10-nvidia-no-freeze-session.conf" + install -Dm644 "${srcdir}/systemd-suspend-override.conf" "${pkgdir}/usr/lib/systemd/system/systemd-suspend-then-hibernate.service.d/10-nvidia-no-freeze-session.conf" + install -Dm644 "${srcdir}/systemd-suspend-override.conf" "${pkgdir}/usr/lib/systemd/system/systemd-hibernate.service.d/10-nvidia-no-freeze-session.conf" + install -Dm644 "${srcdir}/systemd-suspend-override.conf" "${pkgdir}/usr/lib/systemd/system/systemd-hybrid-sleep.service.d/10-nvidia-no-freeze-session.conf" + + # distro specific files must be installed in /usr/share/X11/xorg.conf.d + install -Dm644 "${srcdir}/nvidia-drm-outputclass.conf" "${pkgdir}/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf" + + install -Dm644 "${srcdir}/nvidia-utils.sysusers" "${pkgdir}/usr/lib/sysusers.d/$pkgname.conf" + + install -Dm644 "${srcdir}/nvidia.rules" "$pkgdir"/usr/lib/udev/rules.d/60-nvidia.rules + + # Enable kernel suspend notifiers for open modules and override TemporaryFilePath + # from default /tmp to /var/tmp + install -Dm644 "${srcdir}/nvidia-utils.conf" "${pkgdir}/usr/lib/modprobe.d/nvidia-utils.conf" + + # Lists NVIDIA driver files for container runtimes like nvidia-container-toolkit + install -Dm644 sandboxutils-filelist.json "${pkgdir}/usr/share/nvidia/files.d/sandboxutils-filelist.json" + + create_links +} diff --git a/pkgbuilds/nvidia-utils/README.package.md b/pkgbuilds/nvidia-utils/README.package.md new file mode 100644 index 0000000..791d59e --- /dev/null +++ b/pkgbuilds/nvidia-utils/README.package.md @@ -0,0 +1,36 @@ +# Temporary NVIDIA ARM packaging correction + +Carries Arch Linux's `nvidia-utils` recipe at +[f9ae10b379f8b1d0832ec92bca1c12072aa123e9](https://gitlab.archlinux.org/archlinux/packaging/packages/nvidia-utils/-/commit/f9ae10b379f8b1d0832ec92bca1c12072aa123e9), +restricted to aarch64 and the nvidia-utils output. Upstream contributor credits, +packaging license and support files are retained. The OpenCL/DKMS split outputs +and their unused kernel source preparation are omitted. + +NVIDIA 615.71.09's ARM EGL/GLX libraries require +`libnvidia-rmapi-tegra.so.615.71.09`. NVIDIA includes it in its archive, but the +Arch recipe omits it. Adding that library and its generated symlink fixes +Hyprland's EGL initialization failure on DGX Spark. No rendering overrides are +installed. The correction passed package installation, normal desktop login +and reboot on a Spark running kernel 7.2.6 with NVIDIA 615.71.09. + +This recipe builds only for edge, using release 1.1 to sit above Arch's broken +release 1 and below a prospective fixed release 2. There is deliberately no +automatic NVIDIA version watcher: driver userspace must remain compatible with +the kernel package supplied by Arch Linux ARM. Check both packages before each +release; a stale overlay must not hold back a driver transition. + +## Delivery and removal + +Publishing requires an aarch64 edge build. Consumers must put `[omarchy]` +before `[extra]` in pacman.conf for unqualified installation and updates to +select this package. A higher pkgrel alone does not overcome repository order. +The tested Spark has that ordering; this PR does not change shared runtime or +installer configuration. Deployment must verify that ordering on the intended +ARM installation/update paths. This is not a claim of fresh-ISO validation. + +The upstream Arch submission is pending account approval. Once Arch Linux ARM +ships the missing library, validate that package on the Spark, remove this +recipe AND the published overlay package/database entry, and verify that normal +updates select the fixed Arch package. A higher Arch version alone does not +bypass an earlier repository's stale package. Do not use an epoch or rename the +package to prevent that transition. diff --git a/pkgbuilds/nvidia-utils/nvidia-drm-outputclass.conf b/pkgbuilds/nvidia-utils/nvidia-drm-outputclass.conf new file mode 100644 index 0000000..9c36f59 --- /dev/null +++ b/pkgbuilds/nvidia-utils/nvidia-drm-outputclass.conf @@ -0,0 +1,8 @@ +Section "OutputClass" + Identifier "nvidia" + MatchDriver "nvidia-drm" + Driver "nvidia" + Option "AllowEmptyInitialConfiguration" + ModulePath "/usr/lib/nvidia/xorg" + ModulePath "/usr/lib/xorg/modules" +EndSection diff --git a/pkgbuilds/nvidia-utils/nvidia-utils.conf b/pkgbuilds/nvidia-utils/nvidia-utils.conf new file mode 100644 index 0000000..580794a --- /dev/null +++ b/pkgbuilds/nvidia-utils/nvidia-utils.conf @@ -0,0 +1,15 @@ +# Blacklist nouveau and nova +blacklist nouveau +blacklist nova_core +blacklist nova_drm + +# Make sure that all modules are loaded after the main one. +softdep nvidia post: nvidia-uvm nvidia-drm + +# https://download.nvidia.com/XFree86/Linux-x86_64/595.45.04/README/powermanagement.html +# Enable Suspend Notifiers for faster and more modern suspend +options nvidia NVreg_UseKernelSuspendNotifiers=1 +# +# The destination should not be using tmpfs, so we prefer +# /var/tmp instead of /tmp +options nvidia NVreg_TemporaryFilePath=/var/tmp diff --git a/pkgbuilds/nvidia-utils/nvidia-utils.install b/pkgbuilds/nvidia-utils/nvidia-utils.install new file mode 100644 index 0000000..e2bb8f8 --- /dev/null +++ b/pkgbuilds/nvidia-utils/nvidia-utils.install @@ -0,0 +1,21 @@ +post_upgrade() { + # With 595+ open kernel modules, video memory preservation is handled by + # kernel suspend notifiers, making the nvidia suspend/hibernate services unnecessary. + # Disable them for users upgrading from older versions. + if (( $(vercmp $2 595.58.03-1) < 0)); then + for service in nvidia-resume nvidia-hibernate nvidia-suspend nvidia-suspend-then-hibernate; do + if systemctl is-enabled --quiet $service 2>/dev/null; then + echo "Disabling $service (no longer needed with open kernel modules)..." + systemctl disable $service + fi + done + fi +} + +pre_remove() { + for service in nvidia-resume nvidia-hibernate nvidia-suspend nvidia-suspend-then-hibernate; do + if systemctl is-enabled --quiet $service 2>/dev/null; then + systemctl disable $service + fi + done +} diff --git a/pkgbuilds/nvidia-utils/nvidia-utils.sysusers b/pkgbuilds/nvidia-utils/nvidia-utils.sysusers new file mode 100644 index 0000000..0166d15 --- /dev/null +++ b/pkgbuilds/nvidia-utils/nvidia-utils.sysusers @@ -0,0 +1 @@ +u! nvidia-persistenced 143 'NVIDIA Persistence Daemon' diff --git a/pkgbuilds/nvidia-utils/nvidia.rules b/pkgbuilds/nvidia-utils/nvidia.rules new file mode 100644 index 0000000..0ae41b2 --- /dev/null +++ b/pkgbuilds/nvidia-utils/nvidia.rules @@ -0,0 +1,7 @@ +# Device nodes are created by nvidia-modprobe, which is called by the nvidia DDX. +# In case the DDX is not started, the device nodes are never created, so call +# nvidia-modprobe in the udev rules to cover the Wayland/EGLStream and compute +# case without a started display. In the case where vfio-pci is used +# nvidia-modprobe should not be invoked. +ACTION=="add", SUBSYSTEM=="module", KERNEL=="nvidia_drm", TEST!="/dev/nvidia-uvm", \ + RUN+="/usr/bin/nvidia-modprobe -c0 -u" diff --git a/pkgbuilds/nvidia-utils/systemd-homed-override.conf b/pkgbuilds/nvidia-utils/systemd-homed-override.conf new file mode 100644 index 0000000..605d113 --- /dev/null +++ b/pkgbuilds/nvidia-utils/systemd-homed-override.conf @@ -0,0 +1,2 @@ +[Service] +Environment="SYSTEMD_HOME_LOCK_FREEZE_SESSION=false" diff --git a/pkgbuilds/nvidia-utils/systemd-suspend-override.conf b/pkgbuilds/nvidia-utils/systemd-suspend-override.conf new file mode 100644 index 0000000..2a45482 --- /dev/null +++ b/pkgbuilds/nvidia-utils/systemd-suspend-override.conf @@ -0,0 +1,2 @@ +[Service] +Environment="SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false" From 85a89659dcb70f4e90e847366f1bfad42add4cd8 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 19 Sep 2026 09:39:22 -0400 Subject: [PATCH 080/121] Update Hype to 0.2.0 (#532) --- pkgbuilds/hype/PKGBUILD | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 66ce55c..80390b6 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,8 +1,8 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.1.0 -pkgrel=4 +pkgver=0.2.0 +pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') url='https://github.com/omacom/hype' @@ -12,9 +12,9 @@ options=('!debug') depends=( 'ffmpeg' 'hicolor-icon-theme' - 'qt6-base>=6.8' - 'qt6-declarative>=6.8' - 'qt6-multimedia' + 'qt6-base>=6.9' + 'qt6-declarative>=6.9' + 'qt6-multimedia>=6.9' 'qt6-imageformats' 'qt6-svg' 'source-highlight' @@ -22,20 +22,17 @@ depends=( 'libwebp' 'xdg-desktop-portal' ) -makedepends=('gcc' 'git' 'make') -# Pin the source until a tagged release is available. -_commit=fc9b3baaad0d6ef357e1bd6a97c67d58e733024e -source=("git+$url.git#commit=$_commit") -# makepkg hashes git archive --format tar of the pinned commit. -sha256sums=('f15ac30a3e42ebebbc9d64eac1f1fe6231a5e7366ba25c211bef5e193a912b07') +makedepends=('gcc' 'make') +source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") +sha256sums=('0fd1380cfa8d2886fedd0759890ba46690186810044dee75a766ea072f75a374') build() { - cd "$srcdir/$pkgname" + cd "$srcdir/$pkgname-$pkgver" ./bin/build } package() { - cd "$srcdir/$pkgname" + cd "$srcdir/$pkgname-$pkgver" install -Dm755 build/hype "$pkgdir/usr/bin/hype" install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" From 65ad77a63dc2fb4774a8432abab4e0609c428357 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 19 Sep 2026 15:43:08 -0400 Subject: [PATCH 081/121] Update Hype to 0.3.0 (#539) --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 80390b6..850059a 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.2.0 +pkgver=0.3.0 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('0fd1380cfa8d2886fedd0759890ba46690186810044dee75a766ea072f75a374') +sha256sums=('f6b937da1f034616300e2c1ce8ef7cd70d47c5284ce4c572509b3dfd2cbcc9f3') build() { cd "$srcdir/$pkgname-$pkgver" From e2d1f4f3875e69b1af4de22a4ff69df741f0985c Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sat, 19 Sep 2026 18:40:03 -0400 Subject: [PATCH 082/121] Fix Bambu Studio packaging and track upstream releases --- .../bambustudio-bin/.omarchy/package.json | 16 ++++- .../.omarchy/patches/appimage-extract.patch | 17 ----- .../.omarchy/patches/desktop-entry.patch | 17 ----- pkgbuilds/bambustudio-bin/BambuStudio.desktop | 4 +- pkgbuilds/bambustudio-bin/PKGBUILD | 67 ++++++++++--------- 5 files changed, 51 insertions(+), 70 deletions(-) delete mode 100644 pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch delete mode 100644 pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch diff --git a/pkgbuilds/bambustudio-bin/.omarchy/package.json b/pkgbuilds/bambustudio-bin/.omarchy/package.json index d36a6a6..ffa5b62 100644 --- a/pkgbuilds/bambustudio-bin/.omarchy/package.json +++ b/pkgbuilds/bambustudio-bin/.omarchy/package.json @@ -1,5 +1,17 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "b962c12d14873f94669e0e256a444f957b1843cd" + "origin": { + "aur": "bambustudio-bin", + "commit": "b962c12d14873f94669e0e256a444f957b1843cd" + }, + "upstream": { + "watch": { + "regex": "https://api.github.com/repos/bambulab/BambuStudio/releases/latest", + "pattern": "\"name\"\\s*:\\s*\"BambuStudio_ubuntu24\\.04-v(?P[0-9]+(?:\\.[0-9]+)*)-(?P[0-9]+)\\.AppImage\"", + "variables": { + "_build": "{build}" + } + } + } } diff --git a/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch b/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch deleted file mode 100644 index 2f1bb39..0000000 --- a/pkgbuilds/bambustudio-bin/.omarchy/patches/appimage-extract.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -10,6 +10,7 @@ - conflicts=('bambustudio' 'bambustudio-git' 'squashfuse') - depends=('mesa' 'glu' 'cairo' 'gtk3' 'libsoup3' 'gstreamer' 'openvdb' 'wayland' 'wayland-protocols' 'libxkbcommon' 'gst-libav' 'webkit2gtk-4.1') - makedepends=('fuse2' 'patchelf') -+options=('!strip') - # Thanks so much for generating random image names Bambu, much appreciated, keeps you on your toes or something I guess... - source=("bambustudio-${pkgver}.AppImage::https://github.com/bambulab/BambuStudio/releases/download/v${pkgver}/BambuStudio_ubuntu24.04-v${pkgver/%/-20260814171356}.AppImage" - "BambuStudio.desktop" -@@ -21,4 +22,6 @@ - package() { - cd "$srcdir" - chmod +x ./bambustudio-${pkgver}.AppImage -+ # AppImage ELF interpreter can fail in build containers; clear the magic byte. -+ printf '\x00' | dd of="./bambustudio-${pkgver}.AppImage" bs=1 seek=8 conv=notrunc status=none - ./bambustudio-${pkgver}.AppImage --appimage-extract diff --git a/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch b/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch deleted file mode 100644 index f16dc57..0000000 --- a/pkgbuilds/bambustudio-bin/.omarchy/patches/desktop-entry.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/BambuStudio.desktop -+++ b/BambuStudio.desktop -@@ -1,7 +1,12 @@ - [Desktop Entry] --Name=BambuStudio -+Name=Bambu Studio -+GenericName=3D Printing Software -+Comment=Slicer for Bambu Lab and other 3D printers - Exec=/usr/bin/bambu-studio %U - Icon=BambuStudio -+Terminal=false - Type=Application --Categories=Utility; -+Categories=Graphics;3DGraphics;Engineering; - MimeType=x-scheme-handler/bambustudio;model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; -+Keywords=3D;Printing;Slicer;gcode;stl;3mf -+StartupWMClass=bambu-studio diff --git a/pkgbuilds/bambustudio-bin/BambuStudio.desktop b/pkgbuilds/bambustudio-bin/BambuStudio.desktop index 5a8fd45..74ab062 100644 --- a/pkgbuilds/bambustudio-bin/BambuStudio.desktop +++ b/pkgbuilds/bambustudio-bin/BambuStudio.desktop @@ -7,6 +7,6 @@ Icon=BambuStudio Terminal=false Type=Application Categories=Graphics;3DGraphics;Engineering; -MimeType=x-scheme-handler/bambustudio;model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; -Keywords=3D;Printing;Slicer;gcode;stl;3mf +MimeType=x-scheme-handler/bambustudio;x-scheme-handler/bambustudioopen;model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; +Keywords=3D;Printing;Slicer;gcode;stl;3mf; StartupWMClass=bambu-studio diff --git a/pkgbuilds/bambustudio-bin/PKGBUILD b/pkgbuilds/bambustudio-bin/PKGBUILD index 21eee3d..f1a7c64 100644 --- a/pkgbuilds/bambustudio-bin/PKGBUILD +++ b/pkgbuilds/bambustudio-bin/PKGBUILD @@ -1,45 +1,48 @@ # Maintainer: goll # Contributor: George Woodall pkgname=bambustudio-bin -pkgver=02.08.02.60 -pkgrel=1.1 +pkgver=02.08.02.61 +pkgrel=1 pkgdesc="PC Software for BambuLab's 3D printers" arch=("x86_64") url="https://github.com/bambulab/BambuStudio" -license=('AGPL3') -conflicts=('bambustudio' 'bambustudio-git' 'squashfuse') -depends=('mesa' 'glu' 'cairo' 'gtk3' 'libsoup3' 'gstreamer' 'openvdb' 'wayland' 'wayland-protocols' 'libxkbcommon' 'gst-libav' 'webkit2gtk-4.1') -makedepends=('fuse2' 'patchelf') -options=('!strip') -# Thanks so much for generating random image names Bambu, much appreciated, keeps you on your toes or something I guess... -source=("bambustudio-${pkgver}.AppImage::https://github.com/bambulab/BambuStudio/releases/download/v${pkgver}/BambuStudio_ubuntu24.04-v${pkgver/%/-20260814171356}.AppImage" +license=('AGPL-3.0-only') +conflicts=('bambustudio' 'bambustudio-git') +depends=('cairo' 'dbus' 'fontconfig' 'gcc-libs' 'glib2' 'glibc' + 'gst-libav' 'gst-plugins-base-libs' 'gstreamer' 'gtk3' 'libglvnd' + 'libx11' 'mesa' 'pango' 'wayland' 'webkit2gtk-4.1') +makedepends=('7zip') +options=('!strip' '!debug') +# The upstream watch updates the timestamp together with pkgver. +_build=20260820225108 +source=("bambustudio-${pkgver}.AppImage::https://github.com/bambulab/BambuStudio/releases/download/v${pkgver}/BambuStudio_ubuntu24.04-v${pkgver}-${_build}.AppImage" "BambuStudio.desktop" "bambu-studio") -sha256sums=('b78d2527a20ee9fbcf70ee82138c3b3ca707aa9c6625881629db29627252acc3' - 'SKIP' - 'SKIP') +noextract=("bambustudio-${pkgver}.AppImage") +sha256sums=( + 'd501b103fac5424513ec0e8d6bc145fb30719de2c7d94d7320d723740c81a7fd' + 'f10718a8b201cad64800746fe8167ccc032c545d05f7ad8caa99eb5fb975f2a1' + 'a3a5c8f6a8b287e42b93957e9602621923c766e0b6a3f10c14eca10b023b15f2' +) + +prepare() { + # Read the embedded SquashFS without executing or modifying the AppImage. + rm -rf "$srcdir/squashfs-root" + 7z x "$srcdir/bambustudio-${pkgver}.AppImage" -o"$srcdir/squashfs-root" >/dev/null +} package() { - cd "$srcdir" - chmod +x ./bambustudio-${pkgver}.AppImage - # AppImage ELF interpreter can fail in build containers; clear the magic byte. - printf '\x00' | dd of="./bambustudio-${pkgver}.AppImage" bs=1 seek=8 conv=notrunc status=none - ./bambustudio-${pkgver}.AppImage --appimage-extract + cd "$srcdir/squashfs-root" + install -Dm755 AppRun "$pkgdir/opt/$pkgname/AppRun" + cp -a bin resources "$pkgdir/opt/$pkgname/" - cd squashfs-root - mkdir -p $pkgdir/opt/bambustudio-bin - cp -r ./usr "$pkgdir/" - cp -r ./* "$pkgdir/opt/bambustudio-bin/" - patchelf --remove-needed libOSMesa.so.8 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" - patchelf --replace-needed libwebkit2gtk-4.0.so.37 libwebkit2gtk-4.1.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" - patchelf --replace-needed libjavascriptcoregtk-4.0.so.18 libjavascriptcoregtk-4.1.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" - patchelf --replace-needed libsoup-2.4.so.1 libsoup-3.0.so.0 "$pkgdir/opt/bambustudio-bin/bin/bambu-studio" + local icon size + for icon in usr/share/icons/hicolor/*/apps/BambuStudio.png; do + size="${icon#usr/share/icons/hicolor/}" + install -Dm644 "$icon" "$pkgdir/usr/share/icons/hicolor/$size" + done - cd "$srcdir" - mkdir "$pkgdir/usr/bin/" - chmod +x ./bambu-studio - cp ./bambu-studio "$pkgdir/usr/bin/" - - mkdir "$pkgdir/usr/share/applications/" - cp ./BambuStudio.desktop "$pkgdir/usr/share/applications/BambuStudio.desktop" + install -Dm755 "$srcdir/bambu-studio" "$pkgdir/usr/bin/bambu-studio" + install -Dm644 "$srcdir/BambuStudio.desktop" \ + "$pkgdir/usr/share/applications/BambuStudio.desktop" } From a1a32908c573cad3ff0c206d99ec6bba4e440d31 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Wed, 16 Sep 2026 10:05:09 -0400 Subject: [PATCH 083/121] Build hyprland-preview-share-picker with stable Rust --- pkgbuilds/hyprland-preview-share-picker/PKGBUILD | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/hyprland-preview-share-picker/PKGBUILD b/pkgbuilds/hyprland-preview-share-picker/PKGBUILD index b3d80be..0862780 100644 --- a/pkgbuilds/hyprland-preview-share-picker/PKGBUILD +++ b/pkgbuilds/hyprland-preview-share-picker/PKGBUILD @@ -2,7 +2,7 @@ pkgname="hyprland-preview-share-picker" pkgver=0.2.1 -pkgrel=1 +pkgrel=2 pkgdesc="An alternative share picker for hyprland with window and monitor previews" arch=(x86_64 aarch64) url="https://github.com/WhySoBad/hyprland-preview-share-picker" @@ -32,14 +32,14 @@ fn main() { } EOF - export RUSTUP_TOOLCHAIN=nightly + export RUSTUP_TOOLCHAIN=stable cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')" } build() { cd "$pkgname-$pkgver" - export RUSTUP_TOOLCHAIN=nightly + export RUSTUP_TOOLCHAIN=stable export CARGO_TARGET_DIR=target cargo build --frozen --release From 72e8b2b3bb61c683484dfad1b7a5761ad6b36f60 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sat, 19 Sep 2026 18:48:53 -0400 Subject: [PATCH 084/121] Add maintainers to the vouched contributors list --- .github/VOUCHED.td | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 2aec3ae..753f35a 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -11,5 +11,12 @@ # -github:username reason for denouncement # # Keep entries sorted alphabetically. +github:bjarneo +github:dhh github:f-trycua +github:HANCORE-linux +github:kwilczynski +github:ryanrhughes github:scottjones +github:spencerbull +github:tobi From 3628915c5dab671446c8df8d25ae5f7e6d38cb99 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 02:10:23 -0400 Subject: [PATCH 085/121] Make build-approved release pending PR workflows --- .github/VOUCHED.td | 5 +- .github/scripts/approve-pr-workflows.cjs | 78 ++++++++ .github/workflows/approve-pr.yml | 46 +++++ .github/workflows/build-pr.yml | 26 ++- .github/workflows/test.yml | 3 + README.md | 13 ++ tests/pr-workflow-approval.cjs | 242 +++++++++++++++++++++++ 7 files changed, 405 insertions(+), 8 deletions(-) create mode 100644 .github/scripts/approve-pr-workflows.cjs create mode 100644 .github/workflows/approve-pr.yml create mode 100644 tests/pr-workflow-approval.cjs diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 753f35a..1707f1f 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -4,7 +4,10 @@ # its author is trusted: repository collaborators are trusted automatically # and do not need listing; external contributors listed here are trusted # too. Anyone else gets the plan only, until a maintainer either adds them -# here or applies the "build-approved" label to that one PR. +# here or applies the "build-approved" label to that one PR. The label also +# releases GitHub's approval hold for that PR's build and test workflows. +# It remains effective while attached, without vouching for the author's +# other PRs. An explicit denouncement cannot be overridden by the label. # # Syntax: # github:username diff --git a/.github/scripts/approve-pr-workflows.cjs b/.github/scripts/approve-pr-workflows.cjs new file mode 100644 index 0000000..0ee32b3 --- /dev/null +++ b/.github/scripts/approve-pr-workflows.cjs @@ -0,0 +1,78 @@ +const BUILD = '.github/workflows/build-pr.yml'; +const TESTS = '.github/workflows/test.yml'; + +module.exports = async function approve({ github, context, core, vouchStatus, + sleep = ms => new Promise(resolve => setTimeout(resolve, ms)), attempts = 36 }) { + // Missing/failed vouch lookups must not become approval. Denouncements + // remain absolute, just as they are in the package build gate. + if (!['unknown', 'bot', 'collaborator', 'vouched'].includes(vouchStatus)) { + throw new Error(`Cannot approve workflows: vouch status is ${vouchStatus || 'missing'}.`); + } + + const expected = context.payload.pull_request; + const eventTime = Date.parse(expected.updated_at); + if (!Number.isFinite(eventTime)) throw new Error('Missing PR event timestamp.'); + const approved = new Set(); + let precedingBuild; + + const stillApproved = async () => { + const { data: pr } = await github.rest.pulls.get({ + ...context.repo, pull_number: expected.number, + }); + return pr.state === 'open' && pr.head.sha === expected.head.sha && + pr.labels.some(label => label.name === 'build-approved'); + }; + + // The label and PR-run events arrive independently. Wait for the build + // belonging to this event, rather than returning after approving an older + // run and leaving the new label-triggered run stuck behind GitHub's gate. + for (let attempt = 0; attempt < attempts; attempt++) { + if (attempt) await sleep(5000); + if (!await stillApproved()) { + core.info('PR closed, head changed, or build-approved removed; stopping.'); + return; + } + + const all = await github.paginate(github.rest.actions.listWorkflowRunsForRepo, { + ...context.repo, event: 'pull_request', head_sha: expected.head.sha, per_page: 100, + }); + const runs = all.filter(run => + run.event === 'pull_request' && run.head_sha === expected.head.sha && + run.head_repository?.id === expected.head.repo.id && run.head_branch === expected.head.ref && + [BUILD, TESTS].includes(run.path) && + // Fork runs awaiting approval often have no pull_requests entries. + (!run.pull_requests?.length || run.pull_requests.some(pr => pr.number === expected.number)) + ).sort((a, b) => a.id - b.id); + + const newestBuild = runs.findLast(run => run.path === BUILD); + if (!newestBuild || !(Date.parse(newestBuild.created_at) >= eventTime) || + !runs.some(run => run.path === TESTS && + (context.payload.action === 'labeled' || Date.parse(run.created_at) >= eventTime))) continue; + + if (precedingBuild) { + const { data: run } = await github.rest.actions.getWorkflowRun({ + ...context.repo, run_id: precedingBuild, + }); + // Approve older builds first, and let them acquire concurrency before + // releasing a newer build. Otherwise an older queued run could start + // last and cancel the label-triggered build that carries approval. + if (!['in_progress', 'completed'].includes(run.status) || run.conclusion === 'action_required') continue; + precedingBuild = undefined; + } + + const pending = runs.filter(run => run.conclusion === 'action_required' && !approved.has(run.id) && + // If the newest build already runs (e.g. a maintainer approved it), + // don't resurrect an obsolete hold that could cancel that newer run. + (run.path !== BUILD || run.id === newestBuild.id || newestBuild.conclusion === 'action_required')); + if (!pending.length) return; + const run = pending[0]; + // Recheck after the API reads, immediately before exercising write access. + if (!await stillApproved()) return; + await github.rest.actions.approveWorkflowRun({ ...context.repo, run_id: run.id }); + approved.add(run.id); + core.info(`Approved ${run.path} run ${run.id} for PR #${expected.number}.`); + if (run.path === BUILD) precedingBuild = run.id; + if (pending.length === 1) return; + } + throw new Error('Timed out waiting for PR workflows. Remove and reapply build-approved to retry.'); +}; diff --git a/.github/workflows/approve-pr.yml b/.github/workflows/approve-pr.yml new file mode 100644 index 0000000..996fdc9 --- /dev/null +++ b/.github/workflows/approve-pr.yml @@ -0,0 +1,46 @@ +name: Approve PR workflows + +# A pull_request workflow cannot approve itself: GitHub can hold it before +# any job starts. This workflow only runs trusted default-branch code and +# releases the ordinary, unprivileged PR workflows after build approval. +on: + pull_request_target: + types: [opened, synchronize, reopened, labeled] + +permissions: + contents: read + pull-requests: read + actions: write + +concurrency: + group: approve-pr-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + approve: + # Match build-pr.yml's events, including other labels applied while this + # PR still carries build-approved: each labeled event creates a build. + if: contains(github.event.pull_request.labels.*.name, 'build-approved') + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + # Never check out the PR head or its merge ref with this write token. + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + - id: vouch + uses: mitchellh/vouch/action/check-user@f23dbb5e745334f97414ec70463ce7301071a661 # v1 + with: + user: ${{ github.event.pull_request.user.login }} + allow-fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Approve this PR's pending build and test runs + uses: actions/github-script@v7 + env: + VOUCH_STATUS: ${{ steps.vouch.outputs.status }} + with: + script: | + const approve = require('./.github/scripts/approve-pr-workflows.cjs'); + await approve({ github, context, core, vouchStatus: process.env.VOUCH_STATUS }); diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index c80927a..764ef90 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -28,8 +28,7 @@ jobs: # collaborators, anyone in .github/VOUCHED.td (read from the default # branch, so a PR cannot vouch for itself), or a PR a maintainer has # labelled "build-approved". Everyone else gets this job's plan output - # and a passing `result`, which is enough for a maintainer to review - # before deciding to spend the compute. + # and a failing `result` until a maintainer approves the build. changes: runs-on: ubuntu-latest outputs: @@ -64,6 +63,19 @@ jobs: allow-fail: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: approval + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const { data: pr } = await github.rest.pulls.get({ + ...context.repo, pull_number: context.payload.pull_request.number, + }); + // Approving or rerunning a held run keeps its original event, + // which may predate the label. Read the current approval instead. + core.setOutput('approved', pr.state === 'open' && + pr.head.sha === context.payload.pull_request.head.sha && + pr.labels.some(label => label.name === 'build-approved')); # One matrix entry per package per architecture. Every package builds # once, against edge; the channels it ships to on merge are carried # along for information. A filename means one set of bytes. @@ -92,16 +104,17 @@ jobs: fi - id: gate env: - STATUS: ${{ steps.vouch.outputs.status || 'dispatch' }} + STATUS: ${{ github.event_name == 'workflow_dispatch' && 'dispatch' || steps.vouch.outputs.status }} AUTHOR: ${{ github.event.pull_request.user.login }} - APPROVED: ${{ contains(github.event.pull_request.labels.*.name, 'build-approved') }} + APPROVED: ${{ steps.approval.outputs.approved || 'false' }} PLANNED: ${{ steps.list.outputs.planned }} run: | case "$STATUS" in bot|collaborator|vouched|dispatch) trusted=true ;; # A denouncement is absolute: the label cannot override it. denounced) trusted=false ;; - *) trusted=$APPROVED ;; + unknown) trusted=$APPROVED ;; + *) trusted=false ;; esac echo "trusted=$trusted" >> "$GITHUB_OUTPUT" if [[ $trusted == true ]]; then @@ -176,8 +189,7 @@ jobs: steps: - run: | echo "trusted=${{ needs.changes.outputs.trusted }} build=${{ needs.build.result }}" - # An untrusted author's PR is held, not failed: the required check - # stays pending until a maintainer vouches or labels it. + # An untrusted author's PR fails until a maintainer vouches or labels it. if [[ "${{ needs.changes.outputs.trusted }}" != "true" ]]; then echo "::error::Builds were not run: author is not vouched. Add to .github/VOUCHED.td or apply the 'build-approved' label." exit 1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ced3ea..acf3704 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,9 @@ jobs: with: persist-credentials: false + - name: Test PR workflow approval + run: node --test tests/pr-workflow-approval.cjs + # An Arch container for vercmp: version ordering has to be decided by # the same comparator pacman uses on users' machines. - name: Run self-tests diff --git a/README.md b/README.md index 5ff0edc..24168ba 100644 --- a/README.md +++ b/README.md @@ -844,6 +844,19 @@ The repository includes GitHub workflows and systemd services for automated rele 1. **sync-upstream.yml** (Every 6 hours): Watches direct upstream feeds and updates owned recipes. Successful package updates reach a PR even if another feed fails; failed recipes stay untouched and the workflow remains red. 2. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR. +To approve builds for an unvouched contributor's PR, apply **`build-approved`**. +This triggers a package build and automatically releases GitHub's pending +build and test workflows for that PR's current commit. The approval workflow +runs only trusted default-branch code; package builds and tests stay in the +ordinary PR workflows. It may take a few minutes for GitHub to register and +release all the runs. + +The label stays effective for that PR while attached, including later commits; +it does not vouch for the author's other PRs. Removing it stops further label +approvals, but does not cancel runs already released. An explicit denouncement +in `.github/VOUCHED.td` still blocks builds. If the approval workflow times out, +remove and reapply the label to retry. + #### Systemd Services All four units run **every 5 minutes**, staggered by a minute each, so a push diff --git a/tests/pr-workflow-approval.cjs b/tests/pr-workflow-approval.cjs new file mode 100644 index 0000000..d2b74f8 --- /dev/null +++ b/tests/pr-workflow-approval.cjs @@ -0,0 +1,242 @@ +const assert = require('node:assert/strict'); +const { readFileSync } = require('node:fs'); +const { join } = require('node:path'); +const { test } = require('node:test'); +const { execFileSync } = require('node:child_process'); +const approve = require('../.github/scripts/approve-pr-workflows.cjs'); + +const BUILD = '.github/workflows/build-pr.yml'; +const TESTS = '.github/workflows/test.yml'; +const time = '2026-09-19T02:47:52Z'; +const earlier = '2026-09-19T02:36:04Z'; +const pr = { + number: 390, state: 'open', updated_at: time, + head: { sha: 'reviewed-sha', ref: 'ghost', repo: { id: 42 } }, + labels: [{ name: 'build-approved' }], +}; +const clone = value => structuredClone(value); +const run = (id, path, overrides = {}) => ({ + id, path, event: 'pull_request', head_sha: pr.head.sha, + head_repository: { id: 42 }, head_branch: 'ghost', pull_requests: [], + status: 'completed', conclusion: 'action_required', created_at: time, + ...overrides, +}); + +function fixture(initial = [run(1, TESTS, { created_at: earlier }), run(2, BUILD)], options = {}) { + const state = { pr: clone(pr), runs: clone(initial), approved: [], reads: 0, tick: 0, transitions: [] }; + const repo = { owner: 'omacom', repo: 'omarchy-pkgs' }; + const github = { + rest: { + pulls: { get: async args => { + assert.deepEqual(args, { ...repo, pull_number: 390 }); + state.reads++; + options.onRead?.(state); + return { data: clone(state.pr) }; + } }, + actions: { + listWorkflowRunsForRepo() {}, + getWorkflowRun: async ({ run_id }) => { + const current = state.runs.find(run => run.id === run_id); + state.transitions.push([run_id, current.status]); + return { data: clone(current) }; + }, + approveWorkflowRun: async args => { + assert.deepEqual(args, { ...repo, run_id: args.run_id }); + options.onApprove?.(state, args.run_id); + const current = state.runs.find(run => run.id === args.run_id); + assert.equal(current.conclusion, 'action_required'); + state.approved.push(current.id); + current.status = 'queued'; + current.conclusion = null; + }, + }, + }, + paginate: async (method, args) => { + assert.equal(method, github.rest.actions.listWorkflowRunsForRepo); + assert.deepEqual(args, { ...repo, event: 'pull_request', head_sha: pr.head.sha, per_page: 100 }); + return clone(state.runs).reverse(); // GitHub returns newest first. + }, + }; + const invoke = overrides => approve({ + github, context: { repo, payload: { action: 'labeled', pull_request: clone(pr) } }, + core: { info() {} }, vouchStatus: 'unknown', attempts: 6, + sleep: async () => { + state.tick++; + for (const current of state.runs) { + if (current.status === 'queued' && state.tick >= (options.queueUntil ?? 1)) current.status = 'in_progress'; + } + options.onSleep?.(state); + }, + ...overrides, + }); + return { state, invoke, github }; +} + +test('an unvouched, labeled fork PR releases both required workflows', async () => { + const { state, invoke } = fixture(); + await invoke(); + assert.deepEqual(state.approved, [1, 2]); +}); + +test('waits for the label-triggered build instead of stopping at the old build', async () => { + const { state, invoke } = fixture([ + run(1, BUILD, { created_at: earlier }), run(2, TESTS, { created_at: earlier }), + ], { + onSleep(state) { + if (state.tick === 2) { + assert.deepEqual(state.approved, []); + state.runs.push(run(3, BUILD)); + } + }, + queueUntil: 4, + onApprove(state, id) { + if (id === 3) assert.equal(state.runs.find(run => run.id === 1).status, 'in_progress'); + }, + }); + await invoke({ attempts: 10 }); + assert.deepEqual(state.approved, [1, 2, 3]); + assert.ok(state.transitions.some(([id, status]) => id === 1 && status === 'queued')); +}); + +test('approves only the two known workflows for this fork, branch, PR and SHA', async () => { + const unrelated = [ + { path: '.github/workflows/publish.yml' }, { event: 'push' }, + { head_sha: 'other-sha' }, { head_repository: { id: 99 } }, + { head_branch: 'other-branch' }, { pull_requests: [{ number: 391 }] }, + ].map((overrides, i) => run(10 + i, BUILD, overrides)); + const { state, invoke } = fixture([run(1, TESTS), run(2, BUILD), ...unrelated]); + await invoke(); + assert.deepEqual(state.approved, [1, 2]); +}); + +test('accepts a run explicitly associated with this PR', async () => { + const { state, invoke } = fixture([ + run(1, TESTS), run(2, BUILD, { pull_requests: [{ number: 390 }] }), + ]); + await invoke(); + assert.deepEqual(state.approved, [1, 2]); +}); + +test('does not restart running or completed workflows', async () => { + const { state, invoke } = fixture([ + run(1, TESTS, { conclusion: 'success' }), + run(2, BUILD, { status: 'in_progress', conclusion: null }), + ]); + await invoke(); + assert.deepEqual(state.approved, []); +}); + +test('an obsolete build hold cannot cancel a newer build that was already released', async () => { + for (const current of [ + { status: 'queued', conclusion: null }, { status: 'in_progress', conclusion: null }, + { status: 'completed', conclusion: 'success' }, { status: 'completed', conclusion: 'failure' }, + ]) { + const { state, invoke } = fixture([ + run(1, BUILD, { created_at: earlier }), run(2, TESTS), run(3, BUILD, current), + ]); + await invoke(); + assert.deepEqual(state.approved, [2]); + } +}); + +for (const status of ['denounced', '', undefined, 'unexpected']) { + test(`vouch status ${String(status)} fails closed`, async () => { + const { state, invoke } = fixture(); + await assert.rejects(invoke({ vouchStatus: status }), /Cannot approve workflows/); + assert.deepEqual(state.approved, []); + }); +} + +for (const status of ['bot', 'collaborator', 'vouched']) { + test(`a labeled ${status} can also clear GitHub's approval gate`, async () => { + const { state, invoke } = fixture(); + await invoke({ vouchStatus: status }); + assert.deepEqual(state.approved, [1, 2]); + }); +} + +for (const [name, change] of [ + ['removed label', pr => { pr.labels = []; }], + ['changed head', pr => { pr.head.sha = 'new-sha'; }], + ['closed PR', pr => { pr.state = 'closed'; }], +]) { + test(`${name} stops approval, including changes immediately before a write`, async () => { + for (const read of [1, 2]) { + const { state, invoke } = fixture(undefined, { onRead(state) { + if (state.reads === read) change(state.pr); + } }); + await invoke(); + assert.deepEqual(state.approved, []); + } + }); +} + +test('revocation between approvals prevents releasing further workflows', async () => { + const { state, invoke } = fixture(undefined, { onSleep(state) { state.pr.labels = []; } }); + await invoke(); + assert.deepEqual(state.approved, [1]); +}); + +test('a delayed tests workflow is also awaited', async () => { + const { state, invoke } = fixture([run(2, BUILD)], { + onSleep(state) { if (state.tick === 2) state.runs.push(run(1, TESTS)); }, + }); + await invoke(); + assert.deepEqual(state.approved, [1, 2]); +}); + +test('reopening a labeled PR waits for its new tests, even if old tests passed at the same SHA', async () => { + const { state, invoke } = fixture([ + run(1, TESTS, { created_at: earlier, conclusion: 'success' }), run(2, BUILD), + ], { onSleep(state) { if (state.tick === 2) state.runs.push(run(3, TESTS)); } }); + await invoke({ context: { repo: { owner: 'omacom', repo: 'omarchy-pkgs' }, + payload: { action: 'reopened', pull_request: clone(pr) } } }); + assert.deepEqual(state.approved, [2, 3]); +}); + +test('missing current runs time out without approving stale builds', async () => { + const { state, invoke } = fixture([run(1, TESTS), run(2, BUILD, { created_at: earlier })]); + await assert.rejects(invoke(), /Timed out/); + assert.deepEqual(state.approved, []); +}); + +test('API failure is reported rather than silently treated as approval', async () => { + const { state, invoke } = fixture(undefined, { onApprove() { throw new Error('Forbidden'); } }); + await assert.rejects(invoke(), /Forbidden/); + assert.deepEqual(state.approved, []); +}); + +// Execute the actual build workflow's approval script and shell gate. This +// covers the stale event payload that originally accompanied held PR runs. +const workflow = readFileSync(join(__dirname, '../.github/workflows/build-pr.yml'), 'utf8'); +const approvalScript = workflow.match(/- id: approval[\s\S]*?script: \|\n([\s\S]*?)(?= # One matrix)/)[1] + .split('\n').map(line => line.replace(/^ /, '')).join('\n'); +const gateScript = workflow.match(/ case "\$STATUS" in[\s\S]*? esac/)[0] + '\nprintf "%s" "$trusted"'; + +test('the build reads the live label rather than its pre-label event payload', async () => { + const execute = new (Object.getPrototypeOf(async function () {}).constructor)('github', 'context', 'core', approvalScript); + for (const [current, approved] of [ + [pr, true], [{ ...pr, labels: [] }, false], + [{ ...pr, head: { ...pr.head, sha: 'new-sha' } }, false], + [{ ...pr, state: 'closed' }, false], + ]) { + const outputs = {}; + await execute({ rest: { pulls: { get: async () => ({ data: current }) } } }, + { repo: {}, payload: { pull_request: { ...pr, labels: [] } } }, + { setOutput: (key, value) => { outputs[key] = value; } }); + assert.equal(outputs.approved, approved); + } +}); + +test('the build gate permits a missing vouch only with approval, never a denouncement or lookup failure', () => { + for (const [status, approved, expected] of [ + ['unknown', 'true', 'true'], ['unknown', 'false', 'false'], + ['denounced', 'true', 'false'], ['', 'true', 'false'], ['unexpected', 'true', 'false'], + ['vouched', 'false', 'true'], ['collaborator', 'false', 'true'], + ['bot', 'false', 'true'], ['dispatch', 'false', 'true'], + ]) { + assert.equal(execFileSync('bash', ['-c', gateScript], { + env: { ...process.env, STATUS: status, APPROVED: approved }, encoding: 'utf8', + }), expected); + } +}); From 158133f15adb3cd03e843385bed6003af0a82d8d Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 02:31:44 -0400 Subject: [PATCH 086/121] Keep unapproved PR builds pending instead of failing --- .github/workflows/build-pr.yml | 33 ++++++++++----- README.md | 7 +++- tests/pr-workflow-approval.cjs | 76 +++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 764ef90..7adbfcc 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -7,9 +7,9 @@ name: Build changed packages # Tooling runs from the base branch; a PR supplies only pkgbuilds/. The # vouch gate limits who may spend compute; this limits what their PR can run. -# No paths filter: `result` is the required status check, so it has to be -# reported on every PR. A PR that touches no package directory gets an empty -# matrix and a passing result in seconds. +# No paths filter: approved PRs must report the required `result` even when +# no package directory changed. Those PRs get an empty matrix and a passing +# result in seconds; unapproved PRs wait for maintainer approval. on: pull_request: types: [opened, synchronize, reopened, labeled] @@ -28,13 +28,14 @@ jobs: # collaborators, anyone in .github/VOUCHED.td (read from the default # branch, so a PR cannot vouch for itself), or a PR a maintainer has # labelled "build-approved". Everyone else gets this job's plan output - # and a failing `result` until a maintainer approves the build. + # while the required `result` stays pending until a maintainer approves. changes: runs-on: ubuntu-latest outputs: matrix: ${{ steps.list.outputs.matrix }} count: ${{ steps.gate.outputs.count }} trusted: ${{ steps.gate.outputs.trusted }} + vouch_status: ${{ steps.vouch.outputs.status }} empty: ${{ steps.list.outputs.empty }} steps: # Same rule as the build job: bin/build-matrix comes from base, the @@ -178,20 +179,21 @@ jobs: if-no-files-found: error retention-days: 7 - # The one required status check. Matrix job names carry the package name, so - # they cannot be listed in branch protection; this job's name is stable and - # it fails if any package failed. It also runs (and passes) when no package - # changed, so tooling-only PRs are not stuck waiting for a status. + # `result` is required by branch protection. An unvouched author awaiting + # approval gets a differently named informational check, leaving `result` + # unreported (pending). Skipping or passing a job named `result` would count + # as satisfying the requirement even though no build was authorized. + # Actual planning/build failures and denouncements still report `result`. result: + name: ${{ needs.changes.result == 'success' && needs.changes.outputs.trusted == 'false' && needs.changes.outputs.vouch_status == 'unknown' && needs.changes.outputs.empty == 'false' && 'Awaiting build approval' || 'result' }} needs: [changes, build] if: always() runs-on: ubuntu-latest steps: - run: | echo "trusted=${{ needs.changes.outputs.trusted }} build=${{ needs.build.result }}" - # An untrusted author's PR fails until a maintainer vouches or labels it. - if [[ "${{ needs.changes.outputs.trusted }}" != "true" ]]; then - echo "::error::Builds were not run: author is not vouched. Add to .github/VOUCHED.td or apply the 'build-approved' label." + if [[ "${{ needs.changes.result }}" != "success" ]]; then + echo "::error::Build planning or the trust check failed. See the changes job." exit 1 fi # Nothing to merge: the PR's diff against its base is empty. Its @@ -200,4 +202,13 @@ jobs: echo "::error::This PR changes no files relative to its base. Its content is already on the target branch; close it instead of merging." exit 1 fi + if [[ "${{ needs.changes.outputs.trusted }}" == "false" && "${{ needs.changes.outputs.vouch_status }}" == "unknown" && "${{ needs.changes.outputs.empty }}" == "false" ]]; then + echo "::notice::Awaiting maintainer build approval. Apply 'build-approved' to this PR or vouch for the author in .github/VOUCHED.td." + echo "Package builds are waiting for maintainer approval. Apply **build-approved** to this PR to start them. The required **result** check remains pending." >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + if [[ "${{ needs.changes.outputs.trusted }}" != "true" ]]; then + echo "::error::Builds are blocked: the author is denounced or the trust result is invalid. The build-approved label cannot override this." + exit 1 + fi [[ "${{ needs.build.result }}" == "success" || "${{ needs.build.result }}" == "skipped" ]] diff --git a/README.md b/README.md index 24168ba..c29aae8 100644 --- a/README.md +++ b/README.md @@ -845,8 +845,11 @@ The repository includes GitHub workflows and systemd services for automated rele 2. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR. To approve builds for an unvouched contributor's PR, apply **`build-approved`**. -This triggers a package build and automatically releases GitHub's pending -build and test workflows for that PR's current commit. The approval workflow +Until approval, the PR shows **Awaiting build approval** and its required +`result` check stays pending, keeping the PR blocked from merging without +reporting a failed build. Actual build failures and denouncements still fail. +Applying the label triggers a package build and automatically releases GitHub's +pending build and test workflows for that PR's current commit. The approval workflow runs only trusted default-branch code; package builds and tests stay in the ordinary PR workflows. It may take a few minutes for GitHub to register and release all the runs. diff --git a/tests/pr-workflow-approval.cjs b/tests/pr-workflow-approval.cjs index d2b74f8..e4fc661 100644 --- a/tests/pr-workflow-approval.cjs +++ b/tests/pr-workflow-approval.cjs @@ -1,8 +1,9 @@ const assert = require('node:assert/strict'); -const { readFileSync } = require('node:fs'); +const { readFileSync, mkdtempSync, rmSync } = require('node:fs'); const { join } = require('node:path'); +const { tmpdir } = require('node:os'); const { test } = require('node:test'); -const { execFileSync } = require('node:child_process'); +const { execFileSync, spawnSync } = require('node:child_process'); const approve = require('../.github/scripts/approve-pr-workflows.cjs'); const BUILD = '.github/workflows/build-pr.yml'; @@ -240,3 +241,74 @@ test('the build gate permits a missing vouch only with approval, never a denounc }), expected); } }); + +// Exercise the actual reporting job, including its GitHub check name: a +// successful/skipped check called "result" would accidentally allow merging +// a PR whose build never ran. GitHub keeps a missing required check pending. +const resultJob = workflow.slice(workflow.indexOf('\n result:\n')); +const resultName = resultJob.match(/^ name: (.+)$/m)[1]; +const resultScript = resultJob.split(' - run: |\n')[1]; +function report({ trusted = 'false', vouch = 'unknown', empty = 'false', changes = 'success', build = 'skipped' } = {}) { + const needs = { + changes: { result: changes, outputs: { trusted, vouch_status: vouch, empty } }, + build: { result: build }, + }; + // The reporting expressions use &&, || and string equality, with the + // same semantics in JavaScript and Actions for these string-only fixtures. + const render = text => text.replace(/\$\{\{(.*?)\}\}/g, (_, expression) => + new Function('needs', `return (${expression})`)(needs)); + const directory = mkdtempSync(join(tmpdir(), 'build-approval-report-')); + const summaryPath = join(directory, 'summary'); + try { + const result = spawnSync('bash', ['-e', '-c', render(resultScript)], { + env: { ...process.env, GITHUB_STEP_SUMMARY: summaryPath }, encoding: 'utf8', + }); + return { name: render(resultName), ...result, + summary: result.stdout.includes('::notice::') ? readFileSync(summaryPath, 'utf8') : '' }; + } finally { + rmSync(directory, { recursive: true, force: true }); + } +} + +test('an unvouched PR waits without publishing a passing or failing required result', () => { + const result = report(); + assert.equal(result.name, 'Awaiting build approval'); + assert.equal(result.status, 0); + assert.match(result.stdout, /::notice::Awaiting maintainer build approval/); + assert.doesNotMatch(result.stdout, /::error::/); + assert.match(result.summary, /required \*\*result\*\* check remains pending/); +}); + +test('applying build-approved transitions the waiting PR to the required build result', () => { + assert.notEqual(report().name, 'result'); + const approved = report({ trusted: 'true', build: 'success' }); + assert.equal(approved.name, 'result'); + assert.equal(approved.status, 0); + const failed = report({ trusted: 'true', build: 'failure' }); + assert.equal(failed.name, 'result'); + assert.notEqual(failed.status, 0); +}); + +test('trusted tooling-only PRs still satisfy the required result without a package build', () => { + const result = report({ trusted: 'true', vouch: 'vouched' }); + assert.equal(result.name, 'result'); + assert.equal(result.status, 0); +}); + +for (const [name, overrides] of [ + ['denounced author', { vouch: 'denounced' }], + ['failed trust lookup', { vouch: '', changes: 'failure' }], + ['missing trust result', { vouch: '' }], + ['missing gate output', { trusted: '' }], + ['failed planning', { changes: 'failure' }], + ['cancelled planning', { changes: 'cancelled' }], + ['empty PR', { empty: 'true' }], + ['cancelled build', { trusted: 'true', build: 'cancelled' }], +]) { + test(`${name} fails the required result instead of masquerading as pending approval`, () => { + const result = report(overrides); + assert.equal(result.name, 'result'); + assert.notEqual(result.status, 0); + assert.doesNotMatch(result.stdout, /::notice::Awaiting maintainer build approval/); + }); +} From 2e01fabfd6dfb0b44d37621661dd4a78118bcd17 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 13:45:17 -0400 Subject: [PATCH 087/121] Fix Elsewhen shell plugin install path --- pkgbuilds/elsewhen/.omarchy/README.md | 4 ++-- pkgbuilds/elsewhen/PKGBUILD | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgbuilds/elsewhen/.omarchy/README.md b/pkgbuilds/elsewhen/.omarchy/README.md index 21b3341..9195490 100644 --- a/pkgbuilds/elsewhen/.omarchy/README.md +++ b/pkgbuilds/elsewhen/.omarchy/README.md @@ -1,12 +1,12 @@ # elsewhen -Installs the Elsewhen world clock plugin from the `v{pkgver}` GitHub tag archive into `/usr/share/omarchy/plugins/omacom.elsewhen/` (the directory name is the plugin id the shell scans for, not the package name), plus `LICENSE` under `/usr/share/licenses/elsewhen/` and the upstream `README.md` under `/usr/share/doc/elsewhen/`. That directory is the packaged plugin root that omarchy PR [#12051](https://github.com/omacom/omarchy/pull/12051) teaches the shell to scan between its bundled plugins and `~/.config/omarchy/plugins`; on an Omarchy without it the package installs cleanly and the shell never looks, so it must ship alongside that change. `depends` carries no version floor for `omarchy` because no release carries #12051 yet; add one once it does. +Installs the Elsewhen world clock plugin from the `v{pkgver}` GitHub tag archive into `/usr/share/omarchy/shell/plugins/omacom.elsewhen/` (the directory name is the plugin id the shell scans for, not the package name), plus `LICENSE` under `/usr/share/licenses/elsewhen/` and the upstream `README.md` under `/usr/share/doc/elsewhen/`. The shell scans this directory alongside its bundled plugins. `package()` copies an explicit allow-list (`manifest.json`, every `*.qml` and `*.js`, `cities.json`, `world.json`, `worldclock-data.py`), so `tests/`, `.github/` and `.gitignore` never ship, and it fails the build if `manifest.json` is missing, does not declare `omacom.elsewhen`, or does not name a present `Panel.qml` as the entry point. An upstream release that adds a runtime file outside those patterns needs the allow-list extended here; the sync only moves versions and checksums. Every file is 0644: `Panel.qml` runs the script as `python3 /worldclock-data.py`, so it needs no execute bit. No install hook: Omarchy restarts the shell after `omarchy update`, and nothing here may write into a user home. The script's only writes go to `$XDG_CACHE_HOME/omacom-elsewhen/`, which it creates itself at runtime. Dependencies, cited as `file: tool` in the upstream tree: -- `omarchy`: `ArcText.qml`, `Chip.qml`, `EarthRow.qml`, `Globe.qml`, `MiniGlobe.qml`, `MoonDot.qml`, `Panel.qml: import qs.Commons`; `EarthRow.qml`, `Globe.qml`, `Panel.qml: import qs.Ui`. Owns `/usr/share/omarchy` and the packaged plugin root the shell scans. +- `omarchy`: `ArcText.qml`, `Chip.qml`, `EarthRow.qml`, `Globe.qml`, `MiniGlobe.qml`, `MoonDot.qml`, `Panel.qml: import qs.Commons`; `EarthRow.qml`, `Globe.qml`, `Panel.qml: import qs.Ui`. Owns `/usr/share/omarchy` and the shell plugin directory. - `quickshell`: `Globe.qml`, `Panel.qml: import Quickshell`; `Globe.qml`, `MiniGlobe.qml`, `Panel.qml: import Quickshell.Io` (`Process`, `FileView`, `StdioCollector`). - `python`: `Panel.qml: python3 /worldclock-data.py` (the facts process). `worldclock-data.py` imports only `json`, `os`, `sys`, `time`, `urllib`. - Left implicit as members of `base`, per Arch convention: `bash` (`Panel.qml`, `Globe.qml: bash -c` wraps every probe), `coreutils` (`Panel.qml`, `Globe.qml: date`, one probe per refresh), `systemd` (`Panel.qml: timedatectl show`, `timedatectl list-timezones`, each with a fallback: `/etc/localtime` for the home zone and `find /usr/share/zoneinfo` for the catalog), `sed` and `grep` (`Panel.qml`: the symlink target of `/etc/localtime` and the zoneinfo catalog filter), `findutils` and `tzdata` (that fallback; `worldclock-data.py: /usr/share/zoneinfo/zone1970.tab`). `omarchy` cannot run without any of them either. diff --git a/pkgbuilds/elsewhen/PKGBUILD b/pkgbuilds/elsewhen/PKGBUILD index 902a5e5..93639b1 100644 --- a/pkgbuilds/elsewhen/PKGBUILD +++ b/pkgbuilds/elsewhen/PKGBUILD @@ -2,7 +2,7 @@ pkgname=elsewhen pkgver=1.0.0 -pkgrel=1 +pkgrel=2 pkgdesc='World clock plugin for the Omarchy shell' arch=('any') url='https://github.com/omacom/elsewhen' @@ -24,11 +24,8 @@ source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") sha256sums=('3124f0c0a19ebc1b158bcf04151cddd6c733ceeead88052186b6a54c46bee263') package() { - # The packaged plugin root, scanned by the shell between its bundled - # plugins and ~/.config/omarchy/plugins since omarchy PR #12051. An older - # shell never looks here, so on it this package installs cleanly and does - # nothing; there is no omarchy version to pin until a release carries #12051. - local plugin="$pkgdir/usr/share/omarchy/plugins/omacom.elsewhen" + # Install alongside the bundled plugins in the shell's plugin directory. + local plugin="$pkgdir/usr/share/omarchy/shell/plugins/omacom.elsewhen" cd "$srcdir/$pkgname-$pkgver" || return 1 # The shell loads the entry point each manifest declares. A tree without From 534f007d6b829428fc8369eb494c07c662dcddfc Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 15 Sep 2026 22:59:31 -0400 Subject: [PATCH 088/121] Add Steam FEX launcher for Apple Silicon (aarch64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Package the tested Asahi Steam launcher as omarchy-steam-fex, with runtime-only dependencies and offline launcher checks in makepkg. Preserve the original launcher behavior and document its runtime requirements and downstream ownership handoff. Co-authored-by: dl-alexandre <166029845+dl-alexandre@users.noreply.github.com> Co-authored-by: Santeri Hernejärvi --- .../omarchy-steam-fex/.omarchy/package.json | 3 + pkgbuilds/omarchy-steam-fex/LICENSE | 20 ++ pkgbuilds/omarchy-steam-fex/PKGBUILD | 25 +++ pkgbuilds/omarchy-steam-fex/README.md | 17 ++ .../omarchy-steam-fex/omarchy-launch-steam | 110 ++++++++++ pkgbuilds/omarchy-steam-fex/test-launcher.py | 196 ++++++++++++++++++ 6 files changed, 371 insertions(+) create mode 100644 pkgbuilds/omarchy-steam-fex/.omarchy/package.json create mode 100644 pkgbuilds/omarchy-steam-fex/LICENSE create mode 100644 pkgbuilds/omarchy-steam-fex/PKGBUILD create mode 100644 pkgbuilds/omarchy-steam-fex/README.md create mode 100755 pkgbuilds/omarchy-steam-fex/omarchy-launch-steam create mode 100644 pkgbuilds/omarchy-steam-fex/test-launcher.py diff --git a/pkgbuilds/omarchy-steam-fex/.omarchy/package.json b/pkgbuilds/omarchy-steam-fex/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/omarchy-steam-fex/LICENSE b/pkgbuilds/omarchy-steam-fex/LICENSE new file mode 100644 index 0000000..f12cfa7 --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/pkgbuilds/omarchy-steam-fex/PKGBUILD b/pkgbuilds/omarchy-steam-fex/PKGBUILD new file mode 100644 index 0000000..c984a57 --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/PKGBUILD @@ -0,0 +1,25 @@ +pkgname=omarchy-steam-fex +pkgver=1.0.0 +pkgrel=2 +pkgdesc='Steam launcher with login workarounds for Apple Silicon using muvm and FEX' +arch=('aarch64') +url='https://github.com/omacom/omarchy-pkgs/tree/master/pkgbuilds/omarchy-steam-fex' +license=('MIT') +checkdepends=('python') +source=('omarchy-launch-steam' 'LICENSE' 'test-launcher.py') +sha256sums=('d89559ef88b3589e7d972b44a4a29e418605542f44f2756afd24ed3ce3227609' + '717ba1949502290f8e47688ae2e323acd06c8ca47aec9f7596b15f678c1af4a2' + '1d31b9ed09292b79dc86d9d4b3fff01d19e8210fdc5e3b13e78b846671808ed5') + +check() { + python test-launcher.py +} + +package() { + # These are runtime-only dependencies; the Asahi stack is not needed to + # assemble or test the scripts in a standard Arch Linux ARM builder. + depends=('bash' 'coreutils' 'python' 'steam' 'muvm' 'FEX-Emu') + + install -Dm755 omarchy-launch-steam "$pkgdir/usr/bin/omarchy-launch-steam" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/pkgbuilds/omarchy-steam-fex/README.md b/pkgbuilds/omarchy-steam-fex/README.md new file mode 100644 index 0000000..a4f6513 --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/README.md @@ -0,0 +1,17 @@ +# Steam launcher for Apple Silicon + +`omarchy-steam-fex` provides `omarchy-launch-steam` for the Asahi Linux `steam`, `muvm`, and `FEX-Emu` stack. Those runtime packages come from `asahi-alarm`; `FEX-Emu` provides `FEXBash`. The package is restricted to aarch64 and assumes that stack's `~/.local/share/fex-steam/steam-launcher/bin_steam.sh` layout. + +The launcher runs Steam through `muvm` and `FEXBash` with the CEF occlusion workaround. Once Steam's client files are present, it also disables bootstrap verification and repair and patches the Steam UI network initialization block that can leave login waiting indefinitely. Initial bootstrap keeps the normal bootstrap flags. If the FEX launcher is unavailable, it falls back to `steam`. + +`omarchy-launch-steam --prepare` writes the current user's desktop override with `Exec=omarchy-launch-steam %U` and applies the same UI patch. Each matching chunk is backed up as `.omarchy-bak` before its first patch; existing backups are preserved, and already-patched and unrecognized chunks are left unchanged. The regex depends on Valve's client code and may need updating when that code changes. + +Only the launcher and license are installed. Steam's system desktop entry and downloaded client files remain outside this package's ownership; preparation runs as the desktop user, never in a package installation hook. A downstream Omarchy package that already owns the launcher must release that path before this package is installed, or in the same upgrade transaction. + +Runtime dependencies are declared in `package()` so assembling the scripts does not require the Asahi stack in the build container. They remain required dependencies in the resulting package. `check()` runs the offline launcher tests using temporary homes and mocked Steam/muvm commands. To run them directly: + +```sh +python pkgbuilds/omarchy-steam-fex/test-launcher.py +``` + +The launcher was extracted from [omarchy-mx-mac commit 5e8e1188](https://github.com/scottjones/omarchy-mx-mac/commit/5e8e1188e39fae70cf4f7bda1a1d85d66eccae51), credited to Scott Jones, dl-alexandre, and Santeri Hernejärvi. The extraction replaces `omarchy-cmd-present` with `command -v`, removing the dependency on Omarchy itself. The launcher matches the version published in [omarchy-pkgs-aarch64](https://github.com/omarchy-mac/omarchy-pkgs-aarch64/tree/main/pkgbuilds/omarchy-steam-fex). diff --git a/pkgbuilds/omarchy-steam-fex/omarchy-launch-steam b/pkgbuilds/omarchy-steam-fex/omarchy-launch-steam new file mode 100755 index 0000000..f61d0db --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/omarchy-launch-steam @@ -0,0 +1,110 @@ +#!/bin/bash + +# omarchy:summary=Launch Steam, applying Asahi muvm login workarounds on Apple Silicon +# omarchy:group=launch +# omarchy:args=[--prepare|steam-args...] + +set -euo pipefail + +steam_root="$HOME/.local/share/Steam" + +write_steam_desktop() { + local app_dir="$HOME/.local/share/applications" + mkdir -p "$app_dir" + cat >"$app_dir/steam.desktop" <<'EOF' +[Desktop Entry] +Name=Steam +Comment=Application for managing and playing games on Steam +Exec=omarchy-launch-steam %U +Icon=steam +Terminal=false +Type=Application +Categories=Network;FileTransfer;Game; +MimeType=x-scheme-handler/steam;x-scheme-handler/steamlink; +EOF +} + +steam_client_ready() { + [[ -d $steam_root/steamui ]] && compgen -G "$steam_root/*/steamui.so" >/dev/null +} + +launch_fex_steam() { + local launcher="$1" + shift + + exec muvm -- FEXBash -c 'exec "$@"' omarchy-steam "$launcher" "$@" +} + +patch_steam_ui() { + local steamui="$steam_root/steamui" + [[ -d $steamui ]] || return 0 + + python3 - "$steamui" <<'PY' +import pathlib +import re +import sys + +steamui = pathlib.Path(sys.argv[1]) +pattern = re.compile( + r"const t=\(0,(\w+)\.(\w+)\)\(\"System\.Network\.RegisterForDeviceChanges\"\);" + r"t&&SteamClient\.System\.Network\.RegisterForDeviceChanges\(this\.OnNetworkDevicesChanged\)," + r"\(0,\1\.\2\)\(\"System\.Network\.GetProxyInfo\"\)&&SteamClient\.System\.Network\.GetProxyInfo\(\)\.then\(e=>this\.m_proxyInfo=e\)," + r"\(0,\1\.\2\)\(\"System\.Network\.RegisterForConnectivityTestChanges\"\)&&SteamClient\.System\.Network\.RegisterForConnectivityTestChanges\(this\.OnConnectivityTestStateChanged\)," + r"t\|\|\(this\.m_bIsAwaitingInitialNetworkState=!1\)" +) +replacement = ( + r'const t=(0,\1.\2)("System.Network.RegisterForDeviceChanges")' + r'&&!!(SteamClient.System&&SteamClient.System.Network&&"function"==typeof SteamClient.System.Network.RegisterForDeviceChanges);' + r'try{t&&SteamClient.System.Network.RegisterForDeviceChanges(this.OnNetworkDevicesChanged)}catch(e){}' + r'try{(0,\1.\2)("System.Network.GetProxyInfo")&&SteamClient.System.Network.GetProxyInfo().then(e=>this.m_proxyInfo=e)}catch(e){}' + r'try{(0,\1.\2)("System.Network.RegisterForConnectivityTestChanges")&&SteamClient.System.Network.RegisterForConnectivityTestChanges(this.OnConnectivityTestStateChanged)}catch(e){}' + r'this.m_bIsAwaitingInitialNetworkState=!1,this.m_bIsConnectedToANetwork=!0' +) + +for path in sorted(steamui.glob("chunk~*.js")): + text = path.read_text(errors="replace") + if "m_bIsConnectedToANetwork=!0" in text and "RegisterForDeviceChanges" in text: + continue + updated, count = pattern.subn(replacement, text, count=1) + if count != 1: + continue + backup = path.with_suffix(path.suffix + ".omarchy-bak") + if not backup.exists(): + backup.write_text(text) + path.write_text(updated) +PY +} + +prepare_asahi() { + [[ $(uname -m) == aarch64 ]] || return 0 + write_steam_desktop + patch_steam_ui +} + +if [[ ${1:-} == --prepare ]]; then + prepare_asahi + exit 0 +fi + +if [[ $(uname -m) == aarch64 ]] && command -v muvm >/dev/null && command -v FEXBash >/dev/null; then + launcher="$HOME/.local/share/fex-steam/steam-launcher/bin_steam.sh" + + if [[ -f $launcher ]]; then + steam_args=(-cef-force-occlusion) + if steam_client_ready; then + prepare_asahi + steam_args+=( + -noverifyfiles + -nobootstrapupdate + -skipinitialbootstrap + -norepairfiles + ) + else + write_steam_desktop + fi + + launch_fex_steam "$launcher" "${steam_args[@]}" "$@" + fi +fi + +exec steam "$@" diff --git a/pkgbuilds/omarchy-steam-fex/test-launcher.py b/pkgbuilds/omarchy-steam-fex/test-launcher.py new file mode 100644 index 0000000..cb4fcd9 --- /dev/null +++ b/pkgbuilds/omarchy-steam-fex/test-launcher.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +"""Offline launcher tests: fake Steam/muvm/FEX, real Bash and Python, temporary HOME.""" + +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + + +LAUNCHER = Path(os.environ.get( + 'STEAM_LAUNCHER_TEST_SCRIPT', + Path(__file__).with_name('omarchy-launch-steam'), +)) + +# A representative minified Steam network initialization block, including +# surrounding code that must survive the patch. Deliberately not a regex. +ORIGINAL = ( + 'before();const t=(0,Ab.cd)("System.Network.RegisterForDeviceChanges");' + 't&&SteamClient.System.Network.RegisterForDeviceChanges(this.OnNetworkDevicesChanged),' + '(0,Ab.cd)("System.Network.GetProxyInfo")&&SteamClient.System.Network.GetProxyInfo().then(e=>this.m_proxyInfo=e),' + '(0,Ab.cd)("System.Network.RegisterForConnectivityTestChanges")&&SteamClient.System.Network.RegisterForConnectivityTestChanges(this.OnConnectivityTestStateChanged),' + 't||(this.m_bIsAwaitingInitialNetworkState=!1);after();' +) +SKIP_BOOTSTRAP = ['-noverifyfiles', '-nobootstrapupdate', '-skipinitialbootstrap', '-norepairfiles'] + +MOCK = ''' +import json, os +from pathlib import Path +import shutil, sys +name = Path(sys.argv[0]).name +if name == 'uname': + print(os.environ.get('TEST_ARCH', 'aarch64')) + sys.exit(0) +with open(os.environ['TEST_CALLS'], 'a') as log: + log.write(json.dumps([name, *sys.argv[1:]]) + '\\n') +if name == 'muvm': + assert sys.argv[1:3] == ['--', 'FEXBash'] + os.execv(shutil.which('FEXBash'), sys.argv[2:]) +if name == 'FEXBash': + os.execv('/bin/bash', ['/bin/bash', *sys.argv[1:]]) +sys.exit(int(os.environ.get('TEST_EXIT', '0'))) +''' + + +class SteamLauncherTests(unittest.TestCase): + def setUp(self): + self.temp = tempfile.TemporaryDirectory(prefix='steam-fex-test-') + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.user_home = self.root / 'home with spaces' + self.user_home.mkdir() + self.tools = self.root / 'tools' + self.tools.mkdir() + self.calls_path = self.root / 'calls.jsonl' + self.env = dict(os.environ, HOME=str(self.user_home), PATH=str(self.tools), + TEST_CALLS=str(self.calls_path), TEST_ARCH='aarch64', TEST_EXIT='0') + for name in ['mkdir', 'cat', 'python3']: + (self.tools / name).symlink_to(shutil.which(name)) + for name in ['uname', 'muvm', 'FEXBash', 'steam']: + self.mock(self.tools / name) + self.fex_launcher = self.user_home / '.local/share/fex-steam/steam-launcher/bin_steam.sh' + self.mock(self.fex_launcher) + self.steam_root = self.user_home / '.local/share/Steam' + self.ui = self.steam_root / 'steamui' + self.desktop = self.user_home / '.local/share/applications/steam.desktop' + + def mock(self, path): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(f'#!{sys.executable}\n' + MOCK) + path.chmod(0o755) + + def run_launcher(self, *args, expected=0): + result = subprocess.run(['/bin/bash', str(LAUNCHER), *args], env=self.env, + capture_output=True, text=True, timeout=10) + self.assertEqual(result.returncode, expected, result.stderr) + return [json.loads(line) for line in self.calls_path.read_text().splitlines()] if self.calls_path.exists() else [] + + def chunk(self, content=ORIGINAL, name='chunk~network.js'): + self.ui.mkdir(parents=True, exist_ok=True) + path = self.ui / name + path.write_text(content) + return path + + def client_ready(self): + self.ui.mkdir(parents=True, exist_ok=True) + binary = self.steam_root / 'ubuntu12_64/steamui.so' + binary.parent.mkdir(parents=True, exist_ok=True) + binary.touch() + + def assert_desktop(self): + text = self.desktop.read_text() + self.assertIn('\nExec=omarchy-launch-steam %U\n', text) + self.assertIn('x-scheme-handler/steam;x-scheme-handler/steamlink;', text) + + def assert_fex(self, calls, flags, user_args): + args = [str(self.fex_launcher), *flags, *user_args] + self.assertEqual(calls, [ + ['muvm', '--', 'FEXBash', '-c', 'exec "$@"', 'omarchy-steam', *args], + ['FEXBash', '-c', 'exec "$@"', 'omarchy-steam', *args], + ['bin_steam.sh', *flags, *user_args], + ]) + + def test_prepare_without_client_only_writes_user_desktop(self): + self.assertEqual(self.run_launcher('--prepare'), []) + self.assert_desktop() + self.assertFalse(self.steam_root.exists()) + + def test_prepare_patches_matching_chunks_and_preserves_original(self): + for identifier in ['Ab.cd', '_A2.x9']: + with self.subTest(identifier=identifier): + original = ORIGINAL.replace('Ab.cd', identifier) + path = self.chunk(original, f'chunk~{identifier}.js') + self.assertEqual(self.run_launcher('--prepare'), []) + patched = path.read_text() + self.assertTrue(patched.startswith('before();')) + self.assertTrue(patched.endswith(';after();')) + self.assertIn(f'const t=(0,{identifier})("System.Network.RegisterForDeviceChanges")&&!!', patched) + self.assertEqual(patched.count('catch(e){}'), 3) + self.assertIn('this.m_bIsAwaitingInitialNetworkState=!1,this.m_bIsConnectedToANetwork=!0', patched) + self.assertEqual(path.with_suffix('.js.omarchy-bak').read_text(), original) + self.assert_desktop() + + def test_repeated_prepare_is_idempotent_and_keeps_first_backup(self): + path = self.chunk() + self.run_launcher('--prepare') + patched, modified = path.read_bytes(), path.stat().st_mtime_ns + self.run_launcher('--prepare') + self.assertEqual(path.read_bytes(), patched) + self.assertEqual(path.stat().st_mtime_ns, modified) + path.write_text(ORIGINAL.replace('Ab.cd', 'New.api')) + self.run_launcher('--prepare') + self.assertIn('(0,New.api)', path.read_text()) + self.assertEqual(path.with_suffix('.js.omarchy-bak').read_text(), ORIGINAL) + + def test_unmatched_code_and_other_filenames_are_untouched(self): + for name, content in [('chunk~changed.js', 'otherNetworkCode();'), ('other.js', ORIGINAL)]: + path = self.chunk(content, name) + self.run_launcher('--prepare') + self.assertEqual(path.read_text(), content) + self.assertFalse(path.with_suffix('.js.omarchy-bak').exists()) + + def test_only_first_matching_block_is_patched(self): + path = self.chunk(ORIGINAL + ORIGINAL) + self.run_launcher('--prepare') + self.assertEqual(path.read_text().count('m_bIsConnectedToANetwork=!0'), 1) + self.assertIn(ORIGINAL, path.read_text()) + + def test_initial_launch_keeps_bootstrap_enabled_and_preserves_arguments(self): + args = ['steam://rungameid/123', 'argument with spaces', '$(touch unwanted)', ''] + calls = self.run_launcher(*args) + self.assert_fex(calls, ['-cef-force-occlusion'], args) + self.assert_desktop() + self.assertFalse(self.steam_root.exists()) + + def test_ui_directory_alone_does_not_disable_bootstrap(self): + path = self.chunk() + self.assert_fex(self.run_launcher(), ['-cef-force-occlusion'], []) + self.assertEqual(path.read_text(), ORIGINAL) + + def test_ready_launch_patches_and_disables_bootstrap(self): + path = self.chunk() + self.client_ready() + args = ['steam://open/main'] + self.assert_fex(self.run_launcher(*args), ['-cef-force-occlusion', *SKIP_BOOTSTRAP], args) + self.assertIn('m_bIsConnectedToANetwork=!0', path.read_text()) + self.assert_desktop() + + def test_missing_fex_components_fall_back_without_modifying_user_files(self): + for missing in [self.tools / 'muvm', self.tools / 'FEXBash', self.fex_launcher]: + with self.subTest(missing=missing.name): + missing.unlink() + self.env['TEST_EXIT'] = '23' + self.assertEqual(self.run_launcher('arg with spaces', expected=23), [['steam', 'arg with spaces']]) + self.assertFalse(self.desktop.exists()) + self.calls_path.unlink() + self.mock(missing) + + def test_x86_prepare_is_noop_and_launch_falls_back(self): + self.env['TEST_ARCH'] = 'x86_64' + path = self.chunk() + self.assertEqual(self.run_launcher('--prepare'), []) + self.assertFalse(self.desktop.exists()) + self.assertEqual(path.read_text(), ORIGINAL) + self.assertEqual(self.run_launcher('steam://open/main'), [['steam', 'steam://open/main']]) + + def test_fex_exit_status_is_preserved(self): + self.env['TEST_EXIT'] = '29' + self.assert_fex(self.run_launcher(expected=29), ['-cef-force-occlusion'], []) + + +if __name__ == '__main__': + unittest.main() From eea7ce6ba651f4682f5eb695d76912fa2fbe521f Mon Sep 17 00:00:00 2001 From: Dan Wahlin Date: Sun, 13 Sep 2026 22:32:35 -0700 Subject: [PATCH 089/121] Add learn-omarchy to the fast ring Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b31dac41-3f83-47ea-b9cb-5a843bd88f20 --- pkgbuilds/learn-omarchy/.omarchy/package.json | 12 +++++++ pkgbuilds/learn-omarchy/PKGBUILD | 34 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 pkgbuilds/learn-omarchy/.omarchy/package.json create mode 100644 pkgbuilds/learn-omarchy/PKGBUILD diff --git a/pkgbuilds/learn-omarchy/.omarchy/package.json b/pkgbuilds/learn-omarchy/.omarchy/package.json new file mode 100644 index 0000000..7fed645 --- /dev/null +++ b/pkgbuilds/learn-omarchy/.omarchy/package.json @@ -0,0 +1,12 @@ +{ + "source": "local", + "release_ring": "fast", + "min_release_age": "24h", + "upstream": { + "github": "DanWahlin/learn-omarchy", + "checksums": "SHA256SUMS", + "assets": { + "any": "learn-omarchy-{pkgver}.tar.gz" + } + } +} diff --git a/pkgbuilds/learn-omarchy/PKGBUILD b/pkgbuilds/learn-omarchy/PKGBUILD new file mode 100644 index 0000000..a69e0c6 --- /dev/null +++ b/pkgbuilds/learn-omarchy/PKGBUILD @@ -0,0 +1,34 @@ +# Maintainer: Dan Wahlin + +pkgname=learn-omarchy +pkgver=0.2.2 +pkgrel=1 +pkgdesc="Interactive, theme-aware courses for learning Omarchy" +arch=('any') +url="https://github.com/DanWahlin/learn-omarchy" +license=('MIT' 'CC-BY-4.0' 'CC0-1.0') +depends=( + 'bash' 'coreutils' 'sudo' 'hyprland' 'mpv' 'nodejs>=22.6' 'omarchy>=4.0.3' + 'quickshell>=0.3' 'qt6-declarative' 'qt6-multimedia' 'qt6-multimedia-ffmpeg' 'xdg-utils' + 'xdg-terminal-exec' 'nautilus' + 'ttf-liberation' 'noto-fonts-emoji' + 'grim' 'slurp' 'gpu-screen-recorder' 'util-linux' 'ffmpeg' +) +makedepends=('make') +optdepends=( + 'btop: activity-monitor practice' + 'tesseract: OCR practice' + 'tesseract-data-eng: English OCR sample recognition' + 'zbar: QR recognition (zbarimg)' + 'qrencode: QR sample creation' + 'voxtype: optional dictation practice' +) +options=('!strip') +source=("$pkgname-$pkgver.tar.gz::$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz") +sha256sums=('67f14778c2b66d56c1504695b0e11cab603f1a002570abc94b4bae9b0bec6066') + +package() { + cd "$srcdir/$pkgname-$pkgver" + node tools/prepare-release.mjs --check . + make DESTDIR="$pkgdir" PREFIX=/usr install +} From bb80d2c4f6a2256017d2d4190df35b48006bcd70 Mon Sep 17 00:00:00 2001 From: Dan Wahlin Date: Sun, 13 Sep 2026 22:51:27 -0700 Subject: [PATCH 090/121] Support omarchy-dev installations Depend on the unversioned omarchy provider so development-channel systems do not need to replace omarchy-dev. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b31dac41-3f83-47ea-b9cb-5a843bd88f20 --- pkgbuilds/learn-omarchy/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgbuilds/learn-omarchy/PKGBUILD b/pkgbuilds/learn-omarchy/PKGBUILD index a69e0c6..90d4071 100644 --- a/pkgbuilds/learn-omarchy/PKGBUILD +++ b/pkgbuilds/learn-omarchy/PKGBUILD @@ -8,7 +8,7 @@ arch=('any') url="https://github.com/DanWahlin/learn-omarchy" license=('MIT' 'CC-BY-4.0' 'CC0-1.0') depends=( - 'bash' 'coreutils' 'sudo' 'hyprland' 'mpv' 'nodejs>=22.6' 'omarchy>=4.0.3' + 'bash' 'coreutils' 'sudo' 'hyprland' 'mpv' 'nodejs>=22.6' 'omarchy' 'quickshell>=0.3' 'qt6-declarative' 'qt6-multimedia' 'qt6-multimedia-ffmpeg' 'xdg-utils' 'xdg-terminal-exec' 'nautilus' 'ttf-liberation' 'noto-fonts-emoji' From ad328b725da5d4b3b187408ce42ca6799a7a0bac Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 15:36:18 -0400 Subject: [PATCH 091/121] Build and test daily package builder images --- .github/workflows/builder-images.yml | 82 +++++++++++++++++ .github/workflows/test.yml | 3 + README.md | 37 ++++++++ bin/builder-image | 66 ++++++++++++++ tests/builder-image.cjs | 130 +++++++++++++++++++++++++++ 5 files changed, 318 insertions(+) create mode 100644 .github/workflows/builder-images.yml create mode 100755 bin/builder-image create mode 100644 tests/builder-image.cjs diff --git a/.github/workflows/builder-images.yml b/.github/workflows/builder-images.yml new file mode 100644 index 0000000..6452813 --- /dev/null +++ b/.github/workflows/builder-images.yml @@ -0,0 +1,82 @@ +name: Refresh builder images + +on: + schedule: + - cron: '23 4 * * *' + push: + branches: [master] + paths: + - build/** + - bin/builder-image + - helpers/paths.sh + - helpers/docker-helpers.sh + - tests/build-isolation.sh + - .github/workflows/builder-images.yml + workflow_dispatch: + +# Complete each refresh before another can replace its tested image tags. +concurrency: + group: builder-images + cancel-in-progress: false + +permissions: + contents: read + +jobs: + refresh: + if: github.repository == 'omacom/omarchy-pkgs' && github.ref == 'refs/heads/master' + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + permissions: + contents: read + packages: write + env: + CONTAINER_ENGINE: docker + REGISTRY_IMAGE: ghcr.io/omacom/omarchy-pkg-builder + CANDIDATE_IMAGE: omarchy-builder-candidate:${{ matrix.arch }} + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Build a fresh environment + run: bin/builder-image build --arch "${{ matrix.arch }}" --mirror edge --tag "$CANDIDATE_IMAGE" --fresh + - name: Test isolated package builds + env: + TEST_BUILDER_IMAGE: ${{ env.CANDIDATE_IMAGE }} + run: tests/build-isolation.sh + - name: Publish tested image + env: + GH_TOKEN: ${{ github.token }} + GH_ACTOR: ${{ github.actor }} + DOCKER_CONFIG: ${{ runner.temp }}/builder-registry-auth + run: | + set -euo pipefail + mkdir -p "$DOCKER_CONFIG" + trap 'rm -rf "$DOCKER_CONFIG"' EXIT + printf '%s' "$GH_TOKEN" | docker login ghcr.io --username "$GH_ACTOR" --password-stdin + key=$(bin/builder-image key --arch "${{ matrix.arch }}" --mirror edge) + version="$REGISTRY_IMAGE:$key-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" + docker tag "$CANDIDATE_IMAGE" "$version" + docker push "$version" + # GHCR creates new packages private. Do not advertise an image to + # fork PRs until it is public. This is a one-time package setting. + anonymous_config=$(mktemp -d "$RUNNER_TEMP/builder-anonymous.XXXXXX") + if ! DOCKER_CONFIG="$anonymous_config" docker manifest inspect "$version" >/dev/null; then + rm -rf "$anonymous_config" + echo "::error::Make the omacom/omarchy-pkg-builder GHCR package public, then rerun this job. The previous matching image remains selected." + exit 1 + fi + rm -rf "$anonymous_config" + docker tag "$CANDIDATE_IMAGE" "$REGISTRY_IMAGE:$key" + docker push "$REGISTRY_IMAGE:$key" + digest=$(docker image inspect "$version" --format '{{index .RepoDigests 0}}') + printf '### Builder image (%s)\n\nInput key: `%s`\n\nImage: `%s`\n' \ + "${{ matrix.arch }}" "$key" "$digest" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index acf3704..4cb0800 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,6 +35,9 @@ jobs: - name: Test PR workflow approval run: node --test tests/pr-workflow-approval.cjs + - name: Test builder images + run: node --test tests/builder-image.cjs + # An Arch container for vercmp: version ordering has to be decided by # the same comparator pacman uses on users' machines. - name: Run self-tests diff --git a/README.md b/README.md index c29aae8..5089dd7 100644 --- a/README.md +++ b/README.md @@ -825,6 +825,43 @@ using real containers and pacman transactions. It uses the prepared builder image, or an image named by `TEST_BUILDER_IMAGE`; CI builds the small fixture image in `tests/build-isolation.Dockerfile`. +### Daily builder images + +`Refresh builder images` builds fresh `edge` environments daily at 04:23 UTC, +when their inputs change on `master`, and on manual dispatch. x86_64 and +aarch64 build on native GitHub-hosted runners, without occupying the DO +package-builder pool. Each candidate must pass `tests/build-isolation.sh`, +including real package builds, before publication to +`ghcr.io/omacom/omarchy-pkg-builder`. Only `master` in this repository can +publish; PR workflows cannot replace the shared images. + +The compatibility tag contains the architecture, mirror, and a hash of the +entire `build/` context, including executable bits and symlink targets but +excluding checkout timestamps and ownership. This deliberately invalidates +images when mounted build scripts change too. `v1` identifies the image build +contract; change it if the invocation or compatibility rules change. Each +successful refresh also gets a run-specific tag for diagnosis and rollback. +A failed build, isolation test, or push leaves the previous compatible image +selected. Scheduled builds use `--pull --no-cache` so unchanged Dockerfiles +still pick up fresh Arch packages. + +To build and test a candidate locally: + +```bash +bin/builder-image key --arch x86_64 --mirror edge +bin/builder-image build --arch x86_64 --mirror edge --tag builder-candidate:test --fresh +CONTAINER_ENGINE=docker TEST_BUILDER_IMAGE=builder-candidate:test tests/build-isolation.sh +``` + +The workflow uses its repository `GITHUB_TOKEN` with `packages: write`; no +registry PAT is needed. **First publication needs one package setting:** GHCR +creates the package private. In the `omacom/omarchy-pkg-builder` package +settings, change visibility to **Public**, then rerun the failed refresh job. +The workflow checks anonymous registry access before advancing the compatible +tag, so fork PRs will not be directed to an image they cannot pull. Subsequent +refreshes preserve that package visibility. This change only produces images; +package jobs keep their existing behavior until image consumption is enabled. + ## Version Management Packages are only rebuilt if: diff --git a/bin/builder-image b/bin/builder-image new file mode 100755 index 0000000..f23f64b --- /dev/null +++ b/bin/builder-image @@ -0,0 +1,66 @@ +#!/bin/bash +# Build a reusable package environment from this checkout's own inputs. +set -euo pipefail + +BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +source "$BUILD_ROOT/helpers/paths.sh" + +usage() { + echo "Usage: bin/builder-image {key|build} [--arch x86_64|aarch64] [--mirror edge|rc|stable] [--tag IMAGE] [--fresh]" +} + +command=${1:-} +[[ $# -eq 0 ]] || shift +tag="" +fresh=false +while (( $# )); do + case "$1" in + --arch) ARCH=${2:?Missing architecture}; shift 2 ;; + --mirror) MIRROR=${2:?Missing mirror}; shift 2 ;; + --tag) tag=${2:?Missing image tag}; shift 2 ;; + --fresh) fresh=true; shift ;; + *) usage >&2; exit 1 ;; + esac +done +require_valid_arch "$ARCH" +validate_mirror "$MIRROR" || { echo "Invalid mirror: $MIRROR" >&2; exit 1; } +case "$command" in key|build) ;; *) usage >&2; exit 1 ;; esac +if [[ $command == key && ( -n $tag || $fresh == true ) ]]; then + usage >&2 + exit 1 +fi + +# Include the whole build context, conservatively including mounted build +# scripts too. Normalize timestamps and ownership so fresh checkouts agree; +# retain file contents, names, executable bits and symlink targets. Bump v1 +# if the image build invocation or this compatibility contract changes. +hash=$(tar --sort=name --mtime=@0 --owner=0 --group=0 --numeric-owner \ + --format=gnu -cf - -C "$BUILD_DIR" . | sha256sum | cut -d' ' -f1) +key="v1-$ARCH-$MIRROR-$hash" +if [[ $command == key ]]; then + echo "$key" + exit 0 +fi + +source "$BUILD_ROOT/helpers/message-helpers.sh" +source "$BUILD_ROOT/helpers/docker-helpers.sh" +check_engine +platform=$(get_platform_arg "$ARCH") +tag=${tag:-omarchy-pkg-builder:latest-$ARCH-$MIRROR} +revision=$(git -C "$BUILD_ROOT" rev-parse HEAD 2>/dev/null || echo unknown) +args=("$platform" --build-arg "MIRROR=$MIRROR" + --label "org.omarchy.builder.key=$key" + --label "org.opencontainers.image.source=https://github.com/omacom/omarchy-pkgs" + --label "org.opencontainers.image.revision=$revision" + --label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" + --tag "$tag" --file "$BUILD_DIR/Dockerfile") +if [[ $fresh == true ]]; then + # A daily build must refresh Arch even when its Dockerfile has not changed. + args+=(--no-cache) + if [[ $CONTAINER_ENGINE == docker ]]; then args+=(--pull); else args+=(--pull=always); fi +fi +if [[ $CONTAINER_ENGINE == docker ]]; then + docker buildx build --load "${args[@]}" "$BUILD_DIR" +else + podman build "${args[@]}" "$BUILD_DIR" +fi diff --git a/tests/builder-image.cjs b/tests/builder-image.cjs new file mode 100644 index 0000000..c20f306 --- /dev/null +++ b/tests/builder-image.cjs @@ -0,0 +1,130 @@ +const assert = require('node:assert/strict'); +const { spawnSync } = require('node:child_process'); +const { chmodSync, cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, utimesSync, writeFileSync } = require('node:fs'); +const { tmpdir } = require('node:os'); +const { join } = require('node:path'); +const { test } = require('node:test'); + +const root = join(__dirname, '..'); +const workflow = readFileSync(join(root, '.github/workflows/builder-images.yml'), 'utf8'); + +function fixture(t) { + const directory = mkdtempSync(join(tmpdir(), 'builder-image-test-')); + t.after(() => rmSync(directory, { recursive: true, force: true })); + mkdirSync(join(directory, 'bin')); + mkdirSync(join(directory, 'build')); + cpSync(join(root, 'helpers'), join(directory, 'helpers'), { recursive: true }); + cpSync(join(root, 'bin/builder-image'), join(directory, 'bin/builder-image')); + writeFileSync(join(directory, 'build/Dockerfile'), 'FROM scratch\nCOPY input /input\n'); + writeFileSync(join(directory, 'build/input'), 'original input\n'); + const engine = join(directory, 'engine'); + mkdirSync(engine); + const log = join(directory, 'engine.jsonl'); + writeFileSync(join(engine, 'docker'), `#!/usr/bin/env node +const fs = require('node:fs'); +const args = process.argv.slice(2); +fs.appendFileSync(process.env.ENGINE_LOG, JSON.stringify(args) + '\\n'); +if (args[0] === 'manifest' && process.env.PRIVATE_IMAGE === '1') process.exit(1); +if (args[0] === 'push' && process.env.PUSH_FAIL === '1') process.exit(1); +if (args[0] === 'image' && args[1] === 'inspect') console.log('ghcr.io/omacom/omarchy-pkg-builder@sha256:' + 'a'.repeat(64)); +`); + chmodSync(join(engine, 'docker'), 0o755); + const env = { + ...process.env, PATH: `${engine}:${process.env.PATH}`, CONTAINER_ENGINE: 'docker', + ENGINE_LOG: log, ARCH: 'x86_64', MIRROR: 'edge', + }; + const run = (args, extraEnv = {}) => spawnSync(join(directory, 'bin/builder-image'), args, { + cwd: directory, env: { ...env, ...extraEnv }, encoding: 'utf8', + }); + const key = (...args) => { + const result = run(['key', ...args]); + assert.equal(result.status, 0, result.stderr); + return result.stdout.trim(); + }; + const calls = () => readFileSync(log, 'utf8').trim().split('\n').filter(Boolean).map(JSON.parse); + return { directory, env, run, key, calls }; +} + +test('image keys are stable across checkout location and timestamp changes', t => { + const a = fixture(t); + const b = fixture(t); + const key = a.key(); + assert.match(key, /^v1-x86_64-edge-[a-f0-9]{64}$/); + utimesSync(join(b.directory, 'build/input'), new Date(0), new Date(0)); + assert.equal(b.key(), key); +}); + +test('image keys separate architectures, mirrors, content, modes and symlink targets', t => { + const f = fixture(t); + const keys = new Set([f.key(), f.key('--arch', 'aarch64'), f.key('--mirror', 'rc'), f.key('--mirror', 'stable')]); + writeFileSync(join(f.directory, 'build/input'), 'new input\n'); + keys.add(f.key()); + chmodSync(join(f.directory, 'build/input'), 0o755); + keys.add(f.key()); + symlinkSync('input', join(f.directory, 'build/link')); + keys.add(f.key()); + rmSync(join(f.directory, 'build/link')); + symlinkSync('Dockerfile', join(f.directory, 'build/link')); + keys.add(f.key()); + assert.equal(keys.size, 8); + mkdirSync(join(f.directory, 'pkgbuilds/example'), { recursive: true }); + const key = f.key(); + writeFileSync(join(f.directory, 'pkgbuilds/example/PKGBUILD'), 'pkgver=2\n'); + assert.equal(f.key(), key, 'package changes must not invalidate the build environment'); +}); + +test('fresh builds refresh package layers and record their compatibility key', t => { + const f = fixture(t); + const key = f.key('--arch', 'aarch64'); + const result = f.run(['build', '--arch', 'aarch64', '--tag', 'candidate:test', '--fresh']); + assert.equal(result.status, 0, result.stderr); + const build = f.calls().find(args => args[0] === 'buildx'); + assert.ok(build.includes('--no-cache')); + assert.ok(build.includes('--pull')); + assert.ok(build.includes('--load')); + assert.ok(build.includes('--platform=linux/arm64')); + assert.ok(build.includes(`org.omarchy.builder.key=${key}`)); + assert.ok(build.includes('candidate:test')); +}); + +test('invalid targets fail before starting an image build', t => { + const f = fixture(t); + for (const args of [['key', '--arch', 'invalid'], ['build', '--mirror', 'invalid'], ['key', '--fresh']]) { + assert.notEqual(f.run(args).status, 0); + } +}); + +function publish(f, extraEnv = {}) { + const script = workflow.split(' - name: Publish tested image\n')[1].split(' run: |\n')[1] + .replaceAll('${{ matrix.arch }}', 'x86_64'); + return spawnSync('bash', ['-e', '-o', 'pipefail', '-c', script], { + cwd: f.directory, encoding: 'utf8', env: { + ...f.env, REGISTRY_IMAGE: 'ghcr.io/omacom/omarchy-pkg-builder', CANDIDATE_IMAGE: 'candidate:test', + GH_TOKEN: 'fixture', GH_ACTOR: 'fixture', DOCKER_CONFIG: join(f.directory, 'auth'), + RUNNER_TEMP: f.directory, GITHUB_RUN_ID: '123', GITHUB_RUN_ATTEMPT: '1', + GITHUB_STEP_SUMMARY: join(f.directory, 'summary'), ...extraEnv, + }, + }); +} + +test('a public tested image gets a version tag before the compatible-image tag advances', t => { + const f = fixture(t); + const key = f.key(); + const result = publish(f); + assert.equal(result.status, 0, result.stderr); + const calls = f.calls(); + assert.deepEqual(calls.filter(args => args[0] === 'push').map(args => args[1]), [ + `ghcr.io/omacom/omarchy-pkg-builder:${key}-123-1`, `ghcr.io/omacom/omarchy-pkg-builder:${key}`, + ]); + assert.ok(calls.findIndex(args => args[0] === 'manifest') < calls.findLastIndex(args => args[0] === 'push')); +}); + +test('a private image or failed push never replaces the previous compatible-image tag', t => { + for (const extraEnv of [{ PRIVATE_IMAGE: '1' }, { PUSH_FAIL: '1' }]) { + const f = fixture(t); + const key = f.key(); + const result = publish(f, extraEnv); + assert.notEqual(result.status, 0); + assert.equal(f.calls().some(args => args[0] === 'push' && args[1] === `ghcr.io/omacom/omarchy-pkg-builder:${key}`), false); + } +}); From 30af71af24be4a15f1857d9f51857279de0ab6a6 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 15:41:27 -0400 Subject: [PATCH 092/121] Validate proposed builder images on both native architectures --- .github/workflows/builder-images.yml | 38 +++++++++++++++++++++++++++- README.md | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/.github/workflows/builder-images.yml b/.github/workflows/builder-images.yml index 6452813..db2bb08 100644 --- a/.github/workflows/builder-images.yml +++ b/.github/workflows/builder-images.yml @@ -13,16 +13,52 @@ on: - tests/build-isolation.sh - .github/workflows/builder-images.yml workflow_dispatch: + pull_request: + paths: + - build/** + - bin/builder-image + - helpers/paths.sh + - helpers/docker-helpers.sh + - tests/build-isolation.sh + - .github/workflows/builder-images.yml # Complete each refresh before another can replace its tested image tags. concurrency: - group: builder-images + group: builder-images-${{ github.event.pull_request.number || 'master' }} cancel-in-progress: false permissions: contents: read jobs: + # Exercise proposed image changes on native runners with a read-only token. + # Publishing is a separate master-only job with its own write permission. + validate: + if: github.event_name == 'pull_request' + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + env: + CONTAINER_ENGINE: docker + CANDIDATE_IMAGE: omarchy-builder-candidate:${{ matrix.arch }} + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Build a fresh environment + run: bin/builder-image build --arch "${{ matrix.arch }}" --mirror edge --tag "$CANDIDATE_IMAGE" --fresh + - name: Test isolated package builds + env: + TEST_BUILDER_IMAGE: ${{ env.CANDIDATE_IMAGE }} + run: tests/build-isolation.sh + refresh: if: github.repository == 'omacom/omarchy-pkgs' && github.ref == 'refs/heads/master' strategy: diff --git a/README.md b/README.md index 5089dd7..8823595 100644 --- a/README.md +++ b/README.md @@ -834,6 +834,8 @@ package-builder pool. Each candidate must pass `tests/build-isolation.sh`, including real package builds, before publication to `ghcr.io/omacom/omarchy-pkg-builder`. Only `master` in this repository can publish; PR workflows cannot replace the shared images. +PRs that change image inputs also build and test both candidates on native +runners, with a read-only token and no registry publication. The compatibility tag contains the architecture, mirror, and a hash of the entire `build/` context, including executable bits and symlink targets but From 124b067694ae15edcaf4a03c1677630321facb01 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 15:52:02 -0400 Subject: [PATCH 093/121] Carry PR build artifacts inside a tar so epoch package names survive actions/upload-artifact rejects any path containing ':', and makepkg names a package with an epoch `name-1:ver-rel-arch.pkg.tar.zst`. Every PR that built such a package (cursor-cli in the sync PRs, omasnap once it gained an epoch) failed at "Upload artifact" after a successful build, and publish then rebuilt from scratch on merge. The files now ride inside packages.tar for the artifact hop and come back out with makepkg's names untouched: pacman clients and bin/publish-artifact both require the filename to match PKGINFO, and the channels already carry these names. publish.yml still accepts bare pre-packing artifacts until the 7-day retention drains them. helpers/artifact-helpers.sh holds both halves; tests/artifact-helpers.sh covers the round trip and runs with the other self-tests. --- .github/workflows/build-pr.yml | 14 +++++++++++-- .github/workflows/publish.yml | 11 +++++++++-- .github/workflows/test.yml | 1 + helpers/artifact-helpers.sh | 36 ++++++++++++++++++++++++++++++++++ tests/artifact-helpers.sh | 36 ++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 helpers/artifact-helpers.sh create mode 100755 tests/artifact-helpers.sh diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 7adbfcc..b1f051e 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -170,12 +170,22 @@ jobs: - name: Tree hash id: tree run: echo "hash=$(git rev-parse "${{ github.event.pull_request.head.sha || github.sha }}:pkgbuilds/${{ matrix.package }}")" >> "$GITHUB_OUTPUT" - - name: Upload artifact + # The upload action rejects a path containing ':', which is how makepkg + # names a package with an epoch. The files ride inside packages.tar + # (helpers/artifact-helpers.sh); publish.yml unpacks it. + - name: Pack artifact + id: pack if: always() + run: | + source helpers/artifact-helpers.sh + pack_packages build-output/edge/${{ matrix.arch }} packages.tar + tar -tvf packages.tar + - name: Upload artifact + if: always() && steps.pack.outcome == 'success' uses: actions/upload-artifact@v4 with: name: ${{ matrix.package }}-${{ matrix.arch }}-${{ steps.tree.outputs.hash }} - path: build-output/edge/${{ matrix.arch }}/*.pkg.tar.zst + path: packages.tar if-no-files-found: error retention-days: 7 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 75f236f..a61642d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -83,13 +83,17 @@ jobs: cat plan.txt # Fetch each package's PR artifact into build-output/edge//, or - # build it when no artifact exists for exactly this tree. + # build it when no artifact exists for exactly this tree. An artifact + # carries its package files inside packages.tar (see build-pr.yml and + # helpers/artifact-helpers.sh: the upload action rejects the colon in + # an epoch filename). - name: Collect artifacts env: GH_TOKEN: ${{ github.token }} CONTAINER_ENGINE: docker run: | set -uo pipefail + source helpers/artifact-helpers.sh # sources.jsonl: where each package's files came from, or that the # build failed. A failed build ends the run before any publish, and # the record says so instead of the report job finding nothing. @@ -104,7 +108,10 @@ jobs: mkdir -p "build-output/edge/$arch" if [[ -n "$found" ]]; then echo "==> $label: PR artifact" - if curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" && unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch"; then + rm -rf /tmp/artifact; mkdir -p /tmp/artifact + if curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" \ + && unzip -oq /tmp/artifact.zip -d /tmp/artifact \ + && unpack_packages /tmp/artifact "build-output/edge/$arch"; then jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"pr-artifact"}' >> sources.jsonl else jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"artifact-download-failed"}' >> sources.jsonl; failed=1; break diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index acf3704..b1bf54c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,6 +54,7 @@ jobs: ./tests/partial-release.sh ./tests/published-build-plan.sh ./tests/controller.sh + ./tests/artifact-helpers.sh pacman -S --noconfirm --quiet rclone >/dev/null ./tests/publish-artifact.sh ' diff --git a/helpers/artifact-helpers.sh b/helpers/artifact-helpers.sh new file mode 100644 index 0000000..1747f57 --- /dev/null +++ b/helpers/artifact-helpers.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Package files cross from a PR build to publish.yml as one GitHub Actions +# artifact. actions/upload-artifact rejects any path containing ':', and a +# package with an epoch is named `name-1:ver-rel-arch.pkg.tar.zst` by +# makepkg. So the files ride inside a tar with a plain name and keep their +# own names untouched: pacman clients and bin/publish-artifact both rely on +# the filename matching PKGINFO. + +# pack_packages

: every *.pkg.tar.zst directly in into . +# Signatures and the scratch database next to them stay behind. +pack_packages() { + local dir=$1 out=$2 restore files=() + restore=$(shopt -p nullglob); shopt -s nullglob + files=("$dir"/*.pkg.tar.zst) + $restore + (( ${#files[@]} )) || { echo "pack_packages: no *.pkg.tar.zst in $dir" >&2; return 1; } + tar -cf "$out" -C "$dir" -- "${files[@]##*/}" +} + +# unpack_packages : the packages an unzipped artifact +# carried, into . Packed artifacts hold packages.tar; artifacts from +# builds before packing hold the bare files. The bare form can go once +# those artifacts have expired (7-day retention). +unpack_packages() { + local src=$1 dest=$2 restore files=() + mkdir -p "$dest" + if [[ -f "$src/packages.tar" ]]; then + tar -xf "$src/packages.tar" -C "$dest" + return + fi + restore=$(shopt -p nullglob); shopt -s nullglob + files=("$src"/*.pkg.tar.zst) + $restore + (( ${#files[@]} )) || { echo "unpack_packages: nothing to unpack in $src" >&2; return 1; } + cp -- "${files[@]}" "$dest/" +} diff --git a/tests/artifact-helpers.sh b/tests/artifact-helpers.sh new file mode 100755 index 0000000..a0a2fee --- /dev/null +++ b/tests/artifact-helpers.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Self-test for helpers/artifact-helpers.sh: package files survive the +# artifact hop between build-pr.yml and publish.yml with makepkg's names +# intact, including the colon an epoch puts in them. +set -euo pipefail +ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +source "$ROOT/helpers/artifact-helpers.sh" +T=$(mktemp -d); trap 'rm -rf "$T"' EXIT +pass() { echo "PASS: $1"; } +fail() { echo "FAIL: $1"; exit 1; } + +EPOCH='cursor-cli-1:2026.09.18.1.9a7762b-1-x86_64.pkg.tar.zst' +PLAIN='beta-1.0-1-x86_64.pkg.tar.zst' +mkdir -p "$T/built" "$T/artifact" "$T/out" +echo epoch > "$T/built/$EPOCH" +echo plain > "$T/built/$PLAIN" +echo sig > "$T/built/$PLAIN.sig" +echo db > "$T/built/omarchy.db.tar.zst" + +pack_packages "$T/built" "$T/artifact/packages.tar" || fail "pack" +[[ "$(tar -tf "$T/artifact/packages.tar" | sort | tr '\n' ' ')" == "$PLAIN $EPOCH " ]] \ + && pass "packages.tar holds the packages only, no signature or database" || fail "tar contents: $(tar -tf "$T/artifact/packages.tar" | tr '\n' ' ')" +[[ "$(ls "$T/artifact")" == "packages.tar" ]] && pass "the artifact path carries no colon" || fail "artifact listing" + +unpack_packages "$T/artifact" "$T/out" || fail "unpack" +[[ "$(ls "$T/out" | sort | tr '\n' ' ')" == "$PLAIN $EPOCH " && "$(cat "$T/out/$EPOCH")" == epoch ]] \ + && pass "epoch filename and bytes survive the round trip" || fail "round trip: $(ls "$T/out" | tr '\n' ' ')" + +# An artifact uploaded before packing existed: bare package files. +mkdir -p "$T/old" "$T/out2"; cp "$T/built"/*.pkg.tar.zst "$T/old/" +unpack_packages "$T/old" "$T/out2" && [[ "$(ls "$T/out2" | sort | tr '\n' ' ')" == "$PLAIN $EPOCH " ]] \ + && pass "a bare pre-packing artifact still unpacks" || fail "bare artifact" + +mkdir -p "$T/empty" +if pack_packages "$T/empty" "$T/x.tar" 2>/dev/null; then fail "packing an empty build dir should fail"; else pass "empty build dir refused"; fi +if unpack_packages "$T/empty" "$T/out3" 2>/dev/null; then fail "an empty artifact should fail"; else pass "empty artifact refused"; fi From 2c22669d65211be6d99d5ac89ae8bd69843a2cfd Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 16:40:23 -0400 Subject: [PATCH 094/121] Build PR tooling from the base branch tip, not the event's base sha github.event.pull_request.base.sha is a snapshot taken when the PR was last pushed, not the current tip of the base branch. A reopened or rerun PR therefore builds with whatever master looked like at its last push, and a tooling fix that landed on master since then never reaches it: the daily sync PR reopened after #553 merged checked out a base without helpers/artifact-helpers.sh and failed at "Pack artifact". Check out base.ref instead. The plan's diff and the empty-PR check still compare base.sha to head.sha, so the list of changed packages is unaffected; only the tooling that runs on the droplet moves to the tip. --- .github/workflows/build-pr.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index b1f051e..77bcf2e 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -38,11 +38,11 @@ jobs: vouch_status: ${{ steps.vouch.outputs.status }} empty: ${{ steps.list.outputs.empty }} steps: - # Same rule as the build job: bin/build-matrix comes from base, the - # package directories from the PR head. + # Same rule as the build job: bin/build-matrix comes from the base + # branch tip, the package directories from the PR head. - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.base.sha || github.sha }} + ref: ${{ github.event.pull_request.base.ref || github.sha }} fetch-depth: 0 persist-credentials: false - if: github.event_name == 'pull_request' @@ -146,9 +146,13 @@ jobs: # gets built, never how the runner builds it. A PR that changes both # tooling and a package builds the package with the OLD tooling; land # the tooling first. workflow_dispatch has no PR and runs as checked out. + # The base branch tip, not the event's base.sha: that sha is a snapshot + # taken at the PR's last push, so a tooling fix on master would never + # reach an open PR until someone pushed to it (seen on the daily sync + # PR after the artifact packing fix landed). - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.base.sha || github.sha }} + ref: ${{ github.event.pull_request.base.ref || github.sha }} persist-credentials: false - name: Overlay the PR's package directories onto base tooling if: github.event_name == 'pull_request' From 451280ace1adaa23955d468d5b42dc9dd3dc9b3e Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 16:42:24 -0400 Subject: [PATCH 095/121] artifact-helpers: survive bash -e `restore=$(shopt -p nullglob)` exits 1 when nullglob is off, which it is in the workflow shell. Under the `bash -e` that GitHub runs steps with, that ended "Pack artifact" before tar ran: every job on #512 and #550 built fine and then failed with nothing in the log but the command. The self-test never saw it because `pack_packages ... || fail` suppresses errexit. Enumerate package files with a loop instead of toggling shell options, and add a test that calls both helpers under `bash -e` exactly as the workflows do; it fails against the old helper. --- helpers/artifact-helpers.sh | 30 +++++++++++++++++++----------- tests/artifact-helpers.sh | 9 +++++++++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/helpers/artifact-helpers.sh b/helpers/artifact-helpers.sh index 1747f57..3d8bb4f 100644 --- a/helpers/artifact-helpers.sh +++ b/helpers/artifact-helpers.sh @@ -5,14 +5,24 @@ # makepkg. So the files ride inside a tar with a plain name and keep their # own names untouched: pacman clients and bin/publish-artifact both rely on # the filename matching PKGINFO. +# +# Both functions run under the workflow's `bash -e`: nothing in them may +# return non-zero except the final failure. -# pack_packages : every *.pkg.tar.zst directly in into . -# Signatures and the scratch database next to them stay behind. +# package_files : the *.pkg.tar.zst directly in , one per line. +# Signatures and the scratch database next to them are not packages. +package_files() { + local f + for f in "$1"/*.pkg.tar.zst; do + [[ -e "$f" ]] && printf '%s\n' "$f" + done + return 0 +} + +# pack_packages : every package in into . pack_packages() { - local dir=$1 out=$2 restore files=() - restore=$(shopt -p nullglob); shopt -s nullglob - files=("$dir"/*.pkg.tar.zst) - $restore + local dir=$1 out=$2 files=() + mapfile -t files < <(package_files "$dir") (( ${#files[@]} )) || { echo "pack_packages: no *.pkg.tar.zst in $dir" >&2; return 1; } tar -cf "$out" -C "$dir" -- "${files[@]##*/}" } @@ -22,15 +32,13 @@ pack_packages() { # builds before packing hold the bare files. The bare form can go once # those artifacts have expired (7-day retention). unpack_packages() { - local src=$1 dest=$2 restore files=() + local src=$1 dest=$2 files=() mkdir -p "$dest" if [[ -f "$src/packages.tar" ]]; then tar -xf "$src/packages.tar" -C "$dest" - return + return 0 fi - restore=$(shopt -p nullglob); shopt -s nullglob - files=("$src"/*.pkg.tar.zst) - $restore + mapfile -t files < <(package_files "$src") (( ${#files[@]} )) || { echo "unpack_packages: nothing to unpack in $src" >&2; return 1; } cp -- "${files[@]}" "$dest/" } diff --git a/tests/artifact-helpers.sh b/tests/artifact-helpers.sh index a0a2fee..e3ea1a6 100755 --- a/tests/artifact-helpers.sh +++ b/tests/artifact-helpers.sh @@ -31,6 +31,15 @@ mkdir -p "$T/old" "$T/out2"; cp "$T/built"/*.pkg.tar.zst "$T/old/" unpack_packages "$T/old" "$T/out2" && [[ "$(ls "$T/out2" | sort | tr '\n' ' ')" == "$PLAIN $EPOCH " ]] \ && pass "a bare pre-packing artifact still unpacks" || fail "bare artifact" +# The workflows call these bare under `bash -e`, so any non-zero status +# inside them ends the step. (The first version used `shopt -p nullglob`, +# which exits 1 when the option is off; the tests above never saw it because +# `||` suppresses errexit.) +mkdir -p "$T/out4" "$T/out5" +bash -e -c "source '$ROOT/helpers/artifact-helpers.sh'; pack_packages '$T/built' '$T/out4/packages.tar'; tar -tf '$T/out4/packages.tar' >/dev/null; unpack_packages '$T/out4' '$T/out5'" \ + && [[ "$(ls "$T/out5" | sort | tr '\n' ' ')" == "$PLAIN $EPOCH " ]] \ + && pass "pack and unpack succeed under bash -e, as the workflows call them" || fail "bash -e" + mkdir -p "$T/empty" if pack_packages "$T/empty" "$T/x.tar" 2>/dev/null; then fail "packing an empty build dir should fail"; else pass "empty build dir refused"; fi if unpack_packages "$T/empty" "$T/out3" 2>/dev/null; then fail "an empty artifact should fail"; else pass "empty artifact refused"; fi From cb59806455d0ae608decd4c9d3726053aa572651 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 18:47:21 -0400 Subject: [PATCH 096/121] omasnap: update to 1.21.0 Upstream moved to omacom/omasnap and cut 1.21.0 from the same line as 1.20.1, so the version simply increases and no epoch is needed. check() flushes dirty pages before the smoke suite. The suite fsyncs its working documents under /tmp; on the CI droplets the build leaves about a gigabyte of dirty pages, and the flush that starts a few seconds into the suite made those fsyncs stall past the suite's 5-second settle windows on the first run after every build. --- pkgbuilds/omasnap/PKGBUILD | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/pkgbuilds/omasnap/PKGBUILD b/pkgbuilds/omasnap/PKGBUILD index 24b7e08..c5cf340 100644 --- a/pkgbuilds/omasnap/PKGBUILD +++ b/pkgbuilds/omasnap/PKGBUILD @@ -1,11 +1,11 @@ # Maintainer: Tobi Lütke pkgname=omasnap -pkgver=1.20.1 +pkgver=1.21.0 pkgrel=1 pkgdesc="Native Wayland screenshot and annotation overlay for Hyprland" arch=('x86_64' 'aarch64') -url="https://github.com/tobi/omasnap" +url="https://github.com/omacom/omasnap" license=('MIT' 'OFL-1.1') depends=( 'hyprland' @@ -25,7 +25,7 @@ makedepends=( options=('!debug') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('daf8fd17a81890661eebab791e6e78216c331e040043a1a6b72e638d3626b431') +sha256sums=('2f842edf67631825fa1e102876020040ea3e21341221a428b6aeee5580a9d928') build() { cmake -S "$pkgname-$pkgver" -B build -G Ninja \ @@ -35,8 +35,24 @@ build() { } check() { - QT_QPA_PLATFORM=offscreen \ - ./build/omasnap-smoke "$srcdir/omasnap-smoke-output" + # The smoke suite fsyncs its working documents under /tmp. On the CI + # droplets the build leaves about a gigabyte of dirty pages, and the + # flush that starts a few seconds into the suite makes those fsyncs stall + # long enough to overrun the suite's 5-second settle windows. Flush first. + local runtime_dir status started + started=$(date +%s%N); sync + echo "flushed dirty pages in $(( ($(date +%s%N) - started) / 1000000 )) ms" + runtime_dir=$(mktemp -d /dev/shm/omasnap-runtime.XXXXXX) + if QT_QPA_PLATFORM=offscreen QT_FORCE_STDERR_LOGGING=1 \ + XDG_RUNTIME_DIR="$runtime_dir" \ + ./build/omasnap-smoke "$srcdir/omasnap-smoke-output"; then + status=0 + else + status=$? + echo "omasnap-smoke exited with status $status" >&2 + fi + rm -r -- "$runtime_dir" + return "$status" } package() { From b7706e8f6240e6694fc374b64e62c14025fa2fee Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 01:48:15 +0200 Subject: [PATCH 097/121] Update Hype to 0.3.1 (#561) Co-authored-by: Claude Fable 5.1 --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 850059a..e61d515 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.3.0 +pkgver=0.3.1 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('f6b937da1f034616300e2c1ce8ef7cd70d47c5284ce4c572509b3dfd2cbcc9f3') +sha256sums=('cdc347649885aaa7c735562066a21ce9148f18e4c4e6ab54525c90f26e12eea7') build() { cd "$srcdir/$pkgname-$pkgver" From c74c708f3552e056fb55deb750c5647c073b4dbd Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 21:09:55 -0400 Subject: [PATCH 098/121] Reuse existing build artifacts when a PR's package tree is unchanged Every push to a PR rebuilt every package the PR touches, on every architecture, even when only one of them changed. The daily sync PR carries around thirty package/arch pairs; fixing one package meant rebuilding all of them, and an aarch64 build under QEMU takes up to an hour. Nine runs of that PR cost about 36 droplet-hours in two days. The planner now asks the artifact store for -- before adding an entry to the matrix and drops entries that already have one. That is the same lookup publish.yml makes on merge, so a reused entry publishes exactly the file it would have anyway. Dry run against the current sync PR: 27 of 31 entries reused, 4 built. Pack and Upload no longer run with always(): only a successful build uploads, so an artifact's existence means that tree built. workflow_dispatch always builds; it is an explicit request. --- .github/workflows/build-pr.yml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 77bcf2e..ab0bec4 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -81,6 +81,8 @@ jobs: # once, against edge; the channels it ships to on merge are carried # along for information. A filename means one set of bytes. - id: list + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | if [[ -n "${{ github.event.inputs.packages }}" ]]; then names="${{ github.event.inputs.packages }}" @@ -89,6 +91,29 @@ jobs: | awk -F/ '$1=="pkgbuilds" && NF>2 {print $2}' | sort -u) fi matrix=$(printf '%s\n' $names | bin/build-matrix) + # A package directory whose exact tree already has a build artifact + # (label --, uploaded only after a successful + # build) is not built again. Pushing a fix for one package to a PR + # that touches fifty rebuilds one, not fifty; publish.yml finds the + # same artifacts on merge. workflow_dispatch is an explicit request + # and always builds. + if [[ "${{ github.event_name }}" == pull_request ]]; then + head="${{ github.event.pull_request.head.sha }}" + kept=(); reused=() + while read -r entry; do + package=$(jq -r .package <<<"$entry"); arch=$(jq -r .arch <<<"$entry") + label="$package-$arch-$(git rev-parse "$head:pkgbuilds/$package")" + found=$(curl -fsS -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/${{ github.repository }}/actions/artifacts?name=$label&per_page=5" \ + | jq -r '[.artifacts[] | select(.expired|not)] | length' || echo 0) + if (( found > 0 )); then reused+=("$label"); else kept+=("$entry"); fi + done < <(jq -c '.include[]' <<<"$matrix") + matrix=$(printf '%s\n' "${kept[@]}" | jq -sc '{include: .}') + if (( ${#reused[@]} )); then + printf '==> already built, reusing the artifact: %s\n' "${reused[@]}" + { echo "Reused existing build artifacts (${#reused[@]}):"; printf -- '- %s\n' "${reused[@]}"; } >> "$GITHUB_STEP_SUMMARY" + fi + fi echo "matrix=$matrix" >> "$GITHUB_OUTPUT" echo "planned=$(jq '.include | length' <<<"$matrix")" >> "$GITHUB_OUTPUT" jq -r '.include[] | "\(.package) \(.arch) -> \(.channels)"' <<<"$matrix" @@ -163,6 +188,7 @@ jobs: echo "tooling: $(git rev-parse --short HEAD) (base) packages: ${{ github.event.pull_request.head.sha }} (PR head)" git status --short | head - name: Build ${{ matrix.package }} (${{ matrix.arch }}, ships to ${{ matrix.channels }}) + id: build env: CONTAINER_ENGINE: docker run: bin/build --mirror edge --arch ${{ matrix.arch }} --package ${{ matrix.package }} @@ -176,16 +202,16 @@ jobs: run: echo "hash=$(git rev-parse "${{ github.event.pull_request.head.sha || github.sha }}:pkgbuilds/${{ matrix.package }}")" >> "$GITHUB_OUTPUT" # The upload action rejects a path containing ':', which is how makepkg # names a package with an epoch. The files ride inside packages.tar - # (helpers/artifact-helpers.sh); publish.yml unpacks it. + # (helpers/artifact-helpers.sh); publish.yml unpacks it. Only a + # successful build uploads: the artifact's existence is what lets the + # planner above and publish.yml skip rebuilding this exact tree. - name: Pack artifact id: pack - if: always() run: | source helpers/artifact-helpers.sh pack_packages build-output/edge/${{ matrix.arch }} packages.tar tar -tvf packages.tar - name: Upload artifact - if: always() && steps.pack.outcome == 'success' uses: actions/upload-artifact@v4 with: name: ${{ matrix.package }}-${{ matrix.arch }}-${{ steps.tree.outputs.hash }} From 1c0ea5be845113dc77900f989fbed456f03b7391 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Sun, 20 Sep 2026 19:29:34 -0400 Subject: [PATCH 099/121] strata: update to 0.19.0, skip two tests the build host cannot run 0.19.0 adds two restart_waiter tests that run `sh -c 'while kill -0 "$1"; do sleep; done'` with the pid u32::MAX. Arch's sh is bash 5.3, whose kill builtin in POSIX mode prints "not a pid or valid job spec" for that number but exits 0, so the loop never ends; every droplet build of 0.19.0 sat there until the 180-minute job timeout. Upstream CI runs on Ubuntu, where sh is dash and rejects the number. It also adds ownership_probe_errors_disable_in_place_updates, which points the pacman path at a directory and expects Command::output() to fail. aarch64 builds run under QEMU user-mode emulation, where glibc's posix_spawn cannot observe the child's failed execve; the spawn succeeds with exit 127 and the assertion fails. Skipped on aarch64 only; it passes natively. Both skips carry comments; the sync bot rewrites only version fields, so they survive future syncs. --- pkgbuilds/strata/PKGBUILD | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pkgbuilds/strata/PKGBUILD b/pkgbuilds/strata/PKGBUILD index a94b4ed..11cbbd1 100644 --- a/pkgbuilds/strata/PKGBUILD +++ b/pkgbuilds/strata/PKGBUILD @@ -1,5 +1,5 @@ pkgname=strata -pkgver=0.18.0 +pkgver=0.19.0 pkgrel=1 pkgdesc='Fast, keyboard-first file manager for modern Linux desktops' arch=('x86_64' 'aarch64') @@ -39,7 +39,7 @@ conflicts=('strata-git') options=('!debug' '!lto') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('82cfa5701f537e53d235b30e9450e1fcd5f2e7ccfea64ba317941e8e8766094b') +sha256sums=('51701930728625ce1d6394949a4b6b2705f0999fd08be87f1a26d900209d62e0') prepare() { cd "$pkgname-$pkgver" @@ -84,8 +84,22 @@ check() { rm -rf -- "$search_tmp" (( test_status == 0 )) || return "$test_status" + # restart_waiter_* run `sh -c 'while kill -0 "$1"; do sleep; done'` with + # the pid u32::MAX. Arch's sh is bash, and bash's kill builtin in POSIX + # mode prints "not a pid or valid job spec" for that number but exits 0, + # so the loop never ends and the job hits its 180-minute timeout. + # Upstream CI runs on Ubuntu, where sh is dash and rejects the number. + # Skip until upstream waits on a real pid. + local skip=(--skip services::search::tests:: --skip ui::settings::tests::restart_waiter_) + # ownership_probe_errors_disable_in_place_updates points the pacman path + # at a directory and expects Command::output() to fail. aarch64 builds + # run under QEMU user-mode emulation, where glibc's posix_spawn cannot + # observe the child's failed execve (natively it returns EACCES); the + # spawn "succeeds" with exit 127, the probe reads that as "not owned", + # and the assertion fails. Passes natively. + [[ $CARCH == aarch64 ]] && skip+=(--skip services::update_install::tests::ownership_probe_errors_disable_in_place_updates) cargo test --frozen --release --all-targets --all-features \ - -- --test-threads=1 --skip services::search::tests:: + -- --test-threads=1 "${skip[@]}" } package() { From 42493fa731752e5b8e8962f95522ead3c000d1b6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Sep 2026 20:35:00 -0500 Subject: [PATCH 100/121] Update OWE and lock feed to 0.2.2 --- pkgbuilds/owe-lockfeed/PKGBUILD | 8 ++++++-- pkgbuilds/owe/PKGBUILD | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/owe-lockfeed/PKGBUILD b/pkgbuilds/owe-lockfeed/PKGBUILD index 137329f..c05c90d 100644 --- a/pkgbuilds/owe-lockfeed/PKGBUILD +++ b/pkgbuilds/owe-lockfeed/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe-lockfeed -pkgver=0.2.0 +pkgver=0.2.2 pkgrel=1 pkgdesc="Lock screen video feed module for the OWE wallpaper engine" arch=('x86_64' 'aarch64') @@ -9,7 +9,7 @@ license=('MIT') depends=('qt6-declarative') makedepends=('cmake' 'qt6-declarative') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('d667048b0096bbcbb508c0cedd460bf5fb669fafffdcefc432f2886e284295c8') +sha256sums=('80336cae4e3e90336b9597274883a3ef4a219e3bcf638026c2532065e38f8143') build() { cmake -S "$srcdir/owe-$pkgver/qml-plugin" -B build \ @@ -19,6 +19,10 @@ build() { cmake --build build } +check() { + ctest --test-dir build --output-on-failure +} + package() { DESTDIR="$pkgdir" cmake --install build } diff --git a/pkgbuilds/owe/PKGBUILD b/pkgbuilds/owe/PKGBUILD index 4cb2cc4..cf2d0c2 100644 --- a/pkgbuilds/owe/PKGBUILD +++ b/pkgbuilds/owe/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe -pkgver=0.2.0 +pkgver=0.2.2 pkgrel=1 pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)" arch=('x86_64' 'aarch64') @@ -12,7 +12,7 @@ checkdepends=('python') optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs' 'libva-mesa-driver: VAAPI hardware decode on AMD GPUs') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('d667048b0096bbcbb508c0cedd460bf5fb669fafffdcefc432f2886e284295c8') +sha256sums=('80336cae4e3e90336b9597274883a3ef4a219e3bcf638026c2532065e38f8143') build() { meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr From 5e98f9d810116c39902218dbad10888f242697cc Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 21 Sep 2026 00:13:46 -0400 Subject: [PATCH 101/121] flea: update to 0.3.1, run shelfundo tests on tmpfs, skip three under QEMU flea 0.3.0 never published: its shelfundo suite (new in 0.3.0) failed check() on the 2026-09-18 publish build, and 0.3.1 fails the same way on the sync PR. undo_refuses_to_walk_a_stranger_back deletes a file, creates another under the same name, and expects undo to tell them apart by (dev, ino, kind). ext4 hands the freed inode number straight back to the next create, so on the droplet's /tmp the stranger is identical and undo walks it back into a directory that does not exist. tmpfs allocates inode numbers from a counter and never reuses one. The suite joins the filesystem tests that already run with TMPDIR on /dev/shm. On aarch64 three more tests fail: two in backend::child and one in menu_registry expect spawning a missing program to be reported as not started. Under QEMU user-mode emulation glibc's posix_spawn cannot observe the child's failed execve; the spawn succeeds with exit 127. Skipped on aarch64 only. --- pkgbuilds/flea/PKGBUILD | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/flea/PKGBUILD b/pkgbuilds/flea/PKGBUILD index 1c15737..2808c60 100644 --- a/pkgbuilds/flea/PKGBUILD +++ b/pkgbuilds/flea/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: GM pkgname=flea -pkgver=0.3.0 +pkgver=0.3.1 pkgrel=1 pkgdesc='Fast, keyboard-first file manager for Omarchy' arch=('x86_64' 'aarch64') @@ -52,7 +52,7 @@ options=('!debug') source=( "$url/releases/download/v$pkgver/$pkgname-v$pkgver.tar.gz" ) -sha256sums=('975fe4c3d6ee91470be9fe8835e247ec3054e74b1682a8315e19c3aedbef8d05') +sha256sums=('b146ac3f5025da987eae623c4392c44ce69a6a7275a8df3ec1a84563920a4dd2') build() { cd "$pkgname-$pkgver" @@ -103,6 +103,12 @@ check() { # not provide. Keep executable fixtures in the remaining suites on the normal # temp root (/dev/shm is noexec). Note that /dev/shm does NOT buy finer # timestamps -- see the skip below. + # shelfundo::tests::undo_refuses_to_walk_a_stranger_back deletes a file, + # creates another under the same name, and expects undo to tell them + # apart by (dev, ino, kind). ext4 hands the freed inode number straight + # back to the next create, so on the builder's /tmp the stranger is + # identical and undo walks it back. tmpfs allocates inode numbers from a + # counter and never reuses one, which is what the test assumes. local -a filesystem_tests=( backend::menu_actions::tests:: backend::menudelete::tests:: @@ -110,6 +116,7 @@ check() { backend::trashbrowse::tests:: backend::trashdelete:: backend::trashmanifest::tests:: + shelfundo::tests:: ) # redo_refuses_changed_sources_and_destination_collisions writes a file and # then immediately asks redo to notice the edit. flea decides "changed" from @@ -127,6 +134,19 @@ check() { --skip backend::redo::tests::redo_refuses_changed_sources_and_destination_collisions ) + # These three expect spawning a missing or failing program to be reported + # as such. aarch64 builds run under QEMU user-mode emulation, where + # glibc's posix_spawn cannot see the child's failed execve: the spawn + # "succeeds" with exit 127, and the timing test's child never sleeps. + # Passes natively. + if [[ $CARCH == aarch64 ]]; then + test_args+=( + --skip backend::child::tests::a_child_is_noticed_when_it_exits_rather_than_at_the_next_poll_boundary + --skip backend::child::tests::a_child_that_never_started_is_told_apart_from_one_that_ran_and_failed + --skip backend::menu_registry::tests::unavailable_failed_and_oversized_queries_are_named_errors + ) + fi + local test_tmp test_status=0 suite test_tmp=$(mktemp -d /dev/shm/flea-tests.XXXXXXXX) || return 1 TMPDIR="$test_tmp" cargo test --frozen --release -- \ From 016491b41c66344be3a2c11b20844c3d4891787a Mon Sep 17 00:00:00 2001 From: ryanrhughes <1630358+ryanrhughes@users.noreply.github.com> Date: Mon, 21 Sep 2026 04:47:32 +0000 Subject: [PATCH 102/121] chore: sync upstream releases --- pkgbuilds/aether/PKGBUILD | 8 ++++---- pkgbuilds/claude-code/PKGBUILD | 6 +++--- pkgbuilds/cursor-bin/PKGBUILD | 6 +++--- pkgbuilds/cursor-cli/PKGBUILD | 6 +++--- pkgbuilds/limine-snapper-sync/PKGBUILD | 6 +++--- pkgbuilds/lmstudio-bin/PKGBUILD | 8 +++----- pkgbuilds/mise-bin/PKGBUILD | 6 +++--- pkgbuilds/omarchy-billboard-generator/PKGBUILD | 4 ++-- pkgbuilds/openai-codex-bin/PKGBUILD | 8 +++----- pkgbuilds/openai-codex-desktop/PKGBUILD | 6 +++--- pkgbuilds/openclaw/PKGBUILD | 4 ++-- pkgbuilds/schist-bin/PKGBUILD | 6 +++--- 12 files changed, 35 insertions(+), 39 deletions(-) diff --git a/pkgbuilds/aether/PKGBUILD b/pkgbuilds/aether/PKGBUILD index 5456db6..cef077c 100644 --- a/pkgbuilds/aether/PKGBUILD +++ b/pkgbuilds/aether/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Bjarne Øverli pkgname=aether -pkgver=4.29.9 +pkgver=4.30.0 pkgrel=1 pkgdesc='Desktop theming application - extract colors from wallpapers and apply cohesive themes' arch=('x86_64' 'aarch64') @@ -10,9 +10,9 @@ depends=('webkit2gtk-4.1' 'gtk3') source=("aether-${pkgver}.tar.gz::https://github.com/omacom/aether/archive/refs/tags/v${pkgver}.tar.gz") source_x86_64=("aether-linux-amd64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-amd64") source_aarch64=("aether-linux-arm64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-arm64") -sha256sums=('d5f39da9f2566783f7be194efca41b20627e62e79f83c3ff944dd3d0511f0c15') -sha256sums_x86_64=('073784620a18931e8f1389e9e9e8a70dae1458eceda6fce608ae1290f77bee99') -sha256sums_aarch64=('5041c62b0638876d3ee907703bc95b5c2a0d3b1ab3f3a5257997a452cf60ca10') +sha256sums=('f67c8d2c6f27f67a755bc279ece5ddb194f1bb165648280b9a7be86904d36ff5') +sha256sums_x86_64=('75bda600ddd3ecab3338de5c0c5d5e2c9f08cfc0c465b63f8e6cb9c5cb60d68e') +sha256sums_aarch64=('a91d800736def74d86e19d8acbecc4bda3d7c3e64fb95273f809707104c3a5bc') noextract=("aether-linux-amd64-${pkgver}" "aether-linux-arm64-${pkgver}") package() { diff --git a/pkgbuilds/claude-code/PKGBUILD b/pkgbuilds/claude-code/PKGBUILD index b8da20f..10c950a 100644 --- a/pkgbuilds/claude-code/PKGBUILD +++ b/pkgbuilds/claude-code/PKGBUILD @@ -4,7 +4,7 @@ # Automation repository: https://github.com/fabifont/claude-code-aur pkgname=claude-code -pkgver=2.1.276 +pkgver=2.1.278 pkgrel=1 pkgdesc="An agentic coding tool that lives in your terminal" arch=('x86_64' 'aarch64') @@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude") sha256sums=('SKIP') -sha256sums_x86_64=('8a56c8a14bd3cb246e2bdb7e60aefe0f609bff78c8bbcc5ea6b1817c111c6145') -sha256sums_aarch64=('e9ac3df956083645578a382ad64ec304468666e362c33bfdefd803cd6ff596b0') +sha256sums_x86_64=('5c4735937844e84f8a93306e841a5b0e12252909b07870f789b190468da147ab') +sha256sums_aarch64=('7de6cab134e48321148e30182c98614118e8f4666819412bead45865190b34ed') package() { install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude" diff --git a/pkgbuilds/cursor-bin/PKGBUILD b/pkgbuilds/cursor-bin/PKGBUILD index 573c3e8..c8f1c89 100644 --- a/pkgbuilds/cursor-bin/PKGBUILD +++ b/pkgbuilds/cursor-bin/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Gunther Schulz pkgname=cursor-bin -pkgver=3.21.9 +pkgver=3.21.16 pkgrel=1 pkgdesc='AI-first coding environment' arch=('x86_64') @@ -12,11 +12,11 @@ _electron=electron42 depends=(xdg-utils ripgrep $_electron nodejs 'gcc-libs' 'hicolor-icon-theme' 'libxkbfile') options=(!strip !debug) # Don't break ext of VSCode -_commit=9998796a6096ce83d83a9332bfe7473b985db750 +_commit=8ae78e8eee1e63479c7e0504b664bc0a80c6800f source=("https://downloads.cursor.com/production/${_commit}/linux/x64/deb/amd64/deb/cursor_${pkgver}_amd64.deb" "https://gitlab.archlinux.org/archlinux/packaging/packages/code/-/raw/main/code."{sh,mjs} rg.sh) -sha512sums=('a1c26cc9add2bb593068f11bbb18165a5934ccaebe380019b84a552641aad41c942357c600d55998e47cbcd86f0a1d862a295b3502d269f06167cd6891043d71' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') +sha512sums=('032c86a5d51f154ce36b1a0bf34aa06b2d117666b4372a787ea3117fc0b2b1686e952c721388f2eaf7787f2e0581378c98608048126f7470df2e85e9dbd75ca4' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') noextract=(cursor_${pkgver}_amd64.deb) # avoid double tarball _app=usr/share/cursor/resources/app package() { diff --git a/pkgbuilds/cursor-cli/PKGBUILD b/pkgbuilds/cursor-cli/PKGBUILD index 11205d0..c8fc1d5 100644 --- a/pkgbuilds/cursor-cli/PKGBUILD +++ b/pkgbuilds/cursor-cli/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ismet Togay # Contributor: Christopher Cooper pkgname=cursor-cli -pkgver=2026.09.15.1.d2fe57e +pkgver=2026.09.18.1.9a7762b # Upstream is YYYY.MM.DD-. pkgver cannot contain hyphens, and hashes are # not monotonically ordered, so pkgver is YYYY.MM.DD..: n resets to 1 # on a new date and increments when the same date gets a new hash. @@ -25,8 +25,8 @@ source_x86_64=("cursor-cli-${_upstream_ver}-x86_64.tar.gz::https://downloads.cur source_aarch64=("cursor-cli-${_upstream_ver}-aarch64.tar.gz::https://downloads.cursor.com/lab/${_upstream_ver}/linux/arm64/agent-cli-package.tar.gz") b2sums=('d241ee9895bdb1c17514438fde8528222a8f2326568bd7a033d7a1b11432ce6b4575ff1a50625764bfe6bc6f8a9dc060f7439c3be7e95f8fd02912cdd37a011d' '1928e04c713e13911ea607f84c3e4a2fed1f76af9795503811078f43d2b53c753e28b2233e553fc17e766831800fb0dbc272aad2a80b387f95ba6071d7d4116a') -b2sums_x86_64=('ba078241313672770d91286f433b9f0e94aba6f3dd3f7b0e38b927a1dd9d2adc322ac54e8e04f6b87a42d020edbd8929070c330b23bc536a59ab998fdb6200cb') -b2sums_aarch64=('b3fb72843237b79b69b89c3d586bb4f56412bf26b444d08c174ffce8b8774c1be95452fcd84a4278ddcb9381a656d5b1e5dcd2e967d224c356ae31241e4044b2') +b2sums_x86_64=('3fccee6929df1042d03461895e56c222a996d3ae9e4f9c61dcc5e6ab7b1d075d3265c21a44f48dd94de0dcde4f8012cc39bfbf323e2bb0c6106cac79885c35ae') +b2sums_aarch64=('3d3bb0a3cb7e2409acf4925f207eaa4e3f41782c3c947e2834b69664b116b972da0b67eea17147fc524ea248af9919494570adc7c48d12c44f12deca17ba2c28') prepare() { # Block cursor-agent auto-updates by making its versions directory diff --git a/pkgbuilds/limine-snapper-sync/PKGBUILD b/pkgbuilds/limine-snapper-sync/PKGBUILD index 97d9add..51fd558 100644 --- a/pkgbuilds/limine-snapper-sync/PKGBUILD +++ b/pkgbuilds/limine-snapper-sync/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Zesko pkgname="limine-snapper-sync" -pkgver=1.31.0 -pkgrel=1.1 +pkgver=1.32.0 +pkgrel=1 _gradle_version=9.7.1 pkgdesc="Integrates Limine boot entries with Snapper snapshots." arch=('x86_64' 'aarch64') @@ -31,7 +31,7 @@ makedepends=('git') makedepends_x86_64=('gradle') backup=(etc/limine-snapper-sync.conf) conflicts=('limine-snapper-cli' 'limine-snapper-sync-git') -sha256sums=('ed236f1bbab966950bf11ba5a7958e97a76e66db7fd647b7737bab4b48c9fc40') +sha256sums=('6bcc1d3ace58030204260a9a4d40d500c4822416be1b1c6edd153d1df0796b3d') sha256sums_x86_64=('e0be791c8fda4d03b6b0a0cb824fef3149736170057b3a515252b44419606af0') sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71' 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a') diff --git a/pkgbuilds/lmstudio-bin/PKGBUILD b/pkgbuilds/lmstudio-bin/PKGBUILD index 48b1a59..dc1d90e 100644 --- a/pkgbuilds/lmstudio-bin/PKGBUILD +++ b/pkgbuilds/lmstudio-bin/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: noureddinex pkgname=lmstudio-bin -pkgver=0.4.24 -pkgrel=2 +pkgver=0.4.25 +pkgrel=1 _build=1 _pkgver=${pkgver}-${_build} pkgdesc="LM Studio - A desktop app for exploring and running large language models locally" @@ -16,9 +16,7 @@ conflicts=(lmstudio) source=("https://installers.lmstudio.ai/linux/x64/${_pkgver}/LM-Studio-${_pkgver}-x64.AppImage" "lmstudio.png" "lmstudio.desktop") -sha256sums=('17cb8ac6374f9182fc127efae20680265e3c4c17d96eadf147eb5fe6111a9353' - '9f791789c959a11316328692807737a5f1bc1c170ae99ec04c56bfd8ee8263e5' - '635dec12f3e3a57136b9e6fd7c2839ed6da7287fa55b482d64debf6eacf36baa') +sha256sums=('eca467446c833824697e8befab300fe5269fdf984e3ee4385fcbad8502f07c53' '9f791789c959a11316328692807737a5f1bc1c170ae99ec04c56bfd8ee8263e5' '635dec12f3e3a57136b9e6fd7c2839ed6da7287fa55b482d64debf6eacf36baa') prepare() { chmod +x "${srcdir}/${source[0]##*/}" diff --git a/pkgbuilds/mise-bin/PKGBUILD b/pkgbuilds/mise-bin/PKGBUILD index 7162891..7de0e56 100644 --- a/pkgbuilds/mise-bin/PKGBUILD +++ b/pkgbuilds/mise-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Jeff Dickey pkgname=mise-bin -pkgver=2026.9.10 +pkgver=2026.9.11 pkgrel=1 pkgdesc="dev tools, env vars, task runner" arch=('x86_64' 'aarch64') @@ -14,8 +14,8 @@ provides=('mise') conflicts=('mise') source_x86_64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-x64.tar.xz") source_aarch64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-arm64.tar.xz") -sha256sums_x86_64=('c5e4b03cb8266d3114e1c9322924608652fbb5bbcc3347928dbe86cd8b2fa654') -sha256sums_aarch64=('21697d5388315a5271cd7e3b56e12b1a3603796640f8f5760b3e7698d18a49f8') +sha256sums_x86_64=('aec93997952d33a28e4317a4a84cdc473a14361b809c0a2e681811bac2c7d174') +sha256sums_aarch64=('2225f1c443b74cb92098245f62673df9e8dfc1cd8cd66d3921d72f9496963ef5') package() { install -Dm755 "${srcdir}/mise/bin/mise" "${pkgdir}/usr/bin/mise" diff --git a/pkgbuilds/omarchy-billboard-generator/PKGBUILD b/pkgbuilds/omarchy-billboard-generator/PKGBUILD index 0cce74c..b714a61 100644 --- a/pkgbuilds/omarchy-billboard-generator/PKGBUILD +++ b/pkgbuilds/omarchy-billboard-generator/PKGBUILD @@ -5,7 +5,7 @@ # runtime dependencies found on PATH, never downloaded. pkgname=omarchy-billboard-generator -pkgver=0.1.2 +pkgver=0.2.0 pkgrel=1 pkgdesc='Desktop app and CLI that renders animated OMARCHY domain videos' arch=('any') @@ -18,7 +18,7 @@ license=('MIT' 'Apache-2.0' '0BSD' 'OFL-1.1' 'LicenseRef-Omarchy') depends=('nodejs>=22' 'chromium' 'ffmpeg' 'xdg-utils') makedepends=('npm') source=("${pkgname}-${pkgver}.tar.gz::${url}/releases/download/v${pkgver}/${pkgname}.tar.gz") -sha256sums=('e457d061f6714d4c032c980ce00aad1cb57d5753b42dc174a55c31c329a8d641') +sha256sums=('f499dfc1201ed3d6b8fba271496fcd4c8fc6301427f4f2fc53aab8d9c3f64f67') # Pure JavaScript and WebAssembly; nothing here is an ELF to strip. options=('!strip' '!debug') diff --git a/pkgbuilds/openai-codex-bin/PKGBUILD b/pkgbuilds/openai-codex-bin/PKGBUILD index 6cdbbb0..64e5687 100644 --- a/pkgbuilds/openai-codex-bin/PKGBUILD +++ b/pkgbuilds/openai-codex-bin/PKGBUILD @@ -2,7 +2,7 @@ # shellcheck disable=SC2034 # Maintainer: Chmouel Boudjnah pkgname=openai-codex-bin -pkgver=0.154.0 +pkgver=0.155.1 pkgrel=1 pkgdesc="Arch Linux package for OpenAI's Codex CLI - Auto Updated" arch=('x86_64' 'aarch64') @@ -21,10 +21,8 @@ source_x86_64=( "codex-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-x86_64-unknown-linux-musl.tar.gz" "codex-code-mode-host-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-code-mode-host-x86_64-unknown-linux-musl.tar.gz" ) -sha256sums_x86_64=('d7e18b2597ae8f242f5f31ee9e90deef48dbc9edd634d9868fb6435d08c07f02' - 'a68df7cca23c6da7cde175677df7de61c73a234add1333a1254b86d641af01f7') -sha256sums_aarch64=('583b48df32804213bdcd338c2e5adb06b34340821fa757a726cc0a524fa33c27' - '20aefa302c2022b496e32911bf954a5f76c7fd749c6bdb9fbd711e32b66dcbfa') +sha256sums_x86_64=('a0ef8b2debc3bf747e07b1a039354de31300ac0dcc2276498ba281470b5d9115' '9fd083743af55be818aceb351d371fb5136f5b6aa3938f167087373d27067b2d') +sha256sums_aarch64=('d6c7e62fbd688d52ee04f3929d0613705d32a920a42db7a139e366eaf1f4a2d7' '516f2ed76d4ae96c2074d3c08f4576ed1bdc5c3a97e26734d7319de8b6861683') source_aarch64=( "codex-${pkgver}-aarch64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-aarch64-unknown-linux-musl.tar.gz" diff --git a/pkgbuilds/openai-codex-desktop/PKGBUILD b/pkgbuilds/openai-codex-desktop/PKGBUILD index 5f72989..8ca352d 100644 --- a/pkgbuilds/openai-codex-desktop/PKGBUILD +++ b/pkgbuilds/openai-codex-desktop/PKGBUILD @@ -5,7 +5,7 @@ # the version and checksums below from that repository's package index. pkgname=openai-codex-desktop -pkgver=26.915.31029 +pkgver=26.915.31945 pkgrel=1 pkgdesc="Official ChatGPT desktop app with Codex" arch=('x86_64' 'aarch64') @@ -71,8 +71,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c') -sha256sums_x86_64=('932825b76a41e80643204a9aa9ccfd1cb2471ffbfcbe1d314994360fcaaffb35') -sha256sums_aarch64=('5c01ce35eccea9e95d16de052c74f16deed381408931e82b106d7dbeeed8de4a') +sha256sums_x86_64=('d27a9c02919cfe484dcc5f34584b9ea9fd0d7a65c69dcc872b5bdcfa0efb5983') +sha256sums_aarch64=('b94c494b5f0fd7c720fa6fccd5ef609879affc62332ca930ed29b907d537bc6d') package() { cd "${srcdir}" diff --git a/pkgbuilds/openclaw/PKGBUILD b/pkgbuilds/openclaw/PKGBUILD index 71acd80..2cf1665 100644 --- a/pkgbuilds/openclaw/PKGBUILD +++ b/pkgbuilds/openclaw/PKGBUILD @@ -7,7 +7,7 @@ # upstream's release cadence outruns the AUR. pkgname=openclaw -pkgver=2026.9.4 +pkgver=2026.9.5 pkgrel=1 pkgdesc='Multi-channel AI gateway with extensible messaging integrations' arch=(x86_64 aarch64) @@ -29,7 +29,7 @@ optdepends=( 'go: for installing skill tools not packaged for Arch' ) source=($pkgname-$pkgver.tgz::https://registry.npmjs.org/$pkgname/-/$pkgname-$pkgver.tgz) -sha256sums=('4f1f656770461d4677dea755b1899cba12b912b06798c89a59e2f0c18688b761') +sha256sums=('1fb6ef4fae447af14f1e3b1028334f39146d181a66a4cce2848d4f741c636340') options=(!debug !strip) install=$pkgname.install noextract=($pkgname-$pkgver.tgz) diff --git a/pkgbuilds/schist-bin/PKGBUILD b/pkgbuilds/schist-bin/PKGBUILD index 3df4afc..e144cd5 100644 --- a/pkgbuilds/schist-bin/PKGBUILD +++ b/pkgbuilds/schist-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Infrawrench LLC pkgname=schist-bin -pkgver=0.13.0 +pkgver=0.14.0 pkgrel=1 # Upstream's own package release, embedded in the asset name. It is # packages.sh's "release=" and only moves when the packaging changes under @@ -32,8 +32,8 @@ options=(!strip !debug) # script. source_x86_64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-x86_64.pkg.tar.zst") source_aarch64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-aarch64.pkg.tar.zst") -sha256sums_x86_64=('6070dd346ebd69898437d6dfb6c071cca80c82045581feeeba6542264ae23096') -sha256sums_aarch64=('d5eef7b737b35d32a31f3ae34de0a16ab3178348b44245a8096b8d70fe7b03c1') +sha256sums_x86_64=('1e7f51ed0141f4573c65296f73d9e7005c897c1b2fb39085f3d6f7f95bbcefbf') +sha256sums_aarch64=('52c0d6810094183ea1dc2248a147e60afae98ce63f0b41975dafa7f63644ef20') package() { # makepkg has already extracted the payload into srcdir; its .PKGINFO From ec814346842baf57975ba83784f6902cc376aef8 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 21 Sep 2026 02:16:27 -0400 Subject: [PATCH 103/121] strata, flea: compile the test harness in parallel Both upstreams set fat LTO in their release profile (strata also codegen-units = 1), which compiles the final crate on one thread. That is a reasonable trade for the binary users run, and build() keeps it. check() then compiled the same crate a second time under the same profile for the test harness, and threw it away. On the aarch64 builds, which run under QEMU, those two serial compiles were 106 of strata's 118 minutes. check() now builds the harness with thin LTO and 16 codegen units in its own target directory. The shipped binary is unchanged. Measured on the x86_64 builder for strata's test binary: 708 s serial, 223 s with this profile. Local run: shipped strata still 7m30s from target/, tests 3m43s from target-check/, 1998 passed. ttfx has the same upstream profile but no check(), so nothing to do. --- pkgbuilds/flea/PKGBUILD | 10 ++++++++-- pkgbuilds/strata/PKGBUILD | 13 +++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/flea/PKGBUILD b/pkgbuilds/flea/PKGBUILD index 2808c60..a8cd3fd 100644 --- a/pkgbuilds/flea/PKGBUILD +++ b/pkgbuilds/flea/PKGBUILD @@ -2,7 +2,7 @@ pkgname=flea pkgver=0.3.1 -pkgrel=1 +pkgrel=2 pkgdesc='Fast, keyboard-first file manager for Omarchy' arch=('x86_64' 'aarch64') url='https://github.com/thisisgm/flea' @@ -64,7 +64,13 @@ build() { check() { cd "$pkgname-$pkgver" - export CARGO_TARGET_DIR=target + # Upstream's release profile uses fat LTO, whose final link runs on one + # thread. build() keeps it for the shipped binary; the test harness is a + # throwaway second compile, so build it in parallel in its own target + # directory. + export CARGO_TARGET_DIR=target-check + export CARGO_PROFILE_RELEASE_LTO=thin + export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 local -a test_args=() if ! /usr/bin/prlimit --cpu=30 --as=1073741824 \ diff --git a/pkgbuilds/strata/PKGBUILD b/pkgbuilds/strata/PKGBUILD index 11cbbd1..4b6a14b 100644 --- a/pkgbuilds/strata/PKGBUILD +++ b/pkgbuilds/strata/PKGBUILD @@ -1,6 +1,6 @@ pkgname=strata pkgver=0.19.0 -pkgrel=1 +pkgrel=2 pkgdesc='Fast, keyboard-first file manager for modern Linux desktops' arch=('x86_64' 'aarch64') url='https://github.com/lgse/strata' @@ -69,7 +69,16 @@ build() { check() { cd "$pkgname-$pkgver" - export CARGO_TARGET_DIR=target + # Upstream's release profile is fat LTO with one codegen unit, which + # compiles the final crate on a single thread. That is the right trade + # for the binary users run, and build() keeps it. The test harness is a + # second compile of the same crate under the same profile, thrown away + # afterwards; build it in parallel, in its own target directory so the + # shipped binary is untouched. Measured on the x86_64 builder: 708 s + # serial, 223 s with thin LTO and 16 units. + export CARGO_TARGET_DIR=target-check + export CARGO_PROFILE_RELEASE_LTO=thin + export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 export STRATA_BUILD_COMMIT STRATA_BUILD_COMMIT=$(<.build-commit) export STRATA_RELEASE_TAG="v$pkgver" From b2e3469827f4d824472148adc052fa41b3d6f0bb Mon Sep 17 00:00:00 2001 From: Kartik Rao <007kartik007@gmail.com> Date: Tue, 8 Sep 2026 15:40:14 +0530 Subject: [PATCH 104/121] omarchy-nvim: point monokai-pro at loctvl842 (repo not found) The all-themes.lua spec references "gthelding/monokai-pro.nvim", a fork that no longer exists on GitHub (HTTP 404). On every launch lazy.nvim fails to clone it and reports "repository not found", and leaves a stale lazy/monokai-pro.nvim.cloning marker so the error repeats. Restore the canonical, actively maintained upstream "loctvl842/monokai-pro.nvim" -- the value this line held before 80a278206 ("Match nvim themes"). It registers the same "monokai-pro" colorscheme and still supports filter = "ristretto" plus the setup override used by Omarchy 3.8's themes/ristretto/neovim.lua, so nothing downstream changes except that the plugin resolves again. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_011FcsS1gPeUiLSqqi4iKgzm --- pkgbuilds/omarchy-nvim/lua/plugins/all-themes.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgbuilds/omarchy-nvim/lua/plugins/all-themes.lua b/pkgbuilds/omarchy-nvim/lua/plugins/all-themes.lua index 3bbf7a4..0897b96 100644 --- a/pkgbuilds/omarchy-nvim/lua/plugins/all-themes.lua +++ b/pkgbuilds/omarchy-nvim/lua/plugins/all-themes.lua @@ -77,7 +77,7 @@ return { priority = 1000, }, { - "gthelding/monokai-pro.nvim", + "loctvl842/monokai-pro.nvim", lazy = true, priority = 1000, }, From 94b7a853a27e925d967ee785d712d7496fbe19fa Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 21 Sep 2026 02:39:48 -0400 Subject: [PATCH 105/121] Bump omarchy-nvim pkgrel --- pkgbuilds/omarchy-nvim/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgbuilds/omarchy-nvim/PKGBUILD b/pkgbuilds/omarchy-nvim/PKGBUILD index d8f6414..e08f8e5 100644 --- a/pkgbuilds/omarchy-nvim/PKGBUILD +++ b/pkgbuilds/omarchy-nvim/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ryan Hughes pkgname=omarchy-nvim pkgver=2026.8.13 -pkgrel=1 +pkgrel=2 pkgdesc="Pre-built LazyVim configuration with cached plugins" arch=('any') url="https://github.com/LazyVim/LazyVim" From ef22991e6f729d26d75cbdcef176df89469210a5 Mon Sep 17 00:00:00 2001 From: Steve Derico Date: Mon, 21 Sep 2026 02:40:21 -0400 Subject: [PATCH 106/121] Disable Cursor bundled updater in cursor-bin --- pkgbuilds/cursor-bin/PKGBUILD | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgbuilds/cursor-bin/PKGBUILD b/pkgbuilds/cursor-bin/PKGBUILD index c8f1c89..1a69432 100644 --- a/pkgbuilds/cursor-bin/PKGBUILD +++ b/pkgbuilds/cursor-bin/PKGBUILD @@ -2,7 +2,7 @@ pkgname=cursor-bin pkgver=3.21.16 -pkgrel=1 +pkgrel=2 pkgdesc='AI-first coding environment' arch=('x86_64') url="https://www.cursor.com" @@ -24,6 +24,9 @@ package() { bsdtar -xOf ${noextract[0]} data.tar.xz | tar -xJf - -C "$pkgdir" \ --exclude 'usr/share/cursor/[^r]*' --exclude 'usr/share/cursor/*.pak' cd "$pkgdir" + # Disable Cursor's bundled updater; Omarchy manages updates via pacman (#238). + sed -i '/^[[:space:]]*"\(backupUpdateUrl\|updateUrl\)":/d' \ + "${_app}/product.json" mv usr/share/zsh/{vendor-completions,site-functions} ln -sf /usr/bin/node ${_app}/resources/helpers/node install -Dm755 "${srcdir}/rg.sh" ${_app}/node_modules/@vscode/ripgrep/bin/rg From 90ef25ca625db6c6cc0c46ec9c21dd59c1973ffb Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 10:39:15 +0200 Subject: [PATCH 107/121] Update ttfx to v0.3.3 --- pkgbuilds/ttfx/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/ttfx/PKGBUILD b/pkgbuilds/ttfx/PKGBUILD index 4079045..1a386f7 100644 --- a/pkgbuilds/ttfx/PKGBUILD +++ b/pkgbuilds/ttfx/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=ttfx -pkgver=0.3.2 +pkgver=0.3.3 pkgrel=1 pkgdesc="Terminal text effects as a single static binary — Rust port of terminaltexteffects" arch=('x86_64' 'aarch64') @@ -12,7 +12,7 @@ makedepends=('cargo') options=('!debug') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('d0c0df4867e7f03142fb7f77c66670d0e8da15534239c1a7abfd89f19dfc00f6') +sha256sums=('d040da0da2f4a952a367fa3d934ac25999265405f1d2a9f0475625e41211fa7d') prepare() { cd "$pkgname-$pkgver" From ecef7e791bc11ca1da55928570a49a08885d1267 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 11:08:21 +0200 Subject: [PATCH 108/121] Add Gliff remote desktop package --- pkgbuilds/gliff/.omarchy/package.json | 3 ++ pkgbuilds/gliff/PKGBUILD | 53 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 pkgbuilds/gliff/.omarchy/package.json create mode 100644 pkgbuilds/gliff/PKGBUILD diff --git a/pkgbuilds/gliff/.omarchy/package.json b/pkgbuilds/gliff/.omarchy/package.json new file mode 100644 index 0000000..2a9719d --- /dev/null +++ b/pkgbuilds/gliff/.omarchy/package.json @@ -0,0 +1,3 @@ +{ + "source": "local" +} diff --git a/pkgbuilds/gliff/PKGBUILD b/pkgbuilds/gliff/PKGBUILD new file mode 100644 index 0000000..c9d957b --- /dev/null +++ b/pkgbuilds/gliff/PKGBUILD @@ -0,0 +1,53 @@ +# Maintainer: David Heinemeier Hansson + +pkgname=gliff +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Hyprland remote desktop over SSH (Vulkan Video, 4:4:4)" +arch=('x86_64') +url="https://github.com/kevinmcconnell/gliff" +license=('MIT') +depends=('gcc-libs' 'glibc' 'wayland' 'libxkbcommon' 'libdrm' 'mesa' + 'gtk4>=4.14' 'libadwaita>=1.5' 'vulkan-icd-loader' 'openssh') +makedepends=('cargo' 'pkgconf') +optdepends=('vulkan-radeon: Vulkan Video on AMD' + 'vulkan-intel: Vulkan Video on Intel' + 'vulkan-tools: vulkaninfo for debugging' + 'vulkan-validation-layers: driver call validation for development') +options=('!debug') + +# Upstream only publishes a rolling prerelease; pin its source for reproducible builds. +_commit=2edbfba52780c7ace15dbb05ca92177f493d4bc9 +source=("$pkgname-$_commit.tar.gz::$url/archive/$_commit.tar.gz") +sha256sums=('2d75961085a72fb8e34149de63e312a7336daa70fd6e157e30c2cd08c14eb1c7') + +prepare() { + cd "$pkgname-$_commit" + + cargo fetch --locked --target "$CARCH-unknown-linux-gnu" +} + +build() { + cd "$pkgname-$_commit" + + export CARGO_TARGET_DIR=target + cargo build --frozen --release +} + +check() { + cd "$pkgname-$_commit" + + export CARGO_TARGET_DIR=target + cargo test --frozen --release --workspace +} + +package() { + cd "$pkgname-$_commit" + + install -Dm755 target/release/gliff "$pkgdir/usr/bin/gliff" + install -Dm755 target/release/gliff-server "$pkgdir/usr/bin/gliff-server" + install -Dm755 target/release/gliff-probe "$pkgdir/usr/bin/gliff-probe" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md" + install -Dm644 docs/hardware-quirks.md "$pkgdir/usr/share/doc/$pkgname/hardware-quirks.md" +} From 36d785fbc6abc8e88c825f9a3214be5db12c8e80 Mon Sep 17 00:00:00 2001 From: bjarneo Date: Mon, 21 Sep 2026 11:43:46 +0200 Subject: [PATCH 109/121] Update owe and owe-lockfeed to 0.2.3 (#574) 0.2.3 adds one-shot intro playback: owe intro, intro-status, and intro-stop, plus the renderer once/mute load and keep-open hold. Both PKGBUILDs take the v0.2.3 tarball; checksums verified with makepkg --verifysource. Co-authored-by: Bjarne Oeverli <1419214+bjarneo@users.noreply.github.com> --- pkgbuilds/owe-lockfeed/PKGBUILD | 4 ++-- pkgbuilds/owe/PKGBUILD | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/owe-lockfeed/PKGBUILD b/pkgbuilds/owe-lockfeed/PKGBUILD index c05c90d..075d08f 100644 --- a/pkgbuilds/owe-lockfeed/PKGBUILD +++ b/pkgbuilds/owe-lockfeed/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe-lockfeed -pkgver=0.2.2 +pkgver=0.2.3 pkgrel=1 pkgdesc="Lock screen video feed module for the OWE wallpaper engine" arch=('x86_64' 'aarch64') @@ -9,7 +9,7 @@ license=('MIT') depends=('qt6-declarative') makedepends=('cmake' 'qt6-declarative') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('80336cae4e3e90336b9597274883a3ef4a219e3bcf638026c2532065e38f8143') +sha256sums=('10272b563d8d55bf0befa4af4e61530726edbaa1e1e9e94936cc1d432b9d7914') build() { cmake -S "$srcdir/owe-$pkgver/qml-plugin" -B build \ diff --git a/pkgbuilds/owe/PKGBUILD b/pkgbuilds/owe/PKGBUILD index cf2d0c2..1b9d96b 100644 --- a/pkgbuilds/owe/PKGBUILD +++ b/pkgbuilds/owe/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe -pkgver=0.2.2 +pkgver=0.2.3 pkgrel=1 pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)" arch=('x86_64' 'aarch64') @@ -12,7 +12,7 @@ checkdepends=('python') optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs' 'libva-mesa-driver: VAAPI hardware decode on AMD GPUs') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('80336cae4e3e90336b9597274883a3ef4a219e3bcf638026c2532065e38f8143') +sha256sums=('10272b563d8d55bf0befa4af4e61530726edbaa1e1e9e94936cc1d432b9d7914') build() { meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr From 87eb95bf667d27bd5ad0e1cdce988ca287c3e7d0 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 06:12:53 -0400 Subject: [PATCH 110/121] Update Hype to 0.3.2 Co-Authored-By: Claude Opus 5 (1M context) --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index e61d515..d15e374 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.3.1 +pkgver=0.3.2 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('cdc347649885aaa7c735562066a21ce9148f18e4c4e6ab54525c90f26e12eea7') +sha256sums=('4450c23e74795720659b6773afc8cff418fe157b75eb12e16c7b391959739dd8') build() { cd "$srcdir/$pkgname-$pkgver" From 7db7133ea259d1fd16994b1b24288f932bcbd0da Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 06:54:26 -0400 Subject: [PATCH 111/121] Update Hype to 0.3.3 Co-Authored-By: Claude Opus 5 (1M context) --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index d15e374..8a1574d 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.3.2 +pkgver=0.3.3 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('4450c23e74795720659b6773afc8cff418fe157b75eb12e16c7b391959739dd8') +sha256sums=('9d496889ffb8c24e694a611ead8f5168950d37f9141b83d38d29c52f64a1d07a') build() { cd "$srcdir/$pkgname-$pkgver" From 7ce9c9230f2e2fe085022b047560e0f9a7b855d4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 06:59:22 -0500 Subject: [PATCH 112/121] Update Hype to 0.4.0 Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 8a1574d..8179464 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.3.3 +pkgver=0.4.0 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('9d496889ffb8c24e694a611ead8f5168950d37f9141b83d38d29c52f64a1d07a') +sha256sums=('0a27801aefbdf535688dd3fb7e4e8ed7cccb5c080dfc5ed76d078cc1d9ddf5be') build() { cd "$srcdir/$pkgname-$pkgver" From 9543da587cbae88db9741a3686c1163689d1d798 Mon Sep 17 00:00:00 2001 From: Tom Ballard Date: Mon, 21 Sep 2026 13:04:18 +0100 Subject: [PATCH 113/121] Add Task Manager for Omarchy 0.0.3 preview --- .../.omarchy/package.json | 11 +++++++ pkgbuilds/omarchy-task-manager/PKGBUILD | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 pkgbuilds/omarchy-task-manager/.omarchy/package.json create mode 100644 pkgbuilds/omarchy-task-manager/PKGBUILD diff --git a/pkgbuilds/omarchy-task-manager/.omarchy/package.json b/pkgbuilds/omarchy-task-manager/.omarchy/package.json new file mode 100644 index 0000000..8b66e2d --- /dev/null +++ b/pkgbuilds/omarchy-task-manager/.omarchy/package.json @@ -0,0 +1,11 @@ +{ + "source": "local", + "channels": ["edge"], + "upstream": { + "watch": { + "github": "tcballard/omarchy-task-manager", + "pattern": "v(?P[0-9]+\\.[0-9]+\\.[0-9]+)", + "allow_prerelease": true + } + } +} diff --git a/pkgbuilds/omarchy-task-manager/PKGBUILD b/pkgbuilds/omarchy-task-manager/PKGBUILD new file mode 100644 index 0000000..3aecb4c --- /dev/null +++ b/pkgbuilds/omarchy-task-manager/PKGBUILD @@ -0,0 +1,33 @@ +# Canonical recipe. scripts/package-source.sh fills the release source checksum. +# Maintainer: Tom Ballard (tcballard) +pkgname=omarchy-task-manager +pkgver=0.0.3 +pkgrel=1 +url='https://github.com/tcballard/omarchy-task-manager' +pkgdesc='Floating native task manager for Omarchy (preview)' +arch=('x86_64') +license=('MIT') +depends=('qt6-base' 'qt6-declarative' 'qt6-wayland' 'qt6-svg' 'hicolor-icon-theme' 'gcc-libs' 'glibc' 'glib2' 'systemd' 'coreutils') +optdepends=('gdb: live process core dumps' 'nvidia-utils: NVIDIA device telemetry') +makedepends=('cmake' 'ninja' 'rust' 'cargo') +checkdepends=('python' 'desktop-file-utils') +source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz") +sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85') + +build() { + cmake -S "$srcdir/$pkgname-$pkgver" -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib + cmake --build build +} + +check() { + cd "$srcdir/$pkgname-$pkgver" + cargo test --locked + ctest --test-dir "$srcdir/build" --output-on-failure + desktop-file-validate packaging/io.github.tcballard.TaskManager.desktop + python tests/protocol.py "$srcdir/build/omarchy-task-manager-core" +} + +package() { + DESTDIR="$pkgdir" cmake --install build +} From dbc6b07b6281b2db8e959ef0084a8795413612d5 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Sep 2026 07:12:40 -0500 Subject: [PATCH 114/121] Update Hype to 0.4.1 Co-Authored-By: Claude Fable 5.1 --- pkgbuilds/hype/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/hype/PKGBUILD b/pkgbuilds/hype/PKGBUILD index 8179464..af2508f 100644 --- a/pkgbuilds/hype/PKGBUILD +++ b/pkgbuilds/hype/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: David Heinemeier Hansson pkgname=hype -pkgver=0.4.0 +pkgver=0.4.1 pkgrel=1 pkgdesc='Simple Markdown presentations with a visual slide editor' arch=('x86_64' 'aarch64') @@ -24,7 +24,7 @@ depends=( ) makedepends=('gcc' 'make') source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('0a27801aefbdf535688dd3fb7e4e8ed7cccb5c080dfc5ed76d078cc1d9ddf5be') +sha256sums=('0724a9d18df7657b50dff21ffe3dec1c107e9191a9e9fd5ad40b56ed9d5d6f51') build() { cd "$srcdir/$pkgname-$pkgver" From 46597aa24e090cdf289ddb7e0d383572f8f9f207 Mon Sep 17 00:00:00 2001 From: dhh <2741+dhh@users.noreply.github.com> Date: Mon, 21 Sep 2026 13:02:55 +0000 Subject: [PATCH 115/121] chore: sync upstream releases --- pkgbuilds/crush-bin/PKGBUILD | 10 +++++----- pkgbuilds/mise-bin/PKGBUILD | 6 +++--- pkgbuilds/sublime-text-4/PKGBUILD | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pkgbuilds/crush-bin/PKGBUILD b/pkgbuilds/crush-bin/PKGBUILD index 564caf8..6a95b22 100644 --- a/pkgbuilds/crush-bin/PKGBUILD +++ b/pkgbuilds/crush-bin/PKGBUILD @@ -3,7 +3,7 @@ # Maintainer: caarlos0 pkgname='crush-bin' -pkgver=0.95.0 +pkgver=0.96.0 pkgrel=1 pkgdesc='A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal.' url='https://charm.sh/crush' @@ -13,16 +13,16 @@ provides=('crush') conflicts=('crush') source_aarch64=("${pkgname}_${pkgver}_aarch64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_arm64.tar.gz") -sha256sums_aarch64=('b42291307abe5572afb972fba9b8780f63a2058f37fb0dc61ab4c7b435314a8a') +sha256sums_aarch64=('667062a39d499506b0fe151148f8d7a1c5cb5722902080d44bb3dd2ddafbf5c1') source_armv7h=("${pkgname}_${pkgver}_armv7h.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_armv7.tar.gz") -sha256sums_armv7h=('756363804b6475ab6bf811f175a93766f47372beddb6e4a7b6e365ecba3f90ae') +sha256sums_armv7h=('1de4c1ccb237743e4debb8c302df612fcef5c9b3b5378f5b65c8c6f8bc15cbfa') source_i686=("${pkgname}_${pkgver}_i686.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_i386.tar.gz") -sha256sums_i686=('ce7b0dec1f1d9aa5a6e339f04e835bc6b3a335caf816dcb6c83a2f808d9fcd3b') +sha256sums_i686=('4ec66431565de5721afb7afdd99e45ff6bc9c7e667bd18d9696ea7c5622e158d') source_x86_64=("${pkgname}_${pkgver}_x86_64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_x86_64.tar.gz") -sha256sums_x86_64=('edef832ff1fc03e420a0410b9653547feb816bda7e0458589434ea4164210f5e') +sha256sums_x86_64=('5b33303a404acacf761c027e9fa9e69d4d2dd050c2690abe40877c49574b7475') package() { case "$CARCH" in diff --git a/pkgbuilds/mise-bin/PKGBUILD b/pkgbuilds/mise-bin/PKGBUILD index 7de0e56..68cbe05 100644 --- a/pkgbuilds/mise-bin/PKGBUILD +++ b/pkgbuilds/mise-bin/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Jeff Dickey pkgname=mise-bin -pkgver=2026.9.11 +pkgver=2026.9.12 pkgrel=1 pkgdesc="dev tools, env vars, task runner" arch=('x86_64' 'aarch64') @@ -14,8 +14,8 @@ provides=('mise') conflicts=('mise') source_x86_64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-x64.tar.xz") source_aarch64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-arm64.tar.xz") -sha256sums_x86_64=('aec93997952d33a28e4317a4a84cdc473a14361b809c0a2e681811bac2c7d174') -sha256sums_aarch64=('2225f1c443b74cb92098245f62673df9e8dfc1cd8cd66d3921d72f9496963ef5') +sha256sums_x86_64=('30c79a0a24d8f0ad80e6c9b11ec54816be2a9b77e7eeae32c1267a5b9d34d3d7') +sha256sums_aarch64=('7bc2a5558b787a33f22e4b5955cfec58871ad3723658418ad3d2cdf5a0e693b9') package() { install -Dm755 "${srcdir}/mise/bin/mise" "${pkgdir}/usr/bin/mise" diff --git a/pkgbuilds/sublime-text-4/PKGBUILD b/pkgbuilds/sublime-text-4/PKGBUILD index 7114b57..09cdc85 100644 --- a/pkgbuilds/sublime-text-4/PKGBUILD +++ b/pkgbuilds/sublime-text-4/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Manuel Hüsers pkgname=sublime-text-4 -pkgver=4.4200 +pkgver=4.4213 pkgrel=1 pkgdesc='Sophisticated text editor for code, html and prose - stable build' arch=('x86_64' 'aarch64') @@ -16,8 +16,8 @@ source_x86_64=("${pkgname//-/_}_${pkgver/./_}_${pkgrel}_x64.tar.xz::https://down source_aarch64=("${pkgname//-/_}_${pkgver/./_}_${pkgrel}_arm64.tar.xz::https://download.sublimetext.com/sublime_text_build_${pkgver:2}_arm64.tar.xz") sha512sums=('ac56e9b7dddaebb3d222795cfc644109c93cc3f79695b8f9ee56022c74fe04a1134dd54cab07c74ff1f96b783cb3dbc026c16095552f1d2dd83115ea274dc2e9') -sha512sums_x86_64=('0a6ff4be7ae35ce80d568a2bf8dc5ed6fcf9f845517f7a1b8b24f180842f72ef16f9792e91fc70a277cfaf66bf1be482bb1328c98252d7c524d3412cfe9f22e3') -sha512sums_aarch64=('bb8f314e3c0ffff2536f91331fe43fe55d42fed27fca32bced5e779331296c7ee4b619dacc0193bc7f2cfa16a770177a81783ed959c786522e9688b028c7c221') +sha512sums_x86_64=('0d222ba954d7f6c5c7b03ce1eff3751e2d92b233058524208eb8e007c347b9a3628b9487e832c3c5599e7d2bcb940407466bd7b000a4e389f9ed916950bd049e') +sha512sums_aarch64=('e2ee9de786d1ca6ef28f6703626be226dc0b15f74a61ca4de58522fa7c9f295c8a38b052463d95878a8930366bf1f5d4740a876c7022e1655c4b906a0a83cef1') prepare() { sed -i -e "s|@ST_PATH@|/opt/sublime_text|g" "${pkgname}.sh" From 18db53291031f17fbf988952587e55eb2da901c9 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 21 Sep 2026 10:25:37 -0400 Subject: [PATCH 116/121] Update PKGBUILD --- pkgbuilds/omarchy-nvim/PKGBUILD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgbuilds/omarchy-nvim/PKGBUILD b/pkgbuilds/omarchy-nvim/PKGBUILD index e08f8e5..f0026da 100644 --- a/pkgbuilds/omarchy-nvim/PKGBUILD +++ b/pkgbuilds/omarchy-nvim/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ryan Hughes pkgname=omarchy-nvim -pkgver=2026.8.13 -pkgrel=2 +pkgver=2026.9.21 +pkgrel=1 pkgdesc="Pre-built LazyVim configuration with cached plugins" arch=('any') url="https://github.com/LazyVim/LazyVim" From 7043dc72d32a3a7fba8688da0dce715a68142615 Mon Sep 17 00:00:00 2001 From: Tom Ballard Date: Mon, 21 Sep 2026 17:41:21 +0100 Subject: [PATCH 117/121] Backport pause/resume test observation fix for 0.0.3-2 --- pkgbuilds/omarchy-task-manager/PKGBUILD | 14 ++++- .../pause-resume-test.patch | 62 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 pkgbuilds/omarchy-task-manager/pause-resume-test.patch diff --git a/pkgbuilds/omarchy-task-manager/PKGBUILD b/pkgbuilds/omarchy-task-manager/PKGBUILD index 3aecb4c..51b4065 100644 --- a/pkgbuilds/omarchy-task-manager/PKGBUILD +++ b/pkgbuilds/omarchy-task-manager/PKGBUILD @@ -2,7 +2,7 @@ # Maintainer: Tom Ballard (tcballard) pkgname=omarchy-task-manager pkgver=0.0.3 -pkgrel=1 +pkgrel=2 url='https://github.com/tcballard/omarchy-task-manager' pkgdesc='Floating native task manager for Omarchy (preview)' arch=('x86_64') @@ -11,8 +11,16 @@ depends=('qt6-base' 'qt6-declarative' 'qt6-wayland' 'qt6-svg' 'hicolor-icon-them optdepends=('gdb: live process core dumps' 'nvidia-utils: NVIDIA device telemetry') makedepends=('cmake' 'ninja' 'rust' 'cargo') checkdepends=('python' 'desktop-file-utils') -source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz") -sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85') +source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz" + "pause-resume-test.patch") +sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85' + 'ee97d57fed9f9d8b542b934f177560c8a6f0801642767d4d0787a183deafd09a') + +# Backport the test observation fix from upstream PR #11. +prepare() { + cd "$srcdir/$pkgname-$pkgver" + patch -Np1 -i "$srcdir/pause-resume-test.patch" +} build() { cmake -S "$srcdir/$pkgname-$pkgver" -B build -G Ninja \ diff --git a/pkgbuilds/omarchy-task-manager/pause-resume-test.patch b/pkgbuilds/omarchy-task-manager/pause-resume-test.patch new file mode 100644 index 0000000..7bf3fb1 --- /dev/null +++ b/pkgbuilds/omarchy-task-manager/pause-resume-test.patch @@ -0,0 +1,62 @@ +diff --git a/tests/bridge_test.cpp b/tests/bridge_test.cpp +index bab79f2..9c9a38e 100644 +--- a/tests/bridge_test.cpp ++++ b/tests/bridge_test.cpp +@@ -79,37 +79,52 @@ private slots: + const auto before = bridge.history().size(); + QTest::qWait(1100); + QCOMPARE(bridge.history().size(), before); +- QSignalSpy samples(&bridge, &Bridge::snapshotChanged); ++ // Capture at emission: QTRY processes events, so another timer sample can ++ // replace bridge.snapshot() before the waiting assertion runs. ++ QVariantList samples; ++ QList historySizes; ++ connect(&bridge, &Bridge::snapshotChanged, &bridge, [&] { ++ samples.append(bridge.snapshot()); ++ historySizes.append(bridge.history().size()); ++ }); + bridge.setPaused(false); + QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); +- QVERIFY(!bridge.snapshot() ++ QVERIFY(!samples.first().toMap() + .value("system") + .toMap() + .value("continuous") + .toBool()); +- QCOMPARE(bridge.history().size(), 1); ++ QCOMPARE(historySizes.first(), 1); + bridge.active(false); + QTest::qWait(600); + samples.clear(); ++ historySizes.clear(); + bridge.active(true); + QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); +- QVERIFY(!bridge.snapshot() ++ QVERIFY(!samples.first().toMap() + .value("system") + .toMap() + .value("continuous") + .toBool()); + QTRY_VERIFY_WITH_TIMEOUT(!bridge.busy(), 8000); + samples.clear(); ++ historySizes.clear(); + bridge.refresh(); + QVERIFY(bridge.busy()); + bridge.setPaused(true); + bridge.setPaused(false); + QTRY_VERIFY_WITH_TIMEOUT(samples.count() > 0, 8000); +- QVERIFY(!bridge.snapshot() ++ QVERIFY(!samples.first().toMap() + .value("system") + .toMap() + .value("continuous") + .toBool()); ++ QCOMPARE(historySizes.first(), 1); ++ // Keep automatic refresh enabled. The baseline must be followed by a ++ // continuous sample; inspecting only the latest snapshot misses this order. ++ QTRY_VERIFY_WITH_TIMEOUT(samples.count() >= 2, 8000); ++ QVERIFY(samples.at(1).toMap().value("system").toMap() ++ .value("continuous").toBool()); + QTRY_VERIFY_WITH_TIMEOUT(!bridge.busy(), 8000); + QVERIFY(bridge.prepareManagement({{"category", "startup"}}).isEmpty()); + QVERIFY( From 45585daeaa7e9ff59194a9e2dea82a8f88bf7d23 Mon Sep 17 00:00:00 2001 From: Tom Ballard Date: Mon, 21 Sep 2026 17:43:22 +0100 Subject: [PATCH 118/121] Include recorder lifetime guard in pause/resume test backport --- pkgbuilds/omarchy-task-manager/PKGBUILD | 2 +- pkgbuilds/omarchy-task-manager/pause-resume-test.patch | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/omarchy-task-manager/PKGBUILD b/pkgbuilds/omarchy-task-manager/PKGBUILD index 51b4065..8d43690 100644 --- a/pkgbuilds/omarchy-task-manager/PKGBUILD +++ b/pkgbuilds/omarchy-task-manager/PKGBUILD @@ -14,7 +14,7 @@ checkdepends=('python' 'desktop-file-utils') source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz" "pause-resume-test.patch") sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85' - 'ee97d57fed9f9d8b542b934f177560c8a6f0801642767d4d0787a183deafd09a') + 'ce191fc8dc7e4f7018193aa4982d58fd463f66b37e3129b3acce46b7a1c9a89e') # Backport the test observation fix from upstream PR #11. prepare() { diff --git a/pkgbuilds/omarchy-task-manager/pause-resume-test.patch b/pkgbuilds/omarchy-task-manager/pause-resume-test.patch index 7bf3fb1..e256547 100644 --- a/pkgbuilds/omarchy-task-manager/pause-resume-test.patch +++ b/pkgbuilds/omarchy-task-manager/pause-resume-test.patch @@ -1,8 +1,8 @@ diff --git a/tests/bridge_test.cpp b/tests/bridge_test.cpp -index bab79f2..9c9a38e 100644 +index bab79f2..9bed7be 100644 --- a/tests/bridge_test.cpp +++ b/tests/bridge_test.cpp -@@ -79,37 +79,52 @@ private slots: +@@ -79,37 +79,53 @@ private slots: const auto before = bridge.history().size(); QTest::qWait(1100); QCOMPARE(bridge.history().size(), before); @@ -11,7 +11,8 @@ index bab79f2..9c9a38e 100644 + // replace bridge.snapshot() before the waiting assertion runs. + QVariantList samples; + QList historySizes; -+ connect(&bridge, &Bridge::snapshotChanged, &bridge, [&] { ++ QObject sampleObserver; // Disconnect before the captured lists are destroyed. ++ connect(&bridge, &Bridge::snapshotChanged, &sampleObserver, [&] { + samples.append(bridge.snapshot()); + historySizes.append(bridge.history().size()); + }); From e768c4b1ca946ff5aa88d99e9ce72f8d6dc55937 Mon Sep 17 00:00:00 2001 From: Tom Ballard Date: Mon, 21 Sep 2026 18:27:38 +0100 Subject: [PATCH 119/121] Backport verified Bridge shutdown fix as 0.0.3-3; bound Qt test crashes --- pkgbuilds/omarchy-task-manager/PKGBUILD | 11 ++- .../worker-shutdown.patch | 90 +++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 pkgbuilds/omarchy-task-manager/worker-shutdown.patch diff --git a/pkgbuilds/omarchy-task-manager/PKGBUILD b/pkgbuilds/omarchy-task-manager/PKGBUILD index 8d43690..94f01cd 100644 --- a/pkgbuilds/omarchy-task-manager/PKGBUILD +++ b/pkgbuilds/omarchy-task-manager/PKGBUILD @@ -2,7 +2,7 @@ # Maintainer: Tom Ballard (tcballard) pkgname=omarchy-task-manager pkgver=0.0.3 -pkgrel=2 +pkgrel=3 url='https://github.com/tcballard/omarchy-task-manager' pkgdesc='Floating native task manager for Omarchy (preview)' arch=('x86_64') @@ -12,14 +12,17 @@ optdepends=('gdb: live process core dumps' 'nvidia-utils: NVIDIA device telemetr makedepends=('cmake' 'ninja' 'rust' 'cargo') checkdepends=('python' 'desktop-file-utils') source=("$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz" - "pause-resume-test.patch") + "pause-resume-test.patch" + "worker-shutdown.patch") sha256sums=('cc3e24a0bb8fad2b7ce0d4fb780aa774d32b53b8de924b488b55674bdb936c85' - 'ce191fc8dc7e4f7018193aa4982d58fd463f66b37e3129b3acce46b7a1c9a89e') + 'ce191fc8dc7e4f7018193aa4982d58fd463f66b37e3129b3acce46b7a1c9a89e' + '1142aaedf8739bf2ed1cb823a03ed7e406d7ff59d7dfb72748815cc81cfda96b') -# Backport the test observation fix from upstream PR #11. +# Backport upstream PR #11 (sample observation) and PR #12 (worker shutdown). prepare() { cd "$srcdir/$pkgname-$pkgver" patch -Np1 -i "$srcdir/pause-resume-test.patch" + patch -Np1 -i "$srcdir/worker-shutdown.patch" } build() { diff --git a/pkgbuilds/omarchy-task-manager/worker-shutdown.patch b/pkgbuilds/omarchy-task-manager/worker-shutdown.patch new file mode 100644 index 0000000..d71f21b --- /dev/null +++ b/pkgbuilds/omarchy-task-manager/worker-shutdown.patch @@ -0,0 +1,90 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index c940e5e..d1cd40f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -29,7 +29,8 @@ if(BUILD_TESTING) + target_include_directories(bridge-test PRIVATE ui) + target_link_libraries(bridge-test PRIVATE Qt6::Core Qt6::Gui Qt6::Test) + add_dependencies(bridge-test core) +- add_test(NAME bridge COMMAND bridge-test) ++ add_test(NAME bridge COMMAND bridge-test -nocrashhandler) ++ set_tests_properties(bridge PROPERTIES TIMEOUT 60) + endif() + if(BUILD_TESTING) + qt_add_executable(ui-test tests/ui_test.cpp ui/bridge.cpp ui/bridge.h) +@@ -37,5 +38,6 @@ if(BUILD_TESTING) + qt_add_resources(ui-test test_qml PREFIX "/" FILES ${TASK_MANAGER_QML}) + target_link_libraries(ui-test PRIVATE Qt6::Core Qt6::Gui Qt6::Quick Qt6::Qml Qt6::QuickControls2 Qt6::Test) + add_dependencies(ui-test core) +- add_test(NAME ui COMMAND ui-test) ++ add_test(NAME ui COMMAND ui-test -nocrashhandler) ++ set_tests_properties(ui PROPERTIES TIMEOUT 60) + endif() +diff --git a/tests/bridge_test.cpp b/tests/bridge_test.cpp +index 9bed7be..d6737a4 100644 +--- a/tests/bridge_test.cpp ++++ b/tests/bridge_test.cpp +@@ -3,9 +3,46 @@ + #include + #include + #include ++#include ++#include + class BridgeTest : public QObject { + Q_OBJECT + private slots: ++ void shutdownDoesNotPublish_data() { ++ QTest::addColumn("inFlight"); ++ QTest::addColumn("stopped"); ++ QTest::newRow("idle") << false << false; ++ QTest::newRow("sample-in-flight") << true << false; ++ QTest::newRow("stopped-worker") << true << true; ++ } ++ void shutdownDoesNotPublish() { ++ QFETCH(bool, inFlight); ++ QFETCH(bool, stopped); ++ auto bridge = std::make_unique(); ++ QTRY_VERIFY_WITH_TIMEOUT(!bridge->snapshot().isEmpty(), 8000); ++ bridge->m_timer.stop(); ++ QTRY_VERIFY_WITH_TIMEOUT(!bridge->busy(), 8000); ++ // Stop only the disposable worker owned by this bridge, forcing shutdown ++ // through terminate/kill rather than the normal stdin-EOF exit. ++ if (stopped) { ++ const auto workerPid = bridge->m_worker.processId(); ++ QVERIFY(workerPid > 0); ++ QCOMPARE(::kill(workerPid, SIGSTOP), 0); ++ } ++ if (inFlight) { ++ bridge->refresh(); ++ QVERIFY(bridge->busy()); ++ } ++ QSignalSpy snapshots(bridge.get(), &Bridge::snapshotChanged); ++ QSignalSpy statuses(bridge.get(), &Bridge::statusChanged); ++ QSignalSpy busy(bridge.get(), &Bridge::busyChanged); ++ // Closing the app must not publish late samples or worker-exit errors while ++ // its bridge and UI are being destroyed. Spies outlive the bridge on purpose. ++ bridge.reset(); ++ QCOMPARE(snapshots.count(), 0); ++ QCOMPARE(statuses.count(), 0); ++ QCOMPARE(busy.count(), 0); ++ } + void inspectionErrorsAndDismissal() { + Bridge bridge; + QTRY_VERIFY_WITH_TIMEOUT(!bridge.snapshot().isEmpty(), 8000); +diff --git a/ui/bridge.cpp b/ui/bridge.cpp +index 86b5b47..b1fb303 100644 +--- a/ui/bridge.cpp ++++ b/ui/bridge.cpp +@@ -82,7 +82,12 @@ Bridge::Bridge(QObject *p) : QObject(p), m_rows(this) { + m_clock.start(); + } + Bridge::~Bridge() { ++ // waitForFinished() can emit readyRead/error/finished synchronously. Quiesce ++ // callbacks before waiting, including if QProcess outlives our final wait and ++ // emits from its destructor after the other Bridge members are gone. + m_timer.stop(); ++ m_timeout.stop(); ++ m_worker.disconnect(this); + m_worker.closeWriteChannel(); + if (!m_worker.waitForFinished(600)) { + m_worker.terminate(); From e0959b06f5f5745dc67ea2f207619a096bd485fd Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 21 Sep 2026 15:26:42 -0400 Subject: [PATCH 120/121] chore: vouch for tcballard and DanWahlin --- .github/VOUCHED.td | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 1707f1f..188239c 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -15,6 +15,7 @@ # # Keep entries sorted alphabetically. github:bjarneo +github:DanWahlin github:dhh github:f-trycua github:HANCORE-linux @@ -22,4 +23,5 @@ github:kwilczynski github:ryanrhughes github:scottjones github:spencerbull +github:tcballard github:tobi From 77212489259697324f331eeefe735848fdc552f9 Mon Sep 17 00:00:00 2001 From: bjarneo Date: Tue, 22 Sep 2026 08:42:35 +0200 Subject: [PATCH 121/121] Update owe and owe-lockfeed to 0.2.6 (#586) Update both package recipes and source checksums to OWE 0.2.6. This release includes the transition-image timeout and output-selection fixes. Package builds pass on x86_64 and aarch64. --- pkgbuilds/owe-lockfeed/PKGBUILD | 4 ++-- pkgbuilds/owe/PKGBUILD | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgbuilds/owe-lockfeed/PKGBUILD b/pkgbuilds/owe-lockfeed/PKGBUILD index 075d08f..9df2a24 100644 --- a/pkgbuilds/owe-lockfeed/PKGBUILD +++ b/pkgbuilds/owe-lockfeed/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe-lockfeed -pkgver=0.2.3 +pkgver=0.2.6 pkgrel=1 pkgdesc="Lock screen video feed module for the OWE wallpaper engine" arch=('x86_64' 'aarch64') @@ -9,7 +9,7 @@ license=('MIT') depends=('qt6-declarative') makedepends=('cmake' 'qt6-declarative') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('10272b563d8d55bf0befa4af4e61530726edbaa1e1e9e94936cc1d432b9d7914') +sha256sums=('e5c10e60bdfaebed861a3b7515c691a5a78fc0fe3ab29c0e96d934eb1a957cf8') build() { cmake -S "$srcdir/owe-$pkgver/qml-plugin" -B build \ diff --git a/pkgbuilds/owe/PKGBUILD b/pkgbuilds/owe/PKGBUILD index 1b9d96b..8815f55 100644 --- a/pkgbuilds/owe/PKGBUILD +++ b/pkgbuilds/owe/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: owe contributors pkgname=owe -pkgver=0.2.3 +pkgver=0.2.6 pkgrel=1 pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)" arch=('x86_64' 'aarch64') @@ -12,7 +12,7 @@ checkdepends=('python') optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs' 'libva-mesa-driver: VAAPI hardware decode on AMD GPUs') source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz") -sha256sums=('10272b563d8d55bf0befa4af4e61530726edbaa1e1e9e94936cc1d432b9d7914') +sha256sums=('e5c10e60bdfaebed861a3b7515c691a5a78fc0fe3ab29c0e96d934eb1a957cf8') build() { meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr