fix(windows): hide console flash on checkpoint git + skills_hub gh probes

The #54236/#54417 backend git/gh sweep routed git_probe, the repo-file
picker, coding_context, context_references, copilot_auth, and the gateway
process scans through CREATE_NO_WINDOW, but two sibling spawn legs that
also run inside the console-less desktop/gateway backend were missed:

- tools/checkpoint_manager.py `_run_git` (and the one-shot `git init
  --bare` in `_init_store`) — when checkpoints are enabled, every
  file-mutating turn fires multiple bare `git` calls (status, add,
  write-tree/commit-tree, update-ref). Spawned from a parent with no
  console (Electron spawns the backend with windowsHide → CREATE_NO_WINDOW),
  each one allocates its own conhost window → a flurry of terminal popups.
- tools/skills_hub.py `GitHubAuth._try_gh_cli` — `gh auth token`, the same
  bug class as the already-fixed copilot_auth gh probe.

Route both through `windows_hide_flags()` (no-op on POSIX), matching the
established per-site pattern. Tests added to
tests/test_windows_subprocess_no_window_flags.py.
This commit is contained in:
Brooklyn Nicholson 2026-06-28 17:41:47 -05:00
parent 980622d0ec
commit 32087e4bc9
3 changed files with 47 additions and 0 deletions

View file

@ -300,6 +300,44 @@ def test_local_stt_audio_prep_hides_ffmpeg_window(monkeypatch, tmp_path):
assert captured[0][0][0] == "ffmpeg"
assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
def test_checkpoint_manager_git_hides_windows(monkeypatch):
from tools import checkpoint_manager
captured = []
def fake_run(cmd, **kwargs):
captured.append((cmd, kwargs))
return _Completed(stdout="clean\n")
monkeypatch.setattr(checkpoint_manager, "IS_WINDOWS", True)
monkeypatch.setattr(checkpoint_manager, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
monkeypatch.setattr(checkpoint_manager.subprocess, "run", fake_run)
ok, _, _ = checkpoint_manager._run_git(["status", "--short"], Path("C:/store"), ".")
assert ok
assert captured[0][0][0] == "git"
assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
def test_skills_hub_gh_token_hides_windows(monkeypatch):
from tools import skills_hub
captured = []
def fake_run(cmd, **kwargs):
captured.append((cmd, kwargs))
return _Completed(stdout="gho_from_cli\n")
monkeypatch.setattr(skills_hub, "IS_WINDOWS", True)
monkeypatch.setattr(skills_hub, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
monkeypatch.setattr(skills_hub.subprocess, "run", fake_run)
auth = skills_hub.GitHubAuth.__new__(skills_hub.GitHubAuth)
assert auth._try_gh_cli() == "gho_from_cli"
assert captured[0][0] == ["gh", "auth", "token"]
assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
def test_tui_slash_worker_hides_python_window(monkeypatch):
from tui_gateway import server

View file

@ -58,6 +58,7 @@ import subprocess
import time
from pathlib import Path
from hermes_constants import get_hermes_home
from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
from typing import Dict, List, Optional, Set, Tuple
from utils import env_int
@ -321,6 +322,10 @@ def _run_git(
env = _git_env(store, str(normalized_working_dir), index_file=index_file)
cmd = ["git"] + list(args)
allowed_returncodes = allowed_returncodes or set()
# Checkpoints run inside the console-less desktop/gateway backend; a bare
# git spawn there pops a fresh conhost window per call (status, add,
# commit, …) on Windows. No-op on POSIX.
_popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
try:
result = subprocess.run(
cmd,
@ -330,6 +335,7 @@ def _run_git(
env=env,
cwd=str(normalized_working_dir),
stdin=subprocess.DEVNULL,
**_popen_kwargs,
)
ok = result.returncode == 0
stdout = result.stdout.strip()
@ -450,6 +456,7 @@ def _init_store(store: Path, working_dir: str) -> Optional[str]:
capture_output=True, text=True,
env=init_env, timeout=_GIT_TIMEOUT,
stdin=subprocess.DEVNULL,
**({"creationflags": windows_hide_flags()} if IS_WINDOWS else {}),
)
if result.returncode != 0:
return f"Shadow store init failed: {result.stderr.strip()}"

View file

@ -26,6 +26,7 @@ from dataclasses import dataclass, field
from datetime import datetime, timezone
from pathlib import Path, PurePosixPath
from hermes_constants import get_hermes_home
from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
from agent.skill_utils import is_excluded_skill_path
from typing import Any, Dict, List, Optional, Tuple, Union
from urllib.parse import urljoin, urlparse, urlunparse
@ -302,6 +303,7 @@ class GitHubAuth:
["gh", "auth", "token"],
capture_output=True, text=True, timeout=5,
stdin=subprocess.DEVNULL,
**({"creationflags": windows_hide_flags()} if IS_WINDOWS else {}),
)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()