c04c5be2241f0b60e45f42674df5eb802d1f82f1
2169
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c04c5be224 |
docs: USB passthrough is a plugin now, not a recipe you assemble
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 10s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 9s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 18s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 26s
ci / web (push) Successful in 1m5s
docker / builders-arm64cross (push) Successful in 14s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 51s
ci / docs-site (push) Successful in 1m14s
ci / rust-arm64 (push) Successful in 1m18s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m14s
docker / deploy-docs (push) Successful in 31s
ci / rust (push) Successful in 7m20s
Adds a VirtualHere section to the plugins page — what it is, that both halves of VirtualHere are yours to install and licence, that the Devices tab writes a name-based rule so it survives the couch rebooting, and that Diagnostics is where to look when nothing happens. States the coverage limit up front rather than letting somebody discover it: there is no VirtualHere server for iOS or tvOS, so those clients cannot pass devices through, and nothing on our side can change that. Cuts the automation.md recipe from 75 lines to a pointer. It now leads with "use the plugin" and keeps only the zero-code two-hook version for people who would rather not install one — with its trade-offs stated instead of implied: the address is hard-coded so it breaks when the couch reboots, and an abnormal stream end strands the device on the host. Those two failures are exactly what the plugin exists to fix, so the reader gets to make an informed choice. Not build-verified: docs-site does not build standalone in this checkout. Checked by hand that Callout is in fumadocs' default MDX components with a valid `warn` type, that the JSX balances, and that the cross-page anchor matches github-slugger of the heading. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ef2bb56251 |
fix(tray): probe /login without redirects, and open the address the probe checked
ci / docs-site (push) Successful in 1m17s
apple / swift (push) Successful in 1m17s
ci / rust-arm64 (push) Successful in 1m48s
ci / web (push) Successful in 1m56s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 8s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 9s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 6s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 14s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 11s
deb / build-publish-client-arm64 (push) Successful in 2m6s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
deb / build-publish (push) Successful in 5m3s
docker / builders-arm64cross (push) Successful in 6s
deb / build-publish-host (push) Successful in 4m14s
docker / deploy-docs (push) Successful in 27s
ci / rust (push) Successful in 6m52s
android / android (push) Successful in 7m11s
arch / build-publish (push) Failing after 7m24s
apple / screenshots (push) Successful in 14m27s
windows-host / package (push) Successful in 18m20s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Successful in 24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m38s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m10s
Two ways the tray could misreport a healthy console. The probe hit `/`, which is auth-gated and 302s to /login, and ureq follows redirects by default — so TLS, `/`, and a full cold Nitro SSR of /login all had to fit inside one 2s budget, and a console that was merely warming up read as down. It now probes /login with redirects(0) on the agent: one round trip, and a 302 already counted as up. Neither user of that agent wants redirects; the summary is a terminal JSON route. The menu then opened https://localhost:<port> while the poller probed 127.0.0.1. web-run.cmd binds HOST=0.0.0.0 — IPv4 only — and Windows resolves localhost to ::1 first, so the tray could call the console healthy and hand the browser a URL that fails. Both are 127.0.0.1 now, which is what the Linux tray already did, so the menu can no longer disagree with the status printed above it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d9912aa795 |
fix(windows/update): an update puts the status tray back instead of killing it for good
Every update started from the web console killed the tray permanently. Three pieces had to line up, and they did: the installer's StopTrays force-kills every punktfunk-tray.exe (it is one of the files being replaced), its relaunch is a [Run] entry flagged skipifsilent, and the in-console updater spawns the installer with /VERYSILENT. So the tray died on every such update and waited for the next sign-in, because the Run value is a logon trigger. Confirmed on a box whose tray was absent while its Run key, its exe and a session signed in hours before the update were all present. The installer cannot fix this itself. Spawned from the SYSTEM host service, its `runasoriginaluser` resolves to SYSTEM — so relaunching there would place a SYSTEM-owned tray in the user's session, where it would hold the per-session Local\PunktfunkTray mutex and block the real tray at the next sign-in. Strictly worse than the bug. The host does it instead, because only the host has the right token. IntentRecord gains tray_was_running, captured before the installer is spawned (reusing the conflicting-host scan's process snapshot rather than opening a second one), and boot reconciliation reads it off the intent before reconcile consumes it and relaunches through tray::start(). Restored on both terminal outcomes — a rolled-back install killed the tray just as dead as a successful one — but never while an apply is still in flight, where the installer may only kill it again. The field is serde(default), so an intent written by an older host reads as false and behaves exactly as before; covered by a test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c77823d800 |
feat(windows/tray): punktfunk-host tray start|stop|status, so a dead tray is one command away
The status tray is a per-user, per-session GUI process with no recovery path of
its own: the HKLM Run value only fires at sign-in, and nothing in the product
ever restarts one. Anything that kills a tray — an upgrade's StopTrays, a crash —
therefore left the operator without an icon until they signed out and back in,
with no way to ask for it back.
windows/tray.rs becomes the one place that knows tray lifecycle (find, start,
stop, is-running), so the CLI and post-update reconciliation share an
implementation rather than growing two.
start() cannot simply spawn the exe, because the launch crosses a privilege
boundary in one direction only:
- from the host service (SYSTEM) the tray must land in the active console
session under the LOGGED-IN USER's token, which is WTSQueryUserToken +
CreateProcessAsUserW and needs SE_TCB — SYSTEM-only;
- from a shell already in the console session that call fails (an administrator
does not hold SE_TCB either) and a plain spawn is both sufficient and right.
Trying the privileged path and falling back discriminates the two without
inspecting a token, and adds no unsafe to the crate. But a plain fallback from
ssh/RDP would put a tray in a session nobody can see and report success, so on
failure it consults console_session_mismatch() and refuses with an explanation
instead. stop() is graceful first (--quit lets the tray remove its own icon via
NIM_DELETE, as the uninstaller does), then forces any instance in another session.
Verified on Windows: launched from a SYSTEM scheduled task the tray comes up in
the console session owned by the interactive user, not SYSTEM; from an ssh
session (0 -> console 2) it refuses; a second start is a no-op; stop is graceful
and idempotent.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
3bb30cb2f6 |
fix(windows/web-console): a bun exit no longer parks the console until the next sign-in
The PunktfunkWeb task registers RestartCount=10/PT1M, but Task Scheduler honours restart-on-failure only when the action crashes or fails to start — never for a plain non-zero exit. So any bun exit left the console down until the next boot or interactive logon, with the host still streaming perfectly next to it. Seen on glass on a 0.22.3 upgrade: `web setup` started the task one second after the new service came up, bun exited at once (Last Run Result 0xFFFFFFFF), and the console sat dead for hours while its box served clients — which reads to an operator as "the host is gone". web-run.cmd now supervises bun instead of exiting with it: restart on any exit, indefinitely for a console that served a while and then died, but give up after 10 CONSECUTIVE fast exits so a genuinely broken install still surfaces as a failed task. Any run lasting >= 60s resets that counter. It exits 0 rather than respawning when the payload disappears, so an uninstall does not make it spin. Uptime is measured with an unambiguous clock rather than parsed out of %TIME%, which is locale-formatted (12-hour locales append " PM", many others use ',' as the decimal separator) — the box this was found on prints 18:36:28,39. stop_web_console() polls until :47992 is really free instead of sleeping a blind second: both `schtasks /end` and `taskkill /F` are asynchronous, and web_setup starts the new task immediately afterwards, where bun cannot bind a port the corpse still holds. It re-ends the TASK halfway through, not just the listener — with the launcher now supervising, killing bun alone would be undone by its own restart loop. The systemd unit had the same shape of hole: Restart=on-failure leaves a console that exited 0 down. Now Restart=always, which an explicit `systemctl stop` still overrides. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e90c5d5bcd |
fix(gamepad): the output-report ring absorbs haptics-rate writers (PadShm v2.2)
ci / web (push) Successful in 1m1s
windows-drivers / probe-and-proto (push) Successful in 1m3s
ci / docs-site (push) Successful in 1m16s
windows-drivers / driver-build (push) Successful in 2m15s
ci / rust-arm64 (push) Successful in 3m27s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 8s
deb / build-publish-client-arm64 (push) Successful in 2m21s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 9s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 6s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 11s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 15s
apple / swift (push) Successful in 4m36s
deb / build-publish-host (push) Successful in 4m2s
docker / builders-arm64cross (push) Successful in 5s
docker / deploy-docs (push) Successful in 29s
arch / build-publish (push) Failing after 6m11s
deb / build-publish (push) Successful in 6m6s
android / android (push) Successful in 8m29s
ci / rust (push) Successful in 10m32s
windows-host / package (push) Successful in 16m18s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Successful in 12s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m15s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m42s
apple / screenshots (push) Successful in 20m33s
A field log (2026-07-30) showed a game driving the virtual DualSense's output endpoint at >2 kHz sustained for tens of seconds. The 8-slot ring — sized on the assumption that 2 kHz is double any real HID output rate — overflowed every 4 ms poll, which force-silenced rumble for each storm's whole duration and flooded the log at ~230 WARN lines/s (96 % of the user's 5000-line web-console export, evicting the session history it was needed to diagnose). Three legs, negotiated so every old/new host×driver pairing keeps working: - pf-driver-proto: the ring grows in place 8 -> 56 slots; PadShm becomes exactly one page (4096 B), the hard ceiling that keeps cross-generation section views mappable. A new out_ring_len field carries the driver's side of the length negotiation. Deliberately NOT a GAMEPAD_PROTO_VERSION bump (that fails closed - no pad at all). - pf-gamepad driver: picks its ring length from the host's out_ring_ver stamp (>= 2 + a full-size map -> 56) and echoes it before every ring_head bump (now a Release store), so an Acquire-observing drain always reads the modulo that indexed the slots it copies. - host drain: follows the echo (0 = old driver = 8); on genuine overflow it now salvages the legacy latest-report slot - the freshest coalesced state - instead of total silence, and the per-poll overflow WARN is rate-limited to 1 line/s per pad with a suppressed count. Verified on the Windows CI runner (drivers workspace build + clippy -D warnings against the WDK; 64 pf-inject tests incl. the new negotiation/ salvage/limiter tests; pf-inject clippy -D warnings) and on Linux via the CI docker image (82 pf-inject tests). DriverVer needs no manual bump - the installer stamps a strictly-increasing build timestamp per release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ec675261fc |
feat(android): the Sony-pad USB grant is asked on connect, not found in Settings
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 6s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 21s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 13s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
ci / docs-site (push) Successful in 1m4s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 19s
ci / rust-arm64 (push) Successful in 1m21s
ci / web (push) Successful in 1m33s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 1m6s
docker / builders-arm64cross (push) Successful in 6s
android / android (push) Canceled after 1m55s
ci / rust (push) Canceled after 1m56s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 47s
docker / deploy-docs (push) Canceled after 0s
On-glass feedback: burying the grant in the Controllers screen made the user go find it. Now MainActivity asks the moment a Sony pad appears — a fresh attach while the app is open, or the app foregrounding with one already plugged in — once per attach (a deny doesn't re-nag; the Controllers card's button stays as the re-ask). Nothing starts on the grant: an uncaptured pad is an ordinary InputDevice at menu time, so the grant is simply recorded and the next stream's capture engages silently. The grant broadcast is shared with the Controllers card so an open card refreshes from either dialog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1984ddb942 |
feat(android): a USB Sony pad is captured — rumble, adaptive triggers, lightbar, gyro
A DualSense on a phone had rumble only where the kernel exposed force feedback, and adaptive triggers / lightbar / player LEDs nowhere — Android has no platform API for any of them, and Bluetooth offers no raw path (L2CAP is LE-only; hidraw is root-sealed — Sony's own Remote Play declares Android triggers unsupported). Claiming the pad's HID interface over USB is the one unrooted route, so that is what the client now does. - HidUsbLink: the device-agnostic half of Sc2UsbLink (claim, multiplexed UsbRequest loop, newest-wins write queue, signalled-unplug discipline), parameterized by device match / interface filter / keep-alive. Sc2UsbLink keeps only its SC2 specifics (Puck interfaces 2..5, lizard refresh). - GamepadFeedback.PadFeedbackSink: 0xCA rumble + 0xCD Led/PlayerLeds/ Trigger now route to a capture link that owns the pad BEFORE the InputDevice vibrator/lights paths — Trigger stops being log-and-drop. - DsDevice: the byte-exact inverse of the host's dualsense_proto / dualshock4_proto — input report 0x01 parse (buttons/sticks/triggers, gyro+accel, both touch points; Edge FN/BACK → wire paddles) and output builders (DS5 0x02 valid-flag-selective incl. the 11-byte trigger blocks and the lightbar-animation release; DS4 0x05 as composed full-state writes). Covered by DsDeviceTest (pure JVM). - DsCapture: stream-mode capture for DualSense / Edge / DS4 — lazy wire slot on the first parsed report, typed mirror (exit chord included), touch normalized onto the rich plane + per-report motion, feedback rendering with a rumble backstop (a USB pad holds its level, so a stalled poll thread self-terminates via a scheduled zero-write) and a teardown motor-stop over EP0. The claim releases the pad's InputDevice slot itself so the wire index hands over deterministically; uncaptured (toggle off / permission denied / Bluetooth) the pad stays on the ordinary InputDevice path. - Rich-input shims: nativeSendPadTouch / nativeSendPadMotion → RichInput::Touchpad / Motion — the plane the desktop and Apple clients already feed; Android pads gain gyro + touchpad on the virtual pad. - Settings: "DualSense / DualShock passthrough (USB)" (ds_capture, opt-out like the SC2 toggle); Controllers screen card with capture status and a front-loaded USB grant so streams start without the permission dialog. The host needs nothing: the DS5/DS4 backends already consume the typed + rich planes and already emit every feedback event rendered here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
696386dee7 |
fix(host/windows): clippy — SAFETY comments on the WinTrust FFI, explicit truncate(false), sort_by_key
deb / build-publish-client-arm64 (push) Failing after 4s
ci / docs-site (push) Successful in 1m18s
ci / web (push) Successful in 2m12s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 14s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 13s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 11s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 56s
deb / build-publish-host (push) Successful in 4m28s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 31s
docker / builders-arm64cross (push) Successful in 11s
ci / rust-arm64 (push) Successful in 5m49s
docker / deploy-docs (push) Successful in 31s
android / android (push) Successful in 6m54s
deb / build-publish (push) Successful in 5m0s
apple / swift (push) Successful in 5m6s
ci / rust (push) Successful in 6m13s
arch / build-publish (push) Failing after 7m37s
windows-host / package (push) Successful in 15m8s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Successful in 41s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m40s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m39s
apple / screenshots (push) Successful in 21m28s
windows-host.yml's clippy sees what the Linux gate structurally cannot (cfg(windows) code); verified with the same clippy line on the runner this time, not just cargo check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5790a3e334 |
docs(release): v0.22.3 notes — the Updates card and one-click updating join the installer fixes
ci / web (push) Successful in 2m25s
ci / rust-arm64 (push) Successful in 2m53s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 13s
ci / docs-site (push) Successful in 1m6s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 24s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 33s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 13s
docker / builders-arm64cross (push) Successful in 9s
docker / deploy-docs (push) Successful in 33s
ci / rust (push) Successful in 7m2s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3b1485e2a1 |
fix(plugins/windows): the runner can read its own bundle, so it actually starts
ci / rust (push) Canceled after 27s
ci / rust-arm64 (push) Canceled after 28s
ci / web (push) Canceled after 28s
ci / docs-site (push) Canceled after 28s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Canceled after 0s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Canceled after 0s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Canceled after 0s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 0s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
apple / swift (push) Successful in 4m45s
android / android (push) Successful in 4m58s
deb / build-publish-host (push) Successful in 4m14s
deb / build-publish (push) Successful in 5m51s
deb / build-publish-client-arm64 (push) Successful in 1m19s
arch / build-publish (push) Failing after 6m54s
windows-host / package (push) Failing after 10m59s
windows-host / canary-manifest (push) Skipped
windows-host / winget-source (push) Skipped
apple / screenshots (push) Canceled after 14m9s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m17s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 14m33s
Enabling the plugin runner did everything right and then nothing happened.
The task went Ready with LastTaskResult 1 within a second of every start, and
the console kept showing it enabled-but-not-running with nothing to explain
why. Task Scheduler discards the action's output, so the reason never
surfaced anywhere:
error: EPERM reading "C:\Program Files\punktfunk\scripting\runner-cli.js"
This file already knows why. RUNNER_UNIT_DIRS carries the note that bun opens
the files it loads asking for FILE_WRITE_ATTRIBUTES on top of read, so a plain
(RX) grant makes them die with EPERM — found on glass when the plugin and
script directories were fixed. The runner's own entry script was missed. It
lives in {app}\scripting, which carries only Users:(RX), and LocalService
reaches that through Authenticated Users, so bun could never open the one file
it was started to run. The runner has not been able to start since it moved
off SYSTEM, which is a principal that has full control everywhere and so never
met this.
So {app}\scripting now gets the same (OI)(CI)(RX,WA) the unit dirs get, at
enable, revoked at disable like every other grant here. WA moves timestamps
and the read-only bit and cannot touch content, so the three-way split the
module maintains still holds: code read-only, secrets read-only, only
plugin-state writable. A plugin still cannot rewrite the runner.
Measured on glass on .173, same box, same task, only the ACE differing:
without it Ready/lastResult=1 and no runner process; with it Running, a live
runner, and GET /store/runtime answering running:true — which is exactly what
the console reads. Also checked what bun does with the access: nothing. It
opens the entry for write and never writes, and the directory is byte-identical
afterwards.
Windows-only code, so it is rustfmt-clean and type-reviewed but NOT
compile-verified here — the Windows CI job is the gate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
4a540bddc8 |
feat(host/deck): one-click source rebuild — the update.sh run as a transient user unit
ci / rust-arm64 (push) Successful in 1m36s
ci / docs-site (push) Successful in 1m28s
ci / web (push) Successful in 2m25s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 9s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 6s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 1m13s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
deb / build-publish-client-arm64 (push) Successful in 2m27s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m47s
deb / build-publish-host (push) Successful in 5m53s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 7s
android / android (push) Successful in 7m2s
docker / builders-arm64cross (push) Successful in 11s
arch / build-publish (push) Failing after 7m33s
ci / rust (push) Successful in 7m35s
docker / deploy-docs (push) Successful in 39s
windows-host / package (push) Failing after 11m1s
windows-host / canary-manifest (push) Skipped
windows-host / winget-source (push) Skipped
deb / build-publish (push) Successful in 6m53s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m21s
apple / swift (push) Successful in 4m58s
apple / screenshots (push) Successful in 21m32s
The U3.1 leg of planning:host-update-from-web-console.md. The Deck's on-device install gets the Update-now button with no opt-in (user-owned, no root): update.sh --pull runs under systemd-run --user so the script's own restart of punktfunk-host can't kill it mid-build (a child in our cgroup would die with us). Outcome without version equality — which a source rebuild can't promise: a failed build leaves the host alive to report it (unit watched to failure, log attached); a successful one restarts us, and the new source_build intent flag makes intent-present-at-boot itself the success signal (the script only restarts the host after a successful install). The console stops treating a live long build as a timeout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
51d5f6cb29 |
feat(host/windows): boot-loop auto-rollback — the supervisor re-runs the cached previous installer
ci / docs-site (push) Successful in 1m11s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 7s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 6s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 4s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
ci / web (push) Successful in 1m58s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 1m8s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 42s
deb / build-publish-client-arm64 (push) Successful in 3m19s
deb / build-publish-host (push) Successful in 6m17s
ci / rust-arm64 (push) Successful in 6m58s
android / android (push) Successful in 4m51s
docker / builders-arm64cross (push) Successful in 12s
windows-host / package (push) Failing after 5m39s
windows-host / canary-manifest (push) Skipped
windows-host / winget-source (push) Skipped
docker / deploy-docs (push) Successful in 1m58s
arch / build-publish (push) Failing after 8m14s
apple / swift (push) Successful in 4m59s
apple / screenshots (push) Canceled after 0s
deb / build-publish (push) Successful in 11m51s
ci / rust (push) Canceled after 13m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 9m38s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 9m11s
The U3.2 leg of planning:host-update-from-web-console.md. The service worker loop — the one piece that survives an upgrade — detects a fresh update-intent whose target version is the crash-looping child (≥3 rapid restarts, intent <30 min), then exactly once: picks the newest cached non-target installer, requires a valid Authenticode signature, writes a rolled-back result record for the console, deletes the intent, and spawns the installer silently. No cached installer or a failing signature degrade to today's backoff loop with a loud log — never a brick, never an installer loop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3e21398c16 |
fix(lock): pf-update rides the 0.22.3 workspace bump
audit / bun-audit (plugin-kit) (push) Successful in 22s
audit / cargo-audit (push) Successful in 37s
audit / bun-audit (sdk) (push) Successful in 21s
audit / pnpm-audit (push) Successful in 11s
audit / docs-site-audit (push) Successful in 22s
ci / web (push) Successful in 1m52s
ci / docs-site (push) Successful in 2m4s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m58s
android / android (push) Successful in 5m38s
audit / license-gate (push) Successful in 5m0s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m11s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 48s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 4s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 4s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
apple / swift (push) Canceled after 0s
arch / build-publish (push) Failing after 7m37s
apple / screenshots (push) Canceled after 0s
ci / rust (push) Canceled after 6m46s
ci / rust-arm64 (push) Canceled after 6m42s
deb / build-publish (push) Canceled after 4m47s
deb / build-publish-host (push) Canceled after 4m17s
deb / build-publish-client-arm64 (push) Canceled after 2m22s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 29s
docker / deploy-docs (push) Canceled after 0s
audit / bun-audit (web) (push) Successful in 24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 28s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 2m3s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 28s
windows-host / package (push) Canceled after 6s
windows-host / canary-manifest (push) Canceled after 0s
windows-host / winget-source (push) Canceled after 0s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m31s
flatpak / build-publish (push) Successful in 10m8s
release / apple (push) Successful in 26m17s
The U2 branch minted the lock entry at 0.22.2 and the rebase onto the version bump left it stale — --locked builds fail until it matches. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
239c69fd71 |
feat(web,docs): Linux one-click in the card — opt-in hint, staged and nothing-newer outcomes
audit / bun-audit (sdk) (push) Successful in 18s
audit / bun-audit (web) (push) Successful in 18s
audit / docs-site-audit (push) Successful in 23s
audit / pnpm-audit (push) Successful in 12s
audit / cargo-audit (push) Successful in 37s
audit / bun-audit (plugin-kit) (push) Successful in 1m14s
arch / build-publish (push) Failing after 1m17s
ci / rust-arm64 (push) Failing after 44s
ci / web (push) Successful in 1m5s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 21s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 5s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 4s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
ci / docs-site (push) Successful in 2m18s
deb / build-publish-host (push) Failing after 2m15s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 53s
deb / build-publish (push) Failing after 3m43s
audit / license-gate (push) Successful in 4m47s
deb / build-publish-client-arm64 (push) Successful in 3m52s
docker / builders-arm64cross (push) Successful in 14s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 2m49s
ci / rust (push) Failing after 3m6s
docker / deploy-docs (push) Successful in 55s
windows-host / package (push) Failing after 6m27s
windows-host / canary-manifest (push) Skipped
windows-host / winget-source (push) Skipped
android / android (push) Successful in 8m21s
apple / swift (push) Canceled after 0s
apple / screenshots (push) Canceled after 0s
flatpak / build-publish (push) Successful in 4m34s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 4m19s
release / apple (push) Canceled after 57s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 4m45s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Canceled after 2m26s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Canceled after 0s
windows / build (aarch64-pc-windows-msvc) (push) Canceled after 0s
windows / build (x86_64-pc-windows-msvc) (push) Canceled after 0s
The apply panel serves staged kinds too; notify mode shows the group-join command when the helper is installed but not yet enabled; outcomes render 'staged — reboot to finish' and 'your package source had nothing newer yet' distinctly. Docs: the Linux opt-in section (why it's a group, what the grant bounds, the pacman stance). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
06a249e49f |
feat(host/linux): opt-in one-click updates — the pf-update root helper, group-scoped polkit grant, per-PM legs
The U2 leg of planning:host-update-from-web-console.md. A new dep-free root helper (crates/pf-update) runs the distro package manager against the INSTALLED punktfunk packages — apt (index refresh scoped to our list when present), dnf, rpm-ostree (single-transaction re-resolve, reported staged), sysext (the proven signed-feed updater), pacman only behind the explicit PACMAN_FULL_SYSUPGRADE opt-in — then the run-the-binary gate, then a root-written result record. Zero attacker-influenceable parameters end to end: fixed ExecStart oneshot (punktfunk-update.service), polkit rule scoped to that one unit's start verb for the shipped-EMPTY punktfunk-update group (joining it is the auditable opt-in; every postinst creates it, none populate it). The host starts the unit, interprets the record (staged / nothing-newer-yet / changed), and crosses its own restart on the same intent/reconcile machinery as the Windows leg. Status now reports staged results and the opt-in hint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
bb1f93d90e |
feat(web,docs): the Update-now flow — password re-entry at the BFF, restart-tolerant progress, same-origin hardening
apply.post.ts intercepts the one proxied route that restarts the host: the console password is re-verified per apply (login throttle shared, stripped before forwarding) so a 7-day cookie alone can't do it. New Sec-Fetch-Site same-origin check on every mutating request (login CSRF included). The card's apply flow: confirm dialog → live-session force escalation → download/verify/restart progress rendered from the last snapshot while polls fail (the host and, on Windows, this very server restart mid-flow) → durable success/failure from last_result. Docs: the one-click section + kill switch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
bb48225414 |
feat(host/windows): one-click update apply — verified installer download, intent/reconcile, POST /update/apply
The U1 leg of planning:host-update-from-web-console.md. The apply request carries no version/url/channel (the zero-parameter invariant): the host installs exactly what its Ed25519-verified manifest announced. Pipeline: staged download (resume + disk preflight) → manifest sha256 → Authenticode (valid signature, untrusted root tolerated while the cert is self-signed; leaf sha256 pinned via the signed manifest, extracted from the SAME WinVerifyTrust state) → intent record → detached CREATE_BREAKAWAY_FROM_JOB spawn of the winget-blessed silent flags. The installer kills this process by design; boot-time reconciliation reports the outcome (update.applied event / a durable failure with the installer log path) across the restart. Session guard (force to override), PUNKTFUNK_UPDATE_APPLY=0 kill switch, single-flight via job + fresh-intent detection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
73e1224345 |
fix(ci/update): an empty AUTHENTICODE_SHA256 broke the manifest build — jq -R needs one input line
ci / web (push) Successful in 1m5s
ci / docs-site (push) Successful in 2m30s
ci / rust-arm64 (push) Successful in 3m40s
android / android (push) Successful in 4m35s
decky / build-publish (push) Successful in 47s
ci / rust (push) Successful in 6m26s
arch / build-publish (push) Successful in 8m54s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 23s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 12s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m10s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 12m27s
docker / deploy-docs (push) Skipped
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 10s
docker / builders-arm64cross (push) Successful in 11s
apple / swift (push) Successful in 4m45s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m47s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m15s
deb / build-publish-host (push) Successful in 4m45s
deb / build-publish-client-arm64 (push) Successful in 1m25s
apple / screenshots (push) Canceled after 7m43s
deb / build-publish (push) Canceled after 3m20s
printf '%s' hands jq -R no line at all for an empty value; its empty output made --argjson invalid. Seen on the first live canary-manifest run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit a12c8bc99d41c4f7b8e4c426d560171b2b12dd5e) |
||
|
|
1c836afc02 |
chore(release): bump workspace version to 0.22.3
ci / web (push) Successful in 2m4s
ci / docs-site (push) Successful in 2m25s
android-screenshots / screenshots (push) Successful in 2m12s
ci / rust-arm64 (push) Successful in 7m8s
apple / swift (push) Successful in 4m38s
decky / build-publish (push) Successful in 52s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 2m44s
deb / build-publish-client-arm64 (push) Successful in 1m32s
arch / build-publish (push) Successful in 10m25s
linux-client-screenshots / screenshots (push) Successful in 3m16s
audit / bun-audit (plugin-kit) (push) Successful in 28s
audit / bun-audit (sdk) (push) Successful in 27s
audit / bun-audit (web) (push) Successful in 26s
audit / docs-site-audit (push) Successful in 24s
audit / pnpm-audit (push) Successful in 15s
audit / license-gate (push) Successful in 5m11s
sbom / sbom (push) Successful in 35s
android / android (push) Successful in 7m33s
web-screenshots / screenshots (push) Successful in 4m12s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 18s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 11s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 13s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 12s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 13s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 41s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m36s
audit / cargo-audit (push) Successful in 39s
docker / deploy-docs (push) Successful in 42s
docker / builders-arm64cross (push) Successful in 20s
flatpak / build-publish (push) Successful in 6m50s
deb / build-publish-host (push) Successful in 5m19s
deb / build-publish (push) Successful in 6m58s
ci / rust (push) Successful in 17m25s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m37s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m0s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 3m3s
apple / screenshots (push) Canceled after 0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m46s
release / apple (push) Successful in 25m45s
windows-host / package (push) Successful in 10m58s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Failing after 18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m26s
Windows-installer patch release. 0.22.1 and 0.22.2 shipped without the web console in them at all — confirmed from the tag builds' own logs, where the console build step is `skipped` on a cache hit and the job is still green — which also removed the only code that stopped bun before the installer replaced it, hence the "DeleteFile failed; code 5" dialog. Both fixed here, along with updates no longer disabling an operator's plugin runner. Lock touched for the 30 workspace members only. `base64` stays at 0.22.1 and the eight gtk-rs crates stay at 0.22.0 — they share our version space and a blanket sed would move them to versions that do not exist. Diff is versions-only, 30 insertions and 30 deletions; `cargo metadata --locked` resolves; `cargo fmt --all --check` clean in both the main and the packaging/windows/drivers workspaces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>v0.22.3 |
||
|
|
beefeaf9d7 |
fix(ci/windows-host): refuse to pack an installer that is missing a payload
Every payload the job bundles is now asserted before packing: the console, the bun runtime, the plugin runner, the FFmpeg DLLs and VB-CABLE. Each is optional to pack-host-installer.ps1 — right for a local debug pack, and the reason 0.22.1 and 0.22.2 shipped with no web console: one unset variable omitted it behind a single line of log and the build stayed green. CI knows it bundles all five, so a missing input belongs here as a failure rather than downstream as a quietly smaller installer. FFmpeg is the one that would hurt most and was silent too: an amf-qsv host link-imports avcodec, so an installer missing those DLLs ships a host that cannot start at all, and FFMPEG_DIR is a fallback to a provisioned path that nothing verified. The shape is borrowed from the packer's own VB-CABLE check, which already throws on a supplied-but-empty dir "instead of silently shipping an installer without the virtual mic - exactly the field regression this bundling fixes". Same lesson, applied to the rest. Both paths were exercised on the Windows runner: all five unset fails with exit 1 naming each one, all five present passes with exit 0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5b6fe7882a |
fix(ci/windows-host): a cached console no longer ships an installer without one
WEB_OUTPUT_DIR was exported on the last line of "Build + smoke-boot web
console", a step that is skipped on a cache hit. So the second and every
later build with an unchanged web/ and sdk/ left it unset — and
pack-host-installer.ps1 reads an unset WEB_OUTPUT_DIR as "don't bundle the
console" and says so in one line of log before carrying on happily.
The installers that fell out of that have no {app}\web at all: no
web-run.cmd, so `web setup` bails with "web launcher missing" before it
registers anything, so there is no PunktfunkWeb task, no console, and no
firewall rule for 47992. A user is left with a working host, a tray that says
"Open web console (not responding)" for ever, and nothing to reinstall their
way out of, because every rebuild reproduces it.
It also explains the bun.exe lock reported separately. bun.exe ships under
WithWeb OR WithScripting, but the pre-copy stop was #ifdef WithWeb — so in a
console-less installer bun still shipped while the only code that stopped bun
was compiled out, and replacing a running bun.exe is the "DeleteFile failed;
code 5" modal.
Exporting the variable from its own unconditional step fixes it. The throw
alongside is the actual lesson: a missing web\.output now fails the job
instead of silently redefining what the installer is.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
c64ada5649 |
fix(windows/installer): an update stops every bun before it replaces bun.exe
Updating to 0.22.1 could die on a modal: "C:\Program Files\punktfunk\bun\ bun.exe — DeleteFile failed; code 5. Access denied." Windows will not delete a running executable, so that message means a bun was still alive when the copy reached it, and the installer had no way to recover. Two things run that bun, and neither is a child of the host service, so stopping the service — which the installer does correctly wait for — never touched either. Both are Task Scheduler tasks: PunktfunkWeb (SYSTEM, the console) and PunktfunkScripting (LocalService, the plugin runner). The only pre-copy stop we had looked for exactly one of them, and found processes by task name or by who was listening on 47992/3000. The plugin runner matched neither clause: different task, and it listens on no port at all. So anyone who had run `plugins enable` held bun.exe mapped through the whole install and failed this way on every single update. The web console could lose the race too. Stop-ScheduledTask returns once termination has been *requested* and Stop-Process is TerminateProcess, so the old code went straight from asking to copying; the Rust twin of that routine has always ended with a deliberate one-second settle. And neither task was disabled for the duration, while both carry restart-on-failure (web ten times a minute apart, scripting 999) and the web task also has a logon trigger — so a force-kill invited a respawn into the middle of a copy that takes well over a minute at lzma2/max. StopBunRuntimes now disables both tasks before stopping them, kills any bun whose image lives under the install dir — by path, so a developer's own bun survives — keeps the old port sweep for pre-bun installs that ran node on 3000, and then waits until both are actually gone rather than assuming. bun.exe also gains restartreplace, so if some bun still escapes all of that, the file lands on the next restart instead of dead-ending the install. Disabling a task is not free, though: unlike a stopped one it does not come back at the next boot, so an install that aborts anywhere after that point would take the console down for good. Hence two restores — a [Run] entry for the normal flow, and DeinitializeSetup, which Inno calls even when the user cancels. Both re-enable only what was enabled before the copy, and enabling an enabled task does nothing, so the pair is idempotent. Putting things back also turned up a second bug worth naming: the scripting entry re-registers its task and then unconditionally disables it, which is right on a first install and has silently switched an operator's plugin runner off on every upgrade since. The restore runs after both re-registrations and honours the prior state, so a fresh install still leaves the opt-in runner off. The Pascal and the PowerShell were both compiled and run on the Windows CI runner (ISCC, plus the query halves of each command) — but the install path itself is not yet exercised on glass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b275e6d34c |
feat(web,docs): the Updates card — version, channel, install kind, and the exact update command
android / android (push) Canceled after 1m54s
apple / swift (push) Canceled after 0s
apple / screenshots (push) Canceled after 0s
ci / docs-site (push) Successful in 1m15s
arch / build-publish (push) Canceled after 1m50s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 14s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
ci / rust (push) Canceled after 59s
ci / rust-arm64 (push) Canceled after 2m31s
ci / web (push) Canceled after 0s
deb / build-publish (push) Canceled after 18s
deb / build-publish-host (push) Canceled after 19s
deb / build-publish-client-arm64 (push) Canceled after 12s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 1m15s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Canceled after 0s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 36s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 2m28s
windows-host / package (push) Canceled after 0s
windows-host / canary-manifest (push) Canceled after 0s
windows-host / winget-source (push) Canceled after 0s
decky / build-publish (push) Successful in 50s
Notify-only (U0): polls /update/status (which keeps the host's manifest cache warm), Check-now with the 30s limit surfaced, release-notes link, stale-feed and check-disabled states, copyable per-install-kind command. en+de strings; docs-site 'Updating the Host' page wired into the install section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c4c4f217bf |
ci(update): build+sign+publish the update manifest — stable at announce, canary after the canary installer
bash+openssl signer (raw-64-byte ed25519 over exact bytes, base64 .sig — the plugin-index format) with the pinned-key cross-check, manifest-then-sig upload order, and a live-feed self-verify. announce.yml re-hashes the installer against its sidecar and fail-closes without UPDATE_MANIFEST_KEY; pre-release tags never enter the stable feed. windows-host.yml grows a Linux canary-manifest job. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
cc01562631 |
feat(host): update check — signed per-channel manifest, install-kind detection, /api/v1/update surface
The U0 leg of planning:host-update-from-web-console.md: a signed update manifest (Ed25519, keys pinned in the binary via the plugin-store verify path, serial floor persisted against rollback, channel-bound, 45-day stale hint) fetched lazily behind GET /update/status + rate-limited POST /update/check, admin lane only (plugin lane whole-prefix denied, absent from the cert allowlist). Install kind + channel come from root-owned facts; deb/rpm/pacman builds now stamp /usr/share/punktfunk/install-kind. Emits update.available once per discovered version. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
940bd0b7ec |
feat(core/abr): the startup capacity probe's target is configurable
ci / docs-site (push) Successful in 1m20s
ci / web (push) Successful in 1m31s
ci / rust-arm64 (push) Successful in 1m44s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 15s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 13s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 13s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 30s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 30s
apple / swift (push) Successful in 4m43s
android / android (push) Successful in 6m18s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 15s
deb / build-publish-host (push) Successful in 6m14s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 13s
deb / build-publish (push) Successful in 5m16s
docker / builders-arm64cross (push) Successful in 12s
docker / deploy-docs (push) Successful in 39s
arch / build-publish (push) Successful in 9m18s
apple / screenshots (push) Canceled after 4m51s
ci / rust (push) Successful in 9m43s
deb / build-publish-client-arm64 (push) Canceled after 8m52s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 8m7s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 8m5s
windows-host / package (push) Canceled after 10m19s
windows-host / winget-source (push) Canceled after 0s
flatpak / build-publish (push) Successful in 7m26s
release / apple (push) Canceled after 9m48s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Canceled after 0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Canceled after 0s
windows / build (aarch64-pc-windows-msvc) (push) Canceled after 0s
windows / build (x86_64-pc-windows-msvc) (push) Canceled after 3m23s
The Automatic startup probe bursts at a fixed 2 Gbps two seconds into every session, deliberately far above any plausible link so the burst measures the link rather than itself. On links the burst DISTURBS, that backfires: on an LG G5 (webOS 10.3), three back-to-back connects to the same Gamescope host split two ways — the two where the probe finished in ~1-2 s had video within 2-4 s, while the one that hit the 6 s timeout showed no video for 14 s. Even a "successful" probe on that link reported send_dropped=20211. The webOS client already caps its own speed test at 320 Mbps because an unbounded firehose starves a 2-3 core TV; core then bursts the same hardware at 2 Gbps. PUNKTFUNK_ABR_PROBE_KBPS now sets that target, so an embedder that caps its own speed test can cap ours to match. Unset, zero, or unparseable keeps the 2 Gbps default, so every existing session behaves exactly as before. The existing opt-out (PUNKTFUNK_ABR_PROBE=0) is no substitute: it leaves the climb ceiling pinned at the negotiated ~20 Mbps. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
77517bbe21 |
style(web): let biome format the message catalogues and the Logs story
ci / web (push) Successful in 1m16s
ci / rust-arm64 (push) Successful in 1m33s
ci / docs-site (push) Successful in 1m37s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 11s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 22s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 18s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 27s
deb / build-publish-client-arm64 (push) Successful in 1m57s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m5s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 41s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 13s
docker / deploy-docs (push) Successful in 37s
deb / build-publish-host (push) Successful in 4m29s
docker / builders-arm64cross (push) Successful in 9s
deb / build-publish (push) Successful in 5m38s
ci / rust (push) Successful in 6m6s
arch / build-publish (push) Successful in 9m36s
windows-host / package (push) Successful in 20m26s
windows-host / winget-source (push) Skipped
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 26m42s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 26m39s
Cosmetic only, and kept out of the feature commit it rode in on so neither has to be read through the other. `biome check --write` reindents both message catalogues from two spaces to tabs (877 lines each, no key, order, or value touched — verified by comparing the parsed objects) and rewraps the Logs story fixtures onto one argument per line with trailing commas. Worth knowing for next time: the catalogues are also written by inlang, which formats with two spaces, so an edit made through that tooling will pull them back. Nothing depends on either shape — `bun run codegen` compiles 440 messages for both locales either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8d6241efae |
feat(web): the logs page can hand a log off — as a file, or to the share sheet
The Logs page could only be read in place. Getting a host log into a bug report meant selecting a screenful of monospace text and hoping the scroll container gave up the rest. Two controls in the toolbar now do it properly. Download writes a .log file named for the moment it was taken; the second button hands the same text to the OS share sheet where there is one (phones, iPads), and copies it to the clipboard everywhere else — which is why it is probed at runtime rather than guessed, and why the button is absent on the one combination where neither exists (plain HTTP, no Web Share). Both export what the filters currently match, not the rendered tail: the 1000-row cap is a DOM budget and has nothing to say about how long a file may be. Lines carry the full date and UTC offset, since a bare wall-clock time stops meaning anything the moment the file leaves the browser. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
384a0adc83 |
chore(release): bump workspace version to 0.22.2
android-screenshots / screenshots (push) Successful in 1m32s
audit / cargo-audit (push) Successful in 38s
audit / bun-audit (plugin-kit) (push) Successful in 20s
audit / bun-audit (sdk) (push) Successful in 15s
audit / bun-audit (web) (push) Successful in 15s
audit / docs-site-audit (push) Successful in 14s
audit / pnpm-audit (push) Successful in 16s
android / android (push) Successful in 5m17s
apple / swift (push) Successful in 5m7s
audit / license-gate (push) Successful in 4m33s
decky / build-publish (push) Successful in 48s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 14s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 12s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 51s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 1m3s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 24s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 20s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 35s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 35s
sbom / sbom (push) Successful in 1m17s
linux-client-screenshots / screenshots (push) Successful in 3m43s
docker / deploy-docs (push) Successful in 19s
docker / builders-arm64cross (push) Successful in 13s
web-screenshots / screenshots (push) Successful in 4m25s
ci / web (push) Successful in 1m6s
ci / rust-arm64 (push) Successful in 3m51s
flatpak / build-publish (push) Successful in 5m18s
ci / docs-site (push) Successful in 1m48s
deb / build-publish (push) Successful in 4m0s
deb / build-publish-client-arm64 (push) Successful in 1m45s
arch / build-publish (push) Successful in 8m9s
ci / rust (push) Successful in 8m20s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m50s
deb / build-publish-host (push) Successful in 5m8s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 4m1s
windows-host / package (push) Successful in 11m9s
windows-host / winget-source (push) Skipped
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m41s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 3m1s
release / apple (push) Successful in 26m25s
apple / screenshots (push) Successful in 20m53s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 20m21s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m39s
Patch release: 0.22.0 and 0.22.1 gave every default-configured Windows host a controller no game could see. The pf-dualsense -> pf-gamepad package rename also renamed a HARDWARE id, so PnP matched none of our models, fell through to the devnode's synthesized USB ids and let Microsoft's inbox input.inf win — HidUsb cannot start on a software-enumerated devnode, and without a start there is no device interface to answer a channel proof. This cut carries that one-line restore, the [Models]-vs-host guard test, and the Punktfunk display-name rebrand across the Windows devices and firewall rules. Windows hosts only; clients and Linux hosts are untouched. Versions-only lock diff, hand-applied: the 30 workspace-member entries move 0.22.1 -> 0.22.2. Two sets of third-party crates deliberately share our version space and are untouched — `base64` at 0.22.1, and the eight gtk-rs crates at 0.22.0 (cairo/gdk-pixbuf/gio/graphene/pango); a blanket sed would corrupt both, so the bump matches on member name only. `cargo metadata --locked` exits 0 on the pinned toolchain. Release notes in docs/releases/v0.22.2.md seed the release body per the Model-1 flow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>v0.22.2 |
||
|
|
553676282a |
feat(windows): the brand reads Punktfunk on every device Windows shows
deb / build-publish-client-arm64 (push) Failing after 4s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 13s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 11s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
ci / web (push) Successful in 1m53s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 13s
ci / docs-site (push) Successful in 2m3s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 15s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 30s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m24s
windows-drivers / driver-build (push) Successful in 2m30s
docker / builders-arm64cross (push) Successful in 6s
docker / deploy-docs (push) Successful in 29s
android / android (push) Successful in 5m7s
apple / swift (push) Canceled after 4m50s
apple / screenshots (push) Canceled after 0s
deb / build-publish (push) Successful in 4m42s
arch / build-publish (push) Canceled after 5m25s
ci / rust (push) Canceled after 5m26s
ci / rust-arm64 (push) Canceled after 5m31s
deb / build-publish-host (push) Canceled after 5m19s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 3m30s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 3m26s
windows-host / package (push) Canceled after 2m29s
windows-host / winget-source (push) Canceled after 0s
windows-drivers / probe-and-proto (push) Successful in 37s
Device Manager, the firewall list and the monitor name all said "punktfunk". The brand
is Punktfunk.
Renamed: the [Strings] blocks of all four driver INFs (device descriptions, install
disks, provider, manufacturer), the `description` on every SwDeviceProfile the host
creates, pf-mouse's HID manufacturer + product strings, pf-vdisplay's IddCx endpoint
friendly + manufacturer names, the EDID 0xFC display-name descriptor — so Windows now
shows `Generic Monitor (Punktfunk)` — and the netsh firewall rule names.
The EDID edit is a single byte (0x70 -> 0x50) and needs no hand-patched checksum:
Edid::generate_with already recomputes both block checksums after patching the serial.
Deliberately left lowercase, because these are IDENTITIES rather than display names and
renaming them would orphan installed state:
* the SwDeviceCreate enumerator `w!("punktfunk")` — it IS the SWD\PUNKTFUNK\... path
every pad instance id is built from
* pf-paths' `join("punktfunk")` — C:\ProgramData\punktfunk
* the CN=punktfunk-driver cert subject, which purge_driver_certs and both driver build
scripts match by string
* install.rs' `lo.contains("punktfunk virtual display")` probes, whose haystack is
to_ascii_lowercase()d, so they already match the capitalised name
Nothing is orphaned by the renames that DID happen either: netsh rule names,
Get-NetFirewallRule -DisplayName and PowerShell's -match are all case-insensitive, so
the firewall delete paths and reset-pf-vdisplay.ps1's -AdapterName / -GhostMatch
defaults still reap what every release up to 0.22.1 created.
Cosmetic, with two consequences worth knowing: it takes a driver rebuild + re-sign to
appear at all, and an existing devnode keeps its cached FriendlyName until it is
recreated.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
02e9cc4691 |
fix(host/windows): a virtual DualSense binds our driver again, not Microsoft's
0.22.0 and 0.22.1 hand every default-configured Windows host a controller no game can
see. `GamepadPref::Auto` resolves to DualSense, so this is the pad almost everyone
gets — which is why it reads as "controllers are broken" rather than as one identity
being broken.
The pf-dualsense -> pf-gamepad PACKAGE rename (
|
||
|
|
152aac291e |
chore(release): bump workspace version to 0.22.1
android-screenshots / screenshots (push) Successful in 1m25s
audit / cargo-audit (push) Successful in 31s
audit / bun-audit (plugin-kit) (push) Successful in 12s
audit / bun-audit (sdk) (push) Successful in 13s
audit / bun-audit (web) (push) Successful in 12s
android / android (push) Successful in 5m37s
audit / pnpm-audit (push) Successful in 7s
audit / docs-site-audit (push) Successful in 13s
decky / build-publish (push) Successful in 23s
ci / rust-arm64 (push) Successful in 1m48s
ci / web (push) Successful in 1m4s
audit / license-gate (push) Successful in 5m21s
ci / docs-site (push) Successful in 2m57s
apple / swift (push) Successful in 4m36s
linux-client-screenshots / screenshots (push) Successful in 9m10s
ci / rust (push) Successful in 12m55s
sbom / sbom (push) Successful in 58s
deb / build-publish-client-arm64 (push) Successful in 5m47s
deb / build-publish-host (push) Successful in 5m38s
web-screenshots / screenshots (push) Successful in 5m54s
docker / builders-arm64cross (push) Successful in 6s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 25s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 57s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 7s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m46s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 28s
docker / deploy-docs (push) Successful in 15s
deb / build-publish (push) Successful in 12m58s
arch / build-publish (push) Successful in 7m25s
windows-host / package (push) Successful in 10m27s
windows-host / winget-source (push) Skipped
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m18s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m45s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 2m50s
flatpak / build-publish (push) Successful in 5m3s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 3m55s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m56s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 21m46s
release / apple (push) Successful in 25m28s
apple / screenshots (push) Canceled after 20m3s
Patch release: 0.22.0 shipped the wrong program as punktfunk-session (the
v0.22.1
|
||
|
|
a48321ee27 |
test(client): CI runs the binaries it ships
ci / web (push) Canceled after 43s
audit / bun-audit (plugin-kit) (push) Successful in 17s
audit / pnpm-audit (push) Successful in 9s
audit / cargo-audit (push) Successful in 34s
audit / bun-audit (sdk) (push) Successful in 1m8s
apple / swift (push) Successful in 1m17s
audit / bun-audit (web) (push) Successful in 1m24s
audit / docs-site-audit (push) Successful in 1m24s
android / android (push) Canceled after 2m9s
apple / screenshots (push) Canceled after 0s
arch / build-publish (push) Canceled after 2m12s
audit / license-gate (push) Canceled after 1m39s
ci / rust (push) Canceled after 1m39s
ci / rust-arm64 (push) Canceled after 1m4s
ci / docs-site (push) Canceled after 43s
deb / build-publish (push) Canceled after 0s
deb / build-publish-host (push) Canceled after 0s
deb / build-publish-client-arm64 (push) Canceled after 0s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Canceled after 0s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Canceled after 0s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Canceled after 0s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 0s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
flatpak / build-publish (push) Canceled after 4s
release / apple (push) Canceled after 1m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 5s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 5s
windows-host / package (push) Canceled after 0s
windows-host / winget-source (push) Canceled after 0s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Canceled after 2m6s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Canceled after 0s
windows / build (aarch64-pc-windows-msvc) (push) Canceled after 0s
windows / build (x86_64-pc-windows-msvc) (push) Canceled after 0s
The 0.22.0 clobber proved a gap no build gate covers: a wrong program wearing the
right binary name compiles green. `cargo build -p punktfunk-client-session` happily
shipped the GTK shell's three-line Windows stub as punktfunk-session, because nothing
between commit and release ever EXECUTED the result.
Two integration tests close the class, and they run under gates that already exist
(ci.yml's workspace test on Linux, windows.yml's test step on Windows):
- contract_smoke spawns the real punktfunk-session against a refusing port and
asserts the stdout contract answers — whatever fails first on the machine
(presenter init headless, the dial elsewhere), the binary must SAY so in a
contract line. Proven non-vacuous by planting the 0.22.0 stub and watching it
fail, then pass again on the real main.rs.
- cli_smoke runs the real punktfunk over its help surface (stdout, exit 0) and an
unknown verb (stderr, exit 5) — store-free and network-free, safe on any runner.
windows.yml now gates punktfunk-cli in all four steps (build, clippy, fmt, test): the
MSIX has shipped its `punktfunk.exe` alias since
|
||
|
|
8e396b8391 |
feat(cli): every command explains itself
`punktfunk help` was one usage blob, and `punktfunk pair --help` was worse than nothing: the flag fell through to the verb, which read "--help" as its subject, printed a terse usage line to stderr and exited 5. For the command that is about to be the documented door for scripts and plugins (Playnite shells to `library --json`), "self-documenting" has to actually hold. Now `punktfunk help <command>` — and `--help`/`-h` after any verb, caught BEFORE dispatch so no verb can mistake the flag for its subject — prints that command's own page: flags, what lands on stdout vs stderr, and which exit code means what, which is the part a script author actually needs. Help goes to stdout and exits 0; an unknown topic refuses with 5. A unit test walks USAGE and asserts every advertised verb has a help page that leads with its own invocation, so the overview and the pages cannot drift apart, and an integration test runs the REAL binary over both spellings. `reachable` also stops scolding: probing an unsaved address is that verb's documented use, but it resolved through the saved-host path first, whose "pair it first" advice printed before the probe ran. It resolves quietly now — same lookup, no lecture. Verified on the Windows CI runner (clippy -D warnings, fmt, 8/8 tests, and the built punktfunk.exe by hand: overview, per-verb pages, quiet `reachable` exit 2) and in the Linux CI image (same gates, 8/8). One field note from the hand run: the exe needs the FFmpeg DLLs beside it or on PATH — true of the session binary already, and the MSIX ships them next to both, so packaging is unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ff01db67ff |
fix(client): punktfunk-session is the session binary again — 0.22.0 shipped the shell's stub
Connecting from the 0.22.0 Windows client bounces straight back to the host list, on every host. The shell is fine; the binary it spawns is not. |
||
|
|
5c0cb84fda |
fix(ci/windows-host): drop the drivers-target cache — act rotates the workspace path
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 12s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 14s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 16s
windows-host / package (push) Canceled after 0s
windows-host / winget-source (push) Canceled after 0s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 21s
ci / rust-arm64 (push) Successful in 1m34s
ci / web (push) Successful in 1m45s
docker / deploy-docs (push) Successful in 37s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 1m29s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 1m30s
ci / docs-site (push) Successful in 1m57s
docker / builders-arm64cross (push) Successful in 9s
ci / rust (push) Successful in 3m51s
I added it yesterday on the theory that cargo's fingerprints would sort out a restored in-tree target/. They can't: act gives each run a different absolute workspace (~/.cache/act/<hash>/hostexecutor), and a target dir restored under a new path carries state pointing at the old one. Measured today — pf-umdf-util died with 14 x 'unable to create file lock (os error 3)' and failed the job. ~1 min of rebuild is the right price, and it's the same rotation that made the other Windows jobs use a fixed C:\t. The web console cache stays: it restored cleanly and skipped its ~2.5 min build+smoke, taking the job 13.6 -> 8.5 min in the same measurement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ba3add85b5 |
fix(ci/windows): install zstd, or every cache save dies on a missing gzip
apple / swift (push) Successful in 1m19s
ci / docs-site (push) Successful in 1m16s
ci / rust (push) Successful in 4m35s
android / android (push) Successful in 5m11s
ci / web (push) Successful in 5m24s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
deb / build-publish-host (push) Successful in 4m26s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
deb / build-publish-client-arm64 (push) Successful in 1m20s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m11s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m34s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 2m35s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 11s
decky / build-publish (push) Successful in 59s
ci / rust-arm64 (push) Successful in 8m59s
docker / deploy-docs (push) Failing after 21s
docker / builders-arm64cross (push) Successful in 1m55s
apple / screenshots (push) Successful in 10m59s
arch / build-publish (push) Successful in 12m32s
deb / build-publish (push) Successful in 14m53s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 20m10s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m53s
The new windows-host cache steps reported '::warning::Failed to save' and nothing ever seeded. actions/cache probes for zstd, doesn't find it, falls back to gzip — and Git's GNU tar then shells out to a gzip that is not on the runner daemon's PATH: 'Child returned status 127', 'cache.tgz: Cannot write: Broken pipe', tar exit 2. Since save failures are warnings, the job stayed green while caching silently did nothing. zstd (+ a staged gzip.exe as insurance) now installs into its own directory — never Git's usr\bin on PATH, which would shadow Windows' find/sort/echo. Applied live to the runner and added to the machine PATH; this step keeps a rebuilt runner honest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b2cf4e908c |
chore(release): bump workspace version to 0.22.0
audit / bun-audit (sdk) (push) Successful in 17s
audit / bun-audit (web) (push) Successful in 17s
audit / docs-site-audit (push) Successful in 17s
audit / pnpm-audit (push) Successful in 11s
audit / bun-audit (plugin-kit) (push) Successful in 3m15s
audit / cargo-audit (push) Successful in 3m24s
android-screenshots / screenshots (push) Successful in 3m40s
apple / swift (push) Successful in 5m0s
audit / license-gate (push) Successful in 7m24s
decky / build-publish (push) Successful in 37s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m17s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 2m3s
arch / build-publish (push) Successful in 19m5s
linux-client-screenshots / screenshots (push) Successful in 10m39s
sbom / sbom (push) Successful in 1m16s
docker / deploy-docs (push) Successful in 11s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 24s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 24s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 8s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 5s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 19s
docker / builders-arm64cross (push) Successful in 5s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 23s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m23s
windows-host / package (push) Successful in 14m34s
windows-host / winget-source (push) Successful in 17s
android / android (push) Successful in 10m16s
web-screenshots / screenshots (push) Successful in 10m52s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m56s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m36s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m51s
deb / build-publish (push) Successful in 13m51s
deb / build-publish-host (push) Successful in 5m27s
deb / build-publish-client-arm64 (push) Successful in 4m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 27m37s
release / apple (push) Successful in 28m45s
apple / screenshots (push) Successful in 21m19s
ci / docs-site (push) Successful in 1m4s
ci / web (push) Successful in 2m46s
ci / rust-arm64 (push) Successful in 3m41s
ci / rust (push) Successful in 3m54s
flatpak / build-publish (push) Successful in 4m24s
256 commits since v0.21.0. Minor, not patch: the headline is settings profiles — named bundles of overrides bound per host, landing on all five clients at once (Linux, Windows, Apple, Android) with one settings surface editing either layer, marked-and-resettable override rows, per-profile colours, host bindings, one-off "Connect with", and pinned host+profile cards. With them: the punktfunk:// link grammar (one parser, one 44-case vector file run by the Rust, Swift and Kotlin suites), double-clickable shortcuts, and `punktfunk` — one headless front-end over the brain layer, which wakes a sleeping host the way a card click does. Also: opt-in HDR on the gamescope path plus the cursor-in-the-node patch that makes those sessions zero-copy; Vulkan Video 10-bit so AMD/Intel HDR keeps the good path; a zero-copy NVENC HDR leg; host OS detection with marks on every client and the console; PUNKTFUNK_HOST_NAME, PUNKTFUNK_MAX_FPS and PUNKTFUNK_VDISPLAY_HZ_MULT; monitor enumeration on Windows; and the release- integrity work (per-asset SHA256 sidecars, a signed sysext feed, one stable driver publisher identity, fail-closed signing guards on a v* tag). Wire protocol stays at 2, the embeddable C ABI at 13 and the Windows virtual- display driver protocol at 6 — 0.18-0.22 hosts and clients keep mixing freely. The Windows virtual-GAMEPAD channel protocol goes 2 -> 3 and fails closed both ways: it carries the fix for a LocalService principal being able to take over a pad's shared input section and forge HID input into the interactive desktop, so the host and its drivers must ship together. The installer ships both. Additive elsewhere: an advisory mDNS `os=` TXT key, HostInfo.os/os_name, MonitorsResponse.pin_supported, an eighth field on the Android JNI discovery record, and appended-last StoredHost fields per the frozen app-widget contract. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>v0.22.0 |
||
|
|
dee9ecf5c5 |
docs(release): v0.21.0's notes describe what v0.21.0 actually shipped
The file had accumulated the gamescope-HDR work as it landed — one "New: HDR on the gamescope path" section plus nine Under-the-hood bullets (the gamescope patches, Vulkan 10-bit, the per-codec probe, the NVENC HDR leg, the EFC BT.2020 model, the managed-spawn flag check, the CI wiring). All of it landed AFTER |
||
|
|
2b82ce6484 |
fix(ci/flatpak): host networking — ostree's resolver never worked through docker's embedded DNS
ci / rust-arm64 (push) Successful in 1m45s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 7s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 6s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 6s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 11s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 13s
ci / web (push) Successful in 4m2s
ci / docs-site (push) Successful in 4m7s
docker / builders-arm64cross (push) Successful in 15s
docker / deploy-docs (push) Successful in 35s
ci / rust (push) Successful in 7m10s
flatpak / build-publish (push) Successful in 7m23s
The flathub fetch has failed 10/10 retries for months, blamed on fleet load and DNS tuning. It is neither. Measured on home-runner-2, all inside ONE container: getent resolved dl.flathub.org, curl fetched the same URL with HTTP 200 (auto and -4), and flatpak still died '[6] Could not resolve hostname'. Rewriting resolv.conf to a real nameserver didn't help; the default bridge failed too; --network host works every time. So it is ostree's own resolver against Docker's embedded 127.0.0.11, and removing that resolver from the path is the fix. retry.sh stays as the backstop for genuine upstream blips. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
53ff313046 |
fix(packaging/gamescope): the shipped compositor starts on SteamOS — a rolling-distro libstdc++ never followed it there
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 14s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 10s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
ci / web (push) Successful in 52s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 1m6s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 1m8s
ci / docs-site (push) Successful in 2m13s
docker / builders-arm64cross (push) Successful in 10s
docker / deploy-docs (push) Successful in 40s
ci / rust (push) Canceled after 5m49s
ci / rust-arm64 (push) Canceled after 5m47s
arch / build-publish (push) Successful in 15m59s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 16m7s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 15m46s
`punktfunk-gamescope-3.16.25.pfhdr2-1` off the pacman repo cannot start on SteamOS 3.8.16: `/usr/lib/libstdc++.so.6: version 'GLIBCXX_3.4.35' not found`. The Arch container CI builds it in is on gcc 16.1.1; SteamOS ships libstdc++ 3.4.34 and moves when Valve says so. Nothing else about the binary was wrong — every other soname resolved on the box, and glibc was never close (it asks for 2.38 at most against SteamOS's 2.41) — so the one dynamic C++ runtime was the whole reason the gamescope backend's own most important platform got a package that dies at `--version`. The C++ runtime therefore goes static, for the same reason wlroots already does: this binary is built on a rolling distro and has to start on a frozen one. It is safe here because gamescope links no shared C++ library at all — its NEEDED list is all C, and glslang/SPIRV are build-time only — so no C++ ABI crosses a shared boundary. Cost is ~1 MB (5.9 → 7.1). The flags are appended to LDFLAGS rather than passed as `-Dcpp_link_args`, which would replace the value meson derives from the environment and silently drop makepkg's `-z relro`/`-z now`/`--as-needed`. A static runtime is invisible in a passing build and only surfaces as a binary that will not start somewhere else, so the build now asserts it: no `libstdc++` in NEEDED, which needs no version threshold to check and turns the regression back into a build failure. Verified by building in `archlinux:base-devel` — the environment arch.yml uses, gcc 16.1.1 and glibc 2.44, both far newer than the target — and running the result on SteamOS 3.8.16 with nothing supplied: banner `punktfunk-gamescope version 3.16.25-4-g6bbe157+pfhdr2`, no libstdc++ in NEEDED, max GLIBC_2.38, every soname resolving. The host's whole HDR gate chain then answers on SteamOS for the first time (780M / RADV PHOENIX): 10-bit PQ capture offered, cursor painted in-node, native-plane HDR and GameStream HDR capable both true once `PUNKTFUNK_GAMESCOPE_HDR` is on, false with the distro's gamescope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
31db452ca9 |
feat(client/apple): the host tile wears its OS mark where the initial was
apple / swift (push) Successful in 4m32s
ci / web (push) Successful in 1m5s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 7s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
ci / docs-site (push) Successful in 1m18s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 8s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 7s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 18s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 21s
docker / builders-arm64cross (push) Successful in 13s
docker / deploy-docs (push) Successful in 40s
ci / rust (push) Failing after 6m10s
ci / rust-arm64 (push) Successful in 14m47s
release / apple (push) Successful in 25m17s
apple / screenshots (push) Canceled after 13m52s
Apple parity with the Android card (a94b1d3c's sibling): the OS mark moves out of the status row and into the tile, replacing the monogram. The initial says nothing the name beside it doesn't already say — twice over on a row of home-worker-N boxes — while the mark identifies the machine at a glance. Both host surfaces, because on tvOS the console home is the only one there is: the touch cards (saved and discovered) and GamepadHomeView's badge, which needed the chain carried on HomeTile to reach it. Sized to the monogram's own point size, so it lands at ~48% of the tile everywhere, and tinted through the same foregroundStyle the letter used — the assets are template imagesets, so they follow it like an SF Symbol. A host that advertises no OS chain, or one we ship no art for, keeps its letter: `osIconImage` already returns nil for both, so a mixed row still reads as one set. The mark carries the accessibility label now, since the status row it used to ride no longer names the OS. Untouched: the widget draws no monogram, and AboutView's is the app's own logo, not a host's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
af817bc03e |
fix(lock): cursor-probe's pf-frame dep reaches the lockfile
audit / bun-audit (web) (push) Successful in 14s
audit / docs-site-audit (push) Successful in 13s
audit / bun-audit (sdk) (push) Successful in 25s
audit / bun-audit (plugin-kit) (push) Successful in 27s
audit / pnpm-audit (push) Successful in 16s
ci / web (push) Successful in 54s
apple / swift (push) Canceled after 2m17s
apple / screenshots (push) Canceled after 0s
ci / rust (push) Canceled after 1m49s
ci / rust-arm64 (push) Canceled after 1m49s
ci / docs-site (push) Canceled after 47s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Canceled after 0s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 0s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Canceled after 0s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Canceled after 0s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
release / apple (push) Canceled after 0s
audit / cargo-audit (push) Successful in 2m46s
audit / license-gate (push) Successful in 6m35s
deb / build-publish-client-arm64 (push) Successful in 8m10s
flatpak / build-publish (push) Failing after 9m0s
deb / build-publish (push) Successful in 9m47s
android / android (push) Successful in 12m25s
windows-host / package (push) Successful in 16m43s
windows-host / winget-source (push) Skipped
arch / build-publish (push) Canceled after 52s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m44s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m26s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 5m24s
deb / build-publish-host (push) Successful in 23m59s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 21m51s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m22s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 3m50s
|
||
|
|
a94b1d3ccc |
fix(client/android): the stream keeps its aspect instead of stretching to the panel
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 7s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 8s
ci / web (push) Successful in 58s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 49s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 6s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 1m6s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 22s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
ci / docs-site (push) Successful in 1m37s
docker / builders-arm64cross (push) Successful in 14s
docker / deploy-docs (push) Successful in 31s
ci / rust-arm64 (push) Failing after 4m29s
android / android (push) Canceled after 4m35s
ci / rust (push) Canceled after 4m39s
MediaCodec scales whatever it decodes to fill the Surface it renders into, and the Surface filled the screen — so a stream whose resolution didn't match the panel's aspect came out stretched. Nothing downstream of the Surface can correct that; the Surface itself has to carry the aspect. Size the video to the negotiated mode's ratio, centred, with the remainder black. The mode is known from the handshake before the first frame arrives, via a new `nativeVideoSize` (the same `client.mode()` the HUD already reports as `w×h@hz`); an older native lib returning nothing falls back to filling, exactly as before. Input follows the picture. Direct-pointer touch, multi-touch passthrough and the pen lane all map positions against the size of the node they sit on, so the gesture layer moves onto the same rect as the video and all three stay correct by construction instead of each needing an offset threaded through it. The physical-mouse path can't work that way — its events arrive from the activity in WINDOW coordinates — so it now measures against the SurfaceView's rect on screen, subtracting the letterbox origin and clamping into the picture: a pointer out on a bar has no host position of its own, and the edge is the honest answer for it. One deliberate consequence: trackpad swipes that START inside a letterbox bar no longer register. Trackpad input is relative and could have kept the whole panel, but one rule — input lands on the picture — beats a mode- dependent input surface, and the pen lane rides inside trackpad mode too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
1f59498c5c |
fix(host/linux): a no-channel session composites the metadata cursor — Mutter never embeds on a virtual stream
ci / web (push) Successful in 3m26s
ci / docs-site (push) Successful in 3m32s
arch / build-publish (push) Failing after 4m29s
apple / swift (push) Successful in 4m38s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 5s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 5s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 4s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 5s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / rust-arm64 (push) Failing after 4m50s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 12s
deb / build-publish (push) Failing after 5m6s
ci / rust (push) Failing after 5m47s
docker / builders-arm64cross (push) Successful in 6s
docker / deploy-docs (push) Successful in 34s
android / android (push) Canceled after 8m16s
apple / screenshots (push) Canceled after 3m46s
deb / build-publish-host (push) Canceled after 4m15s
deb / build-publish-client-arm64 (push) Canceled after 4m7s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 3m6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 2m58s
windows-host / winget-source (push) Canceled after 0s
windows-host / package (push) Canceled after 8m21s
The capture-latched client (console.rs latched_mouse) never advertises CLIENT_CAP_CURSOR, so its session resolved cursor_blend=false and asked Mutter to EMBED the pointer. On a Mutter virtual stream that is a fiction: since Mutter 48 (7ff5334a, hw-cursor inhibition removed) the software cursor overlay is suppressed stage-globally whenever any physical head realizes a HW cursor — dmabuf-recorded frames blit the view without a pointer, and cursor-only motion schedules no re-record either (mutter#4939). Probed on-glass on Mutter 50.3: embedded + relative motion = frozen frame counter; SPA_META_Cursor positions kept flowing in the same setup. So the no-channel session now takes the path that was verified end to end: cursor-as-metadata + the host composites, permanently — the same arm a channel session lands in after its capture-model flip. Embedded remains only the can't-blend fallback (libav VAAPI/NVENC, software). - session_plan::cursor_blend_for grows the no-channel arm (codec + depth in, the same CUDA-payload prediction handshake makes); gamescope excluded so patch-2+ keeps its native-NV12 zero-copy shape - the encode loop's composite refresh + one-shot breadcrumbs now cover the no-channel session; the park schedule keeps retrying while its composite is starved (relative-only clients cannot park themselves) - the compositor retarget re-applies set_hw_cursor — the rebuilt display used to come up EMBEDDED even for channel sessions - the GameStream virtual source takes the same rule (it never has a channel); its stream_body blend flag mirrors the request - punktfunk-probe grows --cursor-nochannel (the latched-capture client, headless); cursor-probe grows --dump (PPM frames + a content-change counter, the pixel evidence the embedded A/B lacked) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9ed967cbaf |
feat(client/android): the host card wears its OS mark where the initial was
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 13s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 20s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 10s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 1m7s
android / android (push) Canceled after 2m56s
ci / rust (push) Canceled after 2m37s
ci / rust-arm64 (push) Canceled after 2m25s
ci / web (push) Canceled after 2m11s
ci / docs-site (push) Canceled after 2m11s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 18s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 1s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
The OS mark rode along at 12 dp in front of the address, competing with the text it prefixed. The avatar circle above it was showing the host's first letter — which says nothing the name underneath doesn't already say, twice over on a row of home-worker-N boxes. Put the mark in the circle instead, at 24 dp in the avatar's own onPrimaryContainer tint, and drop it from the address line. A host that advertises no OS chain — or one we ship no mark for — keeps the initial, so those cards look exactly as they did and a mixed row still reads as one set. On glass: the two Arch hosts wear the Arch mark; steamdeck and the Windows runner, both predating the `os=` TXT, keep their letters. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
be2fabcfba |
feat(ci/windows-host): the console and the drivers stop rebuilding what nobody changed
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 9s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 12s
android / android (push) Canceled after 1m24s
ci / rust (push) Canceled after 1m25s
ci / rust-arm64 (push) Canceled after 1m19s
ci / web (push) Canceled after 1m19s
ci / docs-site (push) Canceled after 1m18s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 44s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
docker / builders-arm64cross (push) Canceled after 0s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
arch / build-publish (push) Canceled after 4m30s
windows-host / package (push) Canceled after 4m34s
windows-host / winget-source (push) Canceled after 0s
The job's two cache-shaped tails, now actually cached (the runner just got wired to the central cache server — it had none): web/.output restores and skips the ~2.5 min bun build+smoke whenever web/ and sdk/ are untouched, and the UMDF drivers' in-tree target/ (which checkout's clean wiped every run because wdk-build can't relocate it) restores so cargo's fingerprints declare it fresh. Typical run: ~13.6 min -> ~10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
6a6be17ce7 |
fix(client/android): a session that receives no video at all now asks, and says so
The keyframe backstop added for the black LG TV only arms while AUs are actually going into the decoder (`fed > fed_at_output`) — deliberately, so an idle stream never asks for anything. That leaves its mirror image uncovered: a session that receives NOTHING. A decoder cannot be starved of output when it was handed no input, so no signal in either loop fires, and the session sits connected — audio, input and the control plane all alive — behind a black surface. That state is what a user just reported as "the stats are all basically 0": fps and Mb/s are counted at AU receipt (`note_received`), so all-zero stats with a drawn overlay means the decode thread started and received nothing. Same bug as the black screen, seen from the HUD. Both loops now watch for it: nothing received 1.5 s into a session ⇒ request a keyframe and log it, re-asking every 2 s while it lasts. Where it can help it does — the host encoding fine while every picture references an IDR this client never saw is precisely a keyframe request away. Where it can't, the log line is the point: "no video received N ms into the session" separates "the host never sent a picture" from "we received AUs and lost them", which no previous black-screen report could distinguish. Not a root cause. The remaining occurrences are still unattributed — this makes the next report diagnosable and recovers the case that is ours to recover. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
bb7baef20b |
fix(client/android): the menus keep their safe area after a stream
Returning from a stream left every menu laid out against the wrong safe area: content shoved right, the profile row sliding under the status bar, the tab labels crowding the gesture pill. Dumped on the reporter's phone, the window's real insets were bars=[0,162,0,72] cutout=[0,162,0,0] while the layout was using the landscape immersive set — cutout left=162 (Material3 lays out against systemBars.union(displayCutout)), bars all zero. No rotation and no IME animation could shake it loose. Compose attaches its OnApplyWindowInsets and WindowInsetsAnimation callbacks when the first composable reads an inset and removes them when the last reader goes away (WindowInsetsHolder.increment / decrementAccessors). StreamScreen reads no insets at all, so a stream drops that count to zero for its whole duration. Survivable on its own — but a session that ends while the app is BACKGROUNDED is the common case (leaving the app ends the session), and then the entire window restore runs on a stopped activity. The corrected insets arrive while Compose has no listener attached; when the menus recompose, incrementAccessors re-attaches and asks for a fresh pass, but a stopped window produces no dispatch and on resume nothing has changed any more, so none ever comes. Compose keeps serving the landscape, bars-hidden values for the rest of the process. Hold one inset reader at the root for the activity's whole life, so the listeners survive the stream and every dispatch lands. It subscribes to no inset VALUE, only the holder object, so it costs one DisposableEffect and no recomposition. Verified on the reporter's device by replaying the real teardown sequence (forced landscape + immersive, composition swapped to a screen that reads no insets, torn down while stopped) and reading the layout back through uiautomator: 3 of 4 runs wrong without this, 4 of 4 correct with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |