windows-v0.4.1: installed-CLI EPERM + agent-shell pipe-name fixes - #9
Merged
Conversation
…t exec from Program Files The installed 0.4.0 launcher baked C:\Program Files\ADE\resources\cli\index.mjs and every `ade` call died with "error: EPERM reading <path>". bun refuses to EXECUTE an entry script from a directory the user cannot write to; the file itself reads fine, and the same bytes run from a temp dir. Bin injection now copies a PACKAGED entry to <home>/<adeDir>/cli/index.mjs — unconditionally, so an upgrade refreshes the copy — and bakes that path into the launcher. A dev checkout's TypeScript entry is left alone: it imports siblings and its tree is writable anyway. ADE_CLI_ENTRY and the exit-127 missing-entry guard are unchanged.
…agent shells ADE's own agent terminals carry neither USERNAME nor USER, and under bun os.userInfo().username then returns the literal string "unknown" instead of throwing — so the existing try/catch env fallbacks never fired and every `ade` call in an agent pane dialled \.\pipe\ade-control-unknown while the app listened on the pipe named for the real user (exit 3, "app is not running"). getUserName() walks lazy steps: userInfo (rejecting "unknown" only there, so a real account of that name is still served by the later steps), $USERNAME, $USER, whoami (DOMAIN\user -> user, spawned only when the cheap steps came up empty, cached per process), basename($USERPROFILE), then the "user" literal. Sanitisation is the same [^A-Za-z0-9-] rule the app applies, so both sides always name the same pipe.
Windows never sets USER and USERNAME was not on the terminal allowlist, so ADE agent shells had no user name at all — which is what made bun report "unknown" and sent the `ade` CLI to a pipe nobody listens on. buildTerminalEnv now injects the app's own os.userInfo().username when the environment has none (never clobbering one that came through), and USERNAME is allowlisted so it survives the terminal-host's buildSafeEnv re-filter. Fixes every user-name consumer in an agent shell, not just `ade`.
The old smoke ran the CLI straight out of a writable checkout with USERNAME set — the two conditions a real install does not have — which is why it stayed green while `ade` was unusable both from the Start-menu install and from ADE's own agent panes. The smoke now invokes the generated <profile>\.ade\bin\ade.cmd (exercising the staged CLI copy, since bun cannot execute the entry from the read-only install dir), asserts the staged bundle exists, and strips USERNAME/USER first (exercising the CLI's whoami fallback). Marker-file judgment and the one retry are unchanged.
Both fixes are Windows-only in effect; the version is the desktop app's, which is what electron-builder names the installer from. Build-report addendum records root causes, canary evidence and the live verification against the running installed 0.4.0; release URL and CI run IDs are left as TODO slots.
Ship-verifier observations, all cheap and all in code this release already touches. stageBundledCliEntry now copies to a sibling temp name and renames over index.mjs, so a crash (or an `ade` call reading the file) mid-copy can no longer leave a truncated entry bun refuses to run. When staging fails and a previously staged copy exists, the launcher keeps pointing at THAT copy — the read-only packaged path is the 0.4.0 bug, so a stale-but-executable entry beats a fresh unusable one. Only a failure with nothing staged falls back to the packaged path. Tests cover both fallback branches. The "unknown" sentinel is now rejected at every step that can carry it, not just at userInfo(): any bun-hosted parent that resolved "unknown" itself and exported it as USERNAME/USER would both re-create the bug and suppress the whoami fallback. Same guard on the app side — buildTerminalEnv skips the injection rather than propagating the sentinel into agent shells, and takes a userInfoUser seam so the test pins a real name instead of comparing against os.userInfo() (self-referential under bun-on-Windows: both sides read "unknown" and the assertion passed on the bug).
The report said POSIX "was checked and deliberately left alone", implying the staging is Windows-only. It is not: stageBundledCliEntry has no platform guard and electron-builder ships resources/cli/index.mjs on mac too, so mac launchers also bake the staged data-dir copy. Deliberate — bun-on-posix has no execute restriction, so staging there is harmless — but the doc claimed something the code does not do. No platform guard added; uniform behaviour is the simpler contract. Also records verifier observation #5 as an accepted known gap: the app-side USERNAME injection has no end-to-end CI gate, and its unit coverage sits in the server-core suite (ADE CI) rather than Windows CI.
boostedchaos
marked this pull request as ready for review
August 10, 2026 00:28
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Two field bugs found running the packaged 0.4.0 on Windows. Both made
adeunusable, and both were invisible to CI, which ran the CLI straight out of a writable checkout withUSERNAMEset — the two conditions a real install does not have.Bug A — installed
adedied withEPERM. The launcher bakedC:\Program Files\ADE\resources\cli\index.mjs, and bun refuses to EXECUTE an entry script from a directory the user cannot write to (error: EPERM reading …, though the file reads fine). Bin injection now copies the packaged bundle to<home>/<adeDir>/cli/index.mjs— unconditionally, so an upgrade refreshes it — and bakes that path. Dev checkouts and POSIX are untouched;ADE_CLI_ENTRYstill overrides.Bug B —
adein ADE's own agent panes reported "app is not running" (exit 3). Agent shells carry neitherUSERNAMEnorUSER, and under bunos.userInfo().usernamereturns the literal"unknown"without throwing — so the existing env fallbacks never fired and the CLI dialled\\.\pipe\ade-control-unknownwhile the app listened on the pipe named for the real user. Fixed on both sides:getUserName(): rejects"unknown"at the userInfo step, then$USERNAME→$USER→whoami(DOMAIN\user→user, spawned only when the cheap steps come up empty, cached) →basename($USERPROFILE)→"user", sanitised with the same rule the app uses.buildTerminalEnvinjects its ownos.userInfo().usernameasUSERNAMEwhen the environment has none (never clobbering), andUSERNAMEis allowlisted so it survives the terminal-host'sbuildSafeEnvre-filter. Fixes every user-name consumer in an agent shell, not justade.CI regression gate. The named-pipe smoke now invokes the generated
<profile>\.ade\bin\ade.cmd(exercising the staged copy), asserts the staged bundle exists, and stripsUSERNAME/USERfirst (exercising the whoami path). It fails against 0.4.0 behavior.Evidence
env.test.tsUSERNAME block 3 fail (Expected "unknown", Received undefined— bun's sentinel, observed live);socket-path.test.tsandade-cli-bin.test.tsfail to importgetUserName/stageBundledCliEntry.USERNAMEandUSERremoved from the environment: patched CLI →list-workspacesexit 0 and the real workspace table; 0.4.0 CLI, same command and env →ADE app is not running (no control socket), exit 3.Draft: release prep (0.4.1 bump, CHANGELOG, WINDOWS.md, build-report addendum) is included; publishing is gated on the orchestrator.