perf(desktop): run packaged WSL backend from Linux filesystem - #5042
perf(desktop): run packaged WSL backend from Linux filesystem#5042ReyJ94 wants to merge 10 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR adds a new WSL runtime staging system that extracts the backend to Linux's native filesystem on first launch for performance. The changes introduce significant new shell scripting, content-addressed caching, archive extraction, and lock-based synchronization - a substantial new capability warranting human review. You can customize Macroscope's approvability policy. Learn more. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6b236d2. Configure here.
6b236d2 to
04816f8
Compare
|
I found a correctness race in the mutable The I reproduced this on Ubuntu/WSL with the PR's actual generated The sequential form is deterministic too: after A stages and returns The desktop single-instance lock reduces how often this can happen, but it doesn't make the staging helper's cross-process/version contract safe for relaunch/update or side-by-side builds. Could you make the returned runtime root content-addressed by version/arch/archive hash (and prune old roots separately) rather than returning a mutable |
Generated-by: GPT-5.6 Sol
Generated-by: GPT-5.6 Sol
|
Sol here — I reproduced the mutable- The prepared runtime root is now content-addressed as I deliberately did not add eager "current + previous" pruning here. This staging boundary has no lease/liveness information for already-running backends, so pruning another hash could recreate the same lazy-load failure under a different policy. Cleanup should be a separate lease-aware or age-based owner rather than part of promotion. I added deterministic sequential and concurrent distinct-archive regressions, and retained the same-hash concurrency coverage. The focused affected suites pass: 98/98, with targeted format/lint plus desktop and scripts typechecks also passing. The related Windows packaging footgun raised on #5769 is separately fixed in — GPT-5.6 Sol (coding agent, posting through @ReyJ94's account) |
CDVolvik
left a comment
There was a problem hiding this comment.
Re-verified on Linux (WSL2 Ubuntu, Node 24) against current main.
Branch as submitted, the two desktop suites this touches:
Test Files 2 passed (2)
Tests 65 passed (65)
The question I could not answer on an earlier pass was whether these tests actually pin the new behaviour or just happen to pass. They do. Swapping only DesktopBackendConfiguration.ts and DesktopWslEnvironment.ts for the current main copies, keeping this PR's tests:
× resolveWsl pins a default-tracking run to the concrete default distro
AssertionError: expected [ 'Ubuntu', 'Ubuntu' ] to deeply equal [ 'Ubuntu', 'Ubuntu', 'Ubuntu' ]
× resolveWsl falls back to the mounted runtime when native staging fails
AssertionError: expected [ Array(1) ] to deeply equal [ '/mnt/c/t3code' ]
× resolveWsl preserves inherited PATH with quote-sensitive values as separate args
Three targeted assertion failures, each naming the behaviour it lost, rather than the whole file failing to load. That distinction matters here because an import-level failure would prove only that the module changed shape, not that anything is covered. These are real assertions on real behaviour, including the /mnt/c fallback path, which is the one worth having pinned given what the PR is for.
Related, since the threads are drifting apart: #6129 raises DEFAULT_BACKEND_READINESS_TIMEOUT from 1 to 3 minutes to absorb a WSL backend on /mnt/c taking 60-98s to answer. This PR and #5769 both remove that cost rather than budget for it. Whichever way maintainers want to go, it is worth deciding deliberately, because landing the timeout bump and then landing this leaves a tripled global readiness timeout with no remaining justification and nothing to prompt putting it back.
|
Closing this as superseded by #6169 and the bundled server topology now on I benchmarked the current materialized server payload in WSL (1,223 files) from both ext4 and The cache-race and missing-prebuild findings on this branch were real, but after #6169 this architecture is no longer the right direction. — GPT-5.6 Sol (coding agent, posting through @ReyJ94's account) |

What this fixes
On Windows, T3 Code currently runs its WSL server from the Windows install folder. Starting the
server makes WSL read thousands of small files through
/mnt/c, which can take longer than the60-second startup limit. This is the cause of the slow starts reported in #4535.
How it works
The Windows build now includes one compressed copy of the server and a checksum. On the first WSL
start, T3 Code verifies that file and unpacks it into WSL's Linux filesystem. Later starts reuse the
same immutable
sha256-<archive hash>root without reading the Windows install again. Differentapp versions can remain live side by side without one launch replacing or deleting another's files.
The cache serializes concurrent starts of the same archive, stages into a temporary directory, and
atomically promotes only a complete tree. If the archive is missing, damaged, or cannot be unpacked,
T3 Code logs a warning and uses the existing Windows-mounted runtime instead, so WSL still starts.
Windows artifact builds now fail if the Linux
node-ptyprebuild was not supplied, rather thanemitting an installer whose WSL backend cannot start.
The WSL script runner also keeps login-profile setup while preventing
.bash_logoutfrom changingthe script's real exit code.
Fixes #4535.
Verification
concurrent same-archive starts, and concurrent distinct archives are covered with real shell and
tar execution
less than 0.01s warm for fix(desktop): Cache Runtime locally on WSL Filesystem, dramatically improving launch times #5769; the extra cold time here is the full archive SHA-256 verification
Attribution
The scripted WSL shell transport (
bash -l -c "exec bash -s") and its.bash_logoutregressioncoverage were also developed in ReyJ94/t3code#3 by
@playb0t. That stacked work was submitted before the equivalent changes landed here; credit and
provenance are preserved through this link.
Generated with GPT-5.6 Sol using Codex in T3 Code.
Note
Run packaged WSL backend from the Linux native filesystem on first launch
stageWslRuntimeArchivein build-desktop-artifact.ts.runWslPreflightin DesktopBackendConfiguration.ts callspreparePackagedRuntimeto extract the archive into the distro's native Linux filesystem, caching it across launches and refreshing on update.flockfor serialization, validates the SHA-256, atomically promotes the extracted tree, and short-circuits on cache hits to avoid touching the Windows mount.ensureNodePtynow accepts alinuxRepoRootdirectly instead of a Windows path, removing an internalwindowsToWslPathconversion.Macroscope summarized b4e9621.
Note
Medium Risk
Touches packaged WSL startup, artifact layout, and preflight fallbacks; mitigated by mount fallback, content-addressed cache, and broad shell/integration tests, but regressions could still affect Windows WSL-only users or CI Windows builds.
Overview
Packaged Windows WSL starts now prefer a Linux-native copy of the server instead of reading thousands of files through
/mnt/c. The installer shipswsl-runtime.tar.gzplus a SHA-256 sidecar; WSL preflight calls newpreparePackagedRuntimeto verify, extract, and cache under an immutablesha256-<hash>root, then launchesnodefrom that tree.Happy-path behavior: cache hits skip the Windows mount; concurrent first starts serialize with
flockand double-check the cache; dev checkouts still use the repo root viawindowsToWslPath. If staging fails (bad/missing archive, tools missing, etc.), preflight logs a warning and falls back to the existing Windows-mountedapp.asar.unpackedlayout so WSL can still start.Build/packaging: Windows artifacts run
stageWslRuntimeArchiveduring staging, ship the archive viaextraResources(excluded from the ASAR), and fail the build when--wsl-prebuildis missing instead of emitting a broken WSL installer. Shared@t3tools/shared/wslRuntimeArchivecentralizes filenames and hash parsing.WSL shell transport: scripts run as
bash -l -c "exec bash -s"so login profile state is kept while~/.bash_logoutcannot mask the real exit code.ensureNodePtynow takes alinuxRepoRootdirectly rather than converting a Windows repo path inside the WSL layer.Reviewed by Cursor Bugbot for commit b4e9621. Bugbot is set up for automated code reviews on this repo. Configure here.