diff --git a/CHANGELOG.md b/CHANGELOG.md index 76119edf..6971242d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Set the Windows title-bar icon from the embedded exe resource. WinUI shows a generic placeholder in the title bar unless the window is handed an icon explicitly, so every shipped host ran with a foreign default glyph while taskbar and shortcuts showed the real brand icon — the icon was compiled into the exe (resource ID 1 since #283) but nothing ever loaded it. The host template now loads it with `LoadIconW` and hands it to `AppWindow.SetIcon` at construction; projects without a `windows-icon` declaration keep the placeholder. Existing products carry the same lines in their own `MainWindow` constructor (podlens landed it first). + - Add the release gate. `raco rivet generate --check` regenerates every client file in memory and fails when the tree differs — the writer and the gate share one regeneration, so a hand-edited version stamp or a forgotten regeneration (four shipped-repo incidents in one week) cannot merge. `raco rivet doctor --release` validates in one command and one exit code: generated freshness, the committed schema baseline, hand-written host sources calling `fetch-update-manifest`/`select-update`/`download-update`/`fetch-sibling-asset` only with keywords the installed rivet accepts (read via `procedure-keywords` from the live functions, closing the payback `#:redirections` class), and every `rivet.git#...` pin being non-empty and consistent with the installed release (the autarx empty-ref incident). The update API keyword contract is a documented, test-guarded stable surface, and `docs/ci.md` warns about the empty `URL#` footgun. - Own the Linux runtime layout discovery and ship the GTK main-thread bridge. `rivet::linux_runtime::discover_layout()` locates `runtime/*.boot` plus `res/core.zo` beside the executable (an explicit-root overload serves tests), `layout_error_hint()` is the remediation message hosts display, and the host template consumes the library instead of carrying a private copy — the staged-versus-packaged layout is Rivet's contract, so the code that knows it lives with it. The template also ships `rpc_bridge.hpp`: `unpack` flattens a generated `Result` (including `Result`) into a value-or-error decided on the reader thread, and `post_to_main` runs the closure on the GTK main loop, freeing it there. A new GTK host starts with the correct pattern instead of rediscovering thread affinity the hard way. diff --git a/platform/windows/host/MainWindow.xaml.cpp b/platform/windows/host/MainWindow.xaml.cpp index 2dc65843..7f2407ee 100644 --- a/platform/windows/host/MainWindow.xaml.cpp +++ b/platform/windows/host/MainWindow.xaml.cpp @@ -5,8 +5,11 @@ #endif #include "GeneratedBackend.hpp" +#include #include +#include + namespace winrt::RivetHost::implementation { namespace { @@ -64,6 +67,16 @@ rivet::windows::RacketRuntimeConfig runtime_config() { MainWindow::MainWindow() { InitializeComponent(); Title(L"Rivet — Racket + WinUI 3"); + // WinUI shows a generic placeholder in the title bar unless the + // window is handed an icon explicitly; rivet embeds the project + // icon in the exe at resource ID 1 (rivet-cli/build.rkt), so + // surface it here. Projects without a windows-icon declaration + // keep the placeholder. + if (HICON const icon = + ::LoadIconW(::GetModuleHandleW(nullptr), MAKEINTRESOURCEW(1))) { + AppWindow().SetIcon(winrt::Microsoft::UI::IconId{ + static_cast(reinterpret_cast(icon))}); + } // Ordinary window close and OS session end (logoff/shutdown) both funnel // into the same orderly backend stop. The console-control callback runs // on its own thread, so it only touches the thread-safe stop() — never