Skip to content

fix(windows): stop persistent gateway console after update + close checker variable-argv blind spot - #53851

Closed
teknium1 wants to merge 1 commit into
mainfrom
fix/windows-gateway-console-and-checker-blindspot
Closed

fix(windows): stop persistent gateway console after update + close checker variable-argv blind spot#53851
teknium1 wants to merge 1 commit into
mainfrom
fix/windows-gateway-console-and-checker-blindspot

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Symptoms (reported by a Windows desktop user)

I updated and dozens of terminals flashed and disappeared. After updating, when the GUI relaunches, a terminal window opens and stays open — if I close it, the gateway dies.

Three prior PRs (#53791, #53810, #53829) targeted this class but closed neither real symptom. There were two distinct bugs:

Bug 1 — persistent console after update that kills the gateway

hermes_cli/gateway.py::_spawn_gateway_restart_watcher correctly rewrote the respawned gateway argv to windowless pythonw.exe (via windowless_gateway_restart_spec), but launched the watcher process itself with sys.executable — the venv's console python.exe during hermes update. uv's venv launcher re-execs the base console interpreter, allocating a conhost that DETACHED_PROCESS/CREATE_NO_WINDOW cannot suppress. The respawned gateway becomes a child of that leftover console → persistent window; closing it kills the gateway.

Fix: resolve the watcher's own interpreter to windowless pythonw.exe too (no-op on POSIX). Verified on a real Windows box: venv → uv-managed pythonw, .venv → system pythonw, both resolve and exist.

Bug 2 — the flash storm (and a latent NameError)

The AST footgun checker (scripts/check-windows-footguns.py) only recognized a flashing program when argv[0] was a string literal. The entire update path builds git_cmd = ["git", "-c", …] once and passes git_cmd + [...] (variable/concat) to ~33 subprocess.run(..., capture_output=True) calls — invisible to the checker, shipped unflagged, one console flash each.

Fixes:

  • Teach _argv_head to resolve variable and concat (BinOp Add) argv via a module-wide name→program map (_build_var_progs), plus [sys.executable, ...]python.
  • Route the 39 newly-visible calls in main.py (the update flow) + 23 across 12 other files the improved checker surfaced through the _subprocess_compat chokepoint (or creationflags=windows_hide_flags()).
  • Fix a latent NameError: main.py called _subprocess_compat.run with no module import in scope — the update path would have crashed on Windows. Added the import.

Verification (real Windows machine)

  • Checker: clean repo-wide (709 files)
  • All edited files compile; hermes_cli.main imports cleanly
  • tests/scripts/test_windows_footgun_subprocess_rule.py: 32/32 pass (incl. repo-clean invariant)
  • watcher/restart/detach tests: 5/5 pass
  • Update suite: my changes reduce failures 29 → 7; the remaining 7 are pre-existing baseline failures (confirmed by stashing all changes and re-running against bare main).

16 files changed, +200/−87.

…ecker variable-argv blind spot

Two distinct Windows console bugs that survived #53791/#53810/#53829:

1. Persistent console after update that kills the gateway when closed.
   _spawn_gateway_restart_watcher rewrote the respawned gateway argv to
   windowless pythonw, but launched the WATCHER process itself with
   sys.executable — the venv console python.exe during `hermes update`.
   uv's venv launcher re-execs the base console interpreter, allocating a
   conhost that DETACHED_PROCESS/CREATE_NO_WINDOW can't suppress; the
   respawned gateway inherits it. Resolve the watcher interpreter to
   pythonw too (no-op on POSIX).

2. The AST footgun checker only resolved a flashing program when argv[0]
   was a string literal, so the update path's `git_cmd = ["git", ...]`
   then `subprocess.run(git_cmd + [...], capture_output=True)` calls were
   invisible and shipped unflagged — one console flash per call. Teach
   _argv_head to resolve variable and concat (BinOp Add) argv via a
   module-wide name->program map. Route the 39 newly-visible calls in
   main.py + 23 across 12 other files through the _subprocess_compat
   chokepoint (or creationflags=windows_hide_flags()).

Also fixes a latent NameError: main.py called _subprocess_compat.run with
no module import in scope — the update path would have crashed on Windows.

Tests: checker 32/32, watcher/restart/detach 5/5. Update suite failures
drop 29->7 (remaining 7 are pre-existing baseline failures).
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/windows-gateway-console-and-checker-blindspot vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11526 on HEAD, 11528 on base (✅ -2)

🆕 New issues (1):

Rule Count
invalid-assignment 1
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

✅ Fixed issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:3014: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

Unchanged: 6070 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1 teknium1 closed this Jun 27, 2026
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard platform/windows Native Windows-specific behavior or breakage P2 Medium — degraded but workaround exists sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-automation Sweeper risk: may affect CI, automerge, label sync, or maintainer automation labels Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists platform/windows Native Windows-specific behavior or breakage sweeper:risk-automation Sweeper risk: may affect CI, automerge, label sync, or maintainer automation sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants