You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(wsl-host): a terminal on a stopped distro offers Start, and New Terminal starts it - #35168
Flag-off: Only WSL hosts are affected, so nothing changes with the experimental WSL host setting off. The new card and the start-before-New-Terminal step only act when a WSL host's last status is "distro stopped". SSH servers, paired servers and local workspaces never reach them. User-risk: WSL host users only. Clicking Start on a pane, or opening a New Terminal, now boots a stopped distro, the same as the chat's Start. Nothing automatic boots it. A host whose Remove is still pending refuses with the existing "removal pending" message rather than starting.
ELI5
If you stop a WSL distro (for example with wsl --terminate Ubuntu), its terminals in Orca used to say "Reconnecting… retrying automatically" forever, and New Terminal didn't help. Orca correctly never starts a stopped distro by itself, but that left no way back. Now the terminal says "Ubuntu is stopped" with a Start button, and opening a New Terminal on that project starts the distro too.
What Changed
Before:
After the distro stopped, every terminal on it showed the server-wide "Reconnecting to Ubuntu (WSL)… Down for N min… retrying automatically" notice indefinitely.
New Terminal on the project failed with "Ubuntu was stopped…".
Only Settings → Remote Orca Servers → Connect, or switching away from the project and back, brought it back.
Start boots the distro, reconnects the host and resumes the pane.
New Terminal (tab bar, the tab group's "+" menu, Cmd+J's New Terminal, "Open in terminal" from the file explorer, and the "new terminal with this shell" option) starts a stopped host first, then opens the terminal.
Background retries still never boot the distro.
Mechanism
Shared start helper:src/renderer/src/lib/wsl-host-user-start.ts holds the Start that the chat used privately. wsl-host-stopped-status.ts holds the store selector the panes read. The reconnect helper is loaded lazily, so terminal creation's module graph doesn't grow.
It calls wslHosts.connect({ environmentId, withdrawPendingRemoval: false }) (the user-mode connect that may boot), then reconnects the host and reloads its projects.
Repeated clicks while it boots share one start.
The chat's Start now uses this helper.
Pane card:TerminalPaneRecoveryPortals reads the host's WSL status. When the workspace's host is a stopped distro, each pane on it gets the new WslHostStoppedCard in place of the reconnect banner, and the server-wide "retrying automatically" notice stays silent.
The card shows whether or not the pane is mid-recovery, because a stopped distro's terminal is dead either way.
It also shows on a pane whose create failed before it reached the host.
It stays behind the existing "WSL hosts are turned off" card, which takes precedence.
Where the card shows, the pane's raw "Ubuntu was stopped…" error toast is hidden (use-wsl-host-stopped-pane.ts, using the same paneShowsWslHostStoppedCard condition as the card), as it already is for SSH recovery. Otherwise the toast sat over the Start button. A pane on another server, or a host that can't run, keeps its real error.
New Terminal:createWebRuntimeSessionTerminal takes a userAct option. It's a client-side option and never goes over the wire.
With it set, a stopped WSL host is started before the create. If the start is refused, nothing is created and the user sees why.
Only the explicit New Terminal paths pass it. The initial-terminal bootstrap, session-tab sync and wake-time terminal creation don't, so they can't boot a distro.
Main is unchanged: runtime calls still go through ensureForRuntimeCall, which never boots.
Why
Renderer-side, at the user's act. Main can't tell a user's create from a background one, because both are the same runtime call. Marking the act where the click happens keeps E9 intact, with no "maybe boot" path in main.
A per-pane card rather than changing the server notice. It mirrors how the existing "WSL hosts are turned off" card already replaces the reconnect UI for a host that can't run, and it needs no new strings.
Linked Issue
Internal WSL rewrite: flag-on blocker from the Windows real-host check.
Visual Proof
From the e2e run below (hidden window, CDP screenshot): the terminal pane on a stopped distro shows "Ubuntu is stopped" with a Start button at the bottom of the pane. I kept the screenshots out of the PR because the terminal prompt shows the test machine's hostname.
Testing
wsl-host-terminal-start.spec.ts (new e2e, fake WSL transport; hidden; passed 4 times locally, about 1 min each):
New Terminal on a running host opens a terminal.
After the distro stops, the pane shows the stopped card. For 10 s the fake records no boot, and the distro stays stopped.
Start boots it and the card goes away.
Stopping again, then New Terminal, boots the distro and opens another terminal.
wsl-host-chat.spec.ts still passes. Its launch helpers moved to tests/e2e/helpers/wsl-host-fake-desktop.ts, as its own comment asked, and the new spec reuses them.
Unit tests:
WslHostStoppedCard.test.tsx: the card names the distro and offers Start, and showing it boots nothing. A click boots with withdrawPendingRemoval: false and then resumes the pane. A refused start toasts and leaves the pane. Repeated clicks start once.
TerminalPaneRecoveryPortals.test.tsx: every pane of a stopped distro gets the card, with no server notice and no reconnect banner. That includes a pane whose create failed before it knew its host.
a user's New Terminal starts the host before creating;
a background create never boots it;
running and non-WSL hosts are untouched;
a refused start creates nothing.
The broad renderer suites pass: terminal-pane, native-chat, runtime, store, tab-group, terminal and lib (2,532 files).
createNewTerminalTab tests moved to terminal-tab-create.test.ts (the module they test), because the old file hit the line cap. Expectations now include { userAct: true }.
Load rule: pnpm tc, typecheck:ci, oxlint, the anti-slop lint, oxfmt, check:code-quality:changed, and the five localization checks. No new strings.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.
Notes
SSH: the card and the start only apply to WSL hosts. A stopped status exists only for them; SSH servers keep their existing Reconnect and sign-in flows.
Windows: the real-host check should be re-run on a Windows machine: wsl --terminate, then Start, then New Terminal.
Mobile and paired web client: they keep their existing behaviour, because wslHosts is desktop-only and the helper does nothing without it.
Checklist
This PR is small and focused
I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
Before/after screenshots or videos attached for UI changes, or N/A with reason
Self-reviewed for correctness, security, and performance
Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.
Walkthrough
The changes add a stopped-WSL recovery card to terminal panes and add host startup before user-requested terminal creation. Shared startup helpers connect to the stopped host and reload its projects. Pane recovery suppresses the remote-outage notice and active-pane error toast for stopped hosts. Terminal-creation and pane-recovery tests cover these paths. Shared fake-WSL test helpers support a new end-to-end test and the existing WSL chat test.
Priority: Normal
Merge Risk: Moderate · previous review e274e
Some bridged panes may show the wrong recovery card, and two test checks can block CI. Address these before merging.
Pre-merge checks: 3 · 2
Failed checks: 2 warnings
Check name
Status
Explanation
Resolution
Description check
The description is detailed and covers the user impact, mechanism, rationale, testing, and scope. However, it does not provide an actual linked issue and does not attach the required visual proof or s…
Add the actual issue reference under Linked Issue. Attach before-and-after screenshots or a video, or write N/A with a brief reason if visual proof is genuinely not applicable. Update the testing and checklist items to reflect whether the…
Docstring Coverage
Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta…
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 3 passed
Check name
Status
Explanation
Title check
The title clearly and concisely describes the main user-facing WSL recovery changes: offering Start for stopped distros and starting them before New Terminal.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Description check
Explanation
The description is detailed and covers the user impact, mechanism, rationale, testing, and scope. However, it does not provide an actual linked issue and does not attach the required visual proof or state N/A exactly for this UI change. Several required validation checklist items also remain unchecked.
Resolution
Add the actual issue reference under Linked Issue. Attach before-and-after screenshots or a video, or write N/A with a brief reason if visual proof is genuinely not applicable. Update the testing and checklist items to reflect whether the required commands passed locally or will be covered by CI.
Full details: Docstring Coverage
Explanation
Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 17 functions across 24 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
Finishing Touches: 💡 2
📝 Generate docstrings: 💡
Commit to this branch
Create a new PR
🛠️ Fix failing CI checks: 💡
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.
Do not treat every null pane environment as the WSL owner.
legacy-relay-bridge-transport.ts returns null for an established bridge, not only for a failed create. The current condition maps that value to the owner’s WslHostStoppedCard, replacing the bridged pane’s reconnect banner. Distinguish the established bridge state from a create failure before showing the stopped-distro card.
The reason will be displayed to describe this comment to others. Learn more.
Major · Functional Correctness · Heavy lift
Suppress errors only for panes covered by the stopped-host card.
If the active pane belongs to another environment, a stopped WSL workspace owner still sets wslHostStopped. This condition then hides that pane's TerminalErrorToast, including its Retry or Close action, although the stopped-host card need not apply to the pane. Match the toast guard to the same pane eligibility used for the stopped-host card.
…can't land in the no-boot window
CI saw 2 extra fake connects right after the first stop. Instrumented runs traced
every boot after a stop to the Start flow's two calls (wslHosts:connect, then the
runtimeEnvironments connect, logged as a pair) and the renderer stack of the
second pair to openNewTerminalTabInActiveWorkspace. In CI the spec clicked New
Terminal, then waited only for the first .xterm. That was the auto-created
terminal, so it wrote the stop while its own New Terminal was still in flight.
That terminal then started the distro as the user act it is. No background path
booted anything.
The spec now runs the tab bar's New Terminal action and awaits it before the
stop. The no-boot assertion is unchanged.
The reason will be displayed to describe this comment to others. Learn more.
Start leaves the pane disconnected
When a pane fails to attach with “Ubuntu was stopped,” connectPane calls recovery.cancel() and leaves recovery idle. After booting the distro, this callback only calls retryRecovery(), which refuses an idle transport. The card disappears, but the pane still cannot accept input.
Add a retry path for this failed-attach state. Test that the pane accepts input after Start, not just that the card disappears.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Flag-off: Only WSL hosts are affected, so nothing changes with the experimental WSL host setting off. The new card and the start-before-New-Terminal step only act when a WSL host's last status is "distro stopped". SSH servers, paired servers and local workspaces never reach them.
User-risk: WSL host users only. Clicking Start on a pane, or opening a New Terminal, now boots a stopped distro, the same as the chat's Start. Nothing automatic boots it. A host whose Remove is still pending refuses with the existing "removal pending" message rather than starting.
ELI5
If you stop a WSL distro (for example with
wsl --terminate Ubuntu), its terminals in Orca used to say "Reconnecting… retrying automatically" forever, and New Terminal didn't help. Orca correctly never starts a stopped distro by itself, but that left no way back. Now the terminal says "Ubuntu is stopped" with a Start button, and opening a New Terminal on that project starts the distro too.What Changed
Mechanism
src/renderer/src/lib/wsl-host-user-start.tsholds the Start that the chat used privately.wsl-host-stopped-status.tsholds the store selector the panes read. The reconnect helper is loaded lazily, so terminal creation's module graph doesn't grow.wslHosts.connect({ environmentId, withdrawPendingRemoval: false })(the user-mode connect that may boot), then reconnects the host and reloads its projects.TerminalPaneRecoveryPortalsreads the host's WSL status. When the workspace's host is a stopped distro, each pane on it gets the newWslHostStoppedCardin place of the reconnect banner, and the server-wide "retrying automatically" notice stays silent.use-wsl-host-stopped-pane.ts, using the samepaneShowsWslHostStoppedCardcondition as the card), as it already is for SSH recovery. Otherwise the toast sat over the Start button. A pane on another server, or a host that can't run, keeps its real error.createWebRuntimeSessionTerminaltakes auserActoption. It's a client-side option and never goes over the wire.ensureForRuntimeCall, which never boots.Why
Linked Issue
Internal WSL rewrite: flag-on blocker from the Windows real-host check.
Visual Proof
From the e2e run below (hidden window, CDP screenshot): the terminal pane on a stopped distro shows "Ubuntu is stopped" with a Start button at the bottom of the pane. I kept the screenshots out of the PR because the terminal prompt shows the test machine's hostname.
Testing
wsl-host-terminal-start.spec.ts(new e2e, fake WSL transport; hidden; passed 4 times locally, about 1 min each):wsl-host-chat.spec.tsstill passes. Its launch helpers moved totests/e2e/helpers/wsl-host-fake-desktop.ts, as its own comment asked, and the new spec reuses them.Unit tests:
WslHostStoppedCard.test.tsx: the card names the distro and offers Start, and showing it boots nothing. A click boots withwithdrawPendingRemoval: falseand then resumes the pane. A refused start toasts and leaves the pane. Repeated clicks start once.TerminalPaneRecoveryPortals.test.tsx: every pane of a stopped distro gets the card, with no server notice and no reconnect banner. That includes a pane whose create failed before it knew its host.web-runtime-terminal-creation.wsl-host-start.test.ts:The broad renderer suites pass: terminal-pane, native-chat, runtime, store, tab-group, terminal and lib (2,532 files).
createNewTerminalTabtests moved toterminal-tab-create.test.ts(the module they test), because the old file hit the line cap. Expectations now include{ userAct: true }.Load rule:
pnpm tc,typecheck:ci, oxlint, the anti-slop lint, oxfmt,check:code-quality:changed, and the five localization checks. No new strings.I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
Notes
wsl --terminate, then Start, then New Terminal.wslHostsis desktop-only and the helper does nothing without it.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)