On 2026-04-24 (Friday morning), starting the rupelmonde-castle-viewer stream on peppy → boom-pickle showed only the Hydra ExperienceNet branded splash on peppy, never the castle. /api/v1/stream/status reported streaming the whole time. Manually killing kioskoverlay.exe on boom-pickle (Stop-Process -Name kioskoverlay -Force) revealed the rendered castle immediately, proving Rupelmonde was rendering correctly and the kiosk overlay was the sole blocker.
The same flow worked on Wed evening (2026-04-22). The difference: today's attempt was a cold boot of boom-pickle.
hydrabody's kiosk overlay has no mechanism to step aside when an experience is streaming. cmd/kioskoverlay/main.go:1017 places the overlay's main window at HWND_BOTTOM with WS_EX_TRANSPARENT (click-through), assuming Rupelmonde's new top-level window will naturally draw above it. That assumption holds when an operator interacts with Rupelmonde during a dev session (Wed) but not when Sunshine launches it cold via CreateProcessAsUserW in an autologin session — the new SDL window can land in background z-order against the long-lived, already-painted fullscreen overlay.
The stream webhooks POST /api/v1/stream/started and /stream/ended (pkg/provider/httpserver.go:54-104) call streamProvider.OnStreamStarted / OnStreamEnded but never touch the kiosk controller — pure design gap.
Verified on boom-pickle:
kioskoverlay.exe was launched without --debug (the topmost debug-window path is not involved).MainWindowHandle=0 from .NET's perspective, but EnumWindows from Session 0 is blind to Session 2 — the window exists, just doesn't appear in cross-session queries.cmd/kioskoverlay/main.go:539 minimizeAllWindows() runs at overlay startup and SW_HIDEs every visible non-system window. If KioskController.Tick() (pkg/provider/kiosk_windows.go:180-186) ever relaunches the overlay during a stream — crash, session transition, manual kill — Rupelmonde's window gets SW_HIDE'd with no recovery (restoreDesktop only runs on graceful exit via the HydraBodyKioskStop named event, not on force-kill).
HydraBodyKioskStop: Global\HydraBodyKioskHide and Global\HydraBodyKioskShow. In cmd/kioskoverlay/main.go a goroutine waits on each and calls ShowWindow(overlayHwnd, SW_HIDE) / SetWindowPos(...HWND_BOTTOM...) + ShowWindow(SW_SHOWNOACTIVATE) on the main overlay hwnd. Store the overlay hwnd in a package-level var when createOverlayWindow creates it.KioskController.HideOverlay() / ShowOverlay() in pkg/provider/kiosk_windows.go that signal the events. No-op stubs in kiosk_other.go.HideOverlay from handleStreamStarted (pkg/provider/httpserver.go:65) and ShowOverlay from handleStreamEnded (line 97). Mirror the call from the sunshine log-watcher path so both stream-detection paths trigger the same hook.minimizeAllWindows skip rule: skip windows whose owning exe is under experiencesBaseDir (C:\experiences\) — uses the constant already in httpserver.go:17.stream/started immediately. Hide only after Rupelmonde's first window appears: poll for non-zero MainWindowHandle on the experience process, or watch for Sunshine's first-frame log line. This way users still see the splash during the ~30s Unreal load.With the new GET /api/v1/debug/screenshot endpoint on the body (shipped in hydrabody v1.11.21), validation can be done end-to-end. Rerun the same stream-start and screenshot the body before/during/after — expect splash → castle → splash on the body's pixels. Without that endpoint, only peppy-side pixels were observable.
Confirm there's a single OnStreamStarted / OnStreamEnded hook point inside the sunshine provider so HTTP webhook + log watcher don't both fire HideOverlay redundantly.
node-74f9fbf2 (boom-pickle-38), bxl1/rupelmonde — currently offline (was the reproduction host)node-4c2be4b0 (cosmic-pretzel-98), bxl1/cloud-seven — also affected; reproduces with the same kiosk_mode_enabled=true config (and currently has a stuck Windows Firewall popup for UnrealGame visible via the new screenshot endpoint)~/.claude/plans/enumerated-cuddling-micali.md (the body screenshot plan that just shipped) contains the full follow-up issue body and the implementation checklist for this fix.