With the control-v2 input-ack disconnect fixed (#139), the session now survives long enough to hit this: the host detaches the viewer after ~20-25s.
22:23:08 membership changed active_viewers=1 reason="connected"
22:23:11 input v2 client accepted session_id=11 focus_generation=8
22:23:35 membership changed active_viewers=0 reason="adaptive_recovery_detach"
Portal: [client] input stream write failed: I/O error: connection lost; disconnecting
Why this is guaranteed rather than unlucky
The same session logs, at attach:
adaptive bitrate and resolution run in shadow: decisions are computed but never applied
reason="gamescope_pipewire.encoder_backend is not in-process-gstreamer"
mode="aggregate-shadow"
RecoveryMutation::Detach in server/adaptive.rs:852 does contributor.detach.send_replace(true) with no check on whether actuation is available. In shadow mode the controller computes a lower bitrate and never applies it, so a viewer under sustained pressure cannot recover by construction — the only remedy is disabled. The recovery state machine then escalates to detach on schedule.
Shadow mode disables the remedy but keeps the punishment.
This is the documented default
docs/sigil-host-activation.md step 5 writes encoder_backend = "external-gst-launch", which is exactly what selects shadow mode. So a host provisioned by following the activation guide will detach any viewer that experiences sustained pressure. On the reference host that is 2560x1600@60 at 12000 kbps to a Wi-Fi client, which is not an unusual amount of pressure.
Suggested direction
Either gate RecoveryMutation::Detach on actuation being available, or treat shadow mode as "observe only" end to end. Detaching is an action, and shadow mode's contract is that decisions are computed but never applied.
Consequences observed
Audio and input both stop when the detach lands, so "no sound" and "keyboard/left click do nothing" are likely symptoms of this rather than separate faults — though neither has been independently confirmed with the session held open, because it cannot currently stay open long enough.
Environment
Bazzite 43 host installed from the published v0.1.0 via the site's install command, activation guide followed end to end, Portal v0.1.0 macOS arm64 with #139 applied.
With the control-v2 input-ack disconnect fixed (#139), the session now survives long enough to hit this: the host detaches the viewer after ~20-25s.
Portal:
[client] input stream write failed: I/O error: connection lost; disconnectingWhy this is guaranteed rather than unlucky
The same session logs, at attach:
RecoveryMutation::Detachinserver/adaptive.rs:852doescontributor.detach.send_replace(true)with no check on whether actuation is available. In shadow mode the controller computes a lower bitrate and never applies it, so a viewer under sustained pressure cannot recover by construction — the only remedy is disabled. The recovery state machine then escalates to detach on schedule.Shadow mode disables the remedy but keeps the punishment.
This is the documented default
docs/sigil-host-activation.mdstep 5 writesencoder_backend = "external-gst-launch", which is exactly what selects shadow mode. So a host provisioned by following the activation guide will detach any viewer that experiences sustained pressure. On the reference host that is 2560x1600@60 at 12000 kbps to a Wi-Fi client, which is not an unusual amount of pressure.Suggested direction
Either gate
RecoveryMutation::Detachon actuation being available, or treat shadow mode as "observe only" end to end. Detaching is an action, and shadow mode's contract is that decisions are computed but never applied.Consequences observed
Audio and input both stop when the detach lands, so "no sound" and "keyboard/left click do nothing" are likely symptoms of this rather than separate faults — though neither has been independently confirmed with the session held open, because it cannot currently stay open long enough.
Environment
Bazzite 43 host installed from the published v0.1.0 via the site's install command, activation guide followed end to end, Portal v0.1.0 macOS arm64 with #139 applied.