emrg: Windows GCM silent-fail stage 1 — no_prompt_env for all git/gh subprocess + github_status command + prompt platform guards - #545
Conversation
…subprocess + github_status command + prompt platform guards
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-183131 (review angle: code correctness + subprocess coverage completeness)
Verified on ca10d53:
1. Coverage completeness — every daemon-spawned git/gh subprocess now carries the prompt-free env:
- bash_tool create_subprocess_shell ✓
- all 8 scheduler git subprocess.run sites (rev-parse ×2, config ×2, tag, checkout, clone, ls-remote) ✓
- git_cmd() helper ✓
- _check_github_auth subprocess ✓
Deliberately unguarded (correctly): _detect_git_remote uses git remote get-url (local .git/config read — no network, GCM cannot trigger); __main__.py update + client/app.py are foreground interactive CLI where the host is present — the rant scope is background-daemon popups only.
2. no_prompt_env() — copies os.environ (PATH etc. preserved, tested), sets all three guards. GIT_ASKPASS='' correctly disables askpass rather than leaving it unset.
3. _check_github_auth() — never raises (TimeoutError/OSError/ValueError caught → degraded not-authenticated); 10s timeout; stderr merged to stdout so both 'Logged in' (stdout) and error text are parsed uniformly; missing gh binary short-circuits before spawning.
4. parse_gh_auth_user() — regex handles both gh output forms ('as ' / 'account '), username charset matches GitHub rules (no leading hyphen), None on empty/unauthenticated (tested).
5. Prompt platform guards — evolution_prompt.md + open_source_prompt.md: uname-gated credential extraction (Windows skips git credential fill → GUI pointer), plus explicit no-retry guidance for unauthenticated cycles.
6. Independent test run on branch: 520 passed; imports OK; CI test run green (31170266317).
Non-blocking observation: on asyncio.wait_for timeout in _check_github_auth the gh process is not explicitly killed — harmless in practice since GCM_INTERACTIVE=never makes unauthenticated gh fail fast, but worth noting for a future hardening pass.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-183646 (review angle: test discriminating power)
Each of the 12 new tests was checked against 'would this fail if the implementation regressed?':
Strong discriminators:
test_bash_child_gets_no_prompt_env— the keystone test: runs a REAL subprocess that reads back $GIT_TERMINAL_PROMPT/$GCM_INTERACTIVE/$GIT_ASKPASS. Removingenv=no_prompt_env()from bash_tool makes all three assertions fail. Verifies actual propagation, not just the helper's return value.test_bash_child_env_overridable_by_command— guards against over-engineering: if someone later 'hardens' the guard by force-resetting vars inside the shell, this fails. Correctly pins the contract (daemon sets defaults, commands may override).parse_gh_auth_userpositive×2 (as/account forms) + negative×2 (unauthenticated text, empty/None) — the negative cases prevent an over-broad regex from false-positiving on error output.test_github_status_authenticated/unauthenticated— dispatch through the REAL_process_messagepath asserting wire frames; deleting the elif branch fails both.test_check_github_auth_no_gh_binary— pins the short-circuit degradation (no spawn, clean dict).test_check_github_auth_parses_gh_output— end-to-end fake-subprocess → authenticated dict; FakeProc's(bytes, None)correctly mirrors stderr=STDOUT.
Verification on ca10d53: 71/71 targeted tests pass locally; CI green (31170266317).
Non-blocking gaps noted (candidate follow-ups, not merge blockers):
_check_github_authtimeout branch (wait_for → TimeoutError → degrade) has no dedicated test- scheduler's 8 subprocess.run env kwargs are verified by code inspection only (no mock-based assertion per site); the bash integration test covers the same propagation mechanism
Vote: 2/3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-184016 (review angle: regression surface + Windows semantics)
Regression surface audit:
- bash_tool env change — the daemon has no TTY, so interactive credential prompts could never have succeeded there; they would only hang until the 30s timeout kill (exactly the rant's GCM loop). Fail-fast is strictly an improvement on all platforms. macOS osxkeychain / Linux credential helpers are non-interactive → unaffected (verified: this very evolution cycle's gh/git operations run through the same bash_tool path on macOS with no change in behavior).
- scheduler env change — clone/fetch of the public EMRG repo needs no credentials; private-repo evolution paths already require gh auth setup-git (Stage 2) or stored credentials. No behavior regression, only popup elimination.
- github_status — purely additive command; unknown msg types from older clients are ignored as before.
- Prompt changes — the uname gate wraps only the credential-extraction branch; Darwin/Linux execute byte-identical commands to before. Windows gets the new GUI-pointer path. No macOS/Linux regression.
- Head SHA immutability — ca10d53 unchanged across all 3 reviews; MERGEABLE + CLEAN vs b522165; 0 conflict markers; 520 passed locally this cycle; CI green.
Windows semantics check: GCM_INTERACTIVE=never is the documented Git Credential Manager switch for suppressing all UI; GIT_TERMINAL_PROMPT=0 covers core git; GIT_ASKPASS='' covers helper-based prompts. The three together close every HTTPS credential prompt path GCM can take.
Vote: 3/3 — merge gate satisfied (3 consecutive ✅ from different cycles, no ❌ between).
Uh oh!
There was an error while loading. Please reload this page.
…ndows TUI input & /rant visibility entries (#547) Co-authored-by: EMRG Evolution <emrg@argszero.dev>
…p tolerance (#552) Version bump 0.2.10 → 0.2.11 across all 6 version sources (pyproject.toml / emrg/__init__.py / gui/package.json / uv.lock / make-installer.sh / build-runtime.sh). Release for Windows verification: - #541 LLM gzip body tolerance - #543 GUI message display fixes (#544 quick-ref) - #545 Windows GCM silent-fail Stage 1 - #546 Windows TUI CJK input + legacy arrow keys + /rant visibility - #548/#549/#550 GitHub auth in GUI (PAT + device flow + banner, Stage 2) - #551 quick-ref All 548 tests green. Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Rant (verbatim, 2026-08-07T10:17:27 UTC)
Stage 1 (this PR) — daemon-side silent-fail core
1. No-credential silent failure (plan §1)
git_utils.no_prompt_env(): copies the environment withGIT_TERMINAL_PROMPT=0,GCM_INTERACTIVE=never,GIT_ASKPASS=— git/gh subprocesses fail fast and silently instead of spawning GCM GUI dialogs.bash_toolchild processes (create_subprocess_shell)git_cmd()helper2. GitHub connection status detection (plan §2)
github_status→{authenticated, user, method}._check_github_auth(): runs bundled ghgh auth status(viaresolve_git_gh()) with 10s timeout in the prompt-free env; parses user viaparse_gh_auth_user()(handles bothas <user>andaccount <user>gh output forms). Never raises — degrades to not-authenticated.3. Prompt platform adaptation (plan §5)
evolution_prompt.md+open_source_prompt.md: thegit credential filltoken-extraction fallback is now platform-guarded — skipped on Windows (it triggers GCM there), with a pointer to the GUI settings page; unauthenticated cycles skip GitHub ops gracefully without retrying.Tests (+12 → 520, doc counts synced per #511 guard)
no_prompt_env: all three guards present + parent env preservedparse_gh_auth_user: as-form / account-form / unauthenticated / emptygithub_status: authenticated / unauthenticated dispatch + missing-gh degradation + real-output parsingRemaining stages (tracked in rant, kept in_progress)
gh auth login --web+ PAT paste fallback +gh auth setup-git)