fix(launcher): establish the user PATH for a fresh WSL session - #56
fix(launcher): establish the user PATH for a fresh WSL session#56sbracewell64 wants to merge 1 commit into
Conversation
firstmate.bat launches `wsl.exe --exec /bin/bash` so the launch never depends on the login shell, but that session's PATH carries only the system directories plus Windows interop. The menu probes each harness with `command -v`, so every harness installed under the account's private bin directories rendered as "not installed" and the Enter default fell through to whatever happened to resolve. bin/fm-wsl-entry.sh now prepends ~/.local/bin and ~/bin when they exist, before handing off to the launcher. Those are exactly the two directories the stock ~/.profile prepends and the ones every supported harness installer targets, so this restores interactive parity as a filesystem fact rather than by evaluating a login profile in a non-interactive launch. Only existing directories are added, only once, and nothing already on the inherited PATH is removed or reordered. firstmate.bat's --exec choice is unchanged. Verified through the real bridge command: `wsl.exe --cd <repo> --exec /bin/bash ./bin/fm-wsl-entry.sh --print-menu` now renders a menu byte-identical to the interactive `bin/fm-launch.sh --print-menu`, for every harness the menu lists.
CI outcome on this head: 12 passed, 2 failedBoth failures are accounted for, and neither comes from this diff. 1. 2. This is pre-existing on the base commit and unrelated to the launcher change. Verified locally by running that test on both heads:
The assertion is a bounded wait for a concurrent inheritance transaction to reach its blocked write. This diff touches only The checks that cover this change all pass, including |
Intent
Fix the Windows launcher's fresh-session PATH gap so the harness menu sees user-installed harnesses and defaults to the ruled default (Claude).
firstmate.batdeliberately launcheswsl.exe --exec /bin/bashso the launch never depends on the login shell, butbin/fm-wsl-entry.shnever re-established the user-level PATH.A fresh session therefore carried only the system directories plus Windows interop appends.
bin/fm-launch.shprobes each menu entry withcommand -v, so every harness installed under the account's private bin directories rendered as "not installed - install " and the Enter default fell away from Claude.Change
bin/fm-wsl-entry.shprepends$HOME/.local/binand$HOME/binwhen they exist, before handing off to the launcher.Those are exactly the two directories the distribution's stock
~/.profileprepends, and every supported harness installer targets~/.local/bin, so this restores interactive parity as a filesystem fact.Evaluating a login profile in a non-interactive launch was ruled out deliberately: it would inherit arbitrary side effects, ordering, and failure modes.
Reusing
bin/fm-remote-job-lib.sh's remote PATH composer was also considered and rejected, because its non-symlink exclusion is a remote-trust rule that would under-detect a locally symlinked~/.local/bin- the opposite of the parity this fix owes.Only existing directories are added, only once, ahead of the system tail in the same order a login shell produces, and nothing already on the inherited PATH is removed or reordered.
firstmate.bat's--exec /bin/bashchoice is deliberately untouched: its no-login-shell rationale stands, and the entry script owns environment establishment.Test evidence
Witnessed red first. With PATH stripped to the system directories, the menu rendered all five entries dim and "nothing is available yet"; the two new cases in
tests/fm-wsl-entry.test.shfailed against the unfixed entry script withclaude=[NOT-ON-PATH].New cases, both green after the fix:
~/.local/binand~/bin, using a fakeHOMEand a PATH stripped to system directories;~/bin.End-to-end through the real bridge command:
now renders a menu byte-identical to the interactive
bin/fm-launch.sh --print-menu- Claude default restored, Codex available, both Pi-routed entries available with their correct sign-in note, and OpenCode still honestly dim because it genuinely is not installed. That covers every harness the menu lists, not only claude.bin/fm-lint.sh(ShellCheck 0.11.0, pinned) andbin/fm-doc-audience-check.shboth clean.CI state - disclosed honestly
This branch was validated through the local no-mistakes pipeline: intent, review, test, document, lint, and push all completed with zero findings.
Two steps did not run and are not evidence of anything:
Consequently no CI run has examined this head yet. Treat the checks on this pull request as the authority; the local pipeline evidence above is not a substitute for them.
Files
bin/fm-wsl-entry.sh- establish the user PATH, with the rationale in the script header.tests/fm-wsl-entry.test.sh- two new behavior cases.docs/windows-launcher.md- operator-facing PATH fact and a troubleshooting line for a harness installed elsewhere.