Mirrors phase6/step1/ from the ohm_gl_fix campaign. Contract-correct
hantro multi-planar / chromium-149-era stateless H.264 port of
bootlin's libva-v4l2-request, patches 0001..0018 + fourier-local.
Honest characterisation in README:
- Builds cleanly on chromium-builder LXC (boltzmann)
- vainfo enumerates H.264 profiles cleanly with LIBVA_DRIVER_NAME=v4l2_request
- NOT on Brave's decode path on ohm_gl_fix stack — Brave uses
Chromium's own V4L2VideoDecoder in media/gpu/v4l2/.
- Most likely useful for a future Firefox-via-libavcodec-vaapi
campaign, modulo a separate Mesa-panfrost WSI pitch issue.
- DEBUG patches (0010, 0011, 0014) intentionally kept in series
for development; remove for cleaner production runs.
Audit trail in the source repo at ohm_gl_fix:
phase6/step1/audit_0008_decode_params_2026-05-01.md
phase6/step1/api_contract_findings_2026-05-01.md
phase3_remeasure_2026-05-02/B3_decoder_discovery.md (why this
isn't on Brave's path)
After the rename, source URLs and extracted-dir refs that used
$pkgname-$pkgver were producing kwin-fourier-6.6.4.tar.xz etc. which
KDE doesn't ship. Use a separate _upname/hardcoded value for the
upstream artifact.
kwin-fourier: introduce _upname=kwin, use everywhere the upstream
dir/tarball name is referenced (source URL, prepare
patch -d, cmake -S)
qt6-base-fourier: $_pkgfn=${pkgbase/6-/} produced 'qtbase-fourier'
with the rename. Hardcode _pkgfn=qtbase.
0002's upstream-shape patch turned out to be semantically equivalent to
stock (sync_file snapshots fences at export, polling the dmabuf fd tracks
later-added fences — the patch swaps one ioctl for one F_DUPFD with a
behaviour change Mutter explicitly moved away from on amdgpu). Hosts
running 0002 are effectively stock and stall during V4L2 stateless
playback because the producer doesn't populate dma_resv exclusive fences,
so the sync_file is a stub and KWin waits forever.
0001 (bypass the watchDmaBuf wait entirely) is the working downstream
carry. Trade-off is that frames can present before the producer signals,
but on V4L2 stateless hardware where no fence is populated at all,
there's nothing to wait for in practice.
Upstream fix lives in the linux-media RFC (vb2 dma_resv producer fences,
sent 2026-04-29). Once that lands and producer drivers opt in, the
0001 carry can be retired and the upstream-shape 0002 reconsidered.
Both patches stay on disk; 0002 is not being upstreamed (MR 9157 closed
on reviewer feedback).
0002-transaction-poll-dmabuf-fd-directly-upstream-shape.patch is the
form we'll be sending to invent.kde.org/plasma/kwin (see
upstream-submissions/kwin-fourier/kde-mr-body.md). Same observable
behavior as 0001 (skip the EXPORT_SYNC_FILE round-trip), cleaner
shape: dup() the dmabuf fd and hand it to TransactionFence directly
instead of bypassing the wait entirely.
0001 is kept on disk for reference; carry could revert to it if the
upstream-shape MR runs into review issues.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a brute-force fallback to v4l2request_open_decoder() that
enumerates /dev/media[0..15] and /dev/video[0..63] directly when
udev_enumerate_scan_devices() returns an error. The fallback uses
absolute paths only (no fd-relative openat), which is what makes it
work inside firefox's RDD seccomp+broker sandbox where Mozilla's
OpenAtTrap rejects fd-relative paths used by systemd's chase()
symlink resolver.
Same approach Chromium uses in media/gpu/v4l2/stateless/ on ChromeOS,
where the sandbox similarly forbids libudev's chase pattern.
No regression: the libudev path runs first and the brute-force path
only activates on its failure. AV_LOG_INFO line announces the
fallback so it's visible in MOZ_LOG=FFmpegLib:5.
Validated on RK3399 / Pinebook Pro / rkvdec:
libudev probe failed (-2), falling back to brute-force /dev/media*
Using V4L2 media driver rkvdec (brute-force) for S264
Reinit context to 1920x1088, pix_fmt: drm_prime
RDD CPU = 4.9%
Bumps pkgrel=2. Worth submitting to Kwiboo's fork upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends Mozilla's RDD sandbox to permit /dev/media* (driver-matched),
the MEDIA_IOC_* ioctl family ('|'), and the sysfs paths libudev would
need to enumerate the media controller (read-only AddTree on
/sys/class, /sys/bus, /sys/dev/char, /sys/devices/platform plus
/run/udev, /etc/udev/udev.conf, /proc/self, /dev/dma_heap).
Necessary but not sufficient on its own: Mozilla's OpenAtTrap
rejects fd-relative openat used by systemd's chase() inside libudev.
The companion ffmpeg-v4l2-request-git patch adds a brute-force
fallback that opens /dev/media[0..15] directly with absolute paths,
which composes with this broker policy.
Validated on RK3399 / Pinebook Pro / mainline rkvdec: with both
patches in place, default RDD sandbox runs HW decode at ~5% CPU on
1080p30 H.264 (vs ~64% software fallback before). Closes the
parity gap with MOZ_DISABLE_RDD_SANDBOX=1 baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier todays edit on patch 3 (commit e0af915) replaced the
hw_configs-only sanity check with the dual-mechanism (named codec
first, hw_configs fallback) probe. The patch text body was correct
but the unified-diff hunk header at the .cpp portion still claimed
the original +105-line content while the new content was 130 lines —
so patch -p1 failed with malformed-patch errors.
This commit regenerates the .cpp portion canonically via diff -u
from the boltzmann working tree (which has the corrected logic
applied). The .h portion is unchanged. Patch description body
updated to match the new dual-mechanism behavior.
Empirical evidence the new logic is correct lives in the boltzmann
build; this commit just makes the patch file replay correctly from
scratch.
Diagnostic on fresnel (RK3399 / Mali-T860 / mainline) showed
InitV4L2RequestDecoder running at runtime but failing the
hw_configs sanity check:
FFMPEG: Initialising V4L2 stateless (request API) FFmpeg decoder
FFMPEG: codec h264 has no DRM hwaccel —
libavcodec built without --enable-v4l2-request?
FFMPEG: Initialising V4L2-DRM FFmpeg decoder ← falls through to stateful
FFMPEG: V4L2 codec h264_v4l2m2m : V4L2 mem2mem H.264 decoder wrapper
FFMPEG: Couldn't initialise V4L2 decoder ← stateful also fails
…despite the system libavcodec.so being built with
--enable-v4l2-request and exposing h264_v4l2request, vp8_v4l2request,
etc. as named AVCodec entries.
Root cause: libavcodec exposes v4l2_request through one of two
mechanisms depending on the build:
(a) Named AVCodec entry (legacy, distro-portable): looked up via
avcodec_find_decoder_by_name("h264_v4l2request"). ALARM,
Debian, most distros use this.
(b) hw_configs entry on the generic codec (modern, upstream): the
generic codec's AVCodecHWConfig array advertises
AV_HWDEVICE_TYPE_DRM. Setting hw_device_ctx binds the hwaccel.
Patch 3 originally only probed (b). On builds that ship (a) — the
common case — the check failed even though v4l2_request was fully
functional.
Fix: probe (a) first via the codec-name lookup table, fall back to
(b) walking hw_configs. Both shapes work; the decoder is opened with
whichever AVCodec the probe selected. The DRM hwdevice ctx
attachment is unchanged (both mechanisms need it for surface
allocation).
Patch description and the in-code comment block updated to document
the dual mechanism. Behaviour on stateful-only boards (Pi4 / vendor
MPP) preserved: neither named codec nor hw_configs DRM is registered,
the function bails out, the existing InitV4L2Decoder runs as before.
Mirror github.com/marfrit/fourier kwin-fourier/0002 +
README update to the local Arch package source. PKGBUILD
unchanged — still applies 0001 (the diagnostic bypass).
The 0002 patch (poll dmabuf fd directly, drop the
EXPORT_SYNC_FILE + sync_file roundtrip) is staged for
validation; when validated, swap the source array entry in
PKGBUILD from 0001 to 0002 and rebuild.
Three patches landed on ohm in sequence today: qt6-base-fourier
(GL_ALPHA → GL_R8 on ES 3.x, 3 sites in qtbase), kwin-fourier
(watchDmaBuf no-op test fixture), chromium-fourier patch 4/4
(V4L2 capture pool floor at 16). Each unsticks one layer.
Together they produce smooth 1080p30 H.264 playback under KDE
Plasma 6.6.4 Wayland on RK3566 PineTab2 mainline, where stock
chromium previously stalled in 3 seconds. Combined chrome CPU
~81% steady, KWin ~9%, zero GL_INVALID_VALUE during playback.
Brave's YouTube on the same compositor session also feels snappier
independently — the kwin-fourier watchDmaBuf bypass is a
general-purpose latency reduction for every wp_linux_dmabuf client
on Mali-class hardware, not chrome-specific.
The kernel-side architectural hole is the right upstream-correct
fix: vb2 / hantro / rga don't populate dma_resv exclusive fences
for V4L2 producers, so dma_buf_export_sync_file substitutes a stub
fence representing nothing real. Per-driver fence wiring (3 small
commits: vb2 helper API, hantro opt-in, rga opt-in) plus a parallel
KWin commit using poll(POLLIN) directly on the dmabuf fd is the
planned MR pair. kwin-fourier as it stands is a working diagnostic,
not the upstream-bound shape.
Hypothesis under test: KWin's Transaction::watchDmaBuf calls
DMA_BUF_IOCTL_EXPORT_SYNC_FILE on every plane of every imported
dmabuf and parks the transaction on a QSocketNotifier(POLLIN)
waiting for that sync_file. On V4L2 hantro CAPTURE buffers (RK3566
mainline 6.19, panfrost mesa 26.0.5) the resulting fence either
never signals or signals so late that chrome's 6-buffer V4L2
capture pool exhausts at ~6s, hard-stalling the decoder. mpv with
gpu-next slideshows at 76% drop. weston A/B with same chrome v4
binary plays through clean — KWin's watchDmaBuf is the suspect.
This experiment patches watchDmaBuf to no-op. Wayland clients are
required by spec to ensure buffer contents are complete before
wl_surface.attach+commit, so the fence-wait is a defensive
optimization for misbehaving clients, not a correctness primitive.
If chrome plays through end-to-end at the recorded 34.7% combined
CPU number with this patched KWin, the bug is confirmed and the
upstream fix can be refined (timeout, V4L2-source skip, or use the
dmabuf fd directly in the QSocketNotifier instead of an extra
exported sync_file).
KWIN_PIVOT.md (in chromium-fourier/) carries the discovery thread.
Today's deltas:
- qt6-base-fourier built, installed, validated on ohm. Static-idle
journal shows zero GL_INVALID_VALUE post-relogin; the Qt 6
GL_ALPHA bug is genuinely fixed.
- chrome v4 under KWin still stalls — at ~6s vs ~3s pre-Qt-fix, so
the GL_ALPHA churn was contributing some load but wasn't the
primary cause.
- Clean A/B with weston: same chrome v4 binary, same panfrost,
same V4L2, same hardware → swapping KWin → weston turns the
stall off entirely. Chrome plays through with elevated CPU
(~96 % vs KWin's ~50 % when it isn't stalled) because weston
falls back to LINEAR composite vs KWin's fast-tile path.
- mpv triangulation:
--vo=null --hwdec=v4l2request: clean (decode only)
--vo=drm --hwdec=v4l2request: 0.7 % drops in 19 s (KMS scanout)
--vo=gpu-next --hwdec=v4l2request under KWin: 76 % drops, slideshow
Decode + display hardware path is fully capable. The wall is
specifically KWin's compositor scheduling/presentation pipeline on
this stack — panfrost ES 3.2 + V4L2 stateless NV12 dmabuf clients.
KWIN_PIVOT.md rewritten:
- Phase 4 (qt6 patch, ship, upstream) marked done.
- New Phase 5 (find the KWin culprit): WAYLAND_DEBUG on chrome +
KWin to capture the missing wl_buffer.release / wp_presentation
exchange around the 6 s stall, plus strace-on-kwin and
effects-disable bisection.
- New Phase 6 (fix and ship): kwin-fourier package pattern, ohm
validation, bugs.kde.org filing.
Three small runtime checks in qtbase 6.11.0:
1. src/opengl/qopengltextureglyphcache.cpp createTextureData() and
load_glyph_image_to_texture() — the `#else` branch (active when
qtbase is built with QT_CONFIG(opengles2), every aarch64 distro)
hard-codes GL_ALPHA without checking the runtime context's ES
version. Replace with `useR8 = ctx->format().majorVersion() >= 3`
so ES 3+ contexts get GL_R8 + GL_RED.
2. src/gui/rhi/qrhigles2.cpp toGlTextureFormat() RED_OR_ALPHA8 case
— gated only on caps.coreProfile. Extend with
`caps.gles && caps.ctxMajor >= 3`.
3. src/opengl/qopengltextureuploader.cpp Format_Alpha8 and
Format_Grayscale8 cases — short-circuit on `context->isOpenGLES()`
before reaching the swizzle fallback. Restrict to ES 2 only so
ES 3+ falls through to the existing TextureSwizzle path.
Discovered while validating chromium-fourier patch 3/3 (NV12
EXTERNAL_OES) on ohm. The chrome stall, VLC vout init failure and
mpv "could not initialize video chain" all share this Qt 6 root
cause: every Qt application running on Mali / panfrost / panthor
under a KWin Wayland session emits glTexImage2D(GL_ALPHA) on every
text-glyph cache upload, mesa returns GL_INVALID_VALUE, the
compositor's frame-callback path stalls, and every wayland video
client deadlocks behind it.
PKGBUILD inherits from extra/qt6-base 6.11.0-2 with arch+=aarch64,
epoch=1 to dominate Arch's pkgrel until upstream lands the fix.
qt6-base-cflags.patch and qt6-base-nostrip.patch carried verbatim
from upstream packaging.
KWIN_PIVOT.md (in chromium-fourier/) carries the full diagnosis
thread.
Source-grep collapsed Phase 1+2 onto a single pass. KWin's own GL paths
use GL_R8 correctly (gltexture.cpp:61, shadowitem.cpp:494). The
glTexImage2D(GL_ALPHA) calls observed in the journal originate from
Qt 6:
- qtbase/src/opengl/qopengltextureglyphcache.cpp:111-117 — text glyph
cache upload path. The #else branch (active when qtbase is built
with QT_CONFIG(opengles2)) unconditionally uses GL_ALPHA, with no
runtime check for ES context major version. Correct on ES 2.x;
broken on ES 3.x where GL_ALPHA is no longer a valid glTexImage2D
internalFormat.
- qtbase/src/gui/rhi/qrhigles2.cpp:1373-1378 — Qt-Quick-RHI sibling.
Same logic, gated only on caps.coreProfile, missing the ES≥3 case.
- qtbase/src/opengl/qopengltextureuploader.cpp:253-257 — QImage→GL
upload path; same shape.
KWin runs an ES 3.2 context on Mali-G52 panfrost (RK3566), Qt picks
GL_ALPHA, mesa returns GL_INVALID_VALUE, every dependent draw errors
at level 0, the compositor's frame-callback path stalls. KWin is the
visible victim because it's the compositor, but the bug is in Qt.
KWIN_PIVOT.md rewritten: the patch series and packaging now target
qt6-base-fourier instead of kwin-fourier. Three small hunks (~3 lines
each), runtime-safe via existing caps.gles + caps.ctxMajor / surface
format majorVersion checks. Upstream landing path: bugreports.qt.io
+ Gerrit change against qtbase dev branch.
Earlier framing was wrong — the wall isn't 'Arch ARM clang 22 vs Arch
x86_64 clang 23'. Arch x86_64 is also on 22.1.3; LLVM 23 isn't anywhere
in extra/staging. The flags chromium 147 emits come from chromium's
clang fork (Google maintains an LLVM fork with chromium-specific
passes), not upstream LLVM 23. PKGBUILD'ing clang 23 is the wrong tree.
Right tree: cross-compile from x86_64 so chromium's bundled clang
prebuilt is reachable. CIPD has full linux-amd64 prebuilts, gclient
sync works cleanly, no qemu-x86_64-static dance needed.
his provisioned CT 220 chromium-builder-x86 on data (Ryzen 7 1700,
14 cores, 32 GiB RAM, 200 GiB ZFS). data is normally asleep — woke
via /opt/herding/bin/wake-data. Reach pattern: hertz -> ssh data ->
pct exec 220.
Source fetch running as chromium-fetch.service transient unit on
CT 220. Once src is in, plan: tools/clang/scripts/update.py for
chromium's bundled clang + arm64 sysroot, gn gen with target_cpu=arm64,
build, transfer aarch64 binary to ohm/fresnel/ampere.
boltzmann chromium-builder LXD container preserved as fallback; can
be torn down if cross-compile pans out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First-build summary on chromium-builder@boltzmann. gn gen succeeds
with our V4L2VDA-unlock args. ninja fails immediately on:
1. chromium 147 emits clang flags (-fno-lifetime-dse,
-fsanitize-ignore-for-ubsan-feature=array-bounds) that clang 22
doesn't know. Arch Linux ARM is on clang 22; clang 23 hasn't
landed in extra yet.
2. Bundled x86_64 esbuild is invoked via qemu-x86_64-static but
/lib64/ld-linux-x86-64.so.2 isn't installed — same shape as the
bundled node-linux-x64 issue we already fixed by symlinking to
system node. Smaller wall.
Documents 5 paths forward (grind patches / pin chromium 132 (7Ji's
known-good) / pin 138-141 middle ground / use chromium's bundled
clang / wait for Arch ARM clang 23) with estimated effort and trade-
offs. Recommends pinning to a chromium version that compiles clean
against clang 22 as the fastest path to a working browser, then
bumping as Arch ARM bumps clang.
Build host state preserved — container running, source extracted,
gn-gen'd, no compile artifacts. Easy to resume from any of the five
paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial chromium-fourier shape on the chromium-builder@boltzmann LXD
container we provisioned today. Approach is the 7Ji-style "tarball +
system tools" pattern (no gclient/CIPD, the linux-arm64 dependency
binaries don't exist anyway) but stripped of the MPP/X11/panfork
specifics — chromium-fourier targets mainline kernel + Wayland +
panfrost/panthor + V4L2 stateless on /dev/video0, not the vendor
stack 7Ji's chromium-mpp targets.
PKGBUILD highlights:
- pkgver=147.0.7727.116 (current Chrome stable as of 2026-04-25)
- gn args: use_v4l2_codec=true, use_v4lplugin=true, use_linux_v4l2_only=true,
use_vaapi=true. The first three are the magic that unlocks V4L2VDA on
Linux non-ChromeOS without source patches; if they're sufficient on
their own, the chromeos-pipeline-bypass patch stays a no-op.
- ffmpeg_branding="Chrome" + proprietary_codecs=true for H.264.
- enable_widevine=false, enable_nacl=false to keep the tree small.
- Currently development-shaped: prepare()/build() operate on a
pre-extracted /build/chromium/src rather than makepkg-fetched
source. Will switch to canonical source=(...tarball.xz) shape once
the patches stabilise.
patches/chromeos-pipeline-bypass.patch is a placeholder; the actual
patch (if any) gets developed once we see what 7Ji's gn args do or
don't unlock for us.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stage the next side-project: patch upstream Chromium to do HW video
decode through VaapiVideoDecoder + our marfrit/libva-v4l2-request-fourier
backend on a mainline Linux Wayland system, instead of going through
the chromeos pipeline that fails on Brave today.
STUDY.md captures:
- The exact failure stack we're fixing (PickDecoderOutputFormat ->
ImageProcessor init failure in media/gpu/chromeos/video_decoder_pipeline.cc)
- Three candidate patches (chromeos pipeline bypass, V4L2VideoDecoder
factory un-gate, libva backend default)
- Reference forks (JeffyCN, igel-oss, 7Ji-PKGBUILDs/chromium-mpp,
amazingfate/chromium-debian-build) — all use the older V4L2VDA path
with vendor MPP, not VAAPI; useful for PKGBUILD shape and
factory-un-gating patterns but not directly applicable
- Build plan on fermi (depot_tools, ~30 GB fetch, 6-10 h initial build,
distcc-avahi acceleration through CT108 + tesla)
- Phase order — workspace done now, build env next session,
patches after that, package after that, brave-fourier rebase last
No PKGBUILD added yet; one will land when there's something to actually
package. Build artifacts intentionally not in repo (chromium tree is
~100 GB).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First carrier package for the Fourier umbrella. Tracks Kwiboo's
v4l2-request-n8.1 branch (ffmpeg 8.1 base) pinned at commit b57fbbe —
bump _commit to rebase onto newer tip. CI job chained after
claude-his-any so it serializes on the shared aarch64 repo-db;
continue-on-error: true so long ffmpeg builds don't block the debian
downstream.
Deliberately diverges from the AUR package:
- AUR pins 6.1.1 with epoch=2 → would downgrade stock Arch ffmpeg 2:8.1-3.
We track 8.1 so install is a sideways swap, not a regression.
- AUR pulls X11/AMF/CUDA/FireWire/AviSynth/OpenMPT/Bluray/OpenMAX/JPEG-XL/
Theora/XVid/rsvg/soxr/ssh/vidstab/modplug/SDL2/Vulkan/JACK/GSM/Speex —
dropped here; none are needed on a Wayland ARM video-decode fleet.
- AUR uses #branch=…, sha256sums=(SKIP) → every build is tip-of-branch,
not reproducible. We pin via #commit=<sha>.
Kept: encoders (libx264/libx265/libvpx/libdav1d), VAAPI, libdrm, libv4l2,
neon, OpenGL, PulseAudio, subtitle/font stack, gnutls TLS. SDL2 dropped
means no ffplay binary (mpv covers interactive playback).
provides=(ffmpeg) conflicts=(ffmpeg) so it replaces stock ffmpeg on the
target host deliberately. Primary consumers: ohm (Fourier step 5),
fresnel, ampere.
pkgrel 16 builds ship an upstream distcc 3.4 bug: src/compile.c sizes
the rewritten-compiler-name buffer with strlen(argv[0] + 1) — pointer
arithmetic applied before strlen — under-allocating by 2 bytes. glibc
FORTIFY_SOURCE=2 catches the resulting overflow in strcat and aborts,
so every "distcc gcc ..." invocation dies on a modern Arch.
Patch moves the +1 outside the strlen, as intended.
Closesmarfrit/marfrit-packages#3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tag v0.1.3 added the scripts + quickref, v0.1.4 fixed doc paths.
Package both /usr/bin/repo-inventory.sh and /usr/bin/repo-inventory-nosudo.sh.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Claude Code Edit semantics — literal string replace with uniqueness
check. replace_all flag for bulk edits. Fixes missing edit tool on
lmcp-backed boltzmann / tesla / broglie.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- arch/claude-his-agent/PKGBUILD: fetches v0.1.0 tarball from
git.reauktion.de/marfrit/claude-his-agent, installs agent+skill+helper
to /usr/share/claude-agents/, /usr/share/claude-skills/his/, /usr/bin/
- debian/claude-his-agent/: control+changelog+copyright + build-deb.sh
mirroring the lmcp-debian pattern (dpkg-deb, reproducible mtimes)
- .gitea/workflows/build.yml: two new serialized jobs (claude-his-any +
claude-his-debian) after lmcp-debian; same publish flow as lmcp.
lmcp is arch=any (pure Lua). One build on the aarch64 runner serves
all pacman targets — the pure-Lua package drops into both repo dbs.
Depends on lua + lua-socket from the target distro's base repos.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes install conflict with filesystem pkg on merged-usr systems where
/usr/sbin is a symlink to /usr/bin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- distcc-3.4 tarball hash + local support files hashed (no more SKIP)
- .gitea/workflows/build.yml now builds, signs, repo-adds and rsyncs
to nc via the marfrit-repo-deploy key. Triggers on push to arch/**
or manual workflow_dispatch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>