Skip to content

fix(wsl): scan agent sessions only in running distros - #17072

Merged
nwparker merged 7 commits into
mainfrom
fix/wsl-running-session-discovery
Aug 30, 2026
Merged

nwparker merged 7 commits into
mainfrom
fix/wsl-running-session-discovery

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Aug 28, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 14 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​834 $\color{#cf222e}{\Huge{\mathbf{−}}}$​63 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​771
Prod 16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​551 $\color{#cf222e}{\Huge{\mathbf{−}}}$​148 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​403

ELI5

Agent Session History currently asks every installed WSL distro for its home directory. Asking a stopped distro boots it. This change first asks WSL which distros are already running and only scans those, so a history refresh cannot start a sleeping VM.

What Changed

  • Discover session roots with wsl.exe --list --running --quiet instead of enumerating every installed distro.
  • Fail closed when running-distro discovery fails.
  • Share concurrent running-list probes and per-distro home probes.
  • Revalidate WSL membership for AI Vault, native-chat path translation, transcript watchers/fallback polling, managed Codex roots, cached UNC paths, and the WSL hook relay.
  • Discard stale watcher validation when a distro stops or a validation attempt fails.
  • Share one fresh running-distro snapshot across each transcript-resolution attempt to avoid 2-3 sequential list subprocesses.

No setting, renderer UI, IPC/RPC shape, or remote-wire behavior changes.

Why

getAiVaultWslHomeDirs() on current main calls wsl.exe -d <distro> ... echo $HOME for every installed distro. wsl.exe -d necessarily starts a stopped distro, so opening or refreshing Agent Session History can leave vmmemWSL resident even when the user was not using WSL.

The ownership boundary is WSL discovery, before any consumer can issue a distro-starting command. A default-on opt-out such as #16961 leaves users affected until they discover a setting and requires settings/UI/cache plumbing around the underlying behavior. Running-only discovery removes the side effect for every consumer while still showing sessions whenever the user has started that distro themselves.

This complements #15475, which gates scanner filesystem walks, and #16050, which adds WSL Codex usage lanes. This PR covers the earlier home/root discovery and native-chat/watch paths that can start a distro before a scanner walk.

The broader Windows freeze report in #16038 was investigated separately. A bounded current-main stress run did not establish WSL scanning as its cause, so this PR intentionally makes no broad-freeze claim or unrelated performance change.

Behavior Changes Not Covered Above

Two additional behavior changes ship with this PR that were not called out above:

  • WSL transcript live-tail now polls instead of watching. Native fs.watch is disabled entirely for WSL transcript paths — wsl-transcript-watcher-running-guard.ts returns a no-op watcher (bind always false) for any WSL UNC path. transcript-watch-engine.ts also skips the normal 1s reconciliation timer for WSL paths (if (!isWslPath) { scheduler.startReconciliation() }) and instead drives every re-read off the 2s running-distro poll in wsl-transcript-running-observer.ts. Net effect: live-tail latency for WSL-hosted transcripts goes from ~1s event-driven (native watch) to a strict 2s poll interval.
  • The Codex id-based fallback search is skipped when an authoritative WSL hook path fails, even on a running distro. In session-file-resolver.ts, when the hook-provided transcript_path needs WSL host resolution (needsWslHostResolution(hookPath)) and that resolution attempt fails or comes back empty, resolveSessionFilePath returns null or throws immediately — it does not fall through to resolveSessionFileById's id-based search. This applies even when the failure was a single transient timeout against a distro that is otherwise running, not just when the distro is genuinely stopped.

Neither change is gated by a setting.

Linked Issue

Fixes #16959

Related: #16038, #16961

Visual Proof

N/A — backend WSL discovery behavior only; there is no UI change.

Physical Windows before/after/revert oracle using an isolated distro:

Arm Before After Duration vmmem
Orca 1.4.144 Stopped Running 169 ms increased
current-main lineage Stopped Running 136-165 ms +33 MiB in the exact baseline run
candidate Stopped Stopped 124-125 ms unchanged
candidate with running-only gate reverted Stopped Running 152 ms increased

The cached-UNC watcher oracle also stayed stopped with the candidate and started the distro when its gate was reverted.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated

Windows validation:

  • 17 focused test files: 232 passed, 3 skipped.
  • pnpm tc: passed.
  • Direct oxlint on all 17 changed files: passed.
  • git diff --check: passed.
  • Physical isolated-distro baseline/candidate/revert matrix: candidate alone preserved Stopped.
  • Electron benchmark with 50 sessions x 32 KiB and 40 timed keys: zero missing echoes; parse p95 2.0 ms control / 1.7 ms during refresh; stopped distro stayed stopped.
  • Fresh adversarial review: clean.
  • Fresh performance review: clean (10 files / 74 tests; no P1/P2 or performance finding).

The check:code-quality:changed wrapper is not usable in this Node 24/Windows environment because its spawn pnpm.cmd/npx.cmd call fails with EINVAL; the underlying typecheck, changed-file oxlint, tests, and diff check were run directly.

Platforms exercised: physical Windows 11 + WSL2 and Electron on Windows. Non-Windows returns the existing no-WSL result. SSH, folder workspaces, and mixed-version clients do not cross this local discovery path or any changed wire contract.

Review

  • Security: fixed executable and argv; no shell interpolation or new input surface.
  • Cross-platform: win32-gated; macOS/Linux behavior unchanged.
  • SSH/remote: execution-host ownership is unchanged; no remote protocol changes.
  • Folder workspaces: no Git-worktree assumption added.
  • Performance: one uncached liveness snapshot per attempt, single-flighted across concurrent callers; home probes are single-flighted per distro.
  • Behavior tradeoff: sessions in a stopped distro remain absent until the user starts that distro.

Agent skill upstream boundary

  • Not applicable; no agent-skill installer source or registry content is involved.

Notes

The isolated test distro was unregistered after validation. Unrelated host distros were not started or modified.

Checklist

  • This PR is small and focused
  • I explained what changed and why (including ELI5)
  • 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
  • Focused tests, typecheck, changed-file lint, and an Electron build/run pass locally; CI will cover the full build and suite

@greptile-apps

greptile-apps Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR limits WSL session discovery and transcript access to running distributions so history refreshes do not start stopped WSL instances.

  • Adds shared running-distro discovery, caching, path filtering, and per-attempt resolution snapshots.
  • Applies running-state checks to AI Vault roots, native-chat transcript resolution, transcript polling, managed Codex roots, and the WSL hook relay.
  • Reworks WSL transcript live-tail behavior around running-state observation and polling.

Confidence Score: 4/5

The PR is not yet safe to merge because a failed WSL hook path can still prevent native chat from finding an existing Codex transcript by session ID.

The resolver returns or throws immediately after failed WSL hook-path resolution, even though its existing Codex ID resolver can search other host and running-WSL roots for the same session.

Files Needing Attention: src/main/native-chat/session-file-resolver.ts

Important Files Changed

Filename Overview
src/main/native-chat/session-file-resolver.ts Shares WSL snapshots across transcript resolution, but still short-circuits Codex ID fallback after a failed WSL hook path.
src/main/native-chat/host-readable-transcript-path.ts Adds running-distro snapshots and gates UNC, guest-path, and managed Codex-root resolution without making exact UNC checks await HOME probes.
src/main/native-chat/transcript-watch-engine.ts Replaces native WSL watching and reconciliation with running-state-driven polling while preserving non-WSL watcher behavior.
src/main/wsl-running-distro-cache.ts Centralizes and coalesces running-distribution discovery for concurrent WSL consumers.
src/main/ai-vault/cached-session-list.ts Restricts WSL and configured Codex scan roots to distributions reported as running.

Sequence Diagram

sequenceDiagram
  participant C as Native chat
  participant R as Session resolver
  participant W as WSL running-state discovery
  participant F as Transcript filesystem
  C->>R: Resolve hook path and session ID
  R->>W: List running distributions
  W-->>R: Shared running snapshot
  R->>F: Probe path only in running distribution
  alt Hook path readable
    F-->>R: Transcript path
    R-->>C: Install polling subscription
  else Hook path unavailable
    F-->>R: Missing or refusal
    R-->>C: Missing or unavailable result
  end
Loading

Reviews (7): Last reviewed commit: "fix(build): list the new WSL cache modul..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0b4d5fc6-2df2-4fa3-8080-71910be238c1

📥 Commits

Reviewing files that changed from the base of the PR and between 2256acb and 5ebe9ba.

📒 Files selected for processing (4)
  • src/main/native-chat/transcript-unavailable-snapshot.ts
  • src/main/native-chat/transcript-watch-engine-wsl-lifecycle.test.ts
  • src/main/native-chat/transcript-watch-engine.ts
  • src/main/native-chat/transcript-watch-error.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The change adds shared asynchronous discovery for running WSL distros and their home directories. WSL paths are filtered against active distros. AI Vault scanning uses active WSL homes. Transcript resolution shares runtime state across each resolve attempt. Transcript watchers observe distro state, guard reads and installs, and revalidate paths after distro changes. Tests cover discovery, filtering, observer behavior, snapshot handling, and watcher lifecycle.

Merge Risk: 🟡 Moderate · up to 5ebe9

The change prevents most WSL scans from starting stopped distros, but the running-state check is only a snapshot: if a distro stops between discovery and a later home, path, or watcher operation, that operation can still restart it. This creates a bounded lifecycle-control and resource-use risk that should be explicitly accepted or fixed before merge.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.93% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 54 functions across 28 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR addresses #16959's primary coding objective by preventing stopped WSL distributions from starting during session discovery. It replaces per-distro HOME probes with running-distro discovery, fai…
Out of Scope Changes check ✅ Passed The changes remain within the stated WSL session-discovery objective. Updates to native-chat resolution, transcript watchers, path filtering, caching, and the hook relay support running-distro validat…
Description check ✅ Passed The description is complete and follows the repository template. It explains the change and motivation, links issue #16959, documents behavior changes, provides visual-proof justification, records tes…
Title check ✅ Passed The title clearly identifies the main change: limiting WSL agent-session scanning to running distributions.
Full details: Linked Issues check

Explanation

The PR addresses #16959's primary coding objective by preventing stopped WSL distributions from starting during session discovery. It replaces per-distro HOME probes with running-distro discovery, fails closed, and applies running-distro filtering across the affected consumers. The issue's proposed opt-out setting is not implemented, but the PR explicitly uses a broader underlying-behavior solution.

Full details: Out of Scope Changes check

Explanation

The changes remain within the stated WSL session-discovery objective. Updates to native-chat resolution, transcript watchers, path filtering, caching, and the hook relay support running-distro validation described in the PR objectives. No unrelated UI, IPC, remote-wire, or settings changes are included.

Full details: Description check

Explanation

The description is complete and follows the repository template. It explains the change and motivation, links issue #16959, documents behavior changes, provides visual-proof justification, records testing and platform coverage, and completes the review and checklist sections.

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 550364c5-5478-4b01-9d3b-79a44b29db9e

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc09db and 59dd49d.

📒 Files selected for processing (17)
  • src/main/agent-hooks/wsl-hook-relay-launch.ts
  • src/main/ai-vault/cached-session-list.test.ts
  • src/main/ai-vault/cached-session-list.ts
  • src/main/ipc/ai-vault-scan-coalescing.test.ts
  • src/main/ipc/ai-vault.test.ts
  • src/main/native-chat/host-readable-transcript-path.test.ts
  • src/main/native-chat/host-readable-transcript-path.ts
  • src/main/native-chat/session-file-resolver-codex-roots.test.ts
  • src/main/native-chat/session-file-resolver-wsl-scan-gate.test.ts
  • src/main/native-chat/session-file-resolver-wsl.test.ts
  • src/main/native-chat/session-file-resolver.ts
  • src/main/native-chat/transcript-watch-resolve-poll.test.ts
  • src/main/native-chat/transcript-watch-wsl-exact-path.test.ts
  • src/main/native-chat/transcript-watch.ts
  • src/main/wsl-running-distros.test.ts
  • src/main/wsl-running-path-filter.ts
  • src/main/wsl.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/main/wsl.ts
Comment on lines +325 to +349
const probe = execFileUtf8('wsl.exe', ['-d', distro, '--exec', 'bash', '-c', 'echo $HOME'])
.then((output) => {
const home = output.trim()
if (!home || !home.startsWith('/')) {
return null
}
const uncPath = toWindowsWslPath(home, distro)
wslHomeCache.set(distro, uncPath)
return uncPath
})
.catch(() => null)
.finally(() => {
if (wslHomeProbeCache.get(distro) === probe) {
wslHomeProbeCache.delete(distro)
}
})
wslHomeProbeCache.set(distro, probe)
return probe
}

const uncPath = toWindowsWslPath(home, distro)
wslHomeCache.set(distro, uncPath)
return uncPath
} catch {
return null
}
/** UNC home roots for distros that are running at discovery time. */
export async function listRunningWslHomeDirsAsync(): Promise<string[]> {
const homes = await Promise.all(
(await listRunningWslDistrosAsync()).map((distro) => getWslHomeAsync(distro))
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Prevent the HOME probe from restarting a distro that stopped after discovery.

Line 348 invokes getWslHomeAsync after the running-list snapshot completes. If that distro stops in this interval, Line 325 runs wsl.exe -d <distro>, which starts it again. This reintroduces the stopped-distro side effect during vault scans and transcript snapshots.

Use a HOME discovery mechanism that cannot start WSL. A second running-list check does not close this TOCTOU gap. Add a regression test that terminates the distro after listing and before the queued HOME probe.

🧰 Tools
🪛 ast-grep (0.45.2)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile, execFileSync } from 'node:child_process'
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b9632b9-2019-4b1e-a75a-8d1581336b52

📥 Commits

Reviewing files that changed from the base of the PR and between bb7c924 and 8120482.

📒 Files selected for processing (16)
  • src/main/native-chat/host-readable-transcript-path.ts
  • src/main/native-chat/session-file-resolver-codex-roots.test.ts
  • src/main/native-chat/session-file-resolver-wsl-scan-gate.test.ts
  • src/main/native-chat/session-file-resolver.ts
  • src/main/native-chat/transcript-incremental-reader.ts
  • src/main/native-chat/transcript-watch-engine-wsl-lifecycle.test.ts
  • src/main/native-chat/transcript-watch-engine.ts
  • src/main/native-chat/transcript-watch-resolve-poll.test.ts
  • src/main/native-chat/transcript-watch-wsl-exact-path.test.ts
  • src/main/native-chat/transcript-watch-wsl-stall.test.ts
  • src/main/native-chat/transcript-watch.ts
  • src/main/native-chat/transcript-watcher-count.ts
  • src/main/native-chat/transcript-watcher-install-probe.ts
  • src/main/native-chat/wsl-transcript-running-observer.test.ts
  • src/main/native-chat/wsl-transcript-running-observer.ts
  • src/main/native-chat/wsl-transcript-watcher-running-guard.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment on lines +132 to +137
if (needsWslHostResolution(hookPath)) {
if (unavailable) {
throw unavailable
}
return null
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Guest path fallback is skipped

When a Codex hook reports a stale or unavailable WSL guest path while the transcript remains discoverable by session ID, this branch returns before resolveSessionFileById, causing native chat and transcript watching to miss an existing transcript.

Knowledge Base Used:

…discovery

listRunningWslDistrosAsync failed closed on any probe error (timeout, ENOENT,
wsl.exe hiccup), indistinguishable from "no distros running". A 2s poll
(wsl-transcript-running-observer.ts) calls it indefinitely while any WSL
transcript tab is open, so a persistently broken wsl.exe silently made every
WSL session vanish app-wide with no way to tell "discovery broken" from
"distro stopped", and re-spawned wsl.exe every 2s forever.

Extract a dedicated cache/backoff module (wsl-running-distro-cache.ts,
mirroring the sibling machinery already in wsl.ts for the full distro list)
so a probe failure falls back to the last-known-good running-distro list and
backs off further probes, while a genuine empty result (no distros running)
stays authoritative. Add a consumer-level test simulating a sustained wsl.exe
outage across a live transcript-watcher polling session, asserting the
observer keeps reporting "running" and that real wsl.exe spawns stay bounded.
nwparker added a commit that referenced this pull request Aug 30, 2026
A WSL probe that cannot reach its distro returns the same value as one
that asked and got "no". Downstream nothing can tell them apart, so a
distro that was busy for a second reports no git, or no agent sessions,
until relaunch — sticky, silent, and identical to the real thing.

That has shipped three times: preflight CLI probes, the glab auth
fallback (#8941), and listRunningWslDistrosAsync failing closed with no
last-known-good while polled every 2s (PR #17072).

Scan the WSL and preflight probe modules for the shape and hold the
current set in an allowlist that only shrinks. Scoped deliberately: the
same shape appears ~850 times across src/ and is usually correct,
because for most callers a failure really does mean absent. It is only
dangerous where the answer describes a distro.

The guard cannot see the dangerous part — whether the value is later
cached or gates discovery is dataflow, not syntax. It stops a new
swallow site appearing here without someone saying why it is safe to
pin, which is the review that was missing all three times.
config/tsconfig.tc.web.json enumerates its files explicitly, so a new
module imported by wsl.ts fails the full typecheck with TS6307 until it
is listed. pnpm tc:node passes without it, which is how this got missed.

  src/main/wsl.ts(13,8): error TS6307: File 'src/main/wsl-running-distro-cache.ts'
  is not listed within the file list of project 'config/tsconfig.tc.web.json'.
nwparker added a commit that referenced this pull request Aug 30, 2026
)

* test(wsl): guard probes that report failure as a negative answer

A WSL probe that cannot reach its distro returns the same value as one
that asked and got "no". Downstream nothing can tell them apart, so a
distro that was busy for a second reports no git, or no agent sessions,
until relaunch — sticky, silent, and identical to the real thing.

That has shipped three times: preflight CLI probes, the glab auth
fallback (#8941), and listRunningWslDistrosAsync failing closed with no
last-known-good while polled every 2s (PR #17072).

Scan the WSL and preflight probe modules for the shape and hold the
current set in an allowlist that only shrinks. Scoped deliberately: the
same shape appears ~850 times across src/ and is usually correct,
because for most callers a failure really does mean absent. It is only
dangerous where the answer describes a distro.

The guard cannot see the dangerous part — whether the value is later
cached or gates discovery is dataflow, not syntax. It stops a new
swallow site appearing here without someone saying why it is safe to
pin, which is the review that was missing all three times.

* test(wsl): make ratchet failures actionable

A red build must say what to do. Name the offending files, say the
allowlist is where a safe case goes, and — for a stale entry — say the
change is fine and the list just needs to shrink.

* docs(wsl): track the probe failure-semantics reference

docs/** is gitignored with an explicit allowlist, so the reference the
ratchet points contributors to was silently left out of the branch. A
guard whose error message cites a doc that is not in the repo is worse
than no doc.

* test(wsl): catch a swallow whose reason trails the return

The guard only tolerated comments before `return`, so
`return false // ...` slipped past — including the exact snippet the
doc and the test's own docstring use as the canonical example. The doc
asks authors to write down why a swallow is safe, and the natural place
for that sentence is trailing the return, so following the guidance
defeated the guard.

Verified against both shapes: trailing comment and comment on the line
after.
@nwparker
nwparker merged commit e741ff1 into main Aug 30, 2026
26 checks passed
@nwparker
nwparker deleted the fix/wsl-running-session-discovery branch August 30, 2026 08:49
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…blyai#17352)

* test(wsl): guard probes that report failure as a negative answer

A WSL probe that cannot reach its distro returns the same value as one
that asked and got "no". Downstream nothing can tell them apart, so a
distro that was busy for a second reports no git, or no agent sessions,
until relaunch — sticky, silent, and identical to the real thing.

That has shipped three times: preflight CLI probes, the glab auth
fallback (stablyai#8941), and listRunningWslDistrosAsync failing closed with no
last-known-good while polled every 2s (PR stablyai#17072).

Scan the WSL and preflight probe modules for the shape and hold the
current set in an allowlist that only shrinks. Scoped deliberately: the
same shape appears ~850 times across src/ and is usually correct,
because for most callers a failure really does mean absent. It is only
dangerous where the answer describes a distro.

The guard cannot see the dangerous part — whether the value is later
cached or gates discovery is dataflow, not syntax. It stops a new
swallow site appearing here without someone saying why it is safe to
pin, which is the review that was missing all three times.

* test(wsl): make ratchet failures actionable

A red build must say what to do. Name the offending files, say the
allowlist is where a safe case goes, and — for a stale entry — say the
change is fine and the list just needs to shrink.

* docs(wsl): track the probe failure-semantics reference

docs/** is gitignored with an explicit allowlist, so the reference the
ratchet points contributors to was silently left out of the branch. A
guard whose error message cites a doc that is not in the repo is worse
than no doc.

* test(wsl): catch a swallow whose reason trails the return

The guard only tolerated comments before `return`, so
`return false // ...` slipped past — including the exact snippet the
doc and the test's own docstring use as the canonical example. The doc
asks authors to write down why a swallow is safe, and the natural place
for that sentence is trailing the return, so following the guidance
defeated the guard.

Verified against both shapes: trailing comment and comment on the line
after.
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
* fix(wsl): scan sessions only in running distros

* test(ai-vault): pin WSL discovery platform

* fix(wsl): suspend transcript watchers for stopped distros

* test(wsl): pin transcript scan gate platform

* fix(wsl): settle stopped transcript loading

* fix(wsl): add last-known-good fallback and backoff to running-distro discovery

listRunningWslDistrosAsync failed closed on any probe error (timeout, ENOENT,
wsl.exe hiccup), indistinguishable from "no distros running". A 2s poll
(wsl-transcript-running-observer.ts) calls it indefinitely while any WSL
transcript tab is open, so a persistently broken wsl.exe silently made every
WSL session vanish app-wide with no way to tell "discovery broken" from
"distro stopped", and re-spawned wsl.exe every 2s forever.

Extract a dedicated cache/backoff module (wsl-running-distro-cache.ts,
mirroring the sibling machinery already in wsl.ts for the full distro list)
so a probe failure falls back to the last-known-good running-distro list and
backs off further probes, while a genuine empty result (no distros running)
stays authoritative. Add a consumer-level test simulating a sustained wsl.exe
outage across a live transcript-watcher polling session, asserting the
observer keeps reporting "running" and that real wsl.exe spawns stay bounded.

* fix(build): list the new WSL cache module in the web typecheck project

config/tsconfig.tc.web.json enumerates its files explicitly, so a new
module imported by wsl.ts fails the full typecheck with TS6307 until it
is listed. pnpm tc:node passes without it, which is how this got missed.

  src/main/wsl.ts(13,8): error TS6307: File 'src/main/wsl-running-distro-cache.ts'
  is not listed within the file list of project 'config/tsconfig.tc.web.json'.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Setting to keep Agent Session History from booting WSL distros

2 participants