Three fixes on one delivery path: a Fedora-family box actually getting, and running, the patched gamescope. Found on glass on Nobara 44 (VM 123, RTX 5070 Ti passthrough).
1. The gamescope RPM was never signed
Sign RPMs runs right after Build RPM; punktfunk-gamescope is built ~90 steps later, behind its own ~10-minute cache. It missed the signing pass entirely, so every punktfunk-gamescope RPM ever published went out unsigned — and the repo file we tell users to install carries gpgcheck=1:
Transaction failed: Signature verification failed.
OpenPGP check for package "punktfunk-gamescope-3.16.25.pfhdr4-1.fc44.x86_64" ... The package is not signed.
The package was in the channel the whole time and could not be installed from it, which is worse than absent — the notes and the docs-site both say it is there. sign-rpms.sh now takes explicit paths (defaulting to dist/*.rpm as before) and a second pass signs this one before publish, fail-closed on a tag like the first.
⚠️ The existing tag gate checks the RPM exists, never that it installs. That is the v0.26.0 lesson one layer deeper.
2. Nobara's session never ran the patched gamescope
gamescope-session-plus builds its command as
GAMESCOPECMD="/usr/bin/gamescope \
and reads GAMESCOPE_BINnowhere. All three spawn levers miss at once: the env var is ignored, and an absolute path cannot be redirected by a PATH shim. So the session ran stock gamescope, the capability probe rejected it, and every session died with pipeline build failed (out of retries).
Fixed by binding our wrapper over /usr/bin/gamescopeinside the session unit's mount namespace. Deliberately a bind, not a replacement: punktfunk-gamescope ships under its own name precisely so it sits beside the distro package, and the bind is scoped to the session — nothing outside sees it, nothing is written to /usr.
Both spawn paths are covered: the transient unit gets --property=BindReadOnlyPaths=…, and a box that owns an autologin gamescope-session-plus@<client>.service (restarted in place, no systemd-run) gets the same thing as a drop-in. The drop-in is removed on restore — leaving it would put the patched build and our HDR/cursor flags under the user's ordinary game mode.
3. …and once it did run, every Vulkan client died — black screen
The box's VkLayer_FROG_gamescope_wsi ships with the distro's gamescope and speaks its protocol. Ours disagrees, so the compositor rejects the client's swapchain_feedback ("message too short") and drops it. Steam never paints; there is no other symptom.
vkcube under each build, layer on:
build
protocol err
client killed
ours 3.16.25-17 +pfhdr4
1
1
ours, ENABLE_GAMESCOPE_WSI=0
0
0
old pin 3.16.25-4 +pfhdr2
1
1
stock distro 3.16.23.2
0
0
⭐protocol/gamescope-swapchain.xml is byte-identical between the distro's packaged commit (5cdb5b0) and our pin — same sha, same version="1", same uuuuuus — and vk_engine_name last changed 2025-01. So this is the distro patching gamescope, not a version bump. Hence the gate is "do the upstream triples differ", not a floor, and an unreadable version on either side leaves the layer alone rather than degrading a box that works (Bazzite/SteamOS).
⚠️The old pin fails identically, so reverting the pin bump fixes nothing here — this is pre-existing, not a regression.
Also: the pin moves 8c676c39 → 5fb8dce4
3.16.25-1 → 3.16.25-11, for upstream ff6b924 (vulkan_get_rgb10_capture_format() — the XBGR2101010 fallback for devices with no linear-tiled A2R10G10B10 storage, i.e. every NVIDIA). That covers the paths that are upstream's rather than ours: the RGB intermediate paint_pipewire() takes when the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the other half, and its commit message asked for exactly this bump.
All six patches rebased; only 0006 conflicted (upstream f8be7ee added a declaration immediately above the g_device line our patch turns into a reference — both kept). 0003 and 0005 come out byte-identical.
Patch 0001 additionally offers xBGR_210LE before xRGB_210LE, mirroring the host-side HDR_FORMAT_ORDER on the producer end — we were handing third-party consumers (OBS and friends) the one format NVIDIA fills byte-reversed.
⚠️ Deliberately not done by calling upstream's vulkan_get_rgb10_capture_format() from the patch, which is what pw_pods.rs proposes: that symbol landed after 3.16.25, so it would break packaging/nix/gamescope.nix (which applies these patches to whatever nixpkgs pins) with an opaque C++ error. A note there says so.
pkgrel 2 → 3; .pfhdr4 stays — no capability the host probes for moved.
Verification
gamescope builds clean in the fc44 CI image; banner 3.16.25-17-ga87390d+pfhdr4 (11 upstream + our 6).
pw-cli enum-params on the live node: BGRx, NV12, xBGR_210LE(81), xRGB_210LE(80) — offer order proven, not assumed.
Patch 0006 confirmed by comparison, the only way it is visible: the new build exits 0 where the pre-0006+pfhdr2 build and stock 3.16.23.2 both abort 134.
Patch 0004 (mangoapp overlay) frame-captured off the node with gst-launch-1.0 pipewiresrc, flag ON vs OFF with --mangoapp running in both — HUD present only with the flag.
Signing fix proven with a throwaway key: Signature: (none) → digests signatures OK.
The bind validated against the unpatched distro script: the session's own log reports punktfunk-gamescope version 3.16.25-17-ga87390d+pfhdr4, 0 protocol errors, 0 client kills, 0 aborts.
Gates: scripts/xcheck.sh linux clippy clean, cargo fmt --all --check clean. Non-vacuity re-verified per the xcheck note (planted type error → 3 errors; removed → Finished).
Known and NOT addressed here
A 10-bit HDR stream aborts gamescope in upstream's destroy_buffer (pipewire.cpp:88, assert(false) on an unexpected buffer type — untouched by our patches). HDR negotiation itself is correct; it dies afterwards. Not root-caused: none of the three add-time error messages appear in the log, and the stripped RPM gives no symbolised core. Needs a debug/ASan build.
Three fixes on one delivery path: a Fedora-family box actually getting, and running, the patched gamescope. Found on glass on Nobara 44 (VM 123, RTX 5070 Ti passthrough).
## 1. The gamescope RPM was never signed
`Sign RPMs` runs right after `Build RPM`; `punktfunk-gamescope` is built ~90 steps later, behind its own ~10-minute cache. It missed the signing pass entirely, so **every `punktfunk-gamescope` RPM ever published went out unsigned** — and the repo file we tell users to install carries `gpgcheck=1`:
```
Transaction failed: Signature verification failed.
OpenPGP check for package "punktfunk-gamescope-3.16.25.pfhdr4-1.fc44.x86_64" ... The package is not signed.
```
The package was in the channel the whole time and could not be installed from it, which is worse than absent — the notes and the docs-site both say it is there. `sign-rpms.sh` now takes explicit paths (defaulting to `dist/*.rpm` as before) and a second pass signs this one before publish, fail-closed on a tag like the first.
⚠️ The existing tag gate checks the RPM **exists**, never that it **installs**. That is the v0.26.0 lesson one layer deeper.
## 2. Nobara's session never ran the patched gamescope
`gamescope-session-plus` builds its command as
```sh
GAMESCOPECMD="/usr/bin/gamescope \
```
and reads `GAMESCOPE_BIN` **nowhere**. All three spawn levers miss at once: the env var is ignored, and an absolute path cannot be redirected by a PATH shim. So the session ran stock gamescope, the capability probe rejected it, and every session died with `pipeline build failed (out of retries)`.
Fixed by binding our wrapper over `/usr/bin/gamescope` **inside the session unit's mount namespace**. Deliberately a bind, not a replacement: `punktfunk-gamescope` ships under its own name precisely so it sits *beside* the distro package, and the bind is scoped to the session — nothing outside sees it, nothing is written to `/usr`.
Both spawn paths are covered: the transient unit gets `--property=BindReadOnlyPaths=…`, and a box that owns an autologin `gamescope-session-plus@<client>.service` (restarted in place, no `systemd-run`) gets the same thing as a drop-in. **The drop-in is removed on restore** — leaving it would put the patched build and our HDR/cursor flags under the user's ordinary game mode.
## 3. …and once it did run, every Vulkan client died — black screen
The box's `VkLayer_FROG_gamescope_wsi` ships with the **distro's** gamescope and speaks its protocol. Ours disagrees, so the compositor rejects the client's `swapchain_feedback` ("message too short") and drops it. Steam never paints; there is no other symptom.
`vkcube` under each build, layer on:
| build | protocol err | client killed |
|---|---|---|
| ours 3.16.25-17 `+pfhdr4` | 1 | 1 |
| ours, `ENABLE_GAMESCOPE_WSI=0` | **0** | **0** |
| old pin 3.16.25-4 `+pfhdr2` | 1 | 1 |
| stock distro 3.16.23.2 | 0 | 0 |
⭐ `protocol/gamescope-swapchain.xml` is **byte-identical** between the distro's packaged commit (`5cdb5b0`) and our pin — same sha, same `version="1"`, same `uuuuuus` — and `vk_engine_name` last changed 2025-01. So this is the distro **patching** gamescope, not a version bump. Hence the gate is "do the upstream triples differ", not a floor, and an unreadable version on either side leaves the layer alone rather than degrading a box that works (Bazzite/SteamOS).
⚠️ **The old pin fails identically, so reverting the pin bump fixes nothing here** — this is pre-existing, not a regression.
## Also: the pin moves `8c676c39` → `5fb8dce4`
3.16.25-1 → 3.16.25-11, for upstream `ff6b924` (`vulkan_get_rgb10_capture_format()` — the XBGR2101010 fallback for devices with no linear-tiled A2R10G10B10 storage, i.e. every NVIDIA). That covers the paths that are upstream's rather than ours: the RGB intermediate `paint_pipewire()` takes when the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the other half, and its commit message asked for exactly this bump.
All six patches rebased; only `0006` conflicted (upstream `f8be7ee` added a declaration immediately above the `g_device` line our patch turns into a reference — both kept). `0003` and `0005` come out byte-identical.
Patch `0001` additionally offers **`xBGR_210LE` before `xRGB_210LE`**, mirroring the host-side `HDR_FORMAT_ORDER` on the producer end — we were handing third-party consumers (OBS and friends) the one format NVIDIA fills byte-reversed.
⚠️ Deliberately **not** done by calling upstream's `vulkan_get_rgb10_capture_format()` from the patch, which is what `pw_pods.rs` proposes: that symbol landed after 3.16.25, so it would break `packaging/nix/gamescope.nix` (which applies these patches to whatever nixpkgs pins) with an opaque C++ error. A note there says so.
`pkgrel` 2 → 3; `.pfhdr4` stays — no capability the host probes for moved.
## Verification
* gamescope builds clean in the fc44 CI image; banner `3.16.25-17-ga87390d+pfhdr4` (11 upstream + our 6).
* `pw-cli enum-params` on the live node: `BGRx, NV12, xBGR_210LE(81), xRGB_210LE(80)` — offer order proven, not assumed.
* Patch `0006` confirmed **by comparison**, the only way it is visible: the new build exits 0 where the pre-`0006` `+pfhdr2` build and stock 3.16.23.2 both abort 134.
* Patch `0004` (mangoapp overlay) frame-captured off the node with `gst-launch-1.0 pipewiresrc`, flag ON vs OFF with `--mangoapp` running in **both** — HUD present only with the flag.
* Signing fix proven with a throwaway key: `Signature: (none)` → `digests signatures OK`.
* The bind validated against the **unpatched** distro script: the session's own log reports `punktfunk-gamescope version 3.16.25-17-ga87390d+pfhdr4`, 0 protocol errors, 0 client kills, 0 aborts.
* Gates: `scripts/xcheck.sh linux clippy` clean, `cargo fmt --all --check` clean. Non-vacuity re-verified per the xcheck note (planted type error → 3 errors; removed → Finished).
## Known and NOT addressed here
A 10-bit HDR stream aborts gamescope in upstream's `destroy_buffer` (`pipewire.cpp:88`, `assert(false)` on an unexpected buffer type — untouched by our patches). HDR negotiation itself is correct; it dies afterwards. Not root-caused: none of the three add-time error messages appear in the log, and the stripped RPM gives no symbolised core. Needs a debug/ASan build.
Three things, one delivery path — a Fedora/Nobara box getting the patched gamescope.
**The pin moves 8c676c39 -> 5fb8dce4** (3.16.25-1 -> 3.16.25-11). The commit that matters
is ff6b924, `rendervulkan: fall back to XBGR2101010 when XRGB2101010 is unsupported`: it
probes `linearTilingFeatures` for STORAGE+SAMPLED and captures as XBGR2101010 where
A2R10G10B10 linear storage is unavailable — which is every NVIDIA. That covers the paths
that are upstream's rather than ours: the RGB intermediate `paint_pipewire()` acquires when
the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the
other half, and its commit message asked for exactly this bump.
All six patches rebased. Only 0006 conflicted: upstream's f8be7ee added
`vulkan_has_drm_modifiers_for_features()` immediately above the `g_device` declaration our
patch turns into a reference — both kept. 0003 and 0005 come out byte-identical; 0006 also
picks up the `--zero-commit --no-signature` form 0001-0005 already used.
**Patch 0001 now offers `xBGR_210LE` BEFORE `xRGB_210LE`**, mirroring the host-side
`HDR_FORMAT_ORDER` rationale on the producer end. A consumer takes the first pod it can use,
and we were handing third-party consumers (OBS and friends) the one format NVIDIA fills
byte-reversed under a correct-looking label. Deliberately NOT done by calling upstream's
`vulkan_get_rgb10_capture_format()`, which is what pw_pods.rs proposes: that symbol landed
after 3.16.25, so it would break `packaging/nix/gamescope.nix` — which applies these patches
to whatever gamescope nixpkgs pins — with an opaque C++ error instead of a patch conflict.
The reorder gets the same outcome on any base. Note added there so the next reader does not
"fix" it.
**And the RPM was never signed.** `Sign RPMs` runs right after `Build RPM`; the gamescope
RPM is built ~90 steps later, behind its own ~10-minute cache, so it missed the signing pass
entirely — every punktfunk-gamescope RPM ever published went out unsigned. The repo file we
tell users to install carries `gpgcheck=1`, so `dnf install punktfunk-gamescope` failed with
"The package is not signed" on every Fedora and Nobara box. The package was in the channel
the whole time and could not be installed from it, which is worse than absent: the notes and
the docs-site both say it is there. `sign-rpms.sh` now takes explicit paths (defaulting to
`dist/*.rpm` as before) and a second pass signs this one before publish, fail-closed on a tag
like the first.
Verified on Nobara 44 (VM 123, RTX 5070 Ti passthrough), canary 0.27.0-0.ci12611.g516a2954:
* Builds clean in the fc44 CI image; banner `3.16.25-17-ga87390d+pfhdr4` (11 upstream + our
6), so the marker the host probes still reads 4 — no capability moved, hence pkgrel 3 and
`.pfhdrN` staying put.
* `pw-cli enum-params` on the live node: BGRx, NV12, **xBGR_210LE (81), xRGB_210LE (80)** —
8-bit consumers still negotiate bit-for-bit, 10-bit now leads with the safe one.
* All four patched flags present, `--pipewire-composite-external-overlay` included.
* Patch 0006 confirmed working by comparison, which is the only way to see it: the new build
exits 0 where both the pre-0006 `+pfhdr2` build and the stock 3.16.23.2 abort with 134.
* Signing fix proven with a throwaway key: `Signature: (none)` -> `digests signatures OK`.
* Host health on the canary: synthetic spike 300/300 encoded, loopback 300 recovered, 0
mismatches.
One unexplained one-off: the very first headless run after install segfaulted at exit
(SIGSEGV, after "Primary child shut down!"). Not reproduced in 11 subsequent runs across
every flag combination, so it is recorded rather than diagnosed — the binary is stripped and
there is no symbolised core.
Two independent reasons a Nobara box could never stream from a gamescope session,
both found on glass (VM 123, Nobara 44, RTX 5070 Ti).
**1. The session ran a stock gamescope, so the host refused it.**
Nobara's `gamescope-session-plus` builds its command as
GAMESCOPECMD="/usr/bin/gamescope \
and reads `GAMESCOPE_BIN` NOWHERE. All three of our spawn levers miss at once: the env
var is ignored, and an absolute path cannot be redirected by a PATH shim. So the session
ran stock gamescope, the capability probe rejected it, and every session died with
"pipeline build failed (out of retries) … it ignored GAMESCOPE_BIN / the PATH shim".
`~/.gamescope-cmd.log` — which the script writes with the exact command it ran — settles
that in one line, and is the first thing to read on any such report.
Fixed by binding our wrapper over `/usr/bin/gamescope` inside the transient unit's mount
namespace (`BindReadOnlyPaths`). Deliberately a bind, not a replacement: punktfunk-gamescope
ships under its own name precisely so it sits BESIDE the distro package, and the bind is
scoped to the session — nothing outside it sees the redirect and nothing is written to
`/usr`. Skipped when the resolved binary already IS `/usr/bin/gamescope`.
**2. With the patched gamescope finally running, every Vulkan client died — black screen.**
The box's `VkLayer_FROG_gamescope_wsi` ships with the DISTRO's gamescope and speaks its
`gamescope_swapchain` protocol. Ours disagrees, so the compositor rejects the client's
`swapchain_feedback` ("message too short") and drops it. Steam never paints; there is no
other symptom, which is what makes it expensive to find.
Measured with `vkcube` under each build, layer on:
ours 3.16.25-17 ON -> 1 rejected client
ours 3.16.25-17 OFF -> 0
OLD pin 3.16.25-4 ON -> 1 rejected client
stock 3.16.23.2 ON -> 0
⭐ The upstream protocol XML is BYTE-IDENTICAL between the distro's commit (5cdb5b0) and
our pin — same interface version, same `uuuuuus` signature — so this is the distro patching
gamescope, not a version bump. Hence the gate is "do the upstream triples differ", not a
floor, and an unreadable version on either side leaves the layer alone rather than degrading
a box that works (Bazzite/SteamOS, where it has always been fine).
⚠⚠ The old pin fails identically, so REVERTING the pin bump fixes nothing here — this is
pre-existing, not a regression from 5fb8dce4.
Verified against the UNPATCHED distro script, reproducing exactly what this code emits:
the session's own log reports `punktfunk-gamescope version 3.16.25-17-ga87390d+pfhdr4`,
with 0 swapchain_feedback errors, 0 client-communication errors and 0 aborts.
Gate: `scripts/xcheck.sh linux clippy` clean (0 warning/error lines), `cargo fmt` clean.
Non-vacuity re-verified per the xcheck note — a planted type error in the new function
produced 3 errors, and removing it went back to Finished.
Still open, deliberately NOT addressed here: a 10-bit HDR stream aborts gamescope in
`destroy_buffer` (upstream `pipewire.cpp:88`), which is a separate defect.
`launch_session` spawns a transient unit and can hand `systemd-run` the
`BindReadOnlyPaths` directly, but a box that owns an autologin
`gamescope-session-plus@<client>.service` is RESTARTED IN PLACE instead — no `systemd-run`,
so that path kept running Nobara's hardcoded `/usr/bin/gamescope` and the previous commit
fixed only half the problem. Found on the box: after a reboot the host took the
`ensure_box_gamescope_mode` path (the autologin unit was live) rather than the managed one.
Deliver the same two fixes as a drop-in on that unit — the bind, and the WSI opt-out when the
box's layer was built for a different gamescope — plus `PF_HZ`/`PF_HDR_ARGS`, which the
wrapper reads and would otherwise default to 60 Hz. `daemon-reload` before the restart or
systemd runs the old unit. Best-effort: a failure to write it must not block a restart that
would otherwise work, and it is a no-op on a box already resolving to `/usr/bin/gamescope`.
⚠ REMOVED on restore, deliberately. Leaving it would put the patched build — and our HDR and
cursor flags — under the user's ORDINARY game mode, which is exactly what
`packaging/gamescope/README.md`'s "sits BESIDE the distro package" rule exists to prevent. The
bind is ours only for as long as we are driving the session.
`ensure_box_gamescope_mode` grows an `hdr` param to build those args; both call sites already
had it in scope (`self.hdr`, and `create_managed_session`'s parameter).
Gate: `scripts/xcheck.sh linux clippy` clean (0 warning/error lines), `cargo fmt` clean.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Three fixes on one delivery path: a Fedora-family box actually getting, and running, the patched gamescope. Found on glass on Nobara 44 (VM 123, RTX 5070 Ti passthrough).
1. The gamescope RPM was never signed
Sign RPMsruns right afterBuild RPM;punktfunk-gamescopeis built ~90 steps later, behind its own ~10-minute cache. It missed the signing pass entirely, so everypunktfunk-gamescopeRPM ever published went out unsigned — and the repo file we tell users to install carriesgpgcheck=1:The package was in the channel the whole time and could not be installed from it, which is worse than absent — the notes and the docs-site both say it is there.
sign-rpms.shnow takes explicit paths (defaulting todist/*.rpmas before) and a second pass signs this one before publish, fail-closed on a tag like the first.⚠️ The existing tag gate checks the RPM exists, never that it installs. That is the v0.26.0 lesson one layer deeper.
2. Nobara's session never ran the patched gamescope
gamescope-session-plusbuilds its command asand reads
GAMESCOPE_BINnowhere. All three spawn levers miss at once: the env var is ignored, and an absolute path cannot be redirected by a PATH shim. So the session ran stock gamescope, the capability probe rejected it, and every session died withpipeline build failed (out of retries).Fixed by binding our wrapper over
/usr/bin/gamescopeinside the session unit's mount namespace. Deliberately a bind, not a replacement:punktfunk-gamescopeships under its own name precisely so it sits beside the distro package, and the bind is scoped to the session — nothing outside sees it, nothing is written to/usr.Both spawn paths are covered: the transient unit gets
--property=BindReadOnlyPaths=…, and a box that owns an autologingamescope-session-plus@<client>.service(restarted in place, nosystemd-run) gets the same thing as a drop-in. The drop-in is removed on restore — leaving it would put the patched build and our HDR/cursor flags under the user's ordinary game mode.3. …and once it did run, every Vulkan client died — black screen
The box's
VkLayer_FROG_gamescope_wsiships with the distro's gamescope and speaks its protocol. Ours disagrees, so the compositor rejects the client'sswapchain_feedback("message too short") and drops it. Steam never paints; there is no other symptom.vkcubeunder each build, layer on:+pfhdr4ENABLE_GAMESCOPE_WSI=0+pfhdr2⭐
protocol/gamescope-swapchain.xmlis byte-identical between the distro's packaged commit (5cdb5b0) and our pin — same sha, sameversion="1", sameuuuuuus— andvk_engine_namelast changed 2025-01. So this is the distro patching gamescope, not a version bump. Hence the gate is "do the upstream triples differ", not a floor, and an unreadable version on either side leaves the layer alone rather than degrading a box that works (Bazzite/SteamOS).⚠️ The old pin fails identically, so reverting the pin bump fixes nothing here — this is pre-existing, not a regression.
Also: the pin moves
8c676c39→5fb8dce43.16.25-1 → 3.16.25-11, for upstream
ff6b924(vulkan_get_rgb10_capture_format()— the XBGR2101010 fallback for devices with no linear-tiled A2R10G10B10 storage, i.e. every NVIDIA). That covers the paths that are upstream's rather than ours: the RGB intermediatepaint_pipewire()takes when the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the other half, and its commit message asked for exactly this bump.All six patches rebased; only
0006conflicted (upstreamf8be7eeadded a declaration immediately above theg_deviceline our patch turns into a reference — both kept).0003and0005come out byte-identical.Patch
0001additionally offersxBGR_210LEbeforexRGB_210LE, mirroring the host-sideHDR_FORMAT_ORDERon the producer end — we were handing third-party consumers (OBS and friends) the one format NVIDIA fills byte-reversed.⚠️ Deliberately not done by calling upstream's
vulkan_get_rgb10_capture_format()from the patch, which is whatpw_pods.rsproposes: that symbol landed after 3.16.25, so it would breakpackaging/nix/gamescope.nix(which applies these patches to whatever nixpkgs pins) with an opaque C++ error. A note there says so.pkgrel2 → 3;.pfhdr4stays — no capability the host probes for moved.Verification
3.16.25-17-ga87390d+pfhdr4(11 upstream + our 6).pw-cli enum-paramson the live node:BGRx, NV12, xBGR_210LE(81), xRGB_210LE(80)— offer order proven, not assumed.0006confirmed by comparison, the only way it is visible: the new build exits 0 where the pre-0006+pfhdr2build and stock 3.16.23.2 both abort 134.0004(mangoapp overlay) frame-captured off the node withgst-launch-1.0 pipewiresrc, flag ON vs OFF with--mangoapprunning in both — HUD present only with the flag.Signature: (none)→digests signatures OK.punktfunk-gamescope version 3.16.25-17-ga87390d+pfhdr4, 0 protocol errors, 0 client kills, 0 aborts.scripts/xcheck.sh linux clippyclean,cargo fmt --all --checkclean. Non-vacuity re-verified per the xcheck note (planted type error → 3 errors; removed → Finished).Known and NOT addressed here
A 10-bit HDR stream aborts gamescope in upstream's
destroy_buffer(pipewire.cpp:88,assert(false)on an unexpected buffer type — untouched by our patches). HDR negotiation itself is correct; it dies afterwards. Not root-caused: none of the three add-time error messages appear in the log, and the stripped RPM gives no symbolised core. Needs a debug/ASan build.Two independent reasons a Nobara box could never stream from a gamescope session, both found on glass (VM 123, Nobara 44, RTX 5070 Ti). **1. The session ran a stock gamescope, so the host refused it.** Nobara's `gamescope-session-plus` builds its command as GAMESCOPECMD="/usr/bin/gamescope \ and reads `GAMESCOPE_BIN` NOWHERE. All three of our spawn levers miss at once: the env var is ignored, and an absolute path cannot be redirected by a PATH shim. So the session ran stock gamescope, the capability probe rejected it, and every session died with "pipeline build failed (out of retries) … it ignored GAMESCOPE_BIN / the PATH shim". `~/.gamescope-cmd.log` — which the script writes with the exact command it ran — settles that in one line, and is the first thing to read on any such report. Fixed by binding our wrapper over `/usr/bin/gamescope` inside the transient unit's mount namespace (`BindReadOnlyPaths`). Deliberately a bind, not a replacement: punktfunk-gamescope ships under its own name precisely so it sits BESIDE the distro package, and the bind is scoped to the session — nothing outside it sees the redirect and nothing is written to `/usr`. Skipped when the resolved binary already IS `/usr/bin/gamescope`. **2. With the patched gamescope finally running, every Vulkan client died — black screen.** The box's `VkLayer_FROG_gamescope_wsi` ships with the DISTRO's gamescope and speaks its `gamescope_swapchain` protocol. Ours disagrees, so the compositor rejects the client's `swapchain_feedback` ("message too short") and drops it. Steam never paints; there is no other symptom, which is what makes it expensive to find. Measured with `vkcube` under each build, layer on: ours 3.16.25-17 ON -> 1 rejected client ours 3.16.25-17 OFF -> 0 OLD pin 3.16.25-4 ON -> 1 rejected client stock 3.16.23.2 ON -> 0 ⭐ The upstream protocol XML is BYTE-IDENTICAL between the distro's commit (5cdb5b0) and our pin — same interface version, same `uuuuuus` signature — so this is the distro patching gamescope, not a version bump. Hence the gate is "do the upstream triples differ", not a floor, and an unreadable version on either side leaves the layer alone rather than degrading a box that works (Bazzite/SteamOS, where it has always been fine). ⚠⚠ The old pin fails identically, so REVERTING the pin bump fixes nothing here — this is pre-existing, not a regression from 5fb8dce4. Verified against the UNPATCHED distro script, reproducing exactly what this code emits: the session's own log reports `punktfunk-gamescope version 3.16.25-17-ga87390d+pfhdr4`, with 0 swapchain_feedback errors, 0 client-communication errors and 0 aborts. Gate: `scripts/xcheck.sh linux clippy` clean (0 warning/error lines), `cargo fmt` clean. Non-vacuity re-verified per the xcheck note — a planted type error in the new function produced 3 errors, and removing it went back to Finished. Still open, deliberately NOT addressed here: a 10-bit HDR stream aborts gamescope in `destroy_buffer` (upstream `pipewire.cpp:88`), which is a separate defect.