github Nonary/Vibepollo 2.0.2-nightly.d20261031.r.2.399a420e5fe0

pre-release4 hours ago

This is a nightly release of Vibepollo and contains several bug fixes and may contain new features. Check the commit log for more information.

Windows installer · Linux (Arch x86_64)

Nightly Windows installers are unsigned and include self-signed gamepad components. They may cause false-positive antivirus alerts.

Commit log

Source: 399a420e5fe0

Since the preceding successfully published nightly 2.0.2-nightly.d20261031.r.1.b739553a9653: compare exact sources.

c5e4f21632f0

feat(audio): allow sending continuous audio (#4261)

(cherry picked from commit fbcf2116c287bd7fedd1e3ca5833fa0273b6195e)

e7499d55d8a1

fix(audio): Keep continuous loopback audio on one output clock

Use WASAPI packet timestamps and elapsed time to pace silence without
replaying delayed capture packets. Bound buffered time and stall recovery,
correct device-period units, and retain paced silence on uncertain timestamps.
Cover the production buffer and capture adapter in release-mode tests.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit d6690899e896a31e1e3032459767e8f8bbf80f2f)

0ceccb4f3063

fix(launch): Fix several launch failure conditions (exceptions thrown in child.wait, and boost::split_unix) (#4390)

(cherry picked from commit 852dee0a688ccf320c0210ad00507b66cd739a23)

83bf80a4b986

fix(config): create apps.json from default after loading file_apps cfg (#4568)

(cherry picked from commit 8294ab23c1ba266d8f6ecc3a60b5dfbb6abd0482)

44134825fb5e

chore: clean up implicit conversions (#4611)

(cherry picked from commit aea9512682b020108298c7152d035e9570264a5a)

ab664e0b7b41

feat(api/ui): add client enable/disable access control (#4771)

(cherry picked from commit d03334693c5cbdfba51d7835d7b389b28e4c79d4)

ed14ca546fc3

chore: update global workflows (#4990)

(cherry picked from commit a16c070a8feb509a55a434393690cf76447e9423)

61b21ec951bf

fix(installer): require TrueHDR runtime packaging

Vibeshine could ship RTX HDR support without the pinned TrueHDR runtime DLLs, leaving runtime loading to fail after install. Stage the pinned release during CPack, fail packaging when the DLLs are missing or empty, and keep local builds fast when the files are already present.

Add an integration assertion for the packaging contract so future installer changes cannot silently make the runtime optional again.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 5.5 High
(cherry picked from commit 76b16089f61e4034445020ee4d3a4df8ca0f7da9)

25cd711fa844

feat(linux): prepare Vibeshine Arch release channel

Establish Vibeshine as a first-class Linux package identity with its own binary, configuration, services, and desktop metadata. Add validated Arch/CachyOS packaging, DKMS/MOK handling, and Nonary-owned Pages and signed repository publication while keeping candidate builds isolated on vibe-test until promotion.

Generated with [Codex](https://openai.com/codex/)
Model: GPT 5.6-Sol Medium

(cherry picked from commit afd33f284299fbc2f2d053da01c3d7ff5f53e2ed)

f79b33ca3fde

fix(packaging): Stage required inputs for clean component builds

Run TrueHDR staging in the application component so component installs cannot
skip its downloader. Create the Flatpak build directory before copying generated
dependencies, and exercise complete and component installs with failed inputs.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 4994cf9f232ef953b598bd6035cecce62bbe96a3)

1257f3798ce4

fix(appimage): Keep the portable launcher unprivileged

Direct native installation and removal to the system package instead of
installing obsolete user units or granting capabilities to the public binary.
Preserve quoted launch arguments and isolate portable state with XDG_CONFIG_HOME.
Exercise legacy options and portable execution without touching host services.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 322e9c0a52638ca7f6265b98a59a32d77aade486)

b3af94121804

fix(pyrowave): strip shader debug metadata before compacting IDs

(cherry picked from commit d4b2b7d33a55128224acbcd143882c620974fca0)

2308684a8a4c

fix(process): observe paused applications after clients disconnect

Based on the defect report and monitoring approach by malmaud in Nonary/Vibepollo#654. Serialize liveness checks with app replacement and suppress background deferred launches.

(cherry picked from commit 05eb669ce8437fb149f9ddc4814f21a599372018)

84ea45fd9073

docs(security): Clarify reporting and Windows elevation

Distinguish public hardening improvements from vulnerabilities requiring private reports.
Explain Windows user-token elevation so scanner findings establish an actual security boundary bypass.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 12651e4c6b45f7eb8fa40527d12eecf5bbbeaf83)

ede56e8734d8

Steam Controller (2026) support over the VHF virtual gamepad (#629)

* Steam Controller (2026): protocol constants and control packets 0x5504/0x5505

Define the Moonlight extensions a Steam Controller (2026) client uses in one
header, src/steam_controller_protocol.h: the LI_CTYPE_STEAM arrival type, the
LI_CCAP_GRIP_SENSE / STICK_TOUCH / STEAM_HAPTIC / SC26_BUTTONS / STEAM_SETTINGS
capability bits, the grip, stick-touch, pad-click and trigger-click button
flags in the upper half of the button word, and the two control packet types.
Each value is a fallback define with a static_assert, so a moonlight-common-c
bump that carries the real names fails the build instead of masking a drift.

Two new gamepad feedback messages carry what the virtual controller's driver
hands back verbatim: a haptic output report (0x80 rumble, 0x81 pulse, 0x82
command, ...) and a settings write (SET_SETTINGS_VALUES triples or
LOAD_DEFAULT_SETTINGS). The control stream encodes them as packet types 0x5504
and 0x5505 (Vibepollo protocol extension), only ever sent to a client that
advertised the matching capability.

The same header defines the firmware attributes extension: the
LI_CCAP_STEAM_ATTRIBUTES capability bit (0x4000), the LI_SCATTR_* field and
transport bits, LI_STEAM_CONTROLLER_ATTRIBUTES and the
SS_STEAM_CONTROLLER_ATTRIBUTES_PACKET input packet (magic 0x55000008, 84 bytes,
u32 fields LE32) exactly as the client fork's Limelight.h/Input.h define them,
again as guarded fallbacks with static_asserts on every value and on the packed
layout, so a submodule bump that disagrees fails the build instead of masking
the fallback.

Input side: the controller touch event now carries the client's touchpadIndex
(the two Steam pads), controller-touch batching keeps the pads apart,
buttonFlags2 is masked to 16 bits before widening (a flag at bit 15 must not
sign-extend), and controller state batching preserves trigger press/release
and full-pull (0xF0) edges so a tap cannot be coalesced away before the
driver's trigger click sees it.

(cherry picked from commit e170d7fa5b7dda8a8adbb25acc993ecb715ccf16)
(cherry picked from commit 617b9897837829ad04c02c3fe0ae329af3c657be)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y2gdXBFREitNzWvBmTrVr
(cherry picked from commit 6e94d9cea428d1bf4f9a3dacf88b8ecaf7622aa4)
(cherry picked from commit 61f314990d44ddc5611dba4d114e3c651b3ca2cb)

* Gamepad feedback queue: bounded classes, stop-key coalescing, short control wait

Steam's UI drives a Steam Controller's pads at a rate the 32-slot gamepad
feedback mailbox was never meant for: per-side haptic stops arrive 0.7 ms
apart, test-screen clicks every 100 ms, and a 20-triple settings write lands
as three events that must survive whole and in order. Overflowing the old
queue cleared every producer's pending output, so one haptic burst could drop
a rumble stop or half a settings write.

Give the queue three classes behind one entry point, raise_gamepad_feedback():
  * state keys (rumble, trigger rumble, LED, motion requests, adaptive
    triggers, periodic 0x80 rumble and the per-side haptic stops) coalesce in
    place of the pending key and are never evicted;
  * settings writes are a reserved class with its own bound (16) that ordinary
    events cannot evict;
  * everything else (haptic pulses and commands) is bounded at 32 and evicts
    its oldest sibling on overflow.
The mailbox is created with capacity 256 and no clear-on-overflow, so an
ordinary raise() on a full queue drops the newest message instead of flushing
the rest. safe::queue_t gains raise_latest_classed() for this; raise_latest()
is unchanged.

A session with a controller attached keeps the control loop on its 5 ms wait
(input::has_gamepad), so a haptic click or a rumble stop is not held for up to
150 ms behind the idle poll.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QUMtkvaR8iaFLhd98mBEA
(cherry picked from commit 7d3ef1de48ef8a0f123f5fb19864f8ea87d1113a)
(cherry picked from commit 2dfeb85a16b55f67276da4d15948067169c60e84)
(cherry picked from commit c2af27c7cb84e0ee1ab524a86c8afb1d03c46c82)

* VHF gamepad: Steam Controller (2026) profile, pad and motion mapping, haptic and settings forwarding

A client that arrives as LI_CTYPE_STEAM (or the new `vhf_steam` option) now
gets the driver's steam_controller profile when the driver offers it: Steam
sees a real Steam Controller with two trackpads, capacitive grips and stick
touch, motion sensors and a battery, instead of a DualSense approximation.
Profile selection is unchanged for a driver that lacks the profile (plain
`vhf` and `auto` retry with the driver's automatic profile; an explicit
`vhf_*` choice is never substituted), so the option is inert on an older
driver rather than a failure.

Input: the LI_CCAP_GRIP_SENSE, STICK_TOUCH and SC26_BUTTONS flags pass the
supported-button mask to the driver, and a client that advertised authoritative
clicks is marked with the driver's sc26_buttons_explicit metadata bit (derived
from the arrival capability, never from client input). A dual-touchpad client
addresses the pads by touchpadIndex; a single-touchpad client's halves map
onto the two pads (map_steam_touch), each pointer keeping the half it went
down on. Contacts are keyed by (touchpad, pointer) since both pads reuse
pointer id 0. Motion is requested at the IMU's native 250 Hz.

Feedback: the driver forwards Steam's haptic output reports and settings
writes verbatim. A client that advertised LI_CCAP_STEAM_HAPTIC receives every
haptic report (nothing is deduplicated: Steam re-sends clicks to keep a buzz
going); any other client gets rumble synthesized from the report
(synthesize_steam_rumble: 0x80 motor speeds with the real unit's safety
timeout, 0x81 pulse trains as duty cycle for the train's length, 0x82
ticks/clicks as timed rumble from their gain), with the 0x81/0x82 side
conventions measured on the real unit (0x81: side 1 left; 0x82: side 0 left;
side 2 both). Settings writes go only to a LI_CCAP_STEAM_SETTINGS client, as
events that are never coalesced. The poll drains up to four events per 8 ms
pass since Steam's per-side stops arrive 0.7 ms apart. When a slot is torn
down its driver-side feedback-drop counters are logged, and feedback still
queued for its client-relative index is discarded before the index is reused.

Two wake-ups of the feedback thread are now notified under its mutex; the
first controller's alloc could otherwise lose the notify between the
predicate and the untimed wait and leave the thread asleep for the session.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QUMtkvaR8iaFLhd98mBEA
(cherry picked from commit 9dd993015ed6249a98498d2c25053e8ed452a4e4)
(cherry picked from commit ceace5c06cc34f566f5ef4f325bca875d8cf7415)
(cherry picked from commit e4fb7335336c6d3802440a81f75be527cc1d7f92)

* Add the vhf_steam gamepad option to the web UI and the configuration docs

The Steam Controller (2026) profile is selectable as `vhf_steam` next to the
other Vibepollo virtual gamepad profiles in both web UIs (the option list,
the platform filter and the English label). docs/configuration.md documents
the option, what plain `vhf` does for a client that reports a Steam, Switch or
PlayStation controller when the driver offers (or lacks) that profile, the
motion_as_ds4/touchpad_as_ds4 hints that also apply under `vhf`, and that
forward_rumble covers Steam Controller haptics.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QUMtkvaR8iaFLhd98mBEA
(cherry picked from commit 78d2348b9f1709bc6f644f4c8624521a641b3da0)
(cherry picked from commit 2193a783523912294aa4d53e8c8d73583e04807a)
(cherry picked from commit 396400b84c7df3577ffdd39fa7914a0c17ba63d0)

* docs: Steam Controller (2026) over the VHF virtual gamepad

Describe how a Steam Controller client is matched to the driver's profile
under auto, vhf and vhf_steam (and what happens on a driver without the
profile), what the host maps (clicks and capacitive touch, the two trackpads
for dual- and single-touchpad clients, 250 Hz motion, battery), the haptic
and settings feedback paths (verbatim to a client that advertised them as
packets 0x5504/0x5505, rumble synthesis otherwise, the side conventions), the
feedback-drop counters logged at slot teardown, the protocol constants and
their static_asserts, the driver dependency and the tests that cover it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QUMtkvaR8iaFLhd98mBEA
(cherry picked from commit c18dc88cd97473fda3a0a266dfa43b4654d4b27c)
(cherry picked from commit b0d8acbd2998eee1abf3a956ae4cfe36abc52288)
(cherry picked from commit 51110df30b54717f36feb2670fa66ad6b4083684)

* Steam Controller (2026): echo the real controller's firmware attributes and warn against firmware updates over the stream

The virtual controller answers Steam's attribute reads with defaults captured
from one wired unit, so Steam used to offer a "controller firmware update" for
the streamed controller whenever those defaults fell behind the real one. A
client that advertises LI_CCAP_STEAM_ATTRIBUTES reads the real controller's
attributes at link setup and sends them after the arrival event on the same
reliable channel as SS_STEAM_CONTROLLER_ATTRIBUTES_PACKET (0x55000008).

Decode and gate (src/input.cpp): the packet is admitted at its exact size and
needs the controller input permission like the other controller packets. The
little-endian fields are decoded, each string keeps at most 15 printable ASCII
characters (anything else becomes '?', always NUL terminated), and the new
platf::gamepad_attributes() is called only for a controller whose arrival
announced LI_CTYPE_STEAM with LI_CCAP_STEAM_ATTRIBUTES; the slot now remembers
the arrival's type and capabilities for that gate. A packet that arrives before
the slot exists is held and applied once the arrival says what the controller
is. Linux and macOS have no virtual Steam Controller and ignore the call.

Slot lifetime: a failed allocation (no free id, or platf::alloc_gamepad
refusing, on the arrival path and on the legacy state-packet path) marks the
slot alloc_failed and drops any held attributes; a packet that arrives after
a failed allocation is not held, since there is nothing to apply it to. The
legacy path stops retrying the allocation for a slot that already failed (one
warning instead of one per packet), and a slot that is only alloc_failed or
only holding pending attributes is reset like an allocated one when the
client's activeGamepadMask drops it, so neither state survives a removal.
A new arrival clears alloc_failed: it is a new attempt whatever an earlier one
did.

Relay (src/platform/windows): the VHF backend maps the packet to
lvg::client::set_steam_controller_attributes() for a slot running
profile::steam_controller whose client advertised LI_CCAP_STEAM_ATTRIBUTES.
The LI_SCATTR_* bits pass through as the driver's sc_attr_* flags (pinned
equal by static_assert) for the six fields the driver takes, a field whose bit
is clear is zeroed, and the radio/dongle firmware build times are logged only
since the virtual device is a wired unit. An installed driver that predates
the call answers ERROR_REVISION_MISMATCH: one info line

  VHF gamepad N (Steam Controller): the driver predates firmware attributes;
  Steam sees the virtual controller's defaults, not the real controller
  firmware build <UTC> (0x...), ...

and the virtual controller keeps its defaults; any other error is a warning.
On success one info line names what Steam will now see:

  VHF gamepad N (Steam Controller): real controller firmware build <UTC>
  (0x...), bootloader <UTC> (0x...), board rev R, build id ..., serial ...,
  via usb|ble|puck

Warning: every Steam Controller slot creation logs

  Do not start a Steam Controller firmware update from Steam while streaming:
  the update would target this virtual controller, not the real one. Update
  with the controller connected directly to a PC.

The same sentence appears verbatim in the gamepad option help of both web UIs
(vhf_steam), in the vhf_steam row of docs/configuration.md and in
docs/steam_controller.md, which also gains a section on the packet, the driver
call and the old-driver fallback, names the call in the driver dependency and
lists the new policy cases and harness under Tests.

The libvirtualgamepad gitlink is not moved here; the driver release that
carries set_steam_controller_attributes is pinned separately.

(cherry picked from commit 799b6975c38ebce23593237cdde523dcce1d8e1c)
(cherry picked from commit ffbbf0121124c3213f32b0368431eb7c357ad01a)
(cherry picked from commit b44d4d371a35a883c0753b92d564c50bc99cb71a)
(cherry picked from commit 3715bf82083abffe5f291230af247fcb56523590, src/input.cpp)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y2gdXBFREitNzWvBmTrVr
(cherry picked from commit 8fe3a44909bfff71f05c21f73b3ab80e968cbbd0)
(cherry picked from commit 972ac893b06a2c08b2bf0c1d0004107af25a66ec)

* tests: Steam Controller policy cases, host harnesses and a PR validation workflow

test_vhf_gamepad_policy.cpp gains the Steam Controller cases: profile
selection for LI_CTYPE_STEAM and `vhf_steam`, the grip/stick-touch/click bits
through the supported-button mask, the sc26_buttons_explicit metadata bit
gated on capability and profile, split-pad touch ownership (map_steam_touch),
verbatim haptic and settings decoding with malformed shapes refused, rumble
synthesis for 0x80/0x81/0x82 including the measured side conventions, the
touch-event sentinel, and the feedback-drop counters. Seven firmware-attribute
cases follow: the packet keeps the client fork's layout (84/76 bytes, driver
mask 0xCF); attributes are accepted only by a steam_controller slot whose
client advertised LI_CCAP_STEAM_ATTRIBUTES; the driver request carries the
fields and flags through; every field the client did not read is zeroed (a
flagged but empty serial reaches the driver empty); strings keep fifteen
printable ASCII characters; Unix build times format as UTC without a locale;
the log description names what Steam will see for full, partial and empty
masks and for each transport.

tests/input gains six harnesses that compile the production code with fake
driver boundaries under ASan/UBSan (documented in tests/input/README.md):
test_haptic_queue.py (raise_steam_haptic and the mailbox classes),
test_steam_settings_forward.py (raise_steam_settings, chunk ordering, the
reserved class), test_vhf_feedback_retirement.py (vhf_gamepad_t::free
discarding a retired slot's queued output), test_vhf_fallback.py (the Windows
allocation path: Steam clients prefer VHF under auto, client-derived profiles
retry the automatic profile, explicit profiles are never substituted,
controller touch is advertised wherever a touchpad can result),
test_sc26_buttons.py (the host adapter against the driver's real Steam
Controller encoder from the libvirtualgamepad submodule) and
test_steam_attributes_forward.py (the production size table, decode, arrival
gate, pending-packet hold and VHF relay against a fake driver client, slot
table and log: field decode and string sanitising, the six fields and flags
reaching the driver, the success info line, re-application on Steam's
re-polls, ERROR_REVISION_MISMATCH as one info line and any other error as a
warning, packets dropped for non-Steam arrivals and for Steam clients without
the capability, the VHF slot's own gate, a packet before the arrival held and
applied once a Steam arrival allocates the slot or dropped for a non-Steam
one, out-of-range numbers refused, nothing decoded with controller input
disabled, and the firmware-update warning sentence present in the backend,
both UIs and both docs).

The allocation-lifetime cases: test_steam_attributes_forward.py checks that a
failed allocation drops held attributes and that a packet after a failed
allocation is not held; test_disconnect_release.py checks that a slot holding
only pending attributes is retired when another controller's activeGamepadMask
drops it, that exhausted ids on the legacy path mark the slot failed and
retire its attributes until the client removes it, and that a failed legacy
allocation is not retried per packet. The two existing harnesses learn the new
input_t members (allocated_gamepads from the feedback-queue commit, the arrival
type/capabilities, alloc_failed and pending_steam_attributes) and the packet
magic, since they compile the production snippets against their own input_t.

.github/workflows/pr-build.yml runs those harnesses on pull requests and
builds the Windows server with tests (build_only, build_tests) through the
existing ci-windows.yml, so the VHF policy gtest runs on every PR.

(cherry picked from commit b1b05cc95350cbeb494ce71c4067243772ba488c)
(cherry picked from commit fd7248469aa38a4e87ae1dedf5d0c68aa25ca563)
(cherry picked from commit 6b6cd20bae816216f3f27ffc2a6075826ac84117)
(cherry picked from commit 3715bf82083abffe5f291230af247fcb56523590, tests/input)

Upstream's tests/unit/test_stream_disconnect_lifecycle.py splices the control packet type table out of
src/stream.cpp; with the Steam haptic and settings packet types in that table the spliced snippet needs
their defines, so the harness now reads STEAM_HAPTIC_PACKET_TYPE / STEAM_SETTINGS_PACKET_TYPE from
src/steam_controller_protocol.h and prefixes them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y2gdXBFREitNzWvBmTrVr
(cherry picked from commit 12b4d88e8b0af3110692b7e464daed484d12142c)
(cherry picked from commit 3c0adc017d4bd7c10cc95ed4f68867adba2241b6)

* STAGING ONLY: pin the VHF driver to jlobue10/libvirtualgamepad v0.1.0-beta.154

Not for upstream. The host sources in this branch need the Steam Controller protocol additions (the profile, the feedback types and the set_steam_controller_attributes call) that only the fork's driver releases carry until the companion Nonary/libvirtualgamepad PR lands; this commit lets the fork's CI build the branch. Replace it with a pin to the Nonary release that includes the companion PR.

The third-party/libvirtualgamepad gitlink moves from Nonary's cc8ee144d47c2a9944f65017fa4ca0f4d6023942 (v0.1.0-beta.8) to jlobue10/libvirtualgamepad 57de074169e5d65d06775edc6cff7ab4ec9305f1, the feat/steam-controller-profile merge commit that beta.153 was released from; the five pin files are regenerated from the release lock.

source revision 57de074169e5d65d06775edc6cff7ab4ec9305f1
DriverVer 10/16/2026,0.1.0.227 (from the release lock)
archive sha256 c81e857be8921cc0005839b5159141ae603a44234be08890c553f291a6845fb4
protocol version 2 (unchanged)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y2gdXBFREitNzWvBmTrVr
(cherry picked from commit a23e17d6aa88f96461bfce4846a8bc61a5091590)

* vhf: the Steam Controller profile only for a Steam Controller client controller

LI_CTYPE_STEAM alone selected the Steam Controller (2026) profile, and a
configured vhf_steam applied it to every controller a client forwards. Both
make a second Steam Controller out of something that is not one: a keyboard's
joystick interface or another pad next to the real controller (two Steam
Controllers in Steam, haptics and firmware prompts to the wrong one), or a
Steam Deck's built-in controls, which moonlight-qt reports as the Steam type
without any of the Steam capabilities.

is_steam_controller_client() requires the Steam type together with at least
one Steam extension (grip sense, pad haptic relay, explicit pad/trigger
clicks), which only the Steam Controller client drivers report. The automatic
path and the auto-mode VHF preference use it; a configured vhf_steam keeps the
profile for such controllers and lets any other controller fall through to
what its own metadata earns, with an info line saying so.

Tests: gtest policy cases for the gate (each extension bit, the SDL Steam
Deck shape, forced vhf_steam with Xbox/PS/unknown/plain-Steam clients); the
fallback harness compiles the helper and gives its Steam client the
extensions; configuration.md says which controllers the profile applies to.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y2gdXBFREitNzWvBmTrVr

* tests(input): follow upstream's speaker bindings in the disconnect harness

The merge commit's message already describes these: the fake input_t
gains a speaker_bindings stand-in (production passthrough now takes a
speaker owner on arrival), forward_steam_attributes is stubbed against
the fake gamepad_t, and the braced vector initializer inside assert()
is parenthesized so the macro sees one argument. All 40 cases pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0142jvYrnZDdtd5D44FB8Wox

* Pin third-party/libvirtualgamepad back to the released driver build

The Windows validation job fetches the signed VHF driver package for the
commit the submodule pins (VHF_SOURCE_REVISION = 57de074), so the pin has
to name a released build of the fork's feat/steam-controller-profile line,
not the upstream-PR branch. 57de074 carries the Steam Controller profile
on top of upstream main at 7b000a2, the same base master pins today. The
pointer moves to Nonary/libvirtualgamepad main once #6 merges.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0142jvYrnZDdtd5D44FB8Wox

* tests(input): follow upstream's speaker PCM and recovery in the CI harnesses

The master merge changed the code these harnesses extract:

- gamepad_feedback_msg_t now carries a controller_speaker_pcm epoch and a
  speaker block, so the feedback-queue, settings-forward and retirement
  harnesses include controller_speaker_pcm.h ahead of the extracted types.
- vhf_gamepad_t::free() and ::attributes() consult the device-removal
  recovery state and report every driver status through observe_status();
  the fake impl_t in both harnesses gains those members, with recovery
  never pending, and the attributes fake slot keeps steam_attributes.
- The attributes harness's fake input_t gains the speaker_bindings stand-in
  that the arrival passthrough now takes a binding from.

All six scripts wired into the Validate Windows workflow pass:
haptic_queue 5, steam_settings_forward 13, vhf_feedback_retirement 13,
vhf_fallback 26, sc26_buttons 2, steam_attributes_forward 29 checks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0142jvYrnZDdtd5D44FB8Wox

* fix(stream): dequeue gamepad feedback atomically in the control loop

The control thread drained the session feedback mailbox with peek()
followed by a blocking pop(). vhf_gamepad_t::free() retires a
controller's queued output from the input thread with discard_if(),
which erases without waking consumers, so a retirement landing between
the two calls left the control loop waiting forever on an item that was
gone (every session on that server stalled). A queue stop() in the same
window made pop() return an empty optional that the loop dereferenced.

Add safe::queue_t::try_pop(), a locked nonblocking dequeue, and drain
with it: the loop ends when the mailbox is empty or stopped.

Test: tests/input/test_vhf_feedback_drain.py compiles the production
drain, queue and slot retirement with a barrier between the readiness
check and the dequeue; it covers retirement of the only queued
controller and of the last controller in that window, a stop in that
window, and FIFO delivery to the surviving controller. Against HEAD
(--baseline) the retirement cases never return and the stop case aborts.
Wired into the Validate Windows host-regressions job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(vhf): admit polled rumble through the protected feedback policy

dispatch_rumble_poll() submitted the decoded ordinary rumble with the
mailbox's plain raise(), which drops the newest message once the
256-slot stream mailbox is full, and reported success regardless. The
feedback thread then recorded the zero-motor stop as delivered, so a
client whose mailbox was saturated (240 protected state keys plus 16
reserved settings chunks) could be left rumbling with no retry.

Give the dispatcher an admission callable and return its verdict.
Production passes raise_gamepad_feedback(), so the stop competes as a
protected state key, replacing the stale motor state for that
controller instead of being dropped. raise_feedback() now records
last_feedback only when every message of the poll was admitted, so a
rejected message is retried by the next poll instead of being lost.

Tests: tests/input/test_vhf_rumble_admission.py fills the production
mailbox to capacity, shows the plain raise is refused there, and checks
the active-to-zero stop is admitted in place of the stale state (fails
against HEAD with --baseline). The policy gtest gains
RumblePollStopSurvivesAFullFeedbackMailbox and now expects a stopped
queue to report rejection. Wired into the Validate Windows
host-regressions job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(windows): migrate MinGW audio DLL CRT link fix

(cherry picked from commit 187cd896b9c01438d20b758d490b6e37a8c5b573)

* fix(input): route legacy feedback producers through coalesced admission

The ViGEm (input.cpp) and inputtino (inputtino_gamepad.cpp) backends
still handed rumble, LED, trigger-effect and motion-request messages to
the client mailbox with plain raise(), which drops the newest message
when the non-flushing 256-slot mailbox is full, and updated their
duplicate caches unconditionally. A final zero could be rejected yet
cached as delivered, so repeated zeros were suppressed; and the
uncoalesced duplicates could exhaust the protected slots and reject
another controller's synthesized rumble expiry stop.

Add raise_gamepad_feedback_deduped(): the message takes the coalesced
state-key admission and the cache is updated only once the mailbox
accepted it, so a refused message is retried by the next callback.
Every shared state producer now uses it (or raise_gamepad_feedback for
uncached requests). With all producers coalesced each (controller, key)
is pending at most once and 240 keys + 16 reserved chunks fit the
mailbox, so a state message is only refused by a stopped mailbox.

Test: tests/input/test_legacy_feedback_admission.py compiles the
production vigem_t::rumble/set_rgb_led and the inputtino rumble/LED
lambdas against the real mailbox: sixteen churning legacy controllers
coalesce under settings and haptic pressure, a ViGEm and an inputtino
zero stop are admitted at capacity with the cache following acceptance,
a Steam slot's synthesized expiry stop is admitted under the same
pressure, duplicates stay suppressed, and a refused stop leaves the
cache stale for retry. Against HEAD (--baseline) 5 of 8 checks fail.
Wired into the Validate Windows host-regressions job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxkWBMb8aUVkm5BbFm9ubx

* fix(input): coalesce DualSense USB/IP trigger programs in the mailbox

The USB/IP backend appended every changed adaptive-trigger program with
try_raise, so with a stalled consumer hundreds of same-key programs
could occupy the mailbox's protected slots and reject another
controller's synthesized rumble expiry stop (whose start was already
consumed, so there was nothing to coalesce with and nothing to retry).

