fix(setup): recover incomplete self-contained Builder runtimes #2449

Merged
Arkex-ai merged 5 commits from fix/windows-runtime-recovery into main 2026-11-11 22:22:51 +00:00
Arkex-ai commented 2026-11-11 19:39:11 +00:00 (Migrated from github.com)

Summary

Windows setup can accept a Builder executable and installed marker even when its private .NET runtime is missing. Incomplete installations now enter recovery, and incomplete staging stops before publication. The diagnostic keeps the affected paths and possible antivirus quarantine cause so retrying setup is actionable; the original cause in #2423 remains unconfirmed.

Technical changes

  • Use one startup-file check before installed reuse, staged publication and fast launch; reject missing/empty components and directories in place of files.
  • Preserve the accepted portable-home paths and rollback publication from #2367. Restore the quarantine/history hint, executable path and staging folder in the failure message.
  • Execute the actual recovery and portable-startup boundaries with authored files, including missing-runtime refusal followed by recovery. Keep checked downloads, explicit repair and the direct-game fallback.

Validation

Head 66f5ba8d8c89ba14330f8fbf118ff0d9b7ff5f47, rebased on main 6f4f28ac.

  • 56 real-Win32 file cases pass. Three independently removed entry guards are rejected by causal regressions; 14 portable-startup scenarios pass, including a missing runtime that cannot start a process and a restored runtime that can.
  • The complete Windows setup compiles and links with llvm-mingw. The refreshed native diagnostic below uses the actual readiness guard and message function with fictitious paths; no installation or game is involved.
  • Full Windows suite: 408 / 2 / 32 versus exact base 406 / 2 / 32 (passed / failed / skipped). Failing check and case identities match: NUP link tests and the VRAM-row fixture. The earlier portable fixture integration failure was corrected before this run. This is not an all-green local suite.
  • Current-head hosted CI is pending. Current Linux GPU/game, complete repair on the rebased source and the reporter's installation history are not validated. This checks the directory-based WPF startup contract, not every optional assembly or installed-file checksum.

Controlled incomplete-runtime diagnostic

Earlier-head validation

On 4171896d, all applicable hosted checks passed. A disposable controlled installation with EXE/marker present and coreclr.dll missing recovered through actual downloads, verified/unpacked pinned official v2.1.0, and ran its private .NET8.0.33 managed CLI help with exit0; original source files stayed unchanged. This was not the reporter's unconfirmed missing-file cause or a full game test, and has not been repeated on the rebased head.

Full suites on dead3fcd versus base 3e95ca68: Windows378/3/31 versus376/3/31; Linux385/2/25 versus385/2/23, with matching failing check identities. These are historical results, not checks of the current head.

Current-head workflow Result
Game-free source regressions Queued
Linux AppImage Running
PR title Queued
Windows builder Queued
## Summary Windows setup can accept a Builder executable and installed marker even when its private .NET runtime is missing. Incomplete installations now enter recovery, and incomplete staging stops before publication. The diagnostic keeps the affected paths and possible antivirus quarantine cause so retrying setup is actionable; the original cause in #2423 remains unconfirmed. ## Technical changes - Use one startup-file check before installed reuse, staged publication and fast launch; reject missing/empty components and directories in place of files. - Preserve the accepted portable-home paths and rollback publication from #2367. Restore the quarantine/history hint, executable path and staging folder in the failure message. - Execute the actual recovery and portable-startup boundaries with authored files, including missing-runtime refusal followed by recovery. Keep checked downloads, explicit repair and the direct-game fallback. ## Validation Head `66f5ba8d8c89ba14330f8fbf118ff0d9b7ff5f47`, rebased on main `6f4f28ac`. - 56 real-Win32 file cases pass. Three independently removed entry guards are rejected by causal regressions; 14 portable-startup scenarios pass, including a missing runtime that cannot start a process and a restored runtime that can. - The complete Windows setup compiles and links with llvm-mingw. The refreshed native diagnostic below uses the actual readiness guard and message function with fictitious paths; no installation or game is involved. - Full Windows suite: **408 / 2 / 32** versus exact base **406 / 2 / 32** (passed / failed / skipped). Failing check and case identities match: NUP link tests and the VRAM-row fixture. The earlier portable fixture integration failure was corrected before this run. This is not an all-green local suite. - Current-head hosted CI is pending. Current Linux GPU/game, complete repair on the rebased source and the reporter's installation history are not validated. This checks the directory-based WPF startup contract, not every optional assembly or installed-file checksum. ![Controlled incomplete-runtime diagnostic](https://raw.githubusercontent.com/Arkex-ai/Hookshot/66f5ba8d8c89ba14330f8fbf118ff0d9b7ff5f47/docs/images/setup-runtime-incomplete.png) <details><summary>Earlier-head validation</summary> On `4171896d`, all applicable hosted checks passed. A disposable controlled installation with EXE/marker present and coreclr.dll missing recovered through actual downloads, verified/unpacked pinned official v2.1.0, and ran its private .NET8.0.33 managed CLI help with exit0; original source files stayed unchanged. This was not the reporter's unconfirmed missing-file cause or a full game test, and has not been repeated on the rebased head. Full suites on `dead3fcd` versus base `3e95ca68`: Windows378/3/31 versus376/3/31; Linux385/2/25 versus385/2/23, with matching failing check identities. These are historical results, not checks of the current head. </details> <!-- pr-ci-status --> | Current-head workflow | Result | |---|---| | [Game-free source regressions](https://github.com/NotRexed/Hookshot/actions/runs/43108434405) | Queued | | [Linux AppImage](https://github.com/NotRexed/Hookshot/actions/runs/43108434577) | Running | | [PR title](https://github.com/NotRexed/Hookshot/actions/runs/43108448286) | Queued | | [Windows builder](https://github.com/NotRexed/Hookshot/actions/runs/43108434381) | Queued | <!-- /pr-ci-status -->
Joey-Magnus (Migrated from github.com) reviewed 2026-11-11 21:23:16 +00:00
Joey-Magnus (Migrated from github.com) left a comment

builder_ready (setup.c:529) checks the 12 startup files, which matches the csproj (SelfContained=true, PublishSingleFile=false), and it's used in all three places that matter. The tests are thorough.

One fix before merge: the new error after unpacking (setup.c:776) drops the old antivirus hint and the folder path. Defender quarantining files is a known cause (the "Wacatac" worklist row), and in that case "Run the setup again" just loops. Please put the hint and the path back.

`builder_ready` (`setup.c:529`) checks the 12 startup files, which matches the csproj (`SelfContained=true`, `PublishSingleFile=false`), and it's used in all three places that matter. The tests are thorough. One fix before merge: the new error after unpacking (`setup.c:776`) drops the old antivirus hint and the folder path. Defender quarantining files is a known cause (the "Wacatac" worklist row), and in that case "Run the setup again" just loops. Please put the hint and the path back.
Arkex-ai commented 2026-11-11 22:03:22 +00:00 (Migrated from github.com)

Restored the quarantine/history hint, affected executable and staging-folder paths, and refreshed the controlled native screenshot.

Rebased on 6f4f28ac, preserving #2367's portable-home paths and rollback publication. That integration also needed the portable startup fixture to include the production readiness helper and authored runtime files; its 14 scenarios now cover refusing an incomplete runtime and launching after restoration. The 56 file cases, three guard mutations and complete setup link pass. Full-suite comparison and current-head CI status are recorded in the updated description; the original reporter's cause remains unconfirmed.

Restored the quarantine/history hint, affected executable and staging-folder paths, and refreshed the controlled native screenshot. Rebased on `6f4f28ac`, preserving #2367's portable-home paths and rollback publication. That integration also needed the portable startup fixture to include the production readiness helper and authored runtime files; its 14 scenarios now cover refusing an incomplete runtime and launching after restoration. The 56 file cases, three guard mutations and complete setup link pass. Full-suite comparison and current-head CI status are recorded in the updated description; the original reporter's cause remains unconfirmed.
hckrman101 (Migrated from github.com) approved these changes 2026-11-11 22:17:28 +00:00
hckrman101 (Migrated from github.com) left a comment

Looks good. builder_ready is bounded correctly (path length checked before each copy, the EXE itself is checked at i=0, directories and zero-size files rejected) and it replaces the bare exists-check in all three places: installed reuse, the post-unpack gate before publish_install, and launch_installed. A missing runtime now falls through to recovery instead of launching a Builder that cannot start.

Joey-Magnus's point about the dropped antivirus hint and folder path is fixed: the new message names the staged exe, the staging folder and the quarantine/history check, and says nothing was published. The #2367 portable-home paths and rollback publication are untouched.

CI is green on this head (Python source checks on Linux and Windows, Windows builder package and setup, Windows Vulkan, AppImage). The PR body is upfront about what is not validated (reporter's real cause, Linux game, the 2 known local failures matching base).

Nit, no action needed: the 12-file list has to follow the csproj publish format; the comment says so, and the new tests would catch drift on the setup side but not a csproj change.

Looks good. `builder_ready` is bounded correctly (path length checked before each copy, the EXE itself is checked at i=0, directories and zero-size files rejected) and it replaces the bare exists-check in all three places: installed reuse, the post-unpack gate before `publish_install`, and `launch_installed`. A missing runtime now falls through to recovery instead of launching a Builder that cannot start. Joey-Magnus's point about the dropped antivirus hint and folder path is fixed: the new message names the staged exe, the staging folder and the quarantine/history check, and says nothing was published. The #2367 portable-home paths and rollback publication are untouched. CI is green on this head (Python source checks on Linux and Windows, Windows builder package and setup, Windows Vulkan, AppImage). The PR body is upfront about what is not validated (reporter's real cause, Linux game, the 2 known local failures matching base). Nit, no action needed: the 12-file list has to follow the csproj publish format; the comment says so, and the new tests would catch drift on the setup side but not a csproj change.
Commenting is not possible because the repository is archived.
No description provided.