Five confirmed findings from the 2026-06-22 adversarial bug sweep:
- S-01: clamp PipeWire capture chunk size to the mapped slice before
indexing, so a bad reported size can't panic (= process abort) from
the RT capture callback. Extracted testable for_each_capture_sample.
- F-04: reserve ring occupancy before publishing a frame on the PipeWire
playback path (mirrors the cpal fix), preventing the RT consumer from
popping an uncounted sample and wrapping fill_gauge to usize::MAX,
which permanently wedged mixer pacing. Extracted publish_frame.
- F-09: GameDetector::spawn now returns io::Result and retains its
JoinHandle (joined on Drop); core fuses a closed watch receiver to
None via next_game_change so a dead detector can't busy-loop select!.
- F-08: collision-free recording paths — Recorder::create and the
multitrack session dir use create_new/create_dir with bounded suffix
retry, so two recordings in the same second no longer truncate the
first.
- S-02: bound the Windows SteamPath registry read (<=4 KiB, even length,
re-checked type/returned length) before allocating/decoding.
403 lib tests pass (+6), clippy --all-targets clean. Implemented by
Codex, reviewed + gates re-run by senior.
Co-Authored-By: Codex <codex@openai.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Field test found Steam games were never detected on Linux. Root cause:
Steam rewrites ~/.steam/registry.vdf only on SHUTDOWN, so its RunningAppID
is stale (often absent) while a game is actually running — polling it can
never see the live game.
Fix: on Linux, read the live appid from the running game's environment
(SteamAppId in /proc/<pid>/environ, the var Steam exports to every game
process — the same signal MangoHud uses; readable for our own processes).
registry.vdf stays as a best-effort fallback. Windows still reads the real
registry's RunningAppID, which IS updated live there. Other Unix keeps the
registry.vdf fallback.
Pure parse_steam_app_id_from_environ() is unit-tested (nonzero filter,
absent, substring-not-fooled, garbage). Also fixes a latent bug in the
first draft where a single non-UTF8 SteamAppId value would abort the whole
scan via ? instead of skipping.
396 lib tests, clippy --all-targets clean.
Step 2-3 of game detection (game-presence-plan.md). The OS edges feeding
the pure seams from the previous commit.
- src/game/steam.rs: SteamProbe — reads the live RunningAppID and resolves
it to a name via appmanifest_<id>.acf (no binary appinfo.vdf). Pure parse
fns (parse_running_app_id / parse_library_paths / parse_app_name) over
file contents are unit-tested incl. current+legacy libraryfolders shapes,
escaped Windows paths, empty/missing names, and garbage. Roots discovered
across native/Flatpak/Snap (Linux) and the registry (Windows); libraries
and resolved names cached + mtime-invalidated so the 3s poll doesn't
rescan. File reads byte-capped.
- src/game/scan.rs: native running-process enumeration — /proc (exe symlink,
comm fallback) on Linux, Toolhelp on Windows — feeding the pure
match_processes. No sysinfo dep (D7).
- Cargo.toml: windows-sys as a direct Windows-only dep for the registry +
Toolhelp FFI. No NEW crate — it was already in the lockfile transitively
via cpal/rfd, so the audit surface is unchanged.
391 lib tests (+5). Linux: build + clippy --all-targets clean. Windows FFI
signatures verified against windows-sys 0.61 source (one *const vs *mut
lpReserved fixed) but NOT yet cross-compiled — defer to the post-UI Windows
build cycle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>