Route the program through raise_gamepad_feedback(): the state key is the
enable set (left, right, both), so a later right-only program never
replaces an unsent left-only one, a newer program for the same enables
replaces its pending predecessor, and a stalled consumer holds at most
three programs per controller. Programs refused by a stopped mailbox
keep their enables merged in pending_triggers, as before.

Test: tests/input/test_usbip_trigger_admission.py compiles the
production flush_output/publish_latest members against an undrained
mailbox: independent left/right programs both stay queued, same-side
replacement, 300 changed programs coalescing to three, a Steam slot's
consumed-start expiry stop admitted afterwards, rumble latest-wins, and
a refused program keeping its enable pending. Against HEAD (--baseline)
4 of 6 checks fail. Wired into the Validate Windows host-regressions job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxkWBMb8aUVkm5BbFm9ubx

* ci(windows): pin libvirtualgamepad v0.1.0-beta.155 (non-power-managed queue)

The pinned producer release beta.154 (source 57de074) still set the
upper filter's sequential IOCTL queue to PowerManaged = WdfTrue above
VHF, the power-policy owner. The correction (e68c4e7, "keep the
upper-filter queue non-power-managed") landed with the merged
Nonary/libvirtualgamepad#6 but was not in a published package.

v0.1.0-beta.155 is that merged head (09e635cc) published through the
fork's release workflow. Tag, archive SHA-256, DriverVer, source
revision and the third-party/libvirtualgamepad gitlink move together, as
the consumer verifier requires; the protocol version is unchanged (2).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxkWBMb8aUVkm5BbFm9ubx

* ci(windows): move the remaining VHF producer pin carriers to beta.155

240593c2 updated the two download/verify blocks and the gitlink but
left the pin's other carriers at beta.154: the CMake contract cache
(cmake/packaging/windows_virtual_gamepad_contract.cmake), the
-DSUNSHINE_VHF_GAMEPAD_* configure arguments, the packaging refresh and
MSI verification steps in ci-windows.yml, and the installed
install.ps1's expected producer identity. The package refresh therefore
compared the beta.155 manifest against the beta.154 expectation and
failed ("Manifest does not match the pinned producer source, DriverVer,
or protocol").

Every occurrence of the tag, asset name, archive SHA-256, source
revision and DriverVer now reads beta.155 / 09e635cc /
56be2b6c... / 10/24/2026,0.1.0.86. Verified locally: the release
contract (cmake -P) and manifest channel contract tests pass, and the
CI download step plus refresh_driver_package.ps1 succeed against the
published beta.155 archive with these values.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxkWBMb8aUVkm5BbFm9ubx

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Chase Payne <chase_payne@outlook.com>
(cherry picked from commit 18742d0a73c3d030b82fe53e9cedb5f817030c10)

Adapt to Vibeshine: keep its packet-validation module, protocol indexes and
unconditional rumble behavior; retain destination installer paths and names.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit dd91f2abfc0f37c892cc851d19adcafe7a5fd5cb)

1c6b4d422ab1

fix: remove stale remote display layout on unpair

(cherry picked from commit 6a75c5aefc7d711d7262bfe05bdeb2fabad7914f)

2047dc872066

fix: retain primary preference after anchor removal

(cherry picked from commit 9488147764a2e9e9c8fc117755ef80e9de31e716)

6bcee63221a0

fix: retain detached primary for extended streams

(cherry picked from commit a60000fc8da11b51c746f292b515271627df007f)

21080d3a453e

fix(playnite): retire alternate connectors and bound pipe retries

(cherry picked from commit be5d3cb1f2e859f24713dccdff30dde0d01f3e1f)

d0765d8cbbe9

fix(playnite): retain failed connector migration state

(cherry picked from commit 6163ce8e5160369abc3736d1e332de96ea1e9ba0)

bf8c4cc61b19

fix(playnite): preserve safe migration retry decisions

(cherry picked from commit d9f9c964c44a1afaf6706aac062331a2ae3def15)

9b4fa2e8a237

fix(display): honor Remote Monitor HDR requests

(cherry picked from commit 18f68113311cec196195f5f4934184ae6003accf)

a1bdb999000b

fix(display): protect active monitor color state on retries

(cherry picked from commit 833042d22f8270a120474f0fba2ae9e2ad007c99)

528e306a3baf

fix(display): verify color and retire abandoned monitor launches

(cherry picked from commit 2b9a90fb121947d692367090355cff1dfa0a97c6)

2a792fe23f66

fix(rtsp): retry abandoned monitor reconciliation

(cherry picked from commit dc61fc42007f3aa5178dee03f44c3a085f1ffe30)

1b6db42ed278

fix(display): verify effective Remote Monitor state

(cherry picked from commit 0ed50d135dfd077d35169ff1895656e92bcd868d)

1a327244db40

fix(display): compose using observed shared geometry

(cherry picked from commit e9a03de0fd3c9ab5ffa8f1bb3ab27be404184e6a)

33bcbddc7501

fix(display): retry deferred mode until geometry is observed

(cherry picked from commit f4e59c8d0ac035cc985de305d8b22b136eafce1c)

d4f0ad4af96e

fix(display): preserve monitor retries after startup failure

(cherry picked from commit 499cb31a2eceeca1af0beaa7028b0319c07218c0)

a75083f6e438

fix(security): harden privileged Windows boundaries

Enforce Web access policy, bound authentication and request buffering, and redact credential-bearing logs. Authenticate display-helper IPC peers and harden installer, state, service-log, and RTSS paths against user-controlled replacement.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 6f4332adc58c532b2c40f519025ad7cb26cf5d63)

