Windows v2 product and architecture redesign
Date: 2026-09-08. Status: following implementation authorization, the WinUI configuration preview, safe C# configuration services, and cross-language/real Runner contracts are implemented. The implementation baseline passed remote WinUI CI. Real galgame testing completed the Steam → Runner → game flow for one Unity game and five independent translated 9-nine packages outside the Steam library, including ordinary exit and Steam status/playtime updates. All five had their Chinese openings verified. After Episode 1’s CHS entry was restored, the local launcher-exits-first/game-and-Runner-keep-waiting scenario also passed; the original entry’s earlier product-ID-check failure remains in the record.
The earlier OS Error 3 was traced to the development host’s AppData redirection, and actual file-location checks were added. Broader launcher compatibility, the installer, and clean-system acceptance are unfinished. This is the main Windows implementation plan, replacing the earlier default manager-ffi approach.
2026-10-02 implementation update: WinUI is now the only Manager. At the user’s request, the Dioxus application, Rust manager-core, Dioxus Native E2E and old UI release chain have been removed. Their historical source remains available at ca6a09e. This supersedes the original staged-retirement decision; it does not change the September measurements or complete the remaining Windows acceptance gates. Mainline integration still delivers a preview, not a stable release. Current priorities are in the roadmap.
1. Return to the original problem
Section titled “1. Return to the original problem”Let Windows players launch translated games or custom launchers through Steam, keeping Steam play status and playtime aligned with the actual game lifecycle as far as possible. Configure once; normally just click Play in Steam.
The requirements below come from repository history, not speculation about unavailable earlier conversations:
| Repository material | Confirmed requirement |
|---|---|
f95770b:README.md (historical v1 baseline) |
A Windows utility for Steam playtime with translated/custom-launcher galgames |
6cb8835:README.md (first v2 design) |
Configure once; separate Manager/Runner; Windows first; no player-installed .NET Runtime, no default SteamEdit requirement, and no full wrapper copied into every game |
e244269:docs/architecture.md |
Steam Launch Options calls an independent Runner; read configuration by AppID; no injection, client modification, DRM bypass, or persistent service |
c871c21:docs/roadmap.md |
Basic Windows flow → safe Windows one-click apply → Windows compatibility, with Linux/SteamOS in later major versions |
bf8929a:docs/distribution.md |
Per-user installer for ordinary players; stable user-directory Runner; portable as an alternative |
The later d0ae626:docs/roadmap.md moved Linux/SteamOS/Proton earlier and one-click apply/Windows distribution later. That was a change in delivery order, not evidence that cross-platform support was always a prerequisite for the first Windows release. C#, Rust, egui, Tauri, and Dioxus appeared at different points in the technical history; using one language was not an original product requirement.
Here, “no .NET Runtime installation” means players need no manual runtime preparation. A self-contained C# installer can meet that experience goal, but it must be verified on a clean system, not inferred from project properties. Initially target supported Windows 11 x64; do not yet promise Windows 10 or ARM64. This is an implementation choice, not a claim that the original requirements prohibited other systems.
2. Product scope and player flow
Section titled “2. Product scope and player flow”Manager is a configuration tool. Its home page centers on configured games and adding a game; a complete library browser or cross-platform distribution platform must not drive the first version’s scope.
- Install and open Manager; check configuration and bundled Runner. If Runner is unavailable, configuration remains viewable/editable and the relevant error is shown near the action.
- Add a game: discover local Steam and installed games, with search. Allow manual selection of custom Steam installations and preserve other results if part of a library is unreadable. A manually created Steam profile requires an explicit AppID.
- Show the read-only Steam installation path separately from the selected runtime folder and translated exe/launcher. The runtime folder may be outside the Steam library and must not be overwritten by scanning. Arguments, working directory, and wait mode belong in advanced settings, with existing values fully preserved. See directory separation for official installations, translated copies, saves, and achievements.
- Save configuration and generate exact Launch Options after confirming stable Runner is available, then paste them into Steam Properties. Tell players to preserve the old options first and explain restoration. Successful copying means copied only.
- Close Manager, launch and exit the game from Steam, and return to that game’s error/log location if something goes wrong.
Distinguish configuration saved, Launch Options copied, applied to Steam (only after future writes and verification), and manually validated launch. Button clicks, TOML saves, or Runner exit codes do not establish correct Steam playtime.
WinUI covers are local-first and offline by default: custom Steam art takes priority over local library-cache images, including hashed filenames and nested hash directories. An explicit, reversible preference enables official Steam CDN fallback for missing art on locally discovered AppIDs, with bounded requests and a small SteamWrapper cache. Missing, unreadable or unavailable images leave friendly placeholders and never affect saving or launch. See cover settings and the remaining P0 acceptance gates. Supported system language by default with English fallback and complete Simplified Chinese support, keyboard use, native file selection, scaling, and recoverable errors remain basic experience requirements.
Account login, online game metadata, general mod management, multiple-target switching, persistent tray operation, background update services, a new Linux/SteamOS GUI, Proton, and store distribution are out of scope for now. Steam Overlay, achievements, and every third-party launcher’s compatibility are not default promises.
3. Technical decisions
Section titled “3. Technical decisions”Use a C#/XAML WinUI 3 Manager + independent Rust Runner. WinUI is the sole Manager implementation. Implement its Windows configuration services in C#, using existing files to work with Runner:
WinUI 3 Manager Views / ViewModels ↓ C# application services: configuration read/edit/write, Steam discovery, Launch Options, Runner installation, logs ↓ %LOCALAPPDATA%\SteamWrapper\profiles.toml %LOCALAPPDATA%\SteamWrapper\bin\SteamWrapperRunner.exe
Steam → existing Launch Options → Rust Runner → read profile → launch/wait for targetManager need not call Runner’s internal functions. TOML, CLI, and stable paths already form a persistent boundary. Adding a C ABI would introduce DLL architecture, string/buffer ownership, error/panic propagation, and release synchronization. There is no current requirement for a second new GUI, so manager-ffi is not selected. Implementing configuration in two languages still costs maintenance; the compatibility checks below are a prerequisite. Microsoft native interop guidance
An all-C# Runner with NativeAOT is also viable and need not depend on preinstalled .NET, but it would simultaneously require reimplementing Job Objects, suspended launch, and process regressions. Retain Rust Runner first rather than coupling UI migration with a lifecycle rewrite. Do not infer startup speed, memory, or package size from language without measurements. Official NativeAOT documentation
Established directories:
apps/manager-winui/ SteamWrapper.Manager/ # WinUI window, ViewModel, platform wiring SteamWrapper.Application/ # independently testable configuration/file services SteamWrapper.Application.Tests/tests/contracts/ # redacted shared C#/Rust config and process fixturesServices expose a small set of named operations; file and scan work is cancellable and does not block UI. Do not add generic RPC, background helpers, a DI plugin platform, or multiple transport-DTO layers. C# models implement the existing protocol rather than creating a second configuration format.
crates/core and the independent Rust Runner retain their protocol and process responsibilities; Windows configuration services live in C#. The former Dioxus app, Rust management layer and UI release workflow are historical references. They were removed on 2026-10-02, rather than retained as a second Manager or future retirement task. The C#/Rust file-contract checks remain necessary.
4. Configuration fidelity is the first gate
Section titled “4. Configuration fidelity is the first gate”These contracts remain unchanged: v2 profiles.toml format, fields, and enum meanings; Windows %LOCALAPPDATA%\SteamWrapper\; Runner bin\SteamWrapperRunner.exe; and the CLI:
"<stable-runner-path>" --appid "<appid>" -- %command%Two behaviors in the historical management/configuration code at ca6a09e motivated the requirements below. They are not descriptions of the current C# configuration service:
- Manager saving reconstructed Profile, resetting
args,working_dir,wait_mode, andprocess_name. Changing a target path must not discard those settings. - Configuration saving called
fs::writedirectly, without atomic replacement or editing-conflict checks. Atomic Runner installation does not make profile saving safe.
The C# configuration service must continue to satisfy:
| Area | Required preserved or verified meaning |
|---|---|
| Read/edit/write | Change edited fields only; retain other profiles, non-Windows entries, and unknown keys. Block and explain writes when the library cannot preserve them safely. Do not downgrade unknown format versions |
| Defaults | Omitted legacy wait_mode currently means root; only new Windows profiles explicitly write job. Interpret omitted args, working_dir, and other fields as the current Rust parser does |
| Identity | Profile table key and app_id are different fields. Preserve legacy alias keys. New Steam profiles use an explicit AppID; do not guess associations or renumber ambiguous entries |
| Paths/arguments | Chinese, spaces, quotes, backslashes, argument arrays, and relative paths. Resolve target/working_dir against game_dir; do not turn an argument array into a new command-line format |
| Write safety | Same-directory temporary files, flushing, backup, and atomic replacement; preserve old files on failure. Prevent cooperating app writers and report external changes after reading, without claiming all external editors can be locked |
| Real consumption | C# TOML is checked for complete semantics by the existing Rust parser, then drives a controlled Runner to verify argv/cwd/waiting. Editing one field of a historical Rust fixture in C# must preserve unedited meaning |
The original TOML-library selection criterion was this roundtrip experiment, rather than an unverified package choice. It remains a regression requirement: cover omitted values, all existing wait modes, alias keys, unknown fields/versions, interrupted writes, and competing writers. Comparing a few text files or showing that both sides parse is insufficient.
5. Runner and Steam acceptance
Section titled “5. Runner and Steam acceptance”Current Runner launches the profile’s target and args. It receives/logs steam_command, without executing or automatically appending it. Keeping %command% is a compatibility contract, not implemented original-command forwarding. Migration must not also launch the original executable, automatically fall back to the official game, or change argument semantics.
New Windows profiles default to job. Real tests must cover launcher-first exit, later child exit, launch failure, Chinese/spaced paths, argv/cwd, Runner error exit, and logs. root waits only for the direct child. process_name is an explicit compatibility choice, not proof that a same-name process belongs to the game.
The local Episode 1 CHS launcher-first scenario passed: after the launcher exited at 14:15:55, the actual game and Runner continued for about 2 minutes 21 seconds until ordinary exit at 14:18:15; Steam playtime changed from 36 to 38 minutes. UI confirmed job, independent process observations had no sampling or metadata failures, and no processes remained. This does not directly establish Job membership or guarantee arbitrary launchers. The current Windows implementation returns the launcher’s status after Job completion; CHS/Runner exit 0 in this log is not the actual game’s exit 0.
Job Objects do not cover arbitrary escape behavior. Child membership depends on creation, breakaway, and parent-job conditions. General completion-port notifications cannot be treated as universally guaranteed delivery. Query and verify actual process state for exceptional cases rather than declaring correctness from API use alone. Windows Job Objects
Routine automation uses isolated Steam/user directories and controlled processes. Release acceptance separately records real Windows Steam launches with Manager closed, Steam showing running during play and ending afterward, client playtime updates, and game/launcher/system versions. Agent operation on a real library requires explicit user authorization; this session’s user authorized real galgame tests on condition that game files remain undamaged. Record old Launch Options and check files before testing, restore options and recheck afterward, and do not resolve ambiguous save/cloud conflicts. Without real evidence, report only the lifecycle behavior established by fixtures.
6. Safe one-click apply and restore
Section titled “6. Safe one-click apply and restore”The Windows preview supports manually copied Launch Options. One-click apply/restore remains planned P4 work, after the P0 configuration and P1/P2 delivery safeguards, and before new cross-platform scope. It does not depend on the optional P3 updater. Establish and verify safe writes before considering them the default flow.
Do not treat Steam’s private local files as a stable public write API. Recheck actual structures before implementation and verify parsing/unrelated-data preservation using redacted fixtures. The flow must:
- Identify the game and Steam user. Let the player choose among multiple users rather than writing every account.
- Detect running Steam and ask the player to exit it; check again before writing without automatically terminating Steam.
- Preview old/new values; back up options, relevant files, and recovery identifiers; check for changes immediately before writing.
- Edit only the target value, write atomically, read back, and record completed/interrupted state. Leave the original untouched on parse, backup, or conflict failure.
- Automatically restore only when the current value still matches this tool’s written value. Preserve and explain later external changes. Never overwrite later changes to other games using a whole old backup.
The manual-copy stage must not claim automatic old-value backup or one-click restore. Existing launch parameters may matter to the game; do not silently discard them or append them to the new profile. Preview and migration guidance should let the player handle them explicitly.
7. Installation, updates, and uninstall
Section titled “7. Installation, updates, and uninstall”The P1 delivery target is an unpackaged self-contained per-user installer and portable ZIP sharing one application layout, bundling both .NET and Windows App SDK. Ordinary players should not install development tools or runtimes. Runner remains an independent Rust EXE; no single-file EXE is promised. Local publishing is available, but the installer and clean-system delivery gate remain unfinished. Official self-contained deployment
Install app files under %LOCALAPPDATA%\Programs\SteamWrapper\; verify bundled Runner before installing it to stable bin. Ensure installation succeeds during first configuration, while keeping ordinary UI access usable on installation failure. If Runner is busy, preserve the old file, configuration, and valid options, allowing a retry after play. Updates must not let an old Manager arbitrarily downgrade installed Runner. Define release metadata and compatibility handling; a different hash alone is not proof that an upgrade is valid.
Manager uninstall preserves profiles, logs, backups, and stable Runner by default so remaining Launch Options still work. Fully removing Runner first requires handling managed Steam options. If manually pasted or unenumerable references cannot be confirmed removed, retain Runner and provide cleanup guidance. Preserving configuration does not make deleting Runner safe.
Every candidate installer and portable package needs clean Windows 11 x64 VM tests for installation, configuration, launch after closing Manager, in-place update, relocation and uninstall/preservation as applicable. Record package size, cold startup, and idle memory before optimizing. Assess MSIX, ARM64, and Windows 10 separately.
P2 now has version-tag automation for unsigned portable prereleases, checksums, complete English/Simplified Chinese notes and an optional CNB binary mirror. Actual tagged download verification, signing and stable delivery acceptance remain open; see distribution. P3 will add optional application updates only after the replacement/recovery and release-trust gates pass. Updates must remain outside Runner’s daily launch path and preserve user data and a usable stable Runner.
8. Implementation order and stop conditions
Section titled “8. Implementation order and stop conditions”The following A–D stages preserve the original 2026-09-08 acceptance framework. They are requirements, not a claim that every stage has passed; the roadmap separates completed evidence from remaining P0–P4 work. The original E retirement condition was superseded by the explicit 2026-10-02 removal decision.
| Stage | Completion condition |
|---|---|
| A. Toolchain/contracts | Pin .NET / Windows App SDK / Windows SDK / Rust MSVC; runnable Windows Runner baseline; passing C#↔Rust fidelity and controlled-process checks; viable lossless writes |
| B. WinUI configuration slice | Select fixture games/targets in a native window, preserve configuration, install stable Runner, and copy exact options; recover from cancellation/missing directories/unwritable or busy files; usable keyboard/Chinese input/scaling |
| C. Usable Windows preview | Real Windows/Steam launch records; clean-VM self-contained installation, updates, Manager relocation, and uninstall preservation; documentation of manual restore and known compatibility |
| D. Safe apply/stabilization | Pass multiple-user, Steam-running, backup, conflict, interruption, and single-game restore checks; expand real launcher testing; then consider default one-click apply |
| E. Original cleanup decision (superseded) | The original design deferred replacing the default Manager/CI and retiring Dioxus until C. The user directed removal on 2026-10-02; unfinished delivery gates remain open. Consider new platform scope only after Windows stabilization |
The original implementation order began with the A→B configuration/controlled-launch slice and incremental Windows build/contract CI. Its decision to retain the old UI workflows is now superseded. Current work proceeds through P0 native WinUI UI automation, broader player feedback and explicitly optional local-first covers; P1 installer/portable acceptance; P2 tagged releases; P3 optional updates; and P4 safe Steam writes. P0 feedback and P1 preparation can overlap, and P4 does not depend on P3. A polished UI or removal of an old implementation does not establish a stable release when configuration, lifecycle or delivery gates remain incomplete. mise is optional; see Windows development for SDK requirements, direct commands and scoped validation records.