0.31.4 — the screens that stayed lit, the power menu that did nothing, and the console no browser would open #394

Merged
enricobuehler merged 1 commits from worktree-release-0314 into main 2026-08-24 22:26:30 +00:00
Owner

Release prep for v0.31.4. 21 commits since v0.31.3 (14 non-merge), cut from c407f6a6 (#393 merged).

Everything docs/releases/README.md step 1 asks for, authored before the tag: version bump, user notes, CHANGELOG section, Play "What's new", and the docs-freshness pass. The tag is deliberately not pushed — that is step 2, and it fans out every build workflow.

The number: a patch, and the cleanest in a while

Nothing versioned moves. Not one row:

surface v0.31.3 → v0.31.4
Wire protocol 2 → 2
C ABI 25 → 25 — include/punktfunk_core.h byte-identical to v0.31.3, and to v0.31.2 and v0.31.1. Third release running
Driver protocol 6 / min 3 — pf-driver-proto no diff
Gamepad channel 3 → 3
Plugin index / host event schema 1 → 1 (events.rs no diff)
api/openapi.json content-identicalinfo.version is the entire diff. First release since v0.31.0 where the management API grows nothing
gamescope patch level +pfhdr8, no new patch files
SDK / plugin-kit 0.1.6 / 0.4.4, both untouched
Dependencies none move, in any of the five Rust lockfiles

Four feat commits, all additive and all client- or Linux-host-side. v0.31.3 and v0.31.1 each carried two feats as a patch on the same reasoning.

The shape

Linux-host, and the faults share a premise: a policy written against one desktop that silently did nothing on the others.

  • #389 (five commits) — Topology::Exclusive on a gamescope session was org_kde_kwin_dpms and reached only a live KDE desktop, so a Game Mode box (the deployment whose TV the operator most wants dark) got nothing. Now a dispatcher: KDE, sway, Hyprland, and a DRM floor for a box with no desktop at all. Plus the managed route's own hold, and the box-session free that was gated on is_steam_launch. GNOME is a structural gap and says so at warn!.
  • #391 — the sleep:idle BLOCK inhibitor refused every Suspend() for a stream's length, including the operator's own from Steam's power menu; and on a DM-stopping takeover polkit's allow_active fallback found no session to elect and dropped all three power actions to auth_admin_keep.
  • #393 — the web console served the legacy identity (every launcher names that pair; none of them can choose), so browsers rejected it outright and the tray's mgmt-pinned probe refused the handshake and labelled a healthy console dead.
  • #392 — the encode down-driver's thresholds were absolute durations calibrated at 120 Hz, and its stand-down was permanent. A 1440p60 session ratcheted 57 → 5 Mbps over ten minutes on a link that never dropped a packet.
  • #387 an installTap format snapshot reaching the ObjC terminate handler · #388 the console's bitrate row · #390 a GTK front door for the console UI.

Two entries worth a reviewer's attention

  • The sway arm of #389 is not verified on glass. The lab has Bazzite, Nobara and SteamOS — no sway box. Hyprland, KDE and the DRM floor were all measured on real machines. The notes say so in "Thanks" rather than burying it.
  • #389's Hyprland arm shipped wrong in its first cut and was corrected on glass (540e282e): the dpms dispatcher is a toggle that ignores the state word, so the blind "send off, later send on" would have lit an already-dark head at stream start and darkened a lit one at teardown — the exact failure the feature exists to prevent.

Docs freshness

#390 and #393 carried their own docs-site updates. Two facts were left owed, both in gamescope.md, both the "stale sentence" class docs-drift cannot catch:

  • the darkening mechanism list still read "KDE, else DRM" and never learned about the sway and Hyprland arms;
  • the "could not deliver a dark screen" example was a box in Game Mode — now precisely the case that is served. The real remaining gap is GNOME/Mutter, so it says that instead.

Also: the punktfunk group grew a third grant this cycle (the three logind power actions), and its callout block enumerated only the usbip nodes — one sentence added.

No new PUNKTFUNK_* variable, no new host subcommand, and no install command, repo URL or port change, so data/platforms.json and the website's vendored copy need nothing.

Verified here

  • check-docs-drift.sh clean — and proven live rather than assumed: a deliberate one-byte break of the openapi copy makes it fail, and it passes again restored.
  • check-docs-links.sh clean.
  • The android.yml Play notes gate run verbatim: 481/500 chars, unique against every other release's file.
  • Both openapi copies cmp identical and stamped 0.31.4.
  • cargo fmt --all --check clean; the repo pre-push hook run manually, exit 0.
  • git diff v0.31.3..HEAD empty on include/punktfunk_core.h, crates/pf-driver-proto, punktfunk-core/src/lib.rs, punktfunk-host/src/events.rs and api/openapi.json — direct evidence for five version rows. git diff v0.31.1..HEAD on the C header also empty, which is the "third release running" claim.
  • Cargo.lock's 36 workspace version strings moved with Cargo.toml; zero 0.31.3 strings remain. 27 crate dirs / 39 workspace members, both unchanged.
  • Notes voice scan clean: zero backticked terms above ## For developers, and zero hits scanning for gamescope/polkit/logind/DPMS/CRTC/DRM/systemd/kwin/mutter/wlroots/rustls/ioctl.
  • CHANGELOG link pinned to src/tag/v0.31.4.

Not run here, and why

Any punktfunk-host build, clippy or cargo test — the host does not compile on macOS at all, and CI covers it. The web/ and docs-site/ bun builds — nothing under web/ is touched by this commit and the docs-site edits are prose in an existing .md. The Android unit tests — nothing here touches Kotlin.

After merge

  1. git tag -a v0.31.4 … && git push origin v0.31.4 — whichever workflow wins the create race seeds the release body from docs/releases/v0.31.4.md.
  2. Wait for every platform to go green. Watch for the merge-sha gap described in docs/releases/README.md: match your own merge sha in the run list, because "CI ran" is not "your commit ran".
  3. Dispatch the announce workflow with the tag.
Release prep for **v0.31.4**. 21 commits since v0.31.3 (14 non-merge), cut from `c407f6a6` (#393 merged). Everything `docs/releases/README.md` step 1 asks for, authored **before** the tag: version bump, user notes, CHANGELOG section, Play "What's new", and the docs-freshness pass. **The tag is deliberately not pushed** — that is step 2, and it fans out every build workflow. ## The number: a patch, and the cleanest in a while **Nothing versioned moves.** Not one row: | surface | v0.31.3 → v0.31.4 | |---|---| | Wire protocol | 2 → 2 | | C ABI | 25 → 25 — `include/punktfunk_core.h` byte-identical to v0.31.3, **and to v0.31.2 and v0.31.1**. Third release running | | Driver protocol | 6 / min 3 — `pf-driver-proto` no diff | | Gamepad channel | 3 → 3 | | Plugin index / host event schema | 1 → 1 (`events.rs` no diff) | | `api/openapi.json` | **content-identical** — `info.version` is the entire diff. First release since v0.31.0 where the management API grows nothing | | gamescope patch level | +pfhdr8, no new patch files | | SDK / plugin-kit | 0.1.6 / 0.4.4, both untouched | | Dependencies | **none move**, in any of the five Rust lockfiles | Four `feat` commits, all additive and all client- or Linux-host-side. v0.31.3 and v0.31.1 each carried two feats as a patch on the same reasoning. ## The shape Linux-host, and the faults share a premise: **a policy written against one desktop that silently did nothing on the others.** - **#389** (five commits) — `Topology::Exclusive` on a gamescope session was `org_kde_kwin_dpms` and reached only a live KDE desktop, so a Game Mode box (the deployment whose TV the operator most wants dark) got nothing. Now a dispatcher: KDE, sway, Hyprland, and a DRM floor for a box with no desktop at all. Plus the managed route's own hold, and the box-session free that was gated on `is_steam_launch`. **GNOME is a structural gap and says so at `warn!`.** - **#391** — the `sleep:idle` BLOCK inhibitor refused *every* `Suspend()` for a stream's length, including the operator's own from Steam's power menu; and on a DM-stopping takeover polkit's `allow_active` fallback found no session to elect and dropped all three power actions to `auth_admin_keep`. - **#393** — the web console served the **legacy** identity (every launcher names that pair; none of them *can* choose), so browsers rejected it outright and the tray's mgmt-pinned probe refused the handshake and labelled a healthy console dead. - **#392** — the encode down-driver's thresholds were absolute durations calibrated at 120 Hz, and its stand-down was permanent. A 1440p60 session ratcheted 57 → 5 Mbps over ten minutes on a link that never dropped a packet. - **#387** an `installTap` format snapshot reaching the ObjC terminate handler · **#388** the console's bitrate row · **#390** a GTK front door for the console UI. ## Two entries worth a reviewer's attention - **The sway arm of #389 is not verified on glass.** The lab has Bazzite, Nobara and SteamOS — no sway box. Hyprland, KDE and the DRM floor were all measured on real machines. The notes say so in "Thanks" rather than burying it. - **#389's Hyprland arm shipped wrong in its first cut and was corrected on glass** (`540e282e`): the dpms dispatcher is a **toggle** that ignores the state word, so the blind "send off, later send on" would have *lit* an already-dark head at stream start and *darkened* a lit one at teardown — the exact failure the feature exists to prevent. ## Docs freshness #390 and #393 carried their own docs-site updates. Two facts were left owed, both in `gamescope.md`, both the "stale sentence" class `docs-drift` cannot catch: - the darkening mechanism list still read "KDE, else DRM" and never learned about the sway and Hyprland arms; - the "could not deliver a dark screen" example was *a box in Game Mode* — now precisely the case that **is** served. The real remaining gap is GNOME/Mutter, so it says that instead. Also: the `punktfunk` group grew a third grant this cycle (the three logind power actions), and its callout block enumerated only the usbip nodes — one sentence added. No new `PUNKTFUNK_*` variable, no new host subcommand, and no install command, repo URL or port change, so `data/platforms.json` and the website's vendored copy need nothing. ## Verified here - `check-docs-drift.sh` clean — and **proven live rather than assumed**: a deliberate one-byte break of the openapi copy makes it fail, and it passes again restored. - `check-docs-links.sh` clean. - The `android.yml` Play notes gate **run verbatim**: 481/500 chars, unique against every other release's file. - Both openapi copies `cmp` identical and stamped 0.31.4. - `cargo fmt --all --check` clean; the repo `pre-push` hook run manually, exit 0. - `git diff v0.31.3..HEAD` **empty** on `include/punktfunk_core.h`, `crates/pf-driver-proto`, `punktfunk-core/src/lib.rs`, `punktfunk-host/src/events.rs` and `api/openapi.json` — direct evidence for five version rows. `git diff v0.31.1..HEAD` on the C header also empty, which is the "third release running" claim. - `Cargo.lock`'s 36 workspace version strings moved with `Cargo.toml`; zero `0.31.3` strings remain. 27 crate dirs / 39 workspace members, both unchanged. - Notes voice scan clean: zero backticked terms above `## For developers`, and zero hits scanning for gamescope/polkit/logind/DPMS/CRTC/DRM/systemd/kwin/mutter/wlroots/rustls/ioctl. - CHANGELOG link pinned to `src/tag/v0.31.4`. ## Not run here, and why Any `punktfunk-host` build, clippy or `cargo test` — the host does not compile on macOS at all, and CI covers it. The `web/` and `docs-site/` bun builds — nothing under `web/` is touched by this commit and the docs-site edits are prose in an existing `.md`. The Android unit tests — nothing here touches Kotlin. ## After merge 1. `git tag -a v0.31.4 … && git push origin v0.31.4` — whichever workflow wins the create race seeds the release body from `docs/releases/v0.31.4.md`. 2. Wait for every platform to go green. Watch for the merge-sha gap described in `docs/releases/README.md`: match your own merge sha in the run list, because "CI ran" is not "your commit ran". 3. Dispatch the `announce` workflow with the tag.
enricobuehler added 1 commit 2026-08-24 21:35:31 +00:00
release: 0.31.4 — version bump, notes, CHANGELOG, Play notes
ci / bun-nix (pull_request) Successful in 39s
ci / docs-drift (pull_request) Successful in 39s
ci / web (pull_request) Successful in 1m13s
ci / docs-site (pull_request) Successful in 1m18s
apple / swift (pull_request) Successful in 2m12s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 4m59s
android / android (pull_request) Successful in 8m34s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 8m7s
nix / flake (pull_request) Successful in 8m13s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 3m56s
ci / rust (pull_request) Successful in 18m25s
1d755ebeeb
21 commits since v0.31.3 (14 non-merge). Cut from origin/main c407f6a6 (#393
merged).

THE NUMBER: a patch, and the cleanest one in a while — NOTHING versioned moves.
WIRE_VERSION 2, C ABI 25 with include/punktfunk_core.h showing NO diff against
the v0.31.3 tag (nor against v0.31.2 or v0.31.1 — third release running), driver
protocol 6 / min 3 with pf-driver-proto unchanged, gamepad channel 3, plugin
index schema 1, host event schema 1 (events.rs no diff), gamescope +pfhdr8 with
no new patch files, SDK 0.1.6 and plugin-kit 0.4.4 both untouched. api/openapi.json
is CONTENT-identical — info.version is the entire diff, the first release since
v0.31.0 where the management API grows nothing. No lockfile moves, in any of the
five. Four feat commits, all additive and all client- or Linux-host-side; v0.31.3
and v0.31.1 each carried two feats as a patch on the same reasoning.

THE SHAPE: Linux-host, and the faults share a premise — a policy written against
ONE desktop that silently did nothing on the others. Topology::Exclusive on a
gamescope session was implemented as org_kde_kwin_dpms and reached only a live
KDE desktop, so a Game Mode box (the deployment whose TV the operator most wants
dark) got nothing: #389 is five commits closing that — a DRM floor for a box with
no desktop at all, sway and Hyprland arms, the managed route's own hold, and the
box-session free that was gated on is_steam_launch. The sleep:idle BLOCK
inhibitor refused every Suspend() for a stream's length including the operator's
own from Steam's power menu, and on a DM-stopping takeover polkit's allow_active
fallback found no session to elect and dropped all three power actions to
auth_admin_keep (#391). The web console served the LEGACY identity because every
launcher names that pair and none of them CAN choose, so browsers rejected it and
the tray's mgmt-pinned probe refused the handshake and labelled a healthy console
dead (#393). Plus the client's encode down-driver (#392), an installTap format
snapshot reaching the ObjC terminate handler (#387), the console's bitrate row
(#388), and a GTK front door for the console UI (#390).

TWO ENTRIES WORTH THE READER'S ATTENTION, both recorded as such:
  * The sway arm of #389 is NOT verified on glass — the lab has Bazzite, Nobara
    and SteamOS, no sway box. Hyprland, KDE and the DRM floor were all measured
    on real machines. The notes say so in "Thanks" rather than burying it.
  * #389's Hyprland arm shipped WRONG in its first cut and was corrected on glass
    (540e282e): the dpms dispatcher is a TOGGLE that ignores the state word, so
    the blind "send off, later send on" would have LIT an already-dark head at
    stream start and DARKENED a lit one at teardown — the exact failure the
    feature exists to prevent. Read -> act only if different -> verify.

DOCS FRESHNESS, per docs/releases/README.md step 1: #390 and #393 carried their
own docs-site updates (clients.md, and #389's two gamescope.md edits). Two facts
were left owed, both in gamescope.md and both the "stale sentence" class that
docs-drift cannot catch:
  * the darkening mechanism list still read "KDE, else DRM" and never learned
    about the sway and Hyprland arms from e0a82201;
  * the "could not deliver a dark screen" example was a box in Game Mode, which
    is now precisely the case that IS served by the DRM floor. The real remaining
    gap is GNOME/Mutter, so it says that instead.
Also: the punktfunk group grew a third grant this cycle (the three logind power
actions, via 49-punktfunk-power.rules), and the group's own callout block
enumerated only the usbip nodes — one sentence added there.
No new PUNKTFUNK_* variable this cycle (PUNKTFUNK_UI_TLS_CERT/KEY are
pre-existing and already in the baseline), no new host subcommand, and no install
command, repo URL or port change, so data/platforms.json and the website's
vendored copy need nothing.

VERIFIED HERE: scripts/ci/check-docs-drift.sh clean, and PROVEN LIVE rather than
assumed — a deliberate one-byte break of the openapi copy makes it fail, and it
passes again restored; scripts/ci/check-docs-links.sh clean; the android.yml Play
notes gate run verbatim, 481/500 characters and unique against every other
release's file; both openapi copies cmp identical and stamped 0.31.4; cargo fmt
--all --check clean; git diff v0.31.3..HEAD empty on include/punktfunk_core.h, on
crates/pf-driver-proto, on punktfunk-core/src/lib.rs, on punktfunk-host/src/events.rs
and on api/openapi.json, which is the direct evidence for those five version rows;
git diff v0.31.1..HEAD on the C header also empty, which is the "third release
running" claim; Cargo.lock's 36 workspace version strings moved with Cargo.toml
and zero 0.31.3 strings remain; 27 crate dirs / 39 workspace members, both
unchanged; notes voice scan clean (zero backticked terms above ## For developers,
and zero internal names on a scan for gamescope/polkit/logind/DPMS/CRTC/DRM/
systemd/kwin/mutter/wlroots/rustls/ioctl); CHANGELOG link pinned to
src/tag/v0.31.4.

NOT RUN HERE, and why: any punktfunk-host build, clippy or cargo test — the host
does not compile on macOS at all, and CI covers it; the web/ and docs-site/ bun
builds — nothing under web/ is touched by this commit and the docs-site edits are
prose in an existing .md; the Android unit tests — nothing here touches Kotlin.

LEFT AS A DECISION, not made here: the tag itself. Notes, CHANGELOG and Play text
are authored ahead of it exactly as docs/releases/README.md step 1 requires, so
whichever workflow wins the create race seeds a complete release body — but
pushing v0.31.4 fans out every build workflow, and that is step 2.
enricobuehler merged commit d2c6e1c9c0 into main 2026-08-24 22:26:30 +00:00
enricobuehler deleted branch worktree-release-0314 2026-08-24 22:26:34 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#394