595db6676269

fix(windows): close display-helper squatting paths

Preclaim private IPC endpoints in the privileged host, pass only a restricted inherited handle to the selected helper, and retire stale sessions atomically during endpoint rotation.

Persist SYSTEM display state through a protected registry locator and atomically elected randomized ProgramData directory so hostile legacy paths cannot redirect or block recovery.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit dcda20fb6c830ec0035af125dbf9290afe455341)

152ebc150e83

fix(display): Show legacy display overrides on Linux

Expose mode remapping in the legacy Linux interface so users can configure display overrides, while retaining Windows-only setup controls. Cover editing and removing overrides on both platforms.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 1035e313ff0937070c38e229196cd751b45cee4a)

1a6fda035845

fix(windows): Keep display-helper pipe authority in the host

Windows cannot inherit handles across sessions. Keep the preclaimed pipe server in the host and let the interactive helper connect with data-only access granted to its actual token SID. Authenticate both process identities before protocol traffic, preserve endpoint generations and restore retries, and restrict helper process and thread access independently of inheritance.

Exercise the production accept loop and endpoint parser with wrong peers, cancellation, deadlines, and endpoint rotation. Windows service-session and pipe ACL runtime qualification remain required.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 6ed40ad295d2b4a9741f78bbd7c17636d59c289e)

