Files
enricobuehler 15dccde2f2 feat: the Steam library source
Ported from the host's in-tree scanner (crates/punktfunk-host/src/library/steam.rs) — the
biggest of the six, and deliberately the LAST to move, so the seam was proven by the other
five first. Almost all of the parsing already lived in `@punktfunk/plugin-kit/library`,
which is exactly what those parsers were hoisted for; this is the assembly on top.

Covers what the scanner covered:

  * Every library's `steamapps/appmanifest_*.acf`, with the install dir resolved under
    `common/`. The FIRST library wins for an appid present in several — the same tie-break
    the host used, and the parity harness compares ids.
  * `isSteamTool` filtering, so Proton, the Steam Linux Runtime and the Steamworks
    redistributables never appear as games.
  * Non-Steam shortcuts from every `userdata/<id>/config/shortcuts.vdf`: hidden ones
    skipped, duplicate appids across profiles collapsed, and the launch value is the
    **64-bit** `rungameid` composition — handing `rungameid` the bare 32-bit appid does not
    launch a shortcut.
  * Art in the host's order: the user's own `userdata/…/grid` overrides, then
    `appcache/librarycache`, then the flat CDN URL. Local files ride out as `file://` so
    the host proxies the bytes and the payload stays tiny. A shortcut's appid has the high
    bit set and is never a store appid, so it gets no CDN guess — grid overrides are the
    only art it can have.
  * `detect.steam_appid` (authoritative on Linux, where Steam's reaper wraps every launch)
    plus the install dir, which is what the Windows matcher keys off instead.

New here: the `steam_ui` launcher tiles (design D4) — Big Picture ON by default, the desktop
client off. Steam is the one store with two UIs, which is why `steam_ui` is the one launch
kind with two values; the host turns each into a command, so the plugin never constructs one
(D1). Their external ids are `big-picture` and `desktop`, which cannot collide with an appid
because every real appid is digits.

An install dir named by a manifest but absent on disk yields NO detect hint rather than a
wrong one — a partial or cancelled install would otherwise bind the session to a path that
does not exist. Same reasoning for a shortcut with an empty target.

Runs under the runner's principal. On Windows that is NT AUTHORITY\LocalService, where HKLM
is readable (measured 2026-08-06) but HKCU is not — the kit's root discovery is built around
that. On Linux the runner is the user's own service, so `~/.steam` and `~/.var/app` are
directly readable.

Gates: tsc --noEmit clean, 10 tests pass, biome clean, `bun run build` produces both entry
points, and the CLI answers honestly off-platform (`detect` -> absent, `scan` -> []).

Still owed, and it matters more here than for any other library plugin: `parity --compare`
against a real install. These are the `steam:<appid>` ids the GameStream app list and every
client's art cache are keyed by, so a drift of even one id is a visible regression. The
Deck / SteamOS leg additionally covers real non-Steam shortcuts launching via the 64-bit
rungameid, which the Rust shortcuts work still owes too.
2026-08-06 15:55:21 +02:00
..
2026-08-06 15:55:21 +02:00