windows: discover provider roots inside WSL distros - #1062
Conversation
Agents run inside a WSL distro write their history to the distro's Linux home, exposed to Windows as \\wsl$\<distro>\... and never under the user profile, so a Windows-only scan reported zero sessions for them. src/wsl.ts lists distros through %SystemRoot%\System32\wsl.exe (absolute, so nothing dropped next to the CLI can impersonate it) with a 3s timeout, decodes its UTF-16LE output, drops container-runtime distros, and enumerates each distro's home/* and root. Running distros only by default: touching \\wsl$ boots a stopped distro. CODEBURN_WSL=all|off opts in or out. Inert off win32 and memoized per process. claude and codex append <wslHome>/.claude and <wslHome>/.codex to their existing root lists, so multi-root discovery, probeRoots() and doctor cover them unchanged. Roots are additive, never an override. CODEBURN_WSL stays out of PROVIDER_ENV_VARS: cache entries are keyed by source path, so it can only add or drop paths, never make a kept entry stale, while declaring it would force a re-parse on every toggle. Fingerprints drop dev/ino for \\wsl$ paths in both caches. The 9P share synthesizes them per mount, so keying on them would re-parse every WSL session on every run; mtime+size still catches edits and appends. Refs #1059
UTF-16 output parsing, utility-distro filtering, CODEBURN_WSL modes, UNC classification, claude/codex root injection and discovery, probeRoots, fingerprint reconciliation with zeroed dev/ino, and the win32 guard that keeps a Linux cwd from being walked on Windows. Refs #1059
Probe \\wsl$\ before \\wsl.localhost\. The older spelling works on every WSL build; probing the newer one first sends builds without it through MUP, SMB and DNS resolution for a host named "wsl.localhost" — seconds of stall per distro, every process. Only accept lines shaped like a distro name. With nothing installed, wsl.exe prints prose on stdout whose lines otherwise read as distro names and get probed over UNC. A name must be a single token with none of the characters Windows bans from a path component and no trailing period, which discards that message in any UI language. Do not evict a \\wsl$ cache entry for being undiscovered, and serve it in write mode too. A stopped distro drops its whole root out of discovery; treating that as a deletion re-parsed everything over 9P on the next start and made totals drop while the read-only serve path still showed them. The exemption is scoped to isWslUncPath — an ordinary path whose file is gone is still evicted. Also: getCachedCodexProject was the one fingerprint site still keying on dev/ino for WSL paths; doctor now prints why it probed no WSL roots; and a distro contributing several homes labels them per user rather than letting makeUniqueLabels number them. Refs #1059
|
@Mateleo — before we merge this, would you test it from the branch and report back? You're the real-world case (#1059) and none of us has a Windows + WSL box. Setup (PowerShell, in a scratch dir): git clone --depth 1 --branch feat/wsl-discovery https://github.com/getagentseal/codeburn.git
cd codeburn
npm ci
npm run build:cliThen, using the fresh build ( wsl.exe --list --quiet --running # sanity: what's running
node dist/cli.js doctor # expect \\wsl$\<distro>\home\<you>\.claude\projects rows — or a one-line note saying why none
node dist/cli.js status --format json # your WSL sessions should now be counted
$env:CODEBURN_WSL="off"; node dist/cli.js doctor # the note should name the opt-out; wsl.exe must not run
Remove-Item Env:CODEBURN_WSL
Measure-Command { node dist/cli.js status } # run this line twice — the 2nd should be much faster
wsl --shutdown; node dist/cli.js status # your WSL spend should STILL show while the distro is stopped
# restart your distro (open a WSL terminal), then:
Measure-Command { node dist/cli.js status } # should still be fast — no full re-scan after the shutdown cycle
node dist/cli.js sessions --provider codex # if you use Codex in WSL: projectPath should show /home/... pathsWhat we'd love in your conclusion:
Everything is read-only — it never writes into WSL. Thanks for filing this; your report decides the merge. |
ozymandiashh
left a comment
There was a problem hiding this comment.
Blocking issue: wslHomes() memoizes the running-distro homes for the lifetime of the process. In long-lived serve/menubar use, a distro cached as running can be shut down and the next refresh still touches its \\wsl$ UNC path—the operation this PR explicitly avoids because it may start the stopped distro. The inverse is also stale: a distro started after an initial empty discovery is invisible until process restart. Please make discovery refresh/revalidate the currently running distro list before any UNC access (a bounded TTL or per-scan refresh would work) and cover both shutdown and later-start transitions. The requested real Windows + WSL validation is also still outstanding.
|
Tell me if @ozymandiashh is indeed blocking, and if not I will test |
# Conflicts: # src/doctor.ts # src/parser.ts # src/providers/claude.ts # src/providers/codex.ts # src/session-cache.ts
wslHomes() memoized the running-distro homes for the process lifetime. In long-lived serve/menubar use a distro cached as running could be shut down and the next refresh would still touch its \\wsl$ UNC path — which can hang win32 fs calls — while a distro started after an empty discovery stayed invisible until restart. Discovery now caches for a 60s TTL only; on expiry the wsl.exe -l --running probe (timeout-bounded) re-validates the running list before any UNC path is touched, and a failed probe fails closed to native-only discovery rather than serving stale homes. Covers both shutdown and later-start transitions. Addresses the blocking review finding on PR #1062.
|
@Mateleo — yes, @ozymandiashh's finding was blocking and is now fixed, plus the branch is freshly rebased onto current main (it had drifted behind the perf wave). What changed:
@ozymandiashh — would value your re-review of @Mateleo — the branch is ready for your real-world test now; same setup steps as my earlier comment, from the updated |
|
Follow-up pushed in Red-before reproductions
What changed
Verification
@Mateleo, the real Windows + WSL run is still the external merge gate; none of the local/CI tests can replace it. Please test the latest I am intentionally leaving the existing requested-changes gate in place until the new CI and that real Windows + WSL validation are both back. |
Fixes #1059.
What
On Windows, CodeBurn only scanned the Windows home, so agents running inside WSL showed zero sessions. This discovers WSL distro homes and adds them as extra provider roots — V1 covers claude and codex (the two providers with an existing multi-root seam; others when reported).
\\wsl$\<distro>boots a stopped distro, so enumeration useswsl.exe --list --quiet --running(absoluteSystem32path, 3 s timeout, UTF-16LE/UTF-8 detected by content, memoized per process).CODEBURN_WSL=allopts into stopped distros (documented as "will start them");offnever spawnswsl.exe. Read-policy env — deliberately outsidePROVIDER_ENV_VARS(can only add/remove source paths; never makes a kept entry stale).\\wsl$\probed first,\\wsl.localhost\fallback (the reverse stalls multi-seconds through MUP→SMB→DNS on builds without the newer name). Utility distros (docker-desktop, podman, rancher) and non-distro output (the localized "no installed distributions" message) filtered by a single-token shape.dev/inozeroed in fingerprints for\\wsl$paths at all four sites (unstable over 9P would force a full re-parse every run); mtime+size matching is the existing codex-cache precedent.wsl --shutdowncycle no longer wipes and re-parses everything over 9P, and read-only/write runs agree./home/u/proj) in those transcripts attribute safely on win32 (fix: OOM on cold parse (V8 SlicedString retention) + kiro projectPath for repo attribution #984's platform guard, test-proven both ways). Multi-home distros label asUbuntu (WSL, alice).codeburn doctorprints one line naming why no WSL roots were probed (off, or nothing running) with theallhint.wsl.exefails in ~0.8 ms, once per process. macOS/Linux: module inert — 31.5 MB of real exported data byte-identical to main.Tests
36 new across
tests/wsl-discovery.test.ts+tests/wsl-spawn.test.ts: UTF-16 (±BOM)/CRLF/UTF-8 parsing, no-distro message yields zero probes, utility filter, env modes (off never callsexecFileSync), prefix fallback + per-distro break, multi-home labels, probeRoots/doctor,/homecwd on win32 (discriminates: fails without the guard), fingerprint carve-out + reconciliation, WSL-offline retention vs normal-path eviction (fails with the carve-out stubbed off).tscclean ·npm test2996 ·test:locks26.Needs a real Windows + WSL box (verification checklist)
@Mateleo — would you be up for running this checklist once it merges (or from the branch)? Your report is the real-world validation this needs.
Follow-up filed: #1061 (Windows menubar quota panel reads only the Windows home).