ba7cb4ffd052

fix(installer): Validate native MSI roots before privileged actions

Direct MSI upgrades must validate existing product roots as well as the
incoming directory before executing installed helpers. Embed a native guard
that rejects writable or redirected trees and resolves legacy roots through
the exact installed product's directory component.

Block early registry-command elevation and reject per-user replacement
registrations before recovery or uninstall dispatch. Preserve validated
machine replacements through the bootstrapper.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit f48fcc56312ec5775b27d5bcf3a44489f3997c52)

9ca2fa3823dc

refactor(dualsense): Remove per-app haptics opt-in

Select composite DualSense audio through the controller profile so applications no longer need a separate haptics setting. Remove the launch readiness wait and ignore older per-app settings.

Co-authored-by: Codex <noreply@openai.com>

Vibepollo adaptation: retain per-app forced haptics, readiness waits, and
composite PCM cleanup. Automatic composite selection is already present.
Port the host-desktop wording correction in both interfaces only.

(cherry picked from commit 3cb6d8979f538eefb858823f17ad306dd4115e85)

a52f60ed1ee0

fix(display): Safely inspect virtual display catalogs

Inspect the bound producer or an unambiguous temporary connection without reconfiguring permanent displays or changing driver readiness. Allow an application virtual display choice to override its own Verify Only setting and explain that behavior in the editor.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 65916a6b67aa6c6f5e7a7f4159d6e41556315413)

