Skip to content

Changelog

Every public Polaris release, newest first, with what changed in each.

Older historical tags remain in the repository for continuity, but the current public product line starts at v1.0.0.

  • A host in Steam Game Mode streams the Game Mode screen. A Steam Deck, or any host running a gamescope Steam session, has one screen and one Steam while Game Mode is up, and both belong to the session, so until now a client could only reach such a host from Desktop Mode. Every stream from a host in Game Mode now shows that screen, whatever stream mode is configured: the configured mode is held while the session lasts and comes back in Desktop Mode. Video comes from the PipeWire node gamescope exports, attached directly with the gamescope ScreenCast portal as the fallback, keyboard and mouse go in through the session’s libei socket, and a controller arrives as a virtual pad that Game Mode’s Steam picks up like one that was plugged in. Proven on a Steam Deck OLED on SteamOS 3.8.16. See Handhelds and Game Mode.
  • A Steam title launched from a client on a Game Mode host opens in Game Mode. The launch is handed to the Steam that is running the session. A host configured for Private Stream no longer tells the client that desktop Steam is active, which made the client offer to close it first, and nothing closes that Steam: not the shutdown a Private Stream asks for, not the steam -shutdown cleanup every Steam title carries when its stream ends, and not a shutdown kept over from Desktop Mode. Ending the session on purpose (End Session on the client, Close App or Disconnect in the console) asks only the title the stream opened to close. A title that was already open on the device is joined without a second launch, which Steam would answer with “Game already running” drawn over the game, and it is left open when the session ends. A client that drops, a paused session that times out, or a Polaris that restarts closes nothing. A Steam title set to launch through Big Picture is launched once, directly, since Game Mode is Big Picture already.
  • A stream that starts on a Game Mode screen that is standing still gets its first frame. gamescope sends a frame only when the window in front draws, and it remembers the last one it sent across viewers, so the client showed black until someone pressed a key. Polaris now asks that window to draw once.
  • A launch that fails after it was admitted in Game Mode closes the title it opened. When capture or the handoff to the client failed, the rollback stopped the session without calling that an end, and ending on purpose is the one thing that closes a title in Game Mode, so the title stayed open with no stream attached.
  • A stream that paused before the host went into Game Mode says why it cannot resume. In Game Mode every launch streams the Game Mode screen, so a paused Private Stream no longer matched and the resume got a bare 409. It is refused with game_mode_started_since_pause and the fix: end the session and start the game again, which streams the Game Mode screen.
  • Touch lands where it is aimed in Game Mode on a Steam Deck. gamescope gives a touchscreen it cannot tie to a screen, which is every virtual one, the orientation of the screen it is showing, and a Deck’s panel is mounted right side up, so each tap from a client was turned 270 degrees and landed somewhere else on the screen. Polaris now works the turn out the way gamescope does, from whether the screen is external, --force-orientation, the panel’s orientation and its shape, and turns each touch back before sending it. Touch is also placed against the Game Mode screen when gamescope fits that screen into a larger frame with a bar down each side.
  • The Desktop tile opens on a Game Mode host right after Polaris restarts. A client’s first look at a host after a restart can be its settings and its game list, and both still named the configured Private Stream, which a Game Mode host cannot run, so Nova planned another mode and refused the Game Mode mirror the host answered with. Those answers name the mirror now, as the profile a launch asks for already did.
  • Nova’s Desktop tile opens Desktop. The library left out the entry named Desktop and showed the Low Res Desktop sample in its place, whose prep command sets an X11 output named HDMI-1 with xrandr and fails on nearly every host, so every desktop stream started with a failed command. The library now lists Desktop, leaves out the sample while it is unchanged and a Desktop entry exists, global prep commands or not, and new installs no longer get it. An apps.json already on a host is not changed, and a Low Res Desktop someone edited stays in the library.
  • The SteamOS install starts Polaris at boot. It runs sudo -H polaris --setup-host --enable-headless-boot, where it used to leave boot start as a second step, so a Steam Deck keeps Polaris running between Desktop Mode and Game Mode from the first install. The Update Center’s SteamOS command keeps boot start as the host has it, so an update never turns it back on after --disable-headless-boot.
  • A host that may not announce itself on the network says so. SteamOS ships avahi with publishing turned off, and Polaris logged avahi::entry_group_new() failed: Not permitted at every start; it now says clients will not find the host on their own and names the addresses to add it by. The SteamOS guide says how.
  • Conditions a host is in on purpose are no longer logged as errors: a Polaris binary set up without KMS capture, a host with no desktop Wayland session, as in Steam Game Mode or at boot, and a GPU without an AV1 encoder, whose refusals FFmpeg reports as errors during the encoder check. A host set to KMS capture whose binary lost the permission to an update still gets the error and the command that fixes it, and a host that never asked for KMS no longer gets a “Silent failure” for it.
  • A VA-API host’s H.264 encoder is read right. The encoder check decomposed every unit of its test frame, and a VA-API encoder at constant bitrate pads frames with filler data FFmpeg cannot decompose, so one unreadable unit failed the whole frame: the SPS went unread, the check reported that the encoder writes no VUI, and each H.264 stream then tried to rewrite an SPS it could not read. Polaris now decomposes only the parameter sets and slice headers it needs, for H.264 and HEVC alike, and a frame with no active SPS returns nothing instead of crashing the reader.
  • sudo -H polaris --setup-host refreshes the Bazzite KMS runtime copy when it has fallen behind the package. The Bazzite guide made /usr/local/bin/polaris-kms during every install until 1.4.5, and no package update touches a file under /usr/local, so those hosts kept running the build they first installed: rpm -q polaris reported the new version while the console reported the old one, and a copy older than 1.4.8 could not say why. Setup now compares the copy with the packaged binary, replaces it and restores its DRM/KMS capability when they differ, and says to restart the service. Only that one path is ever replaced, and only by the packaged binary.
  • The Update Center says when the host process is older than the console it serves. Every build serves the web files the package installed, so after an update the console is new even when the process behind it is not. A host older than 1.4.3 reports no installed package version and one older than 1.4.8 no running binary, so until now such a host only ever read “Update available” for a package that was already installed. It now reads “Console is newer than the host”, with the restart and the --setup-host refresh to try, and it needs no release check to say so.
  • The gaming runtime for NVIDIA graphics borrows this PC’s own driver files instead of carrying a copy of one driver version. A driver update no longer strands a Space, and no longer needs a new runtime image, a new Polaris release and a move of every Space. Polaris checks each file first: owned by root, where the driver package puts it, and built for the architecture it claims, then passes it to the Space read only and never changes it. A Space made on an older runtime keeps working and can move to the borrowing one from its card.
  • Host Setup gains an NVIDIA driver files check while an NVIDIA driver is loaded. It names this distribution’s own 32 bit driver package when that half is missing, which is the case that otherwise shows up as a 32 bit game rendering nothing under Proton.
  • A Space can run Heroic Games Launcher or Lutris, beside Steam. Heroic reads the games installed through its Epic, GOG and Amazon backends, Lutris reads its own database, and both show in the client’s library with the launcher’s own tile first, so a title starts from Nova like a Steam one and runs on Proton or Wine inside the Space. A controller reaches those titles. Heroic’s own menus do not see a controller yet in a Space; use touch or the mouse there.
  • A Space is made by naming its launcher. The Spaces page lists every launcher this PC can make a Space for, says before creating the first Space of a launcher that its runtime will be downloaded, a few gigabytes, and follows the job as it runs. A Space copies the runtime of a live Space of its launcher, so only the first one downloads anything. The page no longer promises a Steam sign-in: a Heroic or Lutris Space keeps a sign-in of its own.
  • Typed text reaches a Space. A Moonlight client sends a key with a high byte set, and the Space input read all sixteen bits and dropped every key it did not know, so only a few bare keys such as Escape ever arrived.
  • A title started from a launcher in a Space shows on the stream. The launcher’s environment named gamescope’s own Wayland socket, a title that finds one takes it, and with no Steam to say which window is the game gamescope ranked it below the launcher, so a Heroic title ran at full speed behind Heroic’s library.
  • A launcher window fills the stream in a Space. Lutris opened at 800x600 in the middle of the stream with black bars at both sides, although the Space starts gamescope with --force-windows-fullscreen: the pinned gamescope sizes a window that names its own size to that size in both places the flag should reach. The runtime carries the upstream fix for both.
  • A Space is offered the newer build of its runtime. A move was offered only when a Space’s image was built for another NVIDIA driver or a runtime that borrows this PC’s driver became available, so a fixed runtime could never reach a Space that already borrowed the driver. /api/multiseat/profiles gains the reason runtime_updated, on any graphics.
  • A Space on an older build of a runtime that borrows this PC’s NVIDIA driver starts. Whether a Space borrows the driver was asked of the catalog alone, so once the catalog named a newer build, a Space still on the older one got no driver files, its worker stopped with libcuda.so.1 did not arrive, and the client heard only that the Space’s runtime did not start.
  • A Space stream no longer sends a keyframe every half second. The Space encoder ran a fixed 60 frame keyframe interval, which at 120 fps is a bitrate spike and a quality pulse twice a second on an 8 Mbps stream. It now sends a keyframe when the client asks for one, as the host encoder does.
  • When the Spaces controller stops admitting launches for a pass, the log says why: the reconcile line carries backend_observation_error with the inventory’s own reason, such as a timed out listing. A worker rejected because its container does not match its launch now names the part that differs.
  • A Heroic Space starts with Heroic’s update check off, so the image’s pinned Heroic no longer opens a dialog over the whole stream telling the player to update through a package manager a Space does not have, and the Heroic and Lutris runtimes carry xz, without which no Windows game could be set up. A GTK launcher draws its icons inside a Space: Lutris aborted before its first window because GTK’s image loader asks for a sandbox a Space refuses.
  • A Space library names a cover only where one can exist, the launcher’s own poster and a title the artwork providers can look up, so a client stops asking for artwork that was never there, and the launcher tile keeps its poster while the library itself cannot be read.
  • Mouse and keyboard reach a game under gamescope_stream. That mode had gamepads only: the one compositor-local input route is for labwc, so mouse and keyboard fell through to host uinput, which a headless Gamescope has no seat to read. Polaris now speaks to Gamescope’s own emulated-input server over libei, the road XWayland’s XTEST support already takes, and Unicode text goes the same way. The route is built when libei-1.0 is present, every official package now carries it, and when the socket cannot be reached input falls back to host uinput exactly as before.
  • Under Gamescope, touch and pen from the client are no longer forwarded to the host desktop.
  • The pointer is visible in a gamescope_stream stream. Gamescope keeps its cursor out of the PipeWire capture unless asked, on the grounds that a consumer would draw its own, and Moonlight and Nova draw none. POLARIS_GAMESCOPE_COMPOSITE_CURSOR=0 turns it off again for a client that does.
  • Polaris on a gamescope_stream host no longer exits when it restarts its own gamescope (#744). Such a host runs Polaris with DISPLAY pointing at the Xwayland of the idle gamescope, which Polaris stops and starts again for an HDR session, for a nested session and to recover the idle compositor. The system tray held an X connection to that server, and when the server went away Xlib ended the process from inside the tray’s event loop, with no log line and no cleanup, which looked from a client like the session dying during launch. The tray now stays off a display Polaris restarts and the log says why; a desktop’s own display keeps its tray.
  • A packaged gamescope session wrapper runs (#745). Polaris ran the polaris-gamescope-session inside its own package before any on PATH, so a packager’s wrapper, the one that exports which gamescope the session should use, never ran: on NixOS the nested session took the distro’s gamescope, without the HDR capture patches, or failed to start at all under the security wrapper PATH offered. POLARIS_GAMESCOPE_SESSION now names the launcher to run and wins when it is an absolute path to an executable file, the Nix module sets it to its own wrapper, and a stale copy on PATH is still named as before. Reported with a full diagnosis by kubicgruenfeld.
  • A host that streams through Gamescope’s portal capture can offer HDR. The encoder check at startup runs against a placeholder image that can only be 8 bit on that path, so its 10 bit attempt failed before the encoder was asked, Polaris advertised SDR only, and clients refused to start an HDR stream. That verdict is now treated as unknown there, only where the 8 bit check passed, and the live stream still fails loudly if the capture cannot carry 10 bits.
  • A client profile’s HDR setting has three states in the console: Auto, On and Off. It was a checkbox, so a profile that followed the client showed as unticked, and saving the form turned Auto into a forced Off that the console could not undo. A client asking for HDR against a profile forced off got SDR where it expected PQ, which looks heavily oversaturated.
  • A device can watch a stream whatever resolution it would ask for. A watcher is handed the owner’s stream as it is and a request for any other mode is refused with 412, but the mode was only said inside that refusal’s sentence. serverinfo now says what there is to watch, the stream’s size, rate, depth and codec and whose it is, and whether a game left open has anybody attached, and the 412 carries the same fields, so a client asks right the first time.
  • A watcher’s request is no longer rewritten by the display mode saved for its device. A saved mode replaced the mode in every request, a watch request included, so a handheld with 1920x1080x120 saved asked to watch a 60 fps stream, asking for exactly the stream’s mode, was rewritten to 120 and refused by the watch check.
  • Device Access on the Spaces page is one table. A row is a device, a column is a place it may play, Desktop and then each Space, and the last column is its Default Space. It replaces a Device Access list on every Space’s card, a Desktop Access list and a Default Space list, which took four sections to say what one device could reach. A device with one place to play is told that place, where it used to get a dropdown with one option, and Save shows only beside a choice that has not been saved. On a narrow window the same rows show as one card per device.
  • The table changes every device at once. An Every device row has All and None for each column, each a single change, where letting thirteen devices into a Space was thirteen saves and every save restarts Spaces. None asks first, because the devices’ Default Space there goes with them. POST /api/multiseat/access/all takes a Space or desktop and allowed, and the host picks the devices, so an out of date page cannot add one that was just unpaired.
  • Give Desktop Access with a Space, a switch above the table. While it is on, a device you let into a Space can open Desktop too. It is off until you turn it on, since Desktop is your whole account, and it leaves devices you have already set up as they are.
  • A Space’s card is shorter. It sums up who can open it, “Retroid Pocket 6, Pixel 10 Pro and 10 more”, where it spelled out every name, and names its launcher.
  • A device that was unpaired leaves the Spaces lists the next time a device’s access is changed on the Spaces page, which is also when a device that was paired again needs its access back. Unpairing never told Spaces, so the id stayed in every Space’s device list, in Desktop Access and as a Default Space for good; one test host still named a Default device that had been unpaired weeks earlier. Nothing is forgotten on a run that could not read its paired devices, where the list is short for another reason.
  • The list a paired device gets of its own Spaces says which launcher each one opens, as an optional launcher word such as steam, so a client can tell Spaces named after people apart. Nova shows it under each name in Change Space.
  • Leaving a Space from the client is no longer logged as Worker media failed: the worker transport ended. Polaris let go of the worker’s connection before it marked the stream as ending, so the same clean exit was written down as an ended stream or as an error depending on timing, and with Steam Big Picture it was usually the error.
  • Quitting a game from inside it, in a Space, ends the stream as an ending. The launcher’s helper returned success, but the worker counted every helper that stopped as a failure, so it reported worker runtime launcher-process-tree exited unexpectedly, left with status 1 and dropped its connection, which Polaris could only log as Worker media failed: the worker transport ended. The worker now reads how the launcher ended, tells Polaris the stream is over with the end_of_stream message the protocol always had, and leaves with status 0. A launcher that fails, and any other helper that stops, is still a failure. What the player sees does not change: the stream ends and Nova returns to the library. This is in the worker image, so it arrives with the next published runtime.
  • A Space’s worker no longer reports runtime session bus exited unexpectedly (exit status 0) and a failed stop after a clean disconnect (#734). The worker stops each helper by signalling its process group, so the helper’s child could exit a moment before the helper heard its own stop. This is in the worker image, so it arrives with the next published runtime.
  • Changing a device’s access to a Space answers “Space access saved”. It answered “Default Space saved”, and when the change failed the Spaces page said the Default Space was not saved.
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

Host Virtual Display on KDE Plasma gets the game, the controller and the touch it was missing, Spaces keep working across an NVIDIA driver update and a reboot, Mirror Desktop streams again when the capture setting does not fit the desktop, and couch co-op gets clearer. Nova 1.4.11 comes out alongside it. Existing configurations and paired devices remain valid.

  • Host Virtual Display on KDE Plasma 6 uses KWin’s own screen by default, even with EVDI loaded. The automatic order tried EVDI first, and an EVDI screen on Plasma is a monitor like any other: it kept whatever layout KWin had stored for it (a 1.35 scale on the test host) and was not primary, so a game opened fullscreen on the primary monitor while the stream showed an empty desktop. The KWin screen is placed at scale 1, ranked after your monitors and gets the game, as tested live with Hades. The automatic order is now the KWin screen on Plasma, then EVDI, then Hyprland, then kscreen-doctor, a Plasma host that gets the KWin screen no longer has the EVDI module loaded for it, and a Backend set to evdi still uses EVDI.
  • Host Virtual Display on KDE Plasma gives the game the focus on the stream screen. KWin moved the window there but kept the focus at the desk, so the game ignored the controller and taps until someone clicked it on the host.
  • Touch and pen from the client land on the KWin stream screen. KWin spread them over every monitor, so a tap landed wherever that point fell on the whole desk. Polaris ties them to the stream screen while it exists and unties them when it goes, undoes a tie to its own screen that a crash left behind, and keeps a tie you made yourself in System Settings.
  • Your monitors stay where they are when Host Virtual Display starts on Plasma. KWin applied a layout it had stored for “these monitors plus a Polaris screen”, which on the test host moved a monitor 1024 pixels to the right for the whole stream. Polaris now puts every monitor back where it was in the same step that places the stream screen.
  • The Doctor names three Host Virtual Display problems on Plasma: another backend used in place of the KWin screen, with the reason; a stream screen at a scale other than 100%; and touch or pen that could not be tied to the stream screen, with KWin’s answer. Troubleshooting lists every host finding now, not just the first, and a finding that needs nothing done reads as a note. The Virtual Display panel says why a KWin screen could not be used.
  • Spaces work with NVIDIA driver 615.71.09. The NVIDIA runtime bakes in the NVIDIA userspace for one driver version, and 1.4.10 shipped only the 610.57.04 image, so a host that updated its driver was told to download a runtime that did not exist for it. A 615.71.09 runtime is now published, signed and admitted next to the 610.57.04 one, and Host Setup picks the one that matches the driver loaded on your PC.
  • A Space made before an NVIDIA driver update can move to the runtime for the new driver and keep its Steam sign-in and installed games. A Space keeps the runtime it was made with, and that runtime carries the NVIDIA userspace for one driver, so after the host updated its driver the Space started with a mismatched userspace and failed without saying why, and the only way back was a new Space with an empty Steam home. Polaris now refuses that launch before anything starts, with space_runtime_driver_mismatch and a fix Nova shows, and the Space’s card on the Spaces page says which driver it was made for and which one the PC runs. Move To The Runtime For Driver downloads the runtime for the loaded driver when it is missing, then points the Space at it and changes nothing else: its home, name, network, devices and Default Space stay, and the home is not prepared again. A move is refused while a Space stream or another change to Spaces is running, and when the new runtime needs a different kind of home, and a move that stops partway leaves the Space as it was. /api/multiseat/profiles gains runtime_driver, host_driver, runtime_mismatch and runtime_move per Space, with runtime_move_available and runtime_move_job; the move is POST /api/multiseat/profiles/runtime.
  • Spaces survive a reboot that renumbers the graphics devices. Guided setup saved the card’s /dev/dri/cardN and renderDN paths, and the kernel does not keep those numbers from one boot to the next: an EVDI display or another GPU that starts first takes them, so after an ordinary reboot Spaces stayed off with a log line about the separate input owner that had nothing to do with it. Polaris now finds the card by the PCI address setup saved with it and uses the card and render nodes that address has on this boot, in memory only, so the saved configuration is left as setup wrote it. Only nodes the kernel lists under that exact device are used, the container still gets real /dev/dri names, and the NVIDIA device nodes are checked as before and never rewritten. When the card is gone, its driver has not loaded yet, or its nodes no longer match setup, Spaces stay off and the log says which, and turning on multiseat_moonlight_input alongside Spaces gets a line of its own.
  • A desktop stream uses the capture backend Polaris found. With Mirror Desktop and capture = wlr on KDE or GNOME, which have no wlroots capture protocols, the capture-source check substituted another backend and Polaris said it was using it, but every stream still asked for wlr by name, found nothing and ended a moment after it started, and Nova showed “Error code: -1”. A stream now asks for what the check can serve: a private labwc session always asks for wlr, a substitution makes it ask for auto so it lands on the substitute, and a session that owns an exact output or runs in Gamescope keeps the configured backend.
  • Changing the host default stream mode from Nova rechecks capture. The change was saved and applied live, but capture stayed checked for the old mode until a restart, so Private Stream asked a Mirror Desktop list for wlr and found nothing. The change is now logged, capture is checked again when no stream is running, and a launch checks again whenever the configuration changed since the last check. The chosen encoder is kept, so the client that made the change is not offered H.264 alone until the next launch.
  • A launch whose capture cannot start is refused with capture_backend_unavailable and a message naming the capture method and the mode, instead of starting and dropping the connection a moment later. kms_capture_needs_capability and no_capture_backend keep precedence where they apply.
  • polaris --help explains --setup-host, each of its options, and points at polaris --setup-host --help.
  • A device that only watches a stream no longer adds a controller to the host. Every session created controller 0 when it started, a watcher’s included, so a couch co-op game counted a second player that nobody held.
  • The Steam Controller (2026) gets an emulated DualSense when the client says that is what it has, as Moonlight’s development builds do. The DualSense carries the controller’s gyro and its touchpads, which an Xbox pad dropped, and the two touchpads land on the left and right halves of the DualSense touchpad so a game sees both. A pad created before the app launched keeps what the client declared, so the split works there too.
  • Troubleshooting’s controller test names every player on the host and the pad each one emulates.
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

Spaces open up, a paired client can put the host to sleep, and Host Virtual Display on KDE Plasma gets a screen of its own from KWin. This is the first release whose compiled runtime catalog admits published Steam runtimes, so a Space can be created on a released build. Completion estimates, Find Cover, ROM folder emulators and support bundles got attention too. Nova 1.4.10 comes out alongside it, and Sleep Host needs both. Existing configurations and paired devices remain valid.

  • A Space can be created on a released Polaris. The runtime catalog compiled into this build admits the two Steam runtimes published to ghcr.io/papi-ux/polaris-worker-steam by digest: one for NVIDIA hosts on driver 610.57.04 and a default one for AMD and Intel. Host Setup downloads the one this host needs without registry credentials, and first Space setup completes. The NVIDIA runtime was exercised end to end on an NVIDIA host, from the same published bytes to a played Steam game and a clean teardown; the default runtime has not run on AMD or Intel hardware yet. The runtime packages move to the 2026-09-18 snapshot, which carries the libinput and PipeWire fixes. A host on 1.4.9 keeps its empty catalog, so creating a Space needs this update.
  • Support bundles, pre-filled GitHub issues, copied support text and the evidence sent to an AI explanation no longer carry network addresses. Credentials were already redacted by name, but an address has no name in front of it, so a line such as a client’s session start went out with its address in full. Each address now becomes a label that keeps what kind it was, such as lan, cgnat (the range Tailscale uses on IPv4), tailscale, link-local or public, and stays the same throughout one export, so a bundle can still show a client moving from the LAN to a tailnet without saying which address it had. Loopback, multicast and example addresses stay readable. The support bundle version is now 5.
  • Host Virtual Display on KDE Plasma 6 gets a screen of its own from KWin instead of borrowing one of your monitors. KWin creates the screen for each stream at the client’s resolution, Polaris places it beside your monitors and asks for the client’s refresh rate with kscreen-doctor (120 and 144 Hz work when KWin accepts the mode), and the screen goes away with the stream, or with Polaris if it stops. The screen is ranked after all of yours and never made primary, so Plasma leaves every desktop, its icons and its panel on the monitor they were on; a small KWin script loaded for the stream moves windows that open during it, the game included, onto the stream screen, and leaves the desktop’s own prompts, such as polkit’s, where you are. No EVDI, dummy plug or VNC server is involved. KWin virtual screens carry no HDR; an HDR request streams SDR and the Doctor says why. The new linux_virtual_display_backend setting (Backend, on the Virtual Display panel) picks EVDI, KWin, Hyprland or kscreen-doctor instead of the automatic order, applies without a restart, and a chosen backend that cannot run refuses the launch with its reason. KWin never offers a screen to a Polaris that holds the capability --enable-kms grants, so with Backend set to KWin and capture left on auto or portal, Polaris drops it at start. /api/vdisplay/status gains backend_preference, and /api/vdisplay/backends lists the KWin backend. (#727)
  • When Polaris drops the capabilities its binary carries, for a portal capture path or a host set to KWin screens, it now does so right after reading its configuration, before it starts any thread, and refuses to make the process dumpable while another thread exists. The drop used to run after logging had started a thread, and capset() changes only the calling thread, so that thread kept cap_sys_admin inside a process other programs of the same user could attach to.
  • A private headless stream no longer rebuilds its whole capture and encode pipeline about once a second while the screen is still, as it did while Steam Big Picture loaded at the start of a session. The stream turns cursor painting on at its first frame, and the ext-image-copy capture reused the session it already had, which cannot change that setting, then waited on it for a frame an idle screen never sends. The session is now created again with the cursor setting the stream asked for, and a new session sends its first frame at once. Every path that used to rebuild without a word now logs why.
  • The Doctor says how the client reached the host and how its display mode was chosen, and keeps both after the stream ends, since a support bundle is usually exported after disconnecting. Session Snapshot gains Network path (lan, cgnat for the range Tailscale uses on IPv4, tailscale, link-local, public or loopback, never the address), which on a tailnet says to run tailscale ping on the client to see whether Tailscale is relaying the stream, and Display mode. When a device’s Display Mode Override replaced the mode the client asked for, which is why such a client cannot choose 1080p, the Doctor checklist shows a Display mode warning that says where to clear it. Both reach the Doctor evidence and the pre-filled GitHub issue. A host that could not raise its capture and encode thread priority reports that as a host configuration warning with the limits that applied, instead of only in one log line at the first stream. /api/stats/stream gains client_network_path and display_mode_decision (requested, applied, pinned_by_host).
  • A paired client can put the host to sleep. Turn on Allow Clients To Sleep This Host in Settings and a paired client that is not watch only can suspend the machine with POST /polaris/v1/host/sleep; Polaris refuses while a stream is still running. GET /polaris/v1/host/power, and the same block on the capabilities response, say whether this host can sleep, whether the setting is on, whether the calling client may ask, and why not when the answer is no, so a client can offer the control only where it will work. A host whose polkit wants interactive authentication for suspend, which is what usually breaks systemctl suspend when Polaris runs it, is named as polkit_denied with the rule to allow instead of failing quietly.
  • Host sleep reports whether the host actually slept. logind can accept a suspend and still fail it, for example when a task blocked in a FUSE mount will not freeze, so Polaris watches for thirty seconds after the request and serves last_sleep_outcome (none, pending, suspended or failed), last_sleep_reason, last_sleep_message and last_sleep_at on the host power block. Nova 1.4.10 uses it to stop saying the host went to sleep when it stayed awake.
  • The configuration docs gain Before you turn it on, four checks for host sleep that were all found on one working desktop: the firmware wake setting and the cold power-down it needs, why Wake-on: g proves nothing, USB devices that wake the host again within seconds, and a task stuck in a network or FUSE mount that aborts the suspend.
  • Settings, General says under Allow Clients To Sleep This Host whether this host can sleep, before any client asks. When it cannot, it says why: polkit wants a password a remote request cannot give, with a link to the rule that allows it, the host reports that it cannot suspend, or logind did not answer. It also says when the last sleep request was accepted and the host never went down. New console route: GET /api/host/power.
  • Find Cover in the app editor works again. It looked covers up from the browser, which the console’s content security policy blocks, so the panel stayed empty. It now runs Nova’s SteamGridDB search on the host: you can change the name it searches for, up to five matching games that have a poster show with their titles and years, read from all ten SteamGridDB returns so “Heroic” finds Heroic Games Launcher, picking a game shows up to five of its posters as Nova’s Artwork Studio does, the previews come from the host, and a missing key, a SteamGridDB failure or a search with no match each say so instead of showing nothing. A missing key links to the field in Settings. The saved cover is the full image, not the preview. The console routes are GET /api/covers/search?name=&uuid=, POST /api/covers/choices with {uuid, provider_game_id, title, steam_appid}, GET /api/covers/preview/<token>?uuid= and POST /api/covers/select with {uuid, token}.
  • A cover saved in the console shows on the Apps and Dashboard pages at once. The cover route told the browser to keep an image for a day under a URL that names the entry rather than the image; it now revalidates each cover against its file.
  • A launcher, an emulator or a desktop entry no longer shows a completion time. The estimate is looked up by title, and a launcher’s title is an ordinary word, so the Heroic entry was given the hours of a game called Heroic Dungeon. Only an entry that names one game is looked up: by Steam app id, by ROM file, or by the id a Heroic or Lutris import carries for its game. A manual entry is taken at its word, and an estimate already saved for a launcher is no longer shown.
  • Completion estimates resolve again. How Long To Beat renamed its search routes in September 2026 and retired the old ones, so every lookup failed without a word and the dataset stopped growing. Polaris uses the new routes, and a lookup outage now logs one warning until the next success instead of nothing. A short title no longer takes a longer one’s estimate: the match allowance scales with the title’s length, so “Eden” no longer matches “BioEden”.
  • The Heroic launcher entry has its own poster, heroic.png, drawn like the Steam and Lutris ones around Heroic’s icon. New imports publish the entry with it, and an existing launcher entry without an image gets it once when Polaris starts.
  • Nova shows a launcher’s bundled poster (lutris.png, heroic.png). The name was read against the working directory, so only the utility entries resolved theirs.
  • Changing an entry’s image reaches Nova. Polaris kept the poster it copied the first time, so a second cover pick or another file left Nova on the old one; a cleared image now also stops showing the copy.
  • A cover picked with Find Cover after artwork was picked for the entry in Nova now shows in Nova. The Nova pick outranked the entry’s image, so the console showed the new cover while Nova kept the old poster. Saving the entry now drops the picked poster and keeps the picked background, logo and icon. Any other image keeps the pick, whether you typed the path yourself or a library rescan refreshed an imported cover.
  • Find Cover asks for a name when the entry has none instead of opening an empty panel, and a failure the host gave no reason for says so in words rather than as an HTTP status code. When the console sign-in has expired, it says to sign in again.
  • An emulator install from Flathub that finishes while you are on another console page is reported when you come back to Apps, and the folder list is scanned again, as it is when you watch the install finish.
  • The right-click menu on an empty Private Stream screen can be read. Its notes were cut off at labwc’s 200 px menu width, so they looked like buttons that did nothing (#715). The notes are shorter, and Polaris writes a themerc-override beside its labwc configuration that gives the menu more room; one of your own is left alone.
  • Session Snapshot’s Network path calls the cgnat range “Tailscale or another VPN” and a link-local address “A direct cable”, and the tailnet note leads with what to do when the stream stutters.
  • The app editor’s Needs command badge and Command: Missing summary count a detached command, so launcher entries such as Heroic and Lutris no longer look broken.
  • A game imported from a ROM folder launches the emulator this host has now. An entry saved while its emulator was missing kept the bare binary name, so installing the Flatpak afterwards still started an empty session with a black screen; launch now resolves the folder’s emulator file, PATH and the Flatpak each time, and a launch whose emulator is still missing is refused with emulator_not_installed, naming the emulator, the game and the fix. A command you edited after import runs as you wrote it.
  • A missing preset emulator can be installed from the ROM folders panel with Install From Flathub. The host runs Flatpak for its own account without a shell, adds the Flathub remote for that account only when it is missing, shows the install on the folder card while it runs, and points that emulator’s imported games at the Flatpak when it finishes. A failure shows Flatpak’s own reason (DuckStation is no longer on Flathub). New route: POST /api/library/emulators/install; GET /api/library/sources gains installable and install_job on presets and folders.
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A setup update shaped by a fresh install: quick setup covers the encoder, the launch mode and a trusted network as well as artwork and AI explanations, saved settings apply without a restart, restart from the console and the tray works again, Nova’s artwork alternatives work, a Space can be removed for good and its host setup fixed from the Spaces page, and host setup, the KMS guidance, the Spaces helper and the Spaces page say what they found. Nova 1.4.9 comes out alongside it, and Nova 1.4.8 keeps working with this host. Existing configurations and paired devices remain valid.

  • A saved SteamGridDB key or AI provider setting takes effect while Polaris runs: the cover search, Nova’s artwork search and AI explanations use the new value at once. The save response carries restart_required, and the settings page and the first-run wizard ask for a restart only when a saved change still needs one.
  • Host setup removes an /etc copy of the udev rules or modules-load configuration that an older Polaris installed, recognising every version Polaris shipped, and its closing summary names a copy it keeps because that copy may hold a local edit.
  • Every Polaris install or update replaces the binary without the KMS capture capability. The startup log, the Doctor, a refused launch and the package notes now say to run sudo -H polaris --setup-host --enable-kms again after each one.
  • KWin screencast permission entries are one per binary: an update no longer adds another dev.polaris-stream.app.Polaris.kwin.*.desktop file, and the entries Polaris wrote for binaries that no longer exist are removed.
  • Virtual display cards such as evdi no longer log a missing render node or the NVENC different GPU warning; real GPUs still do.
  • The Linux desktop entry and its Run in Terminal action carry the Polaris icon (every package except openSUSE shipped Icon= empty), and the tray’s playing, pausing and locked icons each carry their own badge.
  • polaris-spaces-setup names what it refuses: SELinux modules it does not manage with their priorities and the semodule command that removes them, the Polaris processes still running, and an input rule that differs from the packaged one. An input rule identical to the packaged one is adopted instead of refused.
  • On a build without a published gaming runtime, the Spaces page reads as ready and waiting: the Gaming runtime check becomes a neutral waiting row left out of the count, standing in for the Spaces configuration check, Host Setup says Host ready, and nothing says host preparation comes first.
  • Restart from the console and the tray works again and cooperates with systemd. The request no longer depends on a SIGINT that any shell command running at that moment could swallow, which is how a saved SteamGridDB key never reached the running host. Under polaris.service Polaris now exits with status 75 and the unit starts the installed binary, so a restart after an update runs the new version; other launch paths re-execute in place as before, and systemctl stop or restart always gets a real exit instead of a process that outlives the stop timeout.
  • AI explanations in Codex subscription mode follow the Codex CLI. The model list comes from the catalog the CLI caches for the signed-in account, the CLI’s configured model is the default and replaces the hosted-API pre-fill in the settings tab, and a request Codex refuses shows Codex’s own sentence (for example that a model is not supported with a ChatGPT account) in the test result and the log instead of a bare exit code. The Claude hints move to Sonnet 5 and Opus 5.
  • The first-run wizard gains two optional steps. Artwork checks a SteamGridDB key against SteamGridDB before saving it (a new POST /api/covers/key/check, which never stores the key), and AI Explanations offers the provider choice, sign-in, model list, test and enable from the AI tab in a compact form. Both steps can be skipped, both say that the host reads the new settings after a restart, and the last step offers that restart. The SteamGridDB field in Settings says the same.
  • Host Virtual Display says what it will do on a KDE host without EVDI. There the kscreen-doctor fallback cannot add a display; it borrows a connector and resizes it, and the mode card now says so instead of promising an added display. The kscreen-doctor setup panel stays on the settings page after a connector is saved, lists the connectors the host found, says when a new choice still needs a restart, and warns when the connector is the primary output, is lighting the desktop, or has nothing plugged in. The settings page also re-reads the host’s display capabilities when you come back to the tab, so a restart from the tray or systemd no longer leaves the mode card and the panel showing the answer from before the restart (#633)
  • Host Virtual Display can be chosen again on a KDE host that relies on the kscreen-doctor fallback while it runs another mode, such as Private Stream. Loading the configuration retired linux_streaming_output for modes that own no connector, and the default headless_swap_mode made that happen on every start, so the mode read as unconfigured and its card stayed greyed out asking for a connector the file already had. A mode switch from a client also erased the connector from polaris.conf. The connector in the file now keeps Host Virtual Display available and is what the fallback borrows, while modes that own no connector still retire it for capture, and the dashboard preview no longer crops a private session to it. The same holds for a connector left from Headless Dongle: on a host without EVDI, Host Virtual Display is now offered with that dummy plug, and an app that asks for a virtual display on a host that is not streaming privately borrows it (#633)
  • The app editor shows Mirror the host desktop on Linux. It was already why the bundled Desktop entry streams the real desktop on a Private Stream host, but it could only be changed by editing apps.json, and the launch modes and troubleshooting guides still said Desktop opens an empty private session. New entries now save the setting explicitly, and both guides and the app editor reference describe what Desktop actually does and how to get an empty private session instead (#715)
  • Docs: the README catches up with 1.4.8 (the Spaces preview and its limits, the ROM folder library, 240 FPS on created displays, refusals that say why, the capture forecast), and a Spaces or regular streaming page puts the two side by side in one table, linked from the Spaces guide.
  • Docs: an uninstall page in the order that works: the Spaces policies first while the helper still exists, then the package, then what the package leaves behind (rule copies under /etc, a /usr/share/polaris that other files kept alive, the Spaces security record, your own additions) and ~/.config/polaris with a keep-or-wipe table. Every distribution page links it.
  • Docs: the Spaces guide explains the security helper’s three refusals (a policy at another priority, a Polaris process still running, an input rule it did not install) and the fix for each.
  • New installs start in Private Stream: the first start writes linux_stream_mode = headless_stream when labwc and wlr-randr are on the PATH, and a host without them, such as SteamOS, keeps Mirror Desktop. Existing configurations keep their mode, and the bundled Low Res Desktop entry mirrors the desktop like Desktop does.
  • On a build without a published gaming runtime, the Spaces page says plainly that a Space cannot be created yet, points at regular streaming meanwhile, and leaves out the setup steps that cannot run.
  • Removing a Space can now delete it for good. Remove Space offers two choices: archive, still the one selected, which keeps the Space’s games and saves for Restore, or remove for good, which deletes its installed games, saves and Steam sign-in once you type the Space’s name. An archived Space offers Remove for good beside Restore. The host checks the typed name itself, refuses while any Space stream runs, keeps the last Space because new Spaces are made from an existing one, and deletes through Docker only the volume and network it created for that Space, proven by their label, driver, options and mountpoint. If Docker stops partway the Space stays archived and removing it again finishes; the response names a volume or network left behind (kept_volume, kept_network), and /api/multiseat/profiles announces the ability as removal_available.
  • Two Spaces host checks can be fixed from the Spaces page. Polaris access to Docker offers Give Polaris access to Docker, which starts Docker, sets it to start with the PC, and adds the account Polaris runs as to the docker group, and Spaces security support offers Install security support. Polaris runs the packaged polaris-spaces-setup through pkexec with one fixed operation (POST /api/spaces/setup/host-action), and polkit opens the password prompt on the host’s desktop, so someone signed in at the host approves every change and a browser elsewhere can only start the request. The packages ship dev.polaris-stream.app.Polaris.policy with one action per operation, each asking for an administrator every time. Polaris refuses in words on an image based host, without the helper, pkexec or that exact policy, without an active local desktop session, or while a Space, a stream or the first Space setup is active, and Space launches and Spaces changes, Remove for good included, wait while a change runs. The helper leaves only the Polaris that asked out of its busy check, counts a running Space by its SELinux domain, and gains a docker-access operation; the Docker access check says when the account already joined the group and only a restart of the PC is missing. The terminal steps stay beside each button.
  • Nova’s artwork alternatives work. POST /polaris/v1/games/<id>/artwork/choices/<kind> lists up to five SteamGridDB images of one kind for a chosen match, each as an expiring selection token whose preview the candidate route serves, and the match route applies picked tokens given as selections. A pick replaces only the kinds it names, keeps the other custom images, and commits every pick or none. An expired or foreign token gets a 409 with artwork_choice_expired or artwork_choice_mismatch, and capabilities announce artwork_choices_v1 when a SteamGridDB key is set. Earlier hosts had no such route, so Nova said the alternatives could not be loaded.
  • Quick setup has eight steps: Credentials, GPU and Encoder, Launch Mode on Linux, Network, Artwork, AI Explanations, Pair Client, and First App last because it leaves the wizard. GPU and Encoder reads the new GET /api/setup/hardware, which lists each GPU with its driver and the codecs VA-API can encode, the encoder Polaris picks and why, and advice such as the Mesa driver swap an AMD card needs on Fedora for H.264 and HEVC. Launch Mode saves the same settings the Settings page writes for a mode. Network lists the private networks on this PC’s real interfaces from GET /api/setup/networks, so the home network can be trusted with one click, and a saved trusted network now applies to pairing at once, without a restart.
  • Host Setup on the Spaces page has a Gaming runtime check. It names the runtime this PC needs, the NVIDIA build for the loaded driver or the default one, says when the build includes none or the driver does not match, and offers Download, which fetches and verifies the runtime without preparing a Space. When the runtime is already on the PC, first Space setup prepares without a download and its button says Prepare.
  • Spaces turned on from the Spaces page can start and change. First Space setup wrote the marker that ties the Spaces IPC directory to its controller inside that directory, where the Space workers’ startup check refused it, so no Space could start and every Spaces change failed with Space settings could not be restored until a restart. The marker now sits beside the directory, and a host set up by an earlier build repairs itself at its next start. The Spaces controller also logs why it cannot close or rebuild, where it used to fail without a word.
  • Developers: a lab build can compile another Spaces runtime catalog and pull runtimes from another registry with the CMake cache options POLARIS_SPACES_RUNTIME_CATALOG_FILE and POLARIS_SPACES_RUNTIME_REPOSITORY, to test Spaces end to end without publishing a runtime. Release workflows never set them, and a unit test fails if one does. containers/multiseat/RUNTIME-DISTRIBUTION.md has the steps.
  • The game library marks Steam Big Picture on the desktop with steam_big_picture, by the rule Polaris already uses for its Big Picture launch and cleanup handling: the bundled name, or a command that opens Big Picture on an entry that is not a Steam game. Nova’s Play Setup can then pair it with a Space’s Big Picture in either direction, where it used to grey out the other side because Big Picture has no Steam app id to match. A client that does not read the key sees no change.
  • Automatic artwork only takes a match that is the entry. A Steam title finds its SteamGridDB game by app id, and any other entry takes a SteamGridDB search result only when its title is the entry’s name, ignoring case, punctuation and trademark signs, instead of the first result, which gave Low Res Desktop the artwork of Low Magic Age. Entries that stream the desktop never look artwork up, and artwork an earlier build downloaded for them is removed and never offered again. The app editor gains Remove artwork, which deletes every picture downloaded or picked in Nova for an entry and stops automatic lookup for it (POST /api/apps/artwork/remove, a marker beside the entry’s cached artwork that GET /api/apps lists as artwork_lookup_off), and Find artwork again (POST /api/apps/artwork/find), which turns the lookup back on.
  • Default Space only sets where a device opens first. Saving Desktop as a device’s Default Space used to remove the device from every Space; now its Spaces stay under Device Access, so a device can open Desktop first and still change to its Space in Nova. Default Space offers Desktop once the device has Desktop Access and a Space only once the device may open it, and the host refuses anything else with a sentence that says what to tick (desktop_access_required, space_access_required). Unticking a Space under Device Access is how a device leaves it, its Default Space included, and a device that can no longer launch games gets Remove from Spaces. The Space catalog records a Desktop default as desktop_default_clients in schema 5, written only when a device has one, and Nova reads it as default_space_id desktop.
  • When two paired devices share a name, for example Nova and Nova Debug on one handheld, the Devices page and every device list on the Spaces page add when each one paired, or a number when even that repeats.
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A Spaces preview matched with Nova v1.4.8, with a library that fills from a folder of emulator games, higher frame rates on the displays Polaris creates, and launch refusals that say why. Spaces is for configured hosts only and has no public runtime download yet. Existing configurations and paired devices remain valid.

  • A refused Space launch now says why, the way a refused host launch does: Nova shows the host’s sentence and the one change that fixes it (the Space is being played on another device, this device already has a Space running, every Space slot or the encoder is taken, no Space is assigned or selected, the assignment changed) instead of “Space Could Not Start”. Host messages about Spaces use the words the console and Nova use: Space, never profile or seat, and one sentence for “stop the Space streams first”.
  • The Spaces list a device reads now says why, not just whether: unavailable_reason when the host cannot offer Spaces to it (the controller is missing, stopping or reconfiguring, or no Space is assigned to the device), switch_blocked_reason when a stream must end first, default_space_id, the host’s Space budget as capacity (concurrent_limit, concurrent_active, also on the console’s /api/multiseat/profiles), and per Space can_open with a blocked_reason (in use, starting, stopping, at capacity), so a second player sees “one Space at a time” before pressing Open instead of after. The capabilities route announces spaces_v1 on any host with Spaces, whichever Space or Desktop the device has picked, and the Space session status says starting during the start window. All of it is optional keys on the existing schema.
  • First Space setup says what blocks it. The setup snapshot carries unavailable_reason (already_configured, runtime_not_published, journal_fault, journal_locked, closing), the job carries blocked_by (journal_fault, runtime_withdrawn, no_eligible_gpu, closing) and, when its journal could not be secured, a recovery record naming the retained image and reference, and every host check carries a doc_anchor into the Spaces guide, so the console can link the fix instead of showing a dead button. The one thing the job cannot report is download progress, and the docs stop claiming it.
  • The Spaces console speaks the console’s grammar. Every string is translatable (a spaces locale namespace instead of English literals in eight components), Space status and host checks render as the same status badges Doctor uses, Remove, Restore and the setup restart go through the confirmation dialog with Escape, a focus trap and the change’s impact spelled out, the restart reconnects on its own through the shared host-restart helper instead of asking you to, and the buttons, inputs, checkboxes and disclosures are the shared ones. Polling pauses while the tab is hidden and backs off while the host does not answer, and a background refresh no longer disables every control for a moment every ten seconds. A running Space stream now disables the controls it blocks and says which device to stop, instead of sending the request to a refusal; a Desktop Access grant reports its real result (it always read “not confirmed” before); the page no longer shows “Create your first Space” before the first snapshot has loaded or when the load failed; a host’s refusal reason reaches the message on 400-class errors; archived Spaces are no longer offered as the base for a new one; a card’s device list and its Device Access list apply the same permission filter. Host Setup leads the page until the host can offer Spaces, checks sit two per row and link the guide section that fixes them (the host’s own doc_anchor when it sends one), the Docker and security steps for your distribution are on the failing check with a Copy button (package installs are withheld on immutable hosts), the first-setup card says why the download is unavailable, what blocks the job and what was kept for recovery, and the sidebar marks Spaces as a preview and lists it on Linux hosts only.
  • Docs: the Spaces guide is rewritten in the order a player meets it (what a Space is and whether you need one, Docker, the host checks with one section per check, the first Space, recovering an interrupted setup, more Spaces, device access, playing, renaming and removing, sound, what to do when it fails), with the preview status, capability tables, audio protocol and catalog notes moved to research/container-multiseat-preview-status.md behind one “Preview limits” link. Nova’s Spaces payloads (spaces_snapshot, space, spaces_capacity, space_library, space_library_game, space_ref, space_launch_mode, space_legacy_game) are declared in docs/nova-contract.json, built by one function each so the contract audit reads their shape from the source.
  • Spaces preview: an optional Spaces tab manages separate Steam sign-ins, games, and saves. Assign paired devices, allow access to additional Spaces, rename player environments, or remove and restore them while retaining their data. Ordinary streaming keeps its existing setup.
  • Spaces guides Docker and security setup on the host, with persistent preparation progress and retry controls. First runtime download remains unavailable until an approved image is published; initial setup permits one active Space. See the setup guide and current acceptance results for supported paths and remaining audio limits.
  • Import games can bring emulator games in from a ROM folder. Add the folder and the emulator in the import console (Eden, Dolphin, Cemu, DuckStation, PCSX2, PPSSPP, mGBA, or your own command with {rom} in it); every file the emulator can load becomes a candidate named from its filename with the region and version tags removed, update and DLC dumps are skipped, the entry launches the emulator straight into the game with the pad the platform expects, and the emulator itself is published once next to its games. The folder is remembered, so a rescan finds games added later, and covers come from SteamGridDB when a key is set. (#699)
  • Docs: an emulators guide covers the whole path for emulator games, from what each emulator needs before a game boots (keys, BIOS, a Flatpak allowed to read the folder, the pad to map once) through import and covers to saves on End Session and the Nova face-button choice.
  • Quitting a private-compositor session now gives the app its own Exit Timeout to leave after SIGTERM (at least two seconds, at most thirty) before SIGKILL; it was a fixed two seconds regardless of the setting, which cut an emulator’s save write short. Entries imported from a ROM folder get ten. An app that ignores SIGTERM now holds End Session for its timeout instead of two seconds.
  • A ROM folder card names what its emulator still lacks before a game boots, with the fix: Eden’s prod.keys, Cemu’s keys.txt, a BIOS image for DuckStation or PCSX2, or a Flatpak that cannot read the folder (checked against its metadata and overrides, with the flatpak override command spelled out). The add-folder form shows the same for the chosen emulator, and Library health counts the folders that are ready.
  • A ROM folder import picks up a cover that already exists: next to the game (<name>.png, or a covers, boxart or media folder beside it), in ES-DE’s downloaded media for that system, or among RetroArch’s boxarts for it, native or Flatpak. The image is copied into Polaris’s covers directory and set as the entry’s artwork, so console and Nova show it without a SteamGridDB key.
  • The library list tells Nova what a ROM folder entry is: emulator entries carry the console as platform (switch, psx, gba and so on) and the emulator as runtime, with platform_label and runtime_label naming them, and the host announces library_emulators_v1. A client that reads the labels shows “Nintendo Switch · Eden” on the tile; the JSON library route’s source filter also accepts any source name as apps.json spells it.
  • A launch command that single-quotes an argument, such as a path with a space or an AppImage under a folder with a space, is now split the way a shell would before it runs. The command runner kept the quotes and split the path in two, so such an entry never launched; commands without single quotes or backslashes run exactly as before.
  • The support bundle keeps two previous runs instead of one, so a freeze, a reboot and an export no longer lose the run that had been streaming, and it carries the kernel’s GPU-related lines for this boot and the previous one (NVIDIA Xid, i915 hangs, hung tasks, other stacks’ virtual display modules) when the journal is readable, saying so when it is not. A Polaris that cannot bind its RTSP port now names the process holding it, since every Sunshine-family host uses the same port, and keeps that reason in the crash record instead of “unspecified”.
  • The Doctor now pairs the encoder node Polaris actually uses against the GPU the compositor renders on, whether adapter_name was set or Polaris chose the node itself, and knows the compositor’s GPU before any stream has started. On a hybrid laptop that names the split (iGPU desktop, NVIDIA encoder) with both ways out: keep everything on the iGPU, or keep NVENC and turn off NVIDIA runtime power management. Virtual display drivers (evdi, vkms, hermes-kms, vibeshine_drm, udl) are no longer counted as GPUs when Polaris picks an encoder node. Docs: a hybrid laptop section and the order to bisect a whole-machine freeze in.
  • The console’s system-stats poll no longer re-enumerates the host’s Wayland outputs every three seconds. Each enumeration was a fresh client connection to the compositor with a DMA-BUF feedback round trip and nine log lines, and on a laptop that hard-froze during a Mirror Desktop stream the freeze landed on one of those polls while KWin was reading the screen back for the stream. The display list is now cached: refreshed at most every 30 seconds while idle, once when a private-compositor stream starts or ends, never during a stream of the desktop itself, and the enumeration logs at debug so a support bundle keeps its evidence instead of two thousand copies of the monitor list.
  • A refused launch now says why. Every place the host refuses a launch records a reason, and the launch and resume responses carry it as the message the client shows, with the one change that fixes it, plus stable error_code and error_action attributes for Nova. A failed encoder probe names the capture cause when there is one (no capture backend, KMS without the capability) and the NVENC driver detail when that is the reason; a private compositor that did not start, a declined screen sharing prompt, a missing labwc, a virtual display that could not be created, and the previous session still tearing down each get their own code. Moonlight shows the message; before this, all of them were “error 503”.
  • Says which binary is really running. --setup-host reports a user service pointed at a copy of the binary that no longer exists, with the two ways out, and warns when the service runs a copy outside the package that updates will not touch; the Update Center names that copy instead of asking for a restart that would change nothing; the Doctor and the support bundle carry a running_binary row. The Bazzite DRM/KMS recipe creates exactly this copy.
  • The Doctor now says, before any stream, when capture on this host will copy frames through system memory for the configured mode, and why: a package built without CUDA on NVIDIA, an X11 session, a hidden headless compositor that could not hand over DMA-BUF at its last attempt, or the VA-API copy path that AMD and Intel take by design. Each cause names its one fix, and the GPU-native advice no longer fires on a build where it cannot work. The support bundle carries the forecast with build_has_cuda.
  • The Ubuntu 24.04 package is built with CUDA from this release, like the Fedora and Arch packages, so NVIDIA hosts on Ubuntu get the GPU-native capture path instead of a copy through system memory. The Arch package now points at nvidia-utils as the NVIDIA runtime dependency instead of the CUDA toolkit, which is only needed to build.
  • The Doctor now says when KMS capture was refused because the binary lacks CAP_SYS_ADMIN, and names the one command that grants it, instead of blaming compositor protocols and steering you off the only capture path that carries HDR. The HDR finding names the working recipe: capture = kms with a stream mode that shows the real HDR output.
  • Docs: the configuration that carries true HDR on Linux today, all five gates with the journal line that names each one, in runtime.md, configuration.md and troubleshooting.md; and how to point MoonDeck Buddy at Polaris’ apps.json in moonlight.md.
  • Launches where Polaris creates the display itself (Private Stream, Host Virtual Display, Desktop Takeover, Gamescope) were capped at 120 FPS by three separate literals, and /serverinfo advertised a different number again, so a 144 or 165 Hz client was either refused before connecting or quietly served 120. One ceiling now, 240 by default and settable with headless_max_refresh_rate, advertised and enforced from the same value (#686)
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A controller and configuration update matched with Nova v1.4.7. The virtual DualSense maps the way a real one does, and the per-user configuration directory stops being created in a state Polaris then refuses to use. Existing configurations and paired devices remain valid.

  • Corrects the virtual DualSense’s button and stick mapping. Polaris advertised the HID version a USB DualSense reports while creating the pad on the Bluetooth bus, and that combination matches no entry in the controller database clients read, so they fell back to a layout from before the kernel’s PlayStation driver existed: face buttons rotated, and the triggers and the right stick swapped for each other. Clients that reach the pad directly were always correct, which is why the same pad could behave in one game and not the next (#660, #634)
  • Rests the virtual DualSense with its sticks centred and its triggers released. Of the report’s six axes only three were given a starting value, so a pad nobody had touched reported both sticks pushed hard left and the right trigger half pulled until the first real input arrived (#660)
  • Repairs a per-user configuration directory that a privileged run left owned by root. --setup-host now hands it back to the account Polaris runs as, walking it without following symbolic links, and corrects its permissions as well as its owner (#654, #637)
  • Stops creating that directory in a state Polaris then refuses to use. It is narrowed to the owning account when it is created rather than inheriting whatever the account’s umask allows, which on common desktop defaults left it writable by its group and made saving credentials fail from the first run (#659, #637)
  • Names the directory that actually refused, and the remedy that matches the fault. The message reported the directory above the one it had inspected, so it paired one directory’s path with another’s permissions, and it only ever offered to correct ownership even when ownership was already right (#663, #637)
  • Says which driver was running when the hardware encoder did not start, so a host that silently drops to software encoding names the driver version it found instead of leaving the reason in a discarded log line (#657, #650)
  • Explains that unreadable saved authorization state is not fatal: the host clears it, continues with a new identity, and says that any client paired before then has to pair again (#663)
  • Stops building two files without optimisation on compilers that no longer need the workaround, after measuring that the internal compiler error it existed for is gone (#656)
  • Continues the experimental multiseat foundation, still default off and unreachable in production: a negotiated media contract between worker and controller, and the DRM primary node a nested gamescope seat needs in its device catalog (#648, #662)
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A correctness update for Linux hosts that stream a private display, and for three failures that used to happen in silence. A game’s stored virtual-display preference no longer overrides a host that already provides the session’s display, a paused session no longer changes what the host recommends to other clients, and an encoder, a driver reading and a refused directory now each say what went wrong. Existing configurations and paired devices remain valid.

  • Stops an app’s stored virtual-display preference, or a client that never locked its topology, from moving a private headless host onto the host virtual display. A locked client choice, the paired always-virtual default, an explicit session stream mode and desktop mirroring all still win, so the mode stays reachable by asking for it rather than by inheriting it (#649)
  • Keeps a session-scoped display override out of the topology the host recommends to other clients. The override stays in force for its own session, including the whole paused-session resume window, but is no longer read back as the host’s own default, so one client’s choice can no longer become the next client’s recommendation (#649)
  • Reports when a host virtual display backend replaces an explicitly configured capture backend for that session, instead of substituting it silently (#649)
  • Records which input moved a session off the host’s own topology, so a silent promotion no longer reads in the log exactly like a deliberate choice (#651)
  • Adds a contract over the launch topology resolver: across every registered path and every combination of the resolver’s inputs, a private host must either defer to its own default or return a topology the caller named (#651)
  • Rejects nvidia-smi’s failure banner as a driver version. The banner was stored in the driver cache, which is keyed on the tool’s path and modification time rather than its content, so a single bad reading survived restarts and stopped the encoder cache from noticing a driver change; an already-poisoned cache now heals itself
  • Names the directory that refused to hold private state, along with its owner, its mode, the user Polaris runs as, and the remedy. One run under sudo leaves the per-user configuration directory owned by root, after which saving credentials fails permanently, and since v1.4.5 it failed with nothing in the log at all
  • Keeps libav errors at the default verbosity instead of silencing them. An encoder that cannot start because the graphics driver is older than the linked FFmpeg’s nvenc API now reports both versions, rather than falling back to software encoding without explanation
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A Bazzite and Live Tuning update matched with Nova v1.4.5. Live Tuning is one saved host preference that every console surface and paired client reads the same way, Bazzite Desktop launches prepare capture before the stream starts, hosts running a Steam Game Mode session learn why they go offline and how headless boot keeps them reachable, and --setup-host reports it. The supported Bazzite RPM path was exercised end to end on an NVIDIA Open host with a Retroid Pocket 6. Existing configurations and paired devices remain valid.

  • Reworks the supported Bazzite RPM guide around staged installation, explicit reboot, local-RPM replacement, and boot-independent service setup; moves the composefs KMS copy into an optional section and keeps Game Mode hardware limits and the withdrawn system extension explicit
  • Shares one saved Live Tuning preference across Quick Controls, the Audio/Video settings page, paired session status, and session events, independent of AI provider sign-in. Clients see the requested bitrate separately from the encoder-confirmed rate, with waiting, measuring, applying, adjusting, stable, unavailable, and unknown states; turning Live Tuning off holds the last confirmed bitrate, and an explicit fixed bitrate supersedes adaptive ownership (#641)
  • Prepares desktop capture before stream startup on Bazzite, normalises the resume policy, keeps native audio ownership with the session, and corrects CUDA conversion ownership and upload ordering, so a Bazzite Desktop launch or resume no longer prepares the portal too late or inherits unsuitable display semantics (#639)
  • Refreshes display capabilities once the host is back after Save + Apply, so Host Virtual Display no longer stays unavailable on the settings page because of a stale capability response; late responses cannot overwrite the new snapshot and Reset Changes keeps the refreshed capabilities (#642, #633)
  • Keeps DualSense reports in order: a periodic report can no longer land after newer button updates and replay stale input; the sender and reader threads are retained and joined, and descriptors close if construction fails (#643, #634)
  • Preserves the configured physical identity of every virtual input device on all nine uinput creation paths and keeps descriptor ownership until destruction, so reserved-device udev rules identify them reliably (#644, #494)
  • Protects unused encoder capability probes from a null-frame flush, adds actual submission/teardown regressions for the first-launch Vulkan crash, and keeps Doctor from telling a stable AMD VA-API/SHM user to switch to Auto with a promised fallback (#628)
  • Repins native PipeWire session audio when the stream omits its PID by resolving its owning client, while preserving session markers, unrelated desktop audio, and the no-default-sink-claim setting (#629)
  • Recognises hosts with a Steam Game Mode session (SteamOS, Bazzite deck images, CachyOS handheld edition, other gamescope-session hosts). --setup-host says why Polaris goes offline when the host leaves Desktop Mode and prints the headless-boot command, /api/stats/system reports game_mode_host with Game Mode-aware boot readiness and display-session guidance, and the console names a running Game Mode session instead of asking for a desktop restart. New handhelds guide with the Game Mode validation recipe (#626)
  • Adds the experimental multiseat worker foundation (default off and unwired in production), a maintained offline system-extension assembler with locked inputs, a read-only Bazzite host observer for local acceptance runs, and steadier Doctor CI fixtures (#640, #645, #646)
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A packaging and setup update matched with Nova v1.4.4. The application menu entry starts the same Polaris service that autostart and headless boot use, and a privileged setup run no longer mistakes root’s own device access for a ready desktop account. Existing configurations and paired devices remain valid.

  • Starts the packaged user service instead of a second process. A desktop launch used to make the running service instance exit, and nothing brought it back once that window was quit or the session ended, which left a host that had been streaming fine with no Polaris until the next login. The menu entry, autostart, and headless boot now all point at the one service
  • Stops a privileged --setup-host run from treating root’s own access to /dev/uinput and /dev/uhid as proof that the desktop account is ready, so a user still missing the input group is reported instead of passed
  • Adds a fail-closed Bazzite validation receipt checker that binds candidate bytes, source identity, image and driver identity, SELinux results, and physical hardware results, and runs it before release artifacts are bound
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A diagnostics and packaging update matched with Nova v1.4.3. Doctor names the gamescope session helper Polaris will run, the console and Nova get a coded answer when an artwork search fails, and partial configuration writes merge instead of rewriting the file. The standalone system extension initially shipped with this release and was withdrawn on September 5, 2026 because it did not include the runtime dependencies required by Bazzite. Existing configurations and paired devices remain valid.

  • Shows a Gamescope Session Helper card in Doctor & Support on Linux hosts configured for gamescope_stream, naming the launcher Polaris will run, a stale copy shadowing it on PATH, and a launcher or runtime library installed from a different checkout
  • Falls back to the bundled polaris-gamescope-session reference copy when no launcher is installed beside the binary or on PATH, so AppImage and build-tree hosts can start private sessions, and adds a shell test that exercises the gamescope stack installer
  • Adds PATCH /api/config, which merges a partial write onto the existing configuration instead of rewriting the file from the request body the way POST does, and logs how many existing keys a POST left out
  • Names the cause when an artwork search fails: the Nova-facing candidate search and the console cover search now answer with a stable code for a missing SteamGridDB key, a rejected key, rate limiting, or an unreachable provider instead of a bare status or an empty result
  • Names the field when explicit launch fields are rejected, including the value seen, so a comma-decimal fps or a lock flag without its prerequisite no longer reads as “must be complete and within supported bounds”
  • Tells the console when the installed Polaris package is newer than the running process, which is what a package upgrade without a service restart looks like
  • Withdraws Polaris-sysext-x86_64.raw; do not use cached copies. Bazzite remains supported through the Fedora 44 RPM and rpm-ostree
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official package assets

A stability and diagnostics update matched with Nova v1.4.2. Polaris lets a capable Nova client choose the encoder for a single game, closes a Linux Vulkan Video crash at disconnect, keeps SteamOS’s gamescope file capability from breaking private streams, and stops stale helper installs from being debugged as Polaris bugs. Existing configurations and paired devices remain valid.

  • Fixes a Linux Vulkan Video crash at client disconnect by closing FFmpeg’s codec-owned picture views before releasing Polaris’s converter resources, and records bounded teardown phase markers for field verification
  • Advertises the encoder backends compiled into the host and lets a capable Nova client choose one for a single game without rewriting polaris.conf. Among per-game choices, Auto is the only fallback policy; an explicit backend is live-probed strictly, bound to the deterministic launch envelope, reported in session status, and restored to the host default at teardown. Persisted host choices retain their existing fallback behavior, except Vulkan which remains strict
  • Keeps harmless low-latency LAN RTT jitter from reducing the Auto Safe bitrate, and keeps a clean Auto Safe recovery informational in Doctor while confirmed media loss still warns
  • Makes machine-facing decimal parsing and formatting locale-independent across /optimize, display planning, launch profiles, compositor arguments, and telemetry, so a host running under a comma-decimal locale can launch again, and keeps GTK tray initialization from changing Polaris’s numeric semantics
  • Starts the private nested gamescope compositor with no_new_privs, so the cap_sys_nice file capability SteamOS and Arch ship on gamescope can no longer hide /proc ownership from the same-user checks that prove which compositor owns the stream; desktop Game Mode keeps its capability
  • Runtime-masks the idle compositor unit only where one exists, repairs a leaked runtime mask on the idempotent stop path, and classifies the scripts/install layout of an idle unit with the host portal as host-portal instead of refusing it as inconsistent, so standalone packages and manual installs no longer wedge after a failed start
  • Skips the private portal rebind on hosts without a private portal unit instead of polling an absent bus for eight seconds and logging a warning that read like a failure
  • Resolves polaris-gamescope-session beside the Polaris binary before PATH, ships reference copies of the helper modules, and reports at launch when the launcher in use is shadowed by a stale copy or was installed from a different checkout
  • Captures a labwc startup client’s exit status and a bounded, redacted stderr tail when no private-session window appears, and records bounded per-session evidence for encoded frames that exceed the four-block FEC protection envelope; both stay informational in Doctor unless corroborating media-loss or pacing evidence exists
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

A matched performance, access, and Linux workflow update for Nova v1.4.1. Polaris adds guarded experimental Vulkan Video for supported Linux DRM/KMS paths, memory-only guest pairing, Hyprland Desktop Takeover, and more precise Doctor and capture evidence. Existing configurations remain valid, and automatic encoder selection falls back when the exact Vulkan requirements are not met.

  • Adds memory-only guest pairing for Nova QR and Manual PIN clients, with explicit access controls and automatic revocation after the device’s final stream disconnect or a Polaris restart

  • Adds an explicit Hyprland Desktop Takeover mode that creates a client-sized virtual output, moves the live workspaces onto it, blanks the original displays with DPMS, and restores the exact workspace layout before removing the virtual output on final disconnect

  • Adds an experimental Linux Vulkan Video encoder for H.264 and HEVC across DRM/KMS, wlroots, and Portal capture; Auto promotes it only on a compatible AMD private-stream route with an exact live-frame safety probe and VA-API fallback, while an explicit Vulkan choice stays strict and AV1 remains disabled until the bundled FFmpeg path passes Vulkan validation

  • Keeps Vulkan image imports and cursor overlays safe across asynchronous submissions with per-slot fences and descriptor sets, and exposes low-latency CBR tuning plus explicit KMS setup guidance in Settings

  • Pins the prepared FFmpeg bundle carrying Vulkan queued-picture teardown and missing encode-queue error fixes, preventing capability probes and short sessions from leaking image views or opening a broken encoder

  • Separates fresh-install Welcome setup from upgrade and reinstall sign-in across every supported distro guide, preserves existing host state by default, routes hosts with stored credentials away from the first-run wizard, and surfaces the real credential persistence error instead of a generic internal-server message

  • Makes Game Control the default for every newly paired Nova or Moonlight-compatible client, providing the browse, launch, and input permissions needed to play without granting clipboard, file-transfer, or server-command access; renames the old non-launching Standard Access label to Browse & Watch, while leaving every existing device’s saved permissions unchanged

  • Shows the host cursor by default for new or unset configurations so Moonlight-compatible clients retain a usable pointer, including on DRM/KMS capture where the hardware cursor uses a separate plane; preserves explicit disabled settings, Nova’s per-session coordination, and the runtime toggle

  • Preserves write-only SteamGridDB, AI, and legacy API credentials when Settings or Quick Controls saves an otherwise complete redacted configuration; clearing a stored key now requires its explicit clear action

  • Keeps deterministic Doctor output as the source of truth while allowing a configured provider to explain its redacted evidence; OpenAI subscription mode now invokes the signed-in Codex CLI through a private, bounded explanation-only workspace, and provider failure remains an informational deterministic-fallback

  • Starts imported Flatpak Heroic titles through the launcher’s normal visible cold-start protocol path instead of hiding the only actionable launcher feedback; exact older commands generated by Polaris migrate in place without changing UUIDs, artwork, profiles, prep commands, or custom fields

  • Keeps transient stream startup work from becoming a frame-pacing verdict by collecting six complete video telemetry windows and requiring two consecutive warning observations; Doctor reports the incomplete window as unknown and retains its read-only pacing action

  • Grades encoder time against the active stream’s real FPS budget, keeps a measured-healthy SHM compatibility path informational instead of inventing a 60 FPS recovery, avoids recommending a GPU-native mode that already fell back, and points an AMD Private Stream explicitly pinned to VA-API toward Auto’s Vulkan live probe with VA-API fallback

  • Reports missing private-session managed-window evidence as inconclusive for fullscreen and XWayland surfaces instead of claiming that a working stream is empty or rendered on the host desktop

  • Carries Heroic’s recorded platform and Wine or Proton runtime into imported GOG and Epic titles, so a successful import launches through the runtime the player selected instead of discarding that per-game choice

  • Says when client keyboard and mouse seat isolation cannot take effect by reading back the seat marker on each virtual input device and warning when the host input backend dropped it

  • Names the exact wlroots connector selected for capture even when its human-readable description is blank, and preserves the regression where a requested POLARIS-HEADLESS-* output must never fall back to physical monitor zero

  • Updates the web build lockfile to patched @humanfs/node and postcss-selector-parser releases, with npm audit reporting no known vulnerabilities

  • Reworks the Video/Audio settings tab into mode, quality, and display cards that show live host state, adds GET /api/settings/metadata so the console knows each field’s source, sync state, and last writer, and tells host defaults apart from the values a paired device overrides

  • Gives Doctor & Support, Devices, System & Updates, and Security the shared console grammar: read-only status tiles, one button vocabulary, an AI panel that reports its real readiness, a previous-run banner that separates a crash from a deliberate stop, Session Snapshot rows that name the capture path and the last writer, and a per-device view of the host settings a client overrides

  • Adds Sign out to the sidebar and the command palette, and a Clear history action on both Mission Control session lists backed by POST /api/ai/history/clear, which also empties the AI optimizer’s stored session outcomes

  • Moves the AI settings tab onto the same grammar with a guided provider setup and a readiness sentence, and gives the General, Input, Network, Advanced, and Files tabs localized headings with a pointer into the per-tab reference

  • Moves the console’s inline explanations into the documentation: new Play with Moonlight, Pair and manage devices, Add and edit apps, and Mission Control guides, a field reference for every settings tab in the configuration guide, and every (i) hint removed from the console in favour of one docs link per page and one-sentence inline descriptions

  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

A matched feature release for Nova v1.4.0. Doctor turns measured stream evidence into a clear explanation and, only when the evidence supports it, a reversible same-stream fix. Launch fields come from deterministic presets with field-level provenance, while history and AI remain unable to silently change a launch or inject a game-process limiter.

  • Reports frame-pacing Watch evidence under the compatibility reason code frame_pacing, without contradictory Stable state or unsupported network/bitrate blame; static and duplicate-only content is not treated as a pacing fault without source-cadence evidence
  • Removes history, recovery, and AI launch overlays; the legacy apply_recovery_profile_next_launch action is disabled, old recovery records are deprecated, non-applicable, and cancellable, and old apply/verify calls fail as unsupported_deprecated
  • Resolves auto, quality, high_fps, and stability deterministically and returns source, reason code, lock, and normalization provenance for every resolved launch field, including separate width, height, and FPS provenance for mixed high_fps profiles
  • Advertises the deterministic resolved-profile contract so Nova v1.4.0 refuses older Polaris launch policy rather than failing open to legacy history or AI settings
  • Keeps topology exclusively under explicit app/client display semantics and stops synthesizing MangoHud, DXVK, or VKD3D frame limiters for game processes
  • Binds optimize results to the canonical app UUID or ID and exact host-default, mirror, or private topology choice, advertises the versioned topology-assertion contract, and revalidates the complete deterministic profile before both fresh launch and resume
  • Keeps Auto Fix only for same-stream bitrate changes with measured verification, conditional controller ownership, and automatic rollback that never overwrites a newer user/client bitrate; pacing uses Recheck or manual guidance
  • Coordinates Doctor with Auto Safe: while the deterministic adaptive controller owns an active bitrate correction or recovery, Doctor explains the issue and offers a read-only Recheck instead of racing it with a stale second mutation
  • Keeps the exact rollback target fixed until the encoder acknowledges it, then resumes the prior adaptive policy; verified actions return terminal copy instead of leaving clients to reuse an in-progress measurement message
  • Ingests HUD-independent raw media counters from the authenticated active owner and exact stream generation, derives confirmed loss on the host, rejects stale coverage gaps, and enables acknowledged live bitrate reconfiguration for the Linux FFmpeg/NVENC path
  • Binds live Doctor and paired bitrate/adaptive mutations to the exact app-session token and stream generation, retains idempotent terminal results for that whole generation, and restores Doctor’s temporary target before accepting a newer adaptive-policy choice
  • Gives Nova and the Polaris web UI the same typed Doctor success, conflict, and rollback-unconfirmed response contract, preventing a failed safety check from being presented as a successful fix
  • Serializes paused-session expiry with launch and resume admission so an accepted reconnect cancels its timer before the lifecycle gate is released, while an expired timer cannot terminate the newly resumed game or admit media after teardown
  • Adds disabled-by-default Doctor v2 shadow evidence and a separate authenticated, private, one-dimension trial contract; records expire after a 24-hour lifetime, every trial is one-shot, and actions remain hidden until dedicated acceptance enables them
  • Keeps Steam Input manual and read-only without changing VDF files, Steam state, live streams, or launch policy
  • Launches imported Heroic GOG and Epic titles through the matching native or Flatpak install using Heroic’s current protocol, rejects browser-tampered runner/install metadata, deduplicates current and legacy command forms, and narrowly migrates Heroic entries generated by older Polaris releases
  • Keeps built-in utility entries such as Virtual Display on their shipped host artwork instead of automatically matching an unrelated SteamGridDB game, and retires the stale automatic cache without removing an explicit Artwork Studio selection
  • Clarifies Settings navigation, Linux launch modes, and capture paths around player impact; Headless Dongle remains a host-wide choice, planned modes stay visibly non-selectable, and backend details remain available without leading the decision
  • Prevents wrapped nested Gamescope teardown from entering the affected 3.16 Vulkan destructor by keeping a session-owned primary child alive after exact-session Steam exits, then freezing and killing the exact marked private group; verifies whole-group kernel stop state first and positively drains separately grouped or leaderless private-session members while the keeper retains cleanup authority
  • Refuses PipeWire DMA-BUF frames when the running package has no matching encoder importer; CUDA-disabled NVIDIA packages fall back to SHM/CPU capture before the first unusable GPU-only frame can reach the encoder
  • Forwards non-cage detached Steam shutdown through Steam’s no-bootstrap remote client, preventing a vanished listener from starting a replacement client while preserving retry authority when generation cleanup is incomplete
  • Restores distro-package Gamescope sessions to their empty compositor baseline without requiring Nix-only services, and retains the exact recovery claim when safe cleanup cannot be proven
  • Restricts AI and Codex CLI output to typed explanatory text that cannot define settings, actions, confidence overrides, or launch policy; subscription deterministic-fallback remains informational and quiet
  • Retains the GCC 16, Ubuntu snapshot, exact release-source, sanitizer, Arch, public-hygiene, and CodeQL gates from the protected release base
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

A Linux runtime reliability and configuration patch. Polaris now stops the exact Steam app workload before asking the private Steam client to exit, keeps nested compositor teardown serialized and generation-owned, restores several capture and encoder lifecycle invariants, and lets the AI Optimizer clear a stored API key through the same strict validation contract used by the rest of Settings.

  • Quiesces the exact SteamLaunch AppId=<id> lineage, including token-stripped descendants, before requesting full private-client shutdown; requires the pinned Steam game-process stop event plus a bounded settle, and uses exact pidfd SIGKILL rather than entering Steam’s crashing destructor when proof is incomplete
  • Prevents the observed Depot Download HTTP teardown assertion by separating game removal, recording and AutoCloud exit work from global Steam client shutdown
  • Serializes nested Gamescope stop transitions, preserves exact-generation compositor ownership, and sizes nested sessions from the final negotiated render geometry instead of imposing a standalone 4K120 fallback
  • Releases only the EGL context a teardown thread actually bound, reprobes a missing deferred cage encoder before launch, and retires the initial GPU-native conversion object without racing active capture
  • Detects Steam Input settings that can claim Polaris’s isolated virtual controller, keeps the finding after a stream ends, deduplicates aliased Steam profile roots, and offers one guarded Doctor action instead of mutating settings silently
  • Redacts private-session paths from public logs and keeps CI native-build classification, sanitizer coverage, package construction, npm audit --audit-level=high, and snapshot dependency handling fail-closed
  • Accepts canonical boolean spellings without changing unrelated configuration parsing and explicitly allows a typed clear_ai_api_key operation while unsupported keys remain rejected
  • Carries forward v1.3.12’s reviewed Boost 1.92.0-1 Arch package contract, exact versioned Boost SONAME dependencies, package ELF/dependency verification, and current rolling Arch installation gate
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

An Arch packaging compatibility hotfix. Polaris runtime and protocol behavior remain the v1.3.11 line; this release repairs the published package contract that allowed a Boost 1.91-linked binary to install on a rolling system that already provided Boost 1.92.

  • Rebuilds the official Arch package against reviewed Boost 1.92.0-1 inputs while keeping the immutable package snapshot and the current rolling Arch observation as separate gates
  • Declares the five linked Boost providers as exact versioned SONAME dependencies, including libboost_locale.so=1.92.0-64, so a future incompatible Boost transition fails during package resolution instead of at process launch
  • Inspects the finished package’s ELF NEEDED entries and requires every Boost SONAME to have a matching package dependency
  • Installs the exact finished package against current rolling Arch, requires ldd to report zero unresolved libraries, and launches polaris --version before release publication can proceed
  • Contains no Polaris runtime-code, protocol, configuration, or Nova client change; existing v1.3.11 configuration and Nova v1.3.7 pairing remain compatible
  • Keeps exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

A support, private-runtime recovery, display-truth, and reproducibility patch. Polaris can now preserve the evidence around crashes and silent failures, accept a bounded report from an authenticated paired client, recover private Steam and owned Gamescope reconnects, find Flatpak Heroic and Lutris libraries, keep PipeWire VAAPI capture on the safe SHM path by default, and stop describing requested display state as applied until the compositor reports it back.

  • Reports the effective Private Stream path instead of only the configured choice, so a fallback or pending relaunch is visible in status and support evidence
  • Finds Heroic and Lutris libraries in both native and Flatpak homes, emits the matching launch command, deduplicates the two sources, and validates launcher-controlled identifiers before placing them in a command
  • Lets linux_stream_mode = headless_dongle auto-detect and configure its display topology even when display auto-management was initially disabled; this path was validated on a real 4K dummy-plug host with panel blanking and teardown restoration
  • Publishes session_overridable in the mode catalog, keeping topology-swapping modes valid as host defaults while telling clients they cannot select them for one session
  • Verifies Hyprland mode changes from compositor read-back, tries the Hyprland 0.56-compatible fallback when the first command reports success without applying, and reports requested versus actual geometry if neither form lands
  • Records abnormal termination and actions that reported success without taking effect, then carries them into the redacted support bundle and pre-filled issue handoff
  • Accepts a size- and rate-bounded client report only from its authenticated paired-client certificate and stores it beside host evidence for the next bundle
  • Redacts credential names across separated, camel-case, run-together, quoted, structured, numeric, and Web UI session_id forms while keeping ordinary labels and numeric diagnostics readable; shared references and Map, Set, Date, and Error contents are preserved without weakening cycle handling
  • Normalizes one quoting layer around trusted-subnet CIDRs, rejects an empty pairing identifier before session creation, and logs the stored identifier rather than the moved-from request value without claiming the separate VoidLink stall fixed
  • Marks only compositor-private Steam with POLARIS_PRIVATE_SESSION=1, so that exact workload cannot be mistaken for desktop Steam and block a reconnect while missing or unreadable provenance remains fail-closed
  • Ships polaris-gamescope-session and its shared runtime library in all four Linux package families with Bash dependencies and executable package receipts
  • Finalizes the immutable runtime chosen by each launch generation, drains only Gamescope authority owned by Polaris, and reclaims only the proven-owned gamescope-0 / gamescope-0-ei socket pair while ambiguous cleanup remains retryable and fail-closed
  • Warns when a client HDR request reaches a final live SDR stream, outside encoder probes and after final colorspace selection, naming the black-video/working-audio symptom and immediate SDR recovery without changing protocol behavior
  • Keeps PipeWire VAAPI capture on SHM by default for local Gamescope/KWin graphs and portal-remoted streams. CUDA DMA-BUF is unchanged; exact POLARIS_PORTAL_DMABUF=1 is an operator opt-in for a host that has already proved that route, while unset, malformed, and exact 0 values remain on SHM
  • Adds the public papi-ux Matrix Space to the README and System > Resources so community chat is available beside the existing docs, source, releases, and Discussions links
  • Runs every sanitizer suite the repository defines, including the five audio, input, network, pairing, and video suites that had still been omitted after the first CI expansion
  • Pins the Arch build container and package repositories to the immutable 2026/08/17 archive snapshot, removing live mirror database/package-pool skew from release builds
  • Pins sanitizer and Ubuntu APT resolution plus the DEB smoke to snapshot 20260818T000000Z, isolated from runner sources and stale indexes, with partial updates and exceeded deadlines failing closed
  • Keeps npm audit --audit-level=high mandatory
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets
  • Keeps the evidence limits explicit: the maintainer host is KWin rather than Hyprland, native/Flatpak discovery is contract-tested without a live Flatpak launcher install, Nova’s user-facing report action opens Android’s share sheet and does not yet automatically post to the paired-host endpoint, the known 4K dummy-plug SHM capture ceiling remains performance follow-up, and the affected RX 7800 XT has not physically tested this exact safe-default candidate. This release contains the stall by defaulting VAAPI to SHM; it does not claim the underlying DMA-BUF stall is fixed

An install, launch, and crash-containment patch: SteamOS 3.8 becomes installable, nested Steam sessions start again after a v1.3.9 regression, VAAPI private-headless capture returns to the stable SHM path after a v1.3.9 crash report, private high-refresh capture holds its output rate, HDR advertisement returns on capable Mesa hosts, and Doctor stops reporting values the encoder never applied.

  • Removes the labwc dependency from the SteamOS 3.8 package. Polaris links nothing from labwc, but declaring it pulled in wlroots0.19, which pins libdisplay-info.so.2 and forced a downgrade of the libdisplay-info 0.3.0 that SteamOS runs KWin, Mesa, and Vulkan on, so no SteamOS install could complete. labwc is now an optional dependency and the Private Stream paths report it as missing rather than taking the desktop down
  • Documents the pacman keyring bootstrap that SteamOS installs require. SteamOS ships without an initialized keyring, so the first transaction that downloads a dependency failed before installing anything; the SteamOS guide now runs pacman-key --init and pacman-key --populate while the root is writable, and explains which stream paths work on a Steam Deck
  • Starts nested Steam sessions again. v1.3.9 bounded preparation commands by the app’s exit-timeout, which defaults to five seconds, while the nested Gamescope helper needs up to about forty seconds to bring up a compositor, so every launch through that path was terminated mid-startup and returned a 503, on the HDR path as well as the SDR one. Nested startup now has its own 120-second budget and nested teardown its own 30-second budget, both reporting helper diagnostics to the Polaris service journal instead of failing silently. Steam games and Steam Big Picture now take the nested session for SDR clients as well as HDR, keeping the streamed picture and controller focus under one compositor, and the unused Nix injectApps option is removed rather than advertising a no-op
  • Contains the VAAPI private-headless DMA-BUF regression reported after upgrading to v1.3.9 by restoring the conservative system-memory route for every VAAPI capture path, including buffers exported with DRM_FORMAT_MOD_LINEAR; affected hosts report vaapi_headless_dmabuf_disabled_for_stability with capture_transport=shm and frame_residency=cpu, while CUDA/NVENC GPU-native capture is unchanged
  • Probes VAAPI HEVC Main10 with a real 10-bit P010 input surface instead of pairing the Main10 profile with an 8-bit surface, so capable Mesa hosts stop failing the capability probe and suppressing HDR advertisement; profile selection now follows the actual input format across Main, Main10, and RExt, and live-session fallback stays separate from capability detection
  • Paces private-compositor screencopy capture from the compositor’s own frame callbacks instead of placing a second fixed timer in front of it, so a private high-refresh output no longer settles at a capture source below its own refresh. Direct desktop capture stays fixed-interval to preserve client-rate limiting, and output refresh, capture-source FPS, encoded FPS, and capture pacing are now reported as separate values
  • Reports only adaptive bitrate targets the encoder actually applied. A rejected runtime update no longer walks an internal VAAPI target down to the 2000 kbps floor while encoding at the session bitrate, live adaptive control is enabled only for encoders that support runtime updates, and Doctor evidence tracks the bitrate in real use
  • Separates Doctor’s backend detection from configuration readiness, states that Private Stream does not require the Virtual Display path, gives backend-specific configuration guidance, filters expected errors only inside the explicitly safe encoder-probe window, and reports target interval error and target FPS gap separately from network jitter
  • Keeps npm audit --audit-level=high mandatory
  • Builds the Nix polaris-stream package in CI for the first time. The job had never passed on any release: its checkout did not request git submodules, so third-party/ arrived empty and the build died during configure
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets
  • Records the field gates this release does not close: the SteamOS install fix is reasoned from the released artifact and Valve’s package repositories rather than run on a Steam Deck, SteamOS Game Mode remains uncertified, and the VAAPI containment still needs the affected #367 host to confirm the SHM markers and absence of a new coredump; GPU-native VAAPI performance remains follow-up work in #409; and the private high-refresh pacing fix was measured on a host that does not reproduce #434, where it raised encoded cadence from roughly 116 to 120 FPS against a 120 Hz output, so the reporting host has still not confirmed it

A Linux reliability and security patch for private-stream capture, compositor ownership, high-refresh cadence, and hostile-input boundaries.

  • Enables VAAPI GPU-native capture only for the private headless ext-image-copy route when the captured DMA-BUF is explicitly DRM_FORMAT_MOD_LINEAR; tiled, invalid, missing, windowed-private, and direct-monitor modifiers remain on the SHM fallback, and Doctor preserves the exact fallback reason
  • Makes capability-enabled Polaris work with xdg-desktop-portal by dropping capabilities before worker threads start and restoring ordinary same-user /proc access; explicit DRM/KMS capture retains its required capability on a separate process start
  • Accepts capability-enabled owned Gamescope generations, warns when unsupported nested Gamescope WSI can hide a blocking dialog, and prevents owned Gamescope/Xwayland descendants from retaining Polaris listener sockets after host exit
  • Creates and owns only an exact process-scoped Hyprland virtual output, verifies it before use, and fails closed instead of silently capturing a physical display
  • Preserves high-refresh private-stream cadence, exposes launches that never attach, sees override-redirect windows during attach, and bounds preparation commands without releasing lifecycle ownership early
  • Reapplies an explicit same-mode session choice when deterministic runtime, capture, or display companion state has drifted, while retaining the normalized no-op and teardown restoration paths
  • Hardens Wayland frame ownership, VAAPI DRM PRIME descriptors, KMS render descriptors, portal/capture shutdown, session environment snapshots, and exact-generation cleanup boundaries
  • Validates every client launch key, peer-declared control length, Steam app id, artwork URL/redirect hop, pairing PIN claim, and Doctor mutation boundary before use
  • Keeps secondary-client telemetry while preventing duplicate control-channel network-risk samples
  • Keeps npm audit --audit-level=high mandatory
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets
  • Records the remaining field gates without treating CI as hardware proof: linear VAAPI headless capture still needs affected AMD 4K validation, Hyprland virtual-display ownership and same-mode session normalization need affected-host confirmation, and the supported Gamescope Stream route needs an end-to-end portal retest

A safer private-stream daily driver: true-headless GPU-native capture, session-only launch choices, exact process ownership, an evidence-gated Doctor, bounded logs, benchmark controls, and a rebuilt web console.

  • Enables a true-headless Vulkan/ext-image-copy path with a prefetched initialization frame
  • Accepts a validated session-only streamMode launch override, re-evaluates capture sources around that session, reports display fallback explicitly, and leaves the persisted host default untouched; matching client support is versioned separately in Nova v1.3.6
  • Owns detached-only workloads through exact PIDFD identity before detaching, signals and reaps only the captured session generation, stops retained private compositors safely, recaptures demonstrably transient /proc races to bounded quiescence while persistent or ambiguous attribution remains fail-closed, and hardens portal startup/cancellation and restore-token handling
  • Exposes evidence-gated Doctor actions to recheck, perform one guarded bitrate reduction, restore a history-safe profile gradually, verify live telemetry, and Undo through the web console; matching Nova controls are versioned and released independently
  • Caps runtime diagnostics at an 8 MiB active file plus one 8 MiB backup, bounds console/file queues, preserves record-time timestamps, and exposes an authenticated binary-safe tail API with a bounded browser view and truthful truncation state
  • Adds authenticated bounded benchmark-run controls and T0-T2 host-stage evidence while keeping benchmark mode explicitly gated
  • Rebuilds Mission Control around one status hero, one live strip, the Doctor, a safer preview, and five Nova-aligned themes
  • Hardens render-node/GPU pairing, VAAPI-safe device selection, resume refresh restoration, HDR/YUV444 capability probes, virtual-display capture routing, and launch/resume status responses
  • Records the bounded Retroid Pocket 6 release smoke of the exact source commit tagged as v1.3.8: true-headless HEADLESS-1 capture, changing frames, session-only stream mode, durable Doctor apply/verify/Undo, exact-generation teardown, and clean restoration
  • Keeps the remaining field-proof limits visible: the reporter’s AMD 4K60 scenario and host-virtual-display route still need current-v1.3.8 end-to-end confirmation, and SteamOS remains an experimental Desktop Mode package
  • Keeps npm audit --audit-level=high mandatory
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

A use-after-free in VAAPI DMA-BUF capture that AMD hosts on DRM/KMS have been running, and CI that finally builds the nix packaging it patches.

  • Fixes a use-after-free at the VAAPI DMA-BUF import boundary: the VRAM converter destroyed its imported surface before importing the replacement, while an in-flight conversion could still be using it. Reachable on DRM/KMS capture and the non-cage wlroots VRAM path, which is what AMD hosts have been running
  • Fails closed on an invalid surface or texture selection rather than converting it, and closes duplicated DMA-BUF descriptors once ownership transfers
  • Keeps the gamescope-polaris patch stack and the packaged compositor in step, so the +polhdr2 stamp a session negotiates against is one a build proved
  • Checks the vendored patch stacks on every push and builds the nix packages in CI, so a patch that cannot apply fails there rather than on a host
  • Keeps npm audit --audit-level=high mandatory
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

Client-facing fixes for Nova, host setup advice that works on ostree systems, and gamescope session and HDR capture hardening.

  • Prints the input-group command that works on ostree hosts, where the group lives in /usr/lib/group and usermod -aG input cannot find it; Bazzite gets ujust add-user-to-input-group
  • Reports what the artwork resolve endpoint actually did, which Nova requires and no shipped build had ever sent, so library artwork update reported the host as unsupported
  • Serves platform and runtime on library entries from the Lutris runner recorded at import, and only where the runner determines them
  • Lets a manual artwork match decide which game a completion estimate is for, without falling back to the Steam app id that made the wrong estimate confident
  • Records the fields Polaris serves to Nova in docs/nova-contract.json, derived from the source that serves them, and serves vaapi_vendor so a crash report names the driver generation
  • Recovers gamescope session teardown from a dead nested marker, a non-leader attach, and an incomplete attach generation that refused later launches until restart
  • Negotiates PipeWire capture formats against what the stream encodes, so 10-bit PQ cannot feed an SDR encode
  • Claims the stream sink as the session default while streaming, and releases that claim only from the session that took it
  • Keeps npm audit --audit-level=high mandatory
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

Package-update safety, Linux host integration owned by the package, and library playtime and completion estimates.

  • Writes each mutable-distro download to the exact package filename with wget --output-document, preventing a pre-existing file from redirecting the new payload to .1 or .2 while a stale unsuffixed package is installed
  • Makes Fedora, Arch, and Ubuntu update commands short-circuit after download, package-install, sudo -H polaris --setup-host, or restart failures
  • Adds executable regression coverage for failed download, install, setup-host, and successful command paths across all three mutable package families
  • Documents the v1.3.4 bootstrap caveat and provides exact-output commands for the first upgrade to v1.3.5
  • Installs the udev rules and modules-load configuration as package files under /usr/lib, so the package manager owns them and removes them on uninstall
  • Retires an unmodified /etc copy from an older install that would otherwise shadow the packaged rules, and keeps an edited copy with a warning naming the file in effect
  • Lets --setup-host exit without root when the package already provides everything and the virtual input nodes are usable
  • Adds a polaris-debug package to the Arch and SteamOS builds so coredumpctl info polaris yields a real backtrace
  • Closes a systemd-inhibit process leaked on every session, and keeps a private session’s virtual keyboard and mouse out of the desktop session logged in at the machine
  • Warns at startup when seat isolation is enabled and the account Polaris runs as is not in the input group, which otherwise leaves the isolated devices unopenable by Polaris and by the streamed game
  • Warns when back_button_timeout is shorter than the 100ms Home press it emulates, since the setting is milliseconds and a value like 2 turns nearly every Back/Select press into Home
  • Reports the playtime Steam and Lutris already record on disk, and serves completion estimates from a local dataset first, with beat_times_lookup controlling the How Long To Beat fallback; both are announced through /polaris/v1/capabilities so clients can adopt them explicitly
  • Adds a transactional custom artwork workflow with an authenticated resolver, bounded downloads, and atomic caching
  • Surfaces per-app environment variables in the web UI
  • Releases the host loopback when a session turns host audio off, instead of leaving an earlier session’s loopback loaded for the life of the process
  • Applies the session’s requested resolution and refresh when preparing the streaming display
  • Keeps npm audit --audit-level=high mandatory and clears the advisories that were failing every web build
  • Retains exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb as the official release assets

Patch release adding a dedicated SteamOS 3.8 package lane and tightening Linux package, path, setup, and import safety.

  • Added fail-closed packaged binary path validation with explicit source-prefix remapping and retained validation receipts
  • Added secure Bazzite support for the /home to var/home layout without broad canonicalization
  • Dispatched setup-host early and standardized public host-integration commands on sudo -H polaris --setup-host
  • Made ImageMagick discovery locale-safe during Steam cover import
  • Added a dedicated SteamOS 3.8 x86_64 package built against Valve’s versioned repositories, with failure-safe installation and Desktop Mode package and startup validation only
  • Kept physical Steam Deck gameplay, Game Mode, OLED 90 Hz, suspend and resume, and update persistence outside the certified support claim pending hardware evidence
  • Kept npm audit --audit-level=high mandatory and the forbidden webtransport-go v0.10.0 dependency absent
  • Standardized the official release on exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, Polaris-steamos3.8-x86_64.pkg.tar.zst, and Polaris-ubuntu24.04-x86_64.deb

Patch release focused on configuration-save hygiene, controller boundaries, Linux recovery guidance, and Nix session reliability.

  • Stripped response-only runtime, stream-path, credential-presence, and virtual-display metadata before configuration saves so valid v1.3.2 settings edits no longer fail backend validation
  • Kept display-planner presets idempotent across repeated selection and stale dongle-discovery responses
  • Made tray URL launching locale-safe on Linux desktops
  • Rebound preallocated gamepad controller feedback after device reuse so rumble and related output follow the active client
  • Added default-disabled client-gamepad seat isolation with distinct virtual-controller identities and explicit Linux seat-policy limits
  • Documented how Bazzite users can restore Sunshine after testing or uninstalling Polaris
  • Kept Nix-composed idle/session scripts ShellCheck-clean and removed temporary authority files after failed atomic runtime publication
  • Retained the exact release assets Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, and Polaris-ubuntu24.04-x86_64.deb; Fedora 44 remains the sole Fedora package lane and npm audit --audit-level=high remains mandatory

Reliability patch focused on stream lifecycle, Linux private-session isolation, reconnect recovery, and truthful host diagnostics.

  • Hardened RTSP follow-up control admission, live-session command ownership, session teardown, and serialized PulseAudio operations
  • Prevented private-stream controller input from also navigating host Steam Big Picture while preserving normal game input
  • Hardened private Steam teardown ownership and bounded interrupted process waits without broadly terminating desktop Steam
  • Prevented private-session relaunch races by waiting for the prior Steam singleton to be fully released
  • Preserved authenticated web sessions across host restarts and improved recovery from transient host outages
  • Tolerated near-target stream FPS so healthy sessions are not mislabeled as degraded
  • Exposed clearer Linux GPU probe topology diagnostics for capture-path troubleshooting
  • Hardened Dashboard smoke navigation so release checks do not issue duplicate route requests
  • Updated Browser Stream to webtransport-go v0.11.1 and quic-go v0.60.0, fixing remote memory exhaustion from unknown capsule buffering (CVE-2026-57497 / GHSA-g35j-m5xg-vh3q)
  • Removed vulnerable, unnecessary web fixture-server dependencies and added npm audit --audit-level=high as a permanent CI gate
  • Standardized the official release on exactly Polaris-arch-x86_64.pkg.tar.zst, Polaris-fedora44-x86_64.rpm, and Polaris-ubuntu24.04-x86_64.deb; Fedora 42/43 remain historical rather than current package lanes
  • Added explicit Arch vulkan-headers / vulkan-icd-loader and Fedora vulkan-loader-devel package requirements
  • Cleared GCC 15 warning-as-error blockers in Browser Stream setup, dormant preview diagnostics, and Linux display-topology helpers so exact-tag package validation builds cleanly

Linux stream modes / private runtime foundation

Section titled “Linux stream modes / private runtime foundation”
  • Add first-class linux_stream_mode and linux_private_runtime config (Private Stream, Host Virtual Display, Mirror Desktop, GPU-native preference, Gamescope Stream, Headless Dongle).
  • Keep legacy headless_mode / linux_use_cage_compositor / linux_prefer_gpu_native_capture as a compatibility mapping; UI and client-settings write both.
  • Centralize mode resolve/apply/labels in stream_display_policy; path availability probes gamescope on PATH (and dongle outputs at apply).
  • Introduce stream_runtime interface with labwc and gamescope adapters so process session start does not hard-code cage forever.
  • Add stream_path registry (runtime × capture × topology) with reserved slots for community EVDI/Family Mode paths; honest runtime_backend for portal/host/gamescope/labwc.
  • Document the path plugin contract in docs/stream-paths.md.
  • Enable Headless Dongle path (headless_dongle): privacy/extended swap via kscreen-doctor (display_topology, headless_swap_mode); DRM sysfs connector discovery + /api/linux/display-outputs auto-suggest.
  • Enable Gamescope Stream ownership: attach idle gamescope-0 (start polaris-gamescope-idle if needed) or spawn owned headless; wrap app launches into that runtime; never use gamescope-1 for portal.
  • Harden portal/PipeWire capture: disconnect under loop lock; keep restore_token with invalidate+retry on SelectSources failure; wait for AvailableCursorModes ≠ 0; shared ownership so release cannot UAF negotiate/capture waiters.
  • Solid-base stop path: Moonlight /cancel responds before nested teardown; owner cancel ignores stale sessiontoken (case-insensitive UUID); Browser Stream signals shutdown, releases portal/PipeWire, then joins capture (bounded) before pidfd-killing gamescope/labwc; terminate_impl and WebUI disconnect share the same prepare path.
  • Harden Gamescope orphan recovery and nested teardown with generation-pinned socket reclamation, shared shell/C++ ownership locking, atomic session credentials, exact private-SID/pidfd cleanup, and fail-closed portal/idle rebinding.
  • Dashboard preview tries labwc, gamescope-0/1, host Wayland (grim), then spectacle — works across stream paths.
  • Web UI: selectable path cards write full config (including dongle outputs and gamescope/portal capture).
  • SB-5 mode-neutral Steam apps (issue #5): migration v9 + load-time normalize unwrap polaris-gamescope-session hardwires to steam-appid + detached rungameid; gamescope path applies attach X11 env (no host Wayland) via stream_runtime::wrap_cmd / process. Optional Steam Big Picture may keep nested WSI shell.

Security and pairing-state patch focused on current cryptography dependencies, durable client authorization, and clearer paired-device history.

  • Updated the Browser Stream helper’s Go cryptography and supporting modules, clearing the associated Dependabot alerts
  • Added localized Added and Last seen values for paired clients while keeping unknown timestamps truthful for legacy records
  • Hardened canonical X.509 client identity, revocation, duplicate-state validation, and authenticated request-time authorization snapshots
  • Hardened paired-client persistence with private, cross-process atomic state replacement
  • Improved paired-client controls so failed mutations remain visible instead of reporting false success in the web console

Feature release focused on self-service stream diagnostics, safer release visibility, display planning, and more resilient Linux capture startup.

  • Added a manual Update Center with release metadata, package guidance, and a visible update call to action in the web console
  • Added deterministic Polaris Doctor diagnostics and privacy-safe support reports for host readiness, active streams, and post-session troubleshooting
  • Added optional AI Doctor explanations that translate deterministic findings without replacing the local-first diagnostic source of truth
  • Added native network-path probes for route, latency, packet-loss, and reachability evidence in support workflows
  • Added native controller, isolation, and haptics diagnostics so input-path failures can be separated from client or game behavior
  • Added a display resolution planner that explains requested, host, capture, and output-mode compatibility before launch
  • Expanded Mission Control and Troubleshooting self-tests, support bundles, and issue-draft generation with clearer remediation steps
  • Improved Linux desktop capture startup by self-healing stale Wayland, display, and session-bus environment values
  • Hardened headless DMA-BUF capture so conversion failures fall back cleanly instead of leaving private streams stranded
  • Clarified NVIDIA, AMD/VAAPI, GPU-native, and fallback guidance across the public setup and troubleshooting docs

Patch release focused on CachyOS/Arch Settings reliability, Linux audio/capture diagnostics, and safer Moonlight-compatible host troubleshooting.

  • Fixed Settings saves being blocked by an internal SteamGridDB clear-key flag, allowing unrelated Network and trusted-subnet changes to save normally
  • Improved Settings pending-change handling so cancelled SteamGridDB key clears no longer reappear as phantom unsaved edits
  • Added clearer backend error details for failed Settings saves so support can identify rejected config keys instead of treating every failure like a filesystem permission issue
  • Improved PipeWire audio overrun diagnostics so stream support bundles and logs better explain audio-path failures during launch/connect attempts
  • Clarified GPU-native Stream relaunch/fallback reporting for Linux hosts, including AMD/VAAPI SHM fallback messaging and vendor-neutral capture diagnostics
  • Hardened Linux private/windowed compositor capture policy so cage/labwc runtime probes happen against the intended streaming runtime instead of a missing display context
  • Refreshed public docs, screenshots, and install guidance for Moonlight-compatible users arriving through Fedora, Arch/CachyOS, Ubuntu, and Bazzite paths

Feature release focused on Nova-ready private/headless streaming, Portable Chrome cockpit polish, safer launch contracts, Linux input/capture hardening, and broader package coverage.

  • Added the Portable Chrome web theme with a dimmer Moonlight-grey early-2000s retro-futurist skin, stronger chrome panel depth, restrained green status accents, and generic theme-toggle cycling across every registered skin
  • Improved npm run smoke:web so release smoke gates can target live Polaris or built static web assets, check hashed JS/CSS assets plus the unauthenticated login page, and report a clear preflight when the live HTTPS server is not running
  • Added a guided AI Auto Quality optimizer setup checklist with clearer provider/auth/runtime cards and actionable draft test feedback
  • Polished release accessibility/mobile readiness with named icon controls, live status regions, trapped confirmation-dialog focus, and non-sticky handheld review bars
  • Polished Mission Control live-session hierarchy with a stronger top summary for stream quality, latency, FPS, loss, bitrate, capture path, and runtime mode plus collapsible secondary live panels
  • Added a sticky Library import staging summary and review drawer with source counts, per-game removal, clear-all staging, and already-imported confirmation
  • Reduced idle web console polling pressure by deduplicating overlapping system/stream stats fetches and backing off transient fallback failures
  • Added a Settings pending-changes review drawer with safe before/after values, save/apply impact labels, jump links, and per-setting reset controls
  • Added confirmation dialogs and async toast feedback for host-affecting web actions such as disconnecting clients, recovery controls, stale display cleanup, and restart-sensitive quick toggles
  • Hardened Linux lock-screen dismissal so a failed loginctl unlock-session attempt continues through other graphical user sessions before falling back to loginctl unlock-sessions
  • Added Polaris v1 client/session surfaces for Nova: client settings advertisement, session status/stop integration, stream event queueing, and paired-client launch/input permission hardening
  • Hardened private/headless launch policy around desktop Steam, mirror-desktop intent, strict gamepad isolation, host virtual-gamepad metadata, and headless bwrap setup
  • Improved NVIDIA/Linux capture contracts with CUDA/GPU-native capability checks, DMA-BUF fallback diagnostics, virtual display output preservation, and headless VAAPI capture reinitialization
  • Added openSUSE Tumbleweed build coverage and refreshed package/release workflows for the current Fedora, Ubuntu, and Arch asset line

Feature release focused on the Polaris web console, Library workflows, safer pairing defaults, and NVENC split-frame hardening.

  • Polished Mission Control degraded-state handling and Library management flows so active sessions, imports, and app editing are easier to scan and manage
  • Renamed Auto Quality UI surfaces toward clearer stream-profile language
  • Added a server-authoritative Game Control pairing access preset for QR/OTP and manual PIN pairing, granting list/view/launch plus input permissions without clipboard, file transfer, or server-command access
  • Labeled paired clients with the exact Game Control permission mask as Game Control instead of Custom Access
  • Hardened NVENC split-frame defaults by explicitly passing FFmpeg’s disabled split-frame value when split-frame encoding is disabled
  • Improved Linux lock-screen dismissal so Polaris falls back from a systemd manager session to the graphical login session before running loginctl unlock-session
  • Added web, pairing, and video regression coverage for the new access preset and split-frame default behavior

Hotfix release focused on keeping cached AI launch profiles from forcing capable clients back to 720p.

  • Bounded cached AI display-mode optimization by the explicit client request so Shield, Retroid, and Android TV launches that request 1080p keep a 1080p headless compositor
  • Preserved history-safe recovery behavior so confirmed recovery profiles can still lower resolution or FPS when a recent session needs it
  • Smoke-tested a Shield direct Steam launch with Nova v1.0.10, confirming the client request, Polaris-selected mode, labwc headless runtime, and Android decoder all used 1920x1080x60

Hotfix release focused on session lifecycle cleanup after client End and terminate flows.

  • Cleared stale paused/resumable session state when an app is explicitly terminated after the last stream client disconnects
  • Emitted a terminal stream_ended lifecycle event from the terminate cleanup path so Nova can remove stale Active Session/Resume UI
  • Made the session shutdown-request flag thread-safe between HTTPS controls and stream cleanup
  • Added regression coverage for paused app termination, connected-client guards, duplicate idle suppression, and streaming cleanup handoff

Stability hotfix release focused on client certificate verification during reconnect and disconnect flows.

  • Fixed a crash in HTTPS client certificate verification by giving each verification request its own OpenSSL X509_STORE_CTX
  • Protected paired-client certificate state while concurrent HTTPS threads verify Nova/Moonlight clients
  • Added regression coverage for concurrent certificate verification against the pairing certificate chain
  • Rebuilt local master with CUDA enabled and smoke-tested a Retroid Pocket 6 direct Steam launch through headless labwc, DMA-BUF GPU capture, CUDA conversion, and NVENC
  • Confirmed the direct Retroid launch path stayed clear of inherited MangoHud and cleaned up the isolated session without a new coredump

Hotfix release focused on keeping MangoHud out of Linux headless stream runtimes unless a game explicitly opts in.

  • Suppressed inherited and session-pacing MangoHud injection for direct Steam game launches inside the headless cage compositor
  • Kept explicit per-game MangoHud support available for direct game launches while continuing to block MangoHud for Steam Big Picture sessions
  • Cleared MANGOHUD_CONFIG from the isolated labwc and XWayland runtime so compositor/helper processes do not inherit stale FPS-cap configuration
  • Added policy coverage for direct headless cage launches and Steam Big Picture suppression
  • Smoke-tested a direct Retroid Pocket 6 launch under a forced parent MANGOHUD=1 environment and verified stream child processes did not retain MANGOHUD*

Patch release focused on Steam launch reliability, encoder/runtime polish, and safer Linux capture setup.

  • Improved Steam library launch behavior, including direct Steam launch mode and non-default Steam library discovery
  • Added NVIDIA NVENC split-frame encoding support, prepared FFmpeg wiring, configuration validation, and user-facing docs
  • Improved Auto Quality and Adaptive Bitrate behavior so paired-client bitrate, recovery profiles, and clamp edge cases are handled more safely
  • Added AMD GPU telemetry support and clearer dashboard handling for optional vendor-specific metrics
  • Improved Linux unlock fallback, session cleanup, AMD headless DMA-BUF handling, and runtime diagnostics
  • Added safe local development cleanup tooling with script coverage and building-guide documentation
  • Hardened display selection so capture setup handles empty display lists without clamping against an invalid range

Patch release focused on AI Auto Quality, Nova coordination, and Linux stream pacing diagnostics.

  • Added richer Nova/Polaris settings sync so launch optimization, applied stream settings, presentation state, adaptive bitrate status, and optimizer health are visible across both sides
  • Merged adaptive bitrate behavior into the AI Auto Quality path so recovery decisions can consider network pressure, host frame pacing, encode pressure, and session history together
  • Improved AI optimizer feedback handling so short low-confidence sessions do not incorrectly relax safe FPS caps or poison game profiles
  • Added safer history-based recovery profiles, including FPS fallback behavior and clearer host-render-limited session grading
  • Improved Linux headless stream reporting for DMA-BUF capture, CUDA conversion, encoder target, frame residency, and SHM/CPU fallback reasons
  • Added resumable disconnect handling and cleanup improvements for Steam and isolated cage sessions
  • Expanded optimizer, adaptive bitrate, stream stats, process migration, and web UI coverage for the new Auto Quality flow

Patch release focused on corrected Fedora/Bazzite NVIDIA release assets.

  • Rebuilt Fedora 42, Fedora 43, and Fedora 44 release RPMs with CUDA enabled so NVIDIA/NVENC hosts can use the validated GPU-native upload path
  • Added release validation that fails Fedora RPM packaging if a tagged release reports Build features: cuda=disabled
  • Normalized the Fedora CUDA toolkit header patching flow for CUDA 13.2 headers and Fedora 42/43/44 release builds
  • Fixed release dispatch packaging dependencies and Arch release validation so patch-release asset rebuilds are repeatable
  • Kept the v1.0.11 Browser Stream and Linux runtime diagnostics behavior otherwise unchanged

Patch release focused on Browser Stream validation and Linux stream-runtime polish.

  • Added experimental Browser Stream using WebTransport and WebCodecs, with /browser-stream routing and /webrtc compatibility aliases
  • Added the Polaris-launched WebTransport helper, browser session API, WebCodecs playback, and browser keyboard, pointer, wheel, and touch input routing
  • Added Browser Stream UI modes for Game Mode, in-game expansion, pop-out streaming, stream profiles, latency statistics, and unsupported-browser messaging
  • Improved Linux stream runtime diagnostics, stream display policy reporting, and GPU-native/headless capture path explanations
  • Improved Linux launcher integration, labwc refresh-rate handling, headless preview diagnostics, and stream cleanup behavior
  • Fixed Browser Stream close handling so the helper, transport, cage runtime, and launched Steam game are cleaned up together
  • Fixed Steam handoff after Browser Stream cleanup so Nova/Moonlight launches are not blocked by stale Steam child processes
  • Fixed isolated Linux audio routing so game audio streams that move back to the host sink are returned to the Polaris virtual stream sink
  • Added isolated Linux process cleanup for Steam-launched children that escape the direct app process group
  • Fixed SHM capture color handling for reported wlgrab pixel formats and expanded unit coverage for the copy path
  • Tightened HDR metadata gating, web config save behavior, and Browser Stream route/config/status test coverage

Patch release focused on Linux streaming diagnostics and host-session isolation.

  • Gate true HDR streaming on display HDR metadata instead of client dynamic-range requests alone
  • Add Linux true HDR diagnostics to logs, session status, and support data
  • Document the KMS/DRM HDR validation path and current headless labwc SDR behavior
  • Fixed Linux shader runtime path packaging so packaged builds can find shader assets correctly
  • Isolated Linux headless audio routing so Polaris can capture its virtual stream sink without leaving the host desktop default sink redirected
  • Added troubleshooting notes for Linux headless audio routing and HDR metadata validation

Patch release focused on Linux headless color correctness and support clarity.

  • Fixed AMD/Mesa true-headless SHM color channel handling for reported 3bpp and 4bpp formats
  • Prevented the first-run welcome wizard from staying on Saving... when browser-side credential saving fails
  • Clarified Headless Stream vs Desktop Display behavior on Linux
  • Clarified current Linux HDR/Main10 limits and the recommended SDR VAAPI validation path
  • Documented that Polaris can be installed alongside Sunshine, but both hosts should not run on the same default GameStream ports at the same time
  • Clarified that Moonlight is not inherently capped to 60 FPS; Polaris respects the FPS explicitly requested by the client

Patch release focused on Bazzite headless stream validation and host-session isolation.

  • Fixed Linux EVDI virtual display output detection when Polaris opens a pre-created EVDI DRM card
  • Documented the Bazzite EVDI initial_device_count=1 setup path for virtual display validation
  • Replaced the Bazzite service override heredoc with a systemctl --user edit --stdin command and documented the validated headless labwc success markers
  • Clarified the recommended Bazzite Headless Stream optimization, expected SHM/RAM capture warnings, and host-input isolation success markers
  • Routed headless labwc virtual input through the labwc socket and blocked host uinput fallback when the headless runtime is active
  • Cleared host DISPLAY from cage-launched app and Steam follow-up commands so launched processes stay inside the stream runtime

Patch release focused on the first-run credential wizard.

  • Documented the Bazzite composefs workaround for KMS capture: copy Polaris to /usr/local/bin/polaris-kms, apply setcap there, and run the user service from that writable copy
  • Prevented the first-run credential wizard from staying on Saving... forever when the browser-side password request fails

Patch release focused on first-run Bazzite setup clarity and web credential routing.

  • Redirect first-run /login and /recover visits to the welcome wizard when no web credentials exist
  • Clarified first-run setup URLs in the README and Bazzite guide
  • Updated the Bazzite guide to run sudo polaris --setup-host --enable-kms for the DRM/KMS capture path

Patch release focused on cleaner Bazzite/Fedora 44 packaging and headless runtime dependency coverage.

  • Added the Linux headless runtime helpers to package dependencies: labwc, wlr-randr, Xwayland, and xdpyinfo/x11-utils
  • Avoided GPU DMA-BUF capture when the build lacks a matching GPU upload path, preventing invalid CPU frame conversion in headless labwc sessions
  • Added Fedora 44 RPM release assets for Bazzite 44 and Fedora 44 users
  • Simplified the Bazzite install guide around one matching Fedora RPM layered through rpm-ostree

Patch release focused on Bazzite tester feedback and credential recovery.

Highlights:

  • Fixed BGR0 CPU-frame conversion fallback by inferring packed row stride when capture reports row_pitch = 0
  • Prevented headless labwc fallback paths from failing encode conversion with src_stride=0
  • Updated the Bazzite guide with labwc/wlr-randr layering, Desktop Mode-first validation, and known log-message guidance
  • Marked Bazzite and Ubuntu package paths as extremely experimental tester paths until broader real-hardware validation is complete
  • Clarified web credential recovery: run polaris --creds as the same user, restart Polaris afterwards, and avoid shell-confusing placeholder commands

Highlights:

  • Added an experimental Bazzite install path using the Fedora RPM through rpm-ostree
  • Added a Bazzite validation checklist for desktop mode, gamemode, GPU, pairing, and headless behavior
  • Added Ubuntu 24.04 DEB packaging: Polaris-ubuntu24.04-x86_64.deb
  • Added an Ubuntu install guide with package, source-build fallback, and validation notes
  • Polaris config saves now stay isolated from legacy Sunshine config paths

Patch release focused on validated Linux release packages.

Highlights:

  • Fedora 42 and Fedora 43 RPMs now build with package-style install paths under /usr
  • Fedora RPM smoke tests install the generated RPM, verify the packaged binary, and check shared-library resolution
  • Fedora 43 is now part of the official release asset validation matrix
  • Arch package validation now checks the package against the current distro Boost runtime before release upload
  • Public install docs were refreshed for Fedora 43 and current Arch package dependency behavior

Patch release focused on dual-distro packaging, Linux runtime hardening, and public web-console polish.

Highlights:

  • Arch joins Fedora as a first-class GitHub release package target, with refreshed v1.0.1 assets for both distro paths
  • Headless labwc startup, preview routing, and Mission Control preview-source labeling are improved
  • Mission Control charting is split out and the web shell is hardened against local self-signed HTTPS chunk-load failures
  • The web console now pauses polling and live telemetry while hidden, reducing idle browser and host load
  • Browser smoke coverage now checks the key public routes against a live Polaris instance
  • Trusted Pair diagnostics and trusted-subnet matching are clearer, including IPv6 support
  • Client-requested display modes now cap AI/session optimization upshifts instead of being silently exceeded
  • Control-shell AI cache handling is less noisy for Steam UI and desktop-style sessions

First public Polaris release.

Highlights:

  • Linux-first host with a dedicated streaming compositor path
  • Web UI for Mission Control, library management, pairing, settings, security, and troubleshooting
  • Trusted Pair, QR pairing, and manual PIN pairing flows
  • Live session preview, runtime telemetry, diagnostics, and quick controls
  • Steam, Lutris, and Heroic library import flows
  • Nova-aware launch modes, watch mode, and richer session-state integration
  • Adaptive bitrate, AI optimizer support, and per-title tuning

Current official public assets:

  • Polaris-fedora44-x86_64.rpm
  • Polaris-ubuntu24.04-x86_64.deb
  • Polaris-arch-x86_64.pkg.tar.zst