e502b77c730a

fix(windows): repair RTSS trust call site types

(cherry picked from commit 943e4aa5362db565d229ff4d79ca9ccba1e664df)

77c13924c3e0

fix(display): Pin the matching Windows driver release

Ship the producer-built v1.6.5 display driver for the exact checked-in libvirtualdisplay revision. Verify the release identity and payload, and reject Windows builds when the package source and submodule diverge.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 8e821e8cdb36da836d345cb1d354c1eb0c0ca017)

f97613f3c71b

test(display): Align release checks with the pinned driver

Update the packaging assertions to match the reviewed v1.6.5 lock so the
release identity checks validate the driver actually used by the build.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 915ad6c9cf06499833551af0d0e152ad46550a79)

f6c6b286301d

feat(apps): Allow system apps to be removed and restored

Make Desktop, Remote Monitor, and Remote Input manageable in both app
interfaces while retaining their settings and artwork for restoration.
Hide removed launch tiles and preserve reconnect access for current owners.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 9cbb78564f1d1f17a53c688b0211200b13919765)

4002973285d7

fix(stream): Hand off Linux launches after app shutdown

Allow a waiting launch or resume to start after cancellation while
removing requests when the client disconnects or the wait expires.
Keep HTTPS responsive by bounding TLS shutdown and framing busy replies.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 3ed14cda3c5a6f622173200287faabe811cfedb1)

9a68acacfe6c

fix(tests): link handoff TLS test to Boost property tree

(cherry picked from commit 4b5d3bc63028d0fa3275fbfc892eaf6434e26973)

2365090aff51

test(tls): Register native clients in the handoff fixture

Use the native paired certificate record required by Vibepollo while exercising the imported TLS handoff scenarios.

Co-authored-by: Codex <noreply@openai.com>

d3abe8b831f8

fix(remote): Keep cached game tiles launchable

A secondary client can retain a prioritized game tile after the app
list returns to normal, leaving its synthetic ID unresolved.

Remember the advertised target per client and route stale tiles through
normal launch checks while rejecting missing or ambiguous identities.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 76ba7d5643963191a5cd9e5da1716eab5c47553a)

e6528b3b225e

fix(web-legacy): preserve Playnite fullscreen metadata on save

Carry the selected app's existing playnite-fullscreen value into the legacy
editor's replacement payload. Keep ordinary and new apps unchanged.
Cover helper preservation and actual modal hydration/save-handler wiring,
including reusing the modal for ordinary and new apps.

Adapted from Jonathan Malmaud's already merged Nonary/Vibepollo PR #690:
https://github.com/Nonary/Vibepollo/pull/690
Original head: b57fd0a1ac225ae982e94d2de03aa9f605573c0e
Original squash: 1f82fe71297c1830e92b36b42b2c3274db851651

Co-authored-by: Jonathan Malmaud <malmaud@gmail.com>
(cherry picked from commit 398a838502e30399a74f805b1efbf3e37e7d54a3)

042548750bed

fix(installer): Validate install folder after elevation

Existing installations can contain protected session history directories, causing the safety scan to fail before UAC. Run the full install folder checks in the elevated installer before making changes.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 6.1-Terra High
(cherry picked from commit 980b706052f34de0c9a25e3d17a0d1a795dbecda)

53e9078557b1

fix(installer): Honor existing gamepad signer trust

Local gamepad packages can use a different signer that is already trusted by Windows. Allow verified packages with existing trust in both machine stores while preventing alternate signers from adding new trust.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 6.1-Terra High
(cherry picked from commit e10658934fa4c360f080c6be74208d57620dbef7)

53946a84c5c9

feat(input): Default to VHF-preferred automatic keyboard and mouse

Prefer a compatible VHF driver for Windows keyboard and mouse input while retaining explicit SendInput and safe fallback when the driver is unavailable. Preserve press/release ownership, native repeat, wheel detents, and absolute drag ordering to avoid stuck or duplicated input.

Keep local driver packaging isolated from pinned release assets and cover routing, recovery, and Windows key mapping with regression checks.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 6.1-Sol X-High
(cherry picked from commit e4b18b396431ae7b1271d693c3fcd8439a57b751)

a214cd1bcaeb

build(driver): Pin the released VHF keyboard and mouse package

Use the verified Nonary beta.10 driver release so production installers include VHF keyboard and mouse support. Align the archive hash, source revision, runtime installer checks, and audited CI identity with driver 0.1.0.92.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 6.1-Sol X-High
(cherry picked from commit f0fd3b50d566f2508b7bc893a967cf4b076a46f0)

071d903a4602

test(display): Automate production recovery wrapper regression

(cherry picked from commit 920f28c27004db86fae89bae9e0b93daa569325a)

2cb5927f8c92

test(input): Keep feedback fixtures compatible with VHF input

Model keyboard and mouse ownership when extracting production controller retirement, and cover keeping its shared handle alive. Make the same queue checks runnable on Windows while retaining Linux sanitizer coverage.

Generated with [Codex](https://openai.com/codex/)

Model: GPT 6.1-Sol X-High
(cherry picked from commit 3da015ac90b8f7f53c0f9d136f7b713e27e8e48e)

2dbc95c1046b

docs(input): Describe Vibepollo backend and pacing behavior

Name the running Vibepollo host in the new keyboard/mouse setting. Clarify that the downstream demand-based policy limits individual send calls while preserving pacing groups and deadlines.

Co-authored-by: Codex <noreply@openai.com>

7f7ba06aec62

chore: fixes for release automation (#5142)

Vibepollo adaptation: restore the missing workflow at the audited source
tip; retain downstream publication policy and explicit source checkout.

Co-authored-by: Codex <noreply@openai.com>

(cherry picked from commit 82a68ebc4dc7a94230243ca32da2be81f425ccee)

10cf293b54d4

chore: update global workflows (#4725)

Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>

Vibepollo adaptation: restore the missing workflow at the audited source
tip; retain downstream publication policy and explicit source checkout.

Co-authored-by: Codex <noreply@openai.com>

(cherry picked from commit a038cc1375cdd5a20509fe12565f1339535d7954)

ef58b197a46a

ci: run common lint only on manual dispatch

Vibepollo adaptation: restore the missing workflow at the audited source
tip; retain downstream publication policy and explicit source checkout.

Co-authored-by: Codex <noreply@openai.com>

(cherry picked from commit 18053bb4593297948a4330b7c3c5da37af6ea1cb)

150496abec20

build(deps): bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 (#4974)

build(deps): bump peter-evans/create-pull-request in /

Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) in `/` from 8.1.0 to 8.1.1.

Updates `peter-evans/create-pull-request` from 8.1.0 to 8.1.1
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/c0f553fe549906ede9cf27b5156039d195d2ece0...5f6978faf089d4d20b00c7766989d076bb2fc7f1)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: 8.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github_actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

Vibepollo adaptation: restore the missing workflow at the audited source
tip; retain downstream publication policy and explicit source checkout.

Co-authored-by: Codex <noreply@openai.com>

(cherry picked from commit b6a3d6aca1c08893b025564c6b01a23e97ebee93)

a6bd624edf1c

test(display): Check the Vibepollo snapshot registry identity

The migrated restore-policy fixture must assert the downstream locator key used by the installed helper. Keep source-compatible state file names and persistence checks.

Co-authored-by: Codex <noreply@openai.com>

d09a1c2999b5

feat(stream): make demand pacing opt-in

Issue #543 does not yet establish whether smaller sender calls change the reported black screen, wire bursts, or host overhead. Keep this demand-based pacing experiment disabled by default to preserve the published ordinary sender path. When enabled, ordinary Vibeshine streams may use a FEC-aware pacing quantum for group pacing and batch sizing; PyroWave keeps its existing policy.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 98873de1637ae647ffd18565930cae3575b119aa)
(cherry picked from commit f0e01be65a41eae43d01b1d1bd632332b7e5dc82)

Vibepollo adaptation: preserve the existing batch-only setting and expose
group pacing separately as pacing_group_demand_limit, default off. Compose
its deadline with the stricter adaptive and operator limits; preserve
accepted-packet debt and PyroWave behavior.

(cherry picked from commit 866a2e6f5b29c04e319353976bce78e6cec107cb)

c0bd572d00db

fix(ui): Keep Linux display overrides visible in V1

Display automation could hide the legacy override editor on Linux, leaving no way to configure resolution substitutions in the guided setup. Keep the editor visible, explain when automation is disabled, and select the rule list that matches the active display policy.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 55d4a6061a2349d2f00f86c2419c9cc53ba38dba)

3058751bd0dc

fix(homebrew): Use the installed product executable on Linux

Linux builds expose the fork product name, while the Homebrew macOS target remains sunshine. Use the platform-specific installed name consistently for formula tests, service launch and signing.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit db670e942f21b576ad0a7d89cc27ed5832121a5b)

d4867454daec

test: Keep input and packaging fixtures current

Exercise the current VHF and pipe access adapters without changing the coordinate and gamepad regressions they protect. Pin the SteamOS fixture version so exported source checks reach the packaging policy rather than failing version discovery.

Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 71b054d03505d02d4c7ec989393a23211611f594)

97fae7eba359

test: Repair downstream configuration fixture boundaries

Extract only the configuration reset entry so the downstream parser layout does not pull unrelated implementation into the timeout and metrics regressions. Add the catalog text for demand-based pacing groups, including its FEC threshold limitation.

Co-authored-by: Codex <noreply@openai.com>

399a420e5fe0

test(ui): Use the downstream application save URL

The mounted fullscreen regression imported the source absolute API URL, so it ignored successful downstream relative requests. Observe the actual Vibepollo endpoint and verify save counts before checking payload preservation.

Co-authored-by: Codex <noreply@openai.com>

Don't miss a new Vibepollo release

NewReleases is sending notifications on new releases.