{"repo":"NousResearch/hermes-agent","public_id":"54364","display_label":"Suppress unwanted terminal popups on Windows startup","summary":"These issues and PRs address Windows Desktop startup behavior that eagerly spawns agent-browser processes, causing visible console or terminal window flashes. Fixes cover multiple spawn code paths to avoid these background probes.","subsystem":null,"counts":{"members":4,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":54417},"resolution":{"state":"unresolved","by":null},"freshness":{"state":"verified","last_verified_at":"2026-06-28T20:49:09+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.3933333333333333},"fix_edges":[{"issue_number":53016,"pr_number":54417,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":53053,"pr_number":54417,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":53282,"pr_number":54417,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":53539,"pr_number":54417,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":54364,"pr_number":54417,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false}],"members":[{"kind":"issue","number":54364,"title":"Desktop startup eagerly runs agent-browser --version on Windows","url":null,"state":"closed"},{"kind":"issue","number":54375,"title":"Desktop startup should not eagerly run agent-browser --version on Windows","url":null,"state":"closed"},{"kind":"pr","number":54366,"title":"fix(browser): avoid eager agent-browser probe","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#54417","number":54417},{"kind":"pr","value":"#54417","number":54417},{"kind":"pr","value":"#54220","number":54220}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":54417,"title":"fix(windows): cover remaining console-flash spawn legs","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["gateway/run.py","gateway/status.py","hermes_cli/gateway.py","hermes_constants.py","tests/gateway/test_restart_drain.py","tests/gateway/test_status.py","tests/test_hermes_constants.py","tests/test_windows_subprocess_no_window_flags.py","tests/tools/test_browser_chromium_check.py","tests/tools/test_browser_homebrew_paths.py","tools/browser_tool.py","tui_gateway/server.py"],"fix_hunks":[{"file":"gateway/run.py","hunks":["@@ -5501,6 +5501,19 @@ def _alive(p):\n             # run as a self-restart loop guard and the gateway stays stopped.\n             watcher_env.pop(\"_HERMES_GATEWAY\", None)\n             project_root = Path(__file__).resolve().parent.parent\n+            watcher_python = sys.executable\n+            try:\n+                # Prefer a real GUI-subsystem interpreter for the watcher\n+                # itself.  With uv venvs, ``python.exe`` can re-exec the base\n+                # console interpreter and flash even when the Popen carries\n+                # CREATE_NO_WINDOW; pythonw.exe avoids console allocation.\n+                from hermes_cli.gateway_windows import _resolve_detached_python\n+\n+                watcher_python, _watcher_venv_dir, _watcher_site_packages = (\n+                    _resolve_detached_python(sys.executable)\n+                )\n+            except Exception:\n+                watcher_python = sys.executable\n             venv_dir = Path(watcher_env.get(\"VIRTUAL_ENV\") or project_root / \"venv\")\n             site_packages = venv_dir / \"Lib\" / \"site-packages\"\n             if site_packages.exists():","@@ -5510,7 +5523,7 @@ def _alive(p):\n                     pythonpath.append(watcher_env[\"PYTHONPATH\"])\n                 watcher_env[\"PYTHONPATH\"] = os.pathsep.join(dict.fromkeys(pythonpath))\n             subprocess.Popen(\n-                [sys.executable, \"-c\", watcher, str(current_pid), str(restart_after_s), *cmd_argv],\n+                [watcher_python, \"-c\", watcher, str(current_pid), str(restart_after_s), *cmd_argv],\n                 stdout=subprocess.DEVNULL,\n                 stderr=subprocess.DEVNULL,\n                 env=watcher_env,"]},{"file":"gateway/status.py","hunks":["@@ -171,17 +171,18 @@ def _read_process_cmdline(pid: int) -> Optional[str]:\n         if raw:\n             return raw.replace(b\"\\x00\", b\" \").decode(\"utf-8\", errors=\"ignore\").strip()\n \n-    try:\n-        result = subprocess.run(\n-            [\"ps\", \"-p\", str(pid), \"-o\", \"command=\"],\n-            capture_output=True,\n-            text=True,\n-            timeout=5,\n-        )\n-        if result.returncode == 0 and result.stdout.strip():\n-            return result.stdout.strip()\n-    except (OSError, subprocess.TimeoutExpired):\n-        pass\n+    if not _IS_WINDOWS:\n+        try:\n+            result = subprocess.run(\n+                [\"ps\", \"-p\", str(pid), \"-o\", \"command=\"],\n+                capture_output=True,\n+                text=True,\n+                timeout=5,\n+            )\n+            if result.returncode == 0 and result.stdout.strip():\n+                return result.stdout.strip()\n+        except (OSError, subprocess.TimeoutExpired):\n+            pass\n \n     # Windows fallback: psutil (already used by _pid_exists)\n     try:"]},{"file":"hermes_cli/gateway.py","hunks":["@@ -180,7 +180,11 @@ def _get_parent_pid(pid: int) -> int | None:\n         pass\n     except Exception:\n         return None\n-    # Fallback: shell out to ps (POSIX only — bare ``ps`` doesn't exist on Windows).\n+    # Fallback: shell out to ps (POSIX only).  Git Bash installs ``ps.exe`` on\n+    # Windows; running it from the windowless desktop/gateway backend flashes a\n+    # console, and psutil above is the authoritative Windows path anyway.\n+    if is_windows():\n+        return None\n     if not shutil.which(\"ps\"):\n         return None\n     try:"]},{"file":"hermes_constants.py","hunks":["@@ -317,11 +317,14 @@ def node_tool_runnable(path: str | None) -> bool:\n     import subprocess\n \n     try:\n+        from hermes_cli._subprocess_compat import windows_hide_flags\n+\n         result = subprocess.run(\n             [path, \"--version\"],\n             capture_output=True,\n             timeout=10,\n             env=with_hermes_node_path(),\n+            creationflags=windows_hide_flags(),\n         )\n     except (OSError, subprocess.TimeoutExpired, ValueError):\n         return False","@@ -562,11 +565,14 @@ def agent_browser_runnable(path: str | None) -> bool:\n     import subprocess\n \n     try:\n+        from hermes_cli._subprocess_compat import windows_hide_flags\n+\n         result = subprocess.run(\n             [path, \"--version\"],\n             capture_output=True,\n             timeout=10,\n             env=with_hermes_node_path(),\n+            creationflags=windows_hide_flags(),\n         )\n     except (OSError, subprocess.TimeoutExpired, ValueError):\n         return False"]},{"file":"tests/gateway/test_restart_drain.py","hunks":["@@ -353,6 +353,49 @@ def fake_popen(cmd, **kwargs):\n     assert kwargs[\"stderr\"] is subprocess.DEVNULL\n \n \n[redacted:email]\n+async def test_windows_detached_restart_uses_pythonw_for_watcher(monkeypatch, tmp_path):\n+    runner, _adapter = make_restart_runner()\n+    popen_calls = []\n+    venv_dir = tmp_path / \"venv\"\n+    site_packages = venv_dir / \"Lib\" / \"site-packages\"\n+    site_packages.mkdir(parents=True)\n+\n+    monkeypatch.setattr(gateway_run.sys, \"platform\", \"win32\")\n+    monkeypatch.setattr(gateway_run.sys, \"executable\", r\"C:\\venv\\Scripts\\python.exe\")\n+    monkeypatch.setattr(gateway_run, \"_resolve_hermes_bin\", lambda: [\"hermes\"])\n+    monkeypatch.setattr(gateway_run.os, \"getpid\", lambda: 321)\n+    monkeypatch.setenv(\"VIRTUAL_ENV\", str(venv_dir))\n+\n+    import hermes_cli._subprocess_compat as subprocess_compat\n+    import hermes_cli.gateway_windows as gateway_windows\n+\n+    monkeypatch.setattr(\n+        gateway_windows,\n+        \"_resolve_detached_python\",\n+        lambda _python: (r\"C:\\Python311\\pythonw.exe\", venv_dir, [str(site_packages)]),\n+    )\n+    monkeypatch.setattr(\n+        subprocess_compat,\n+        \"windows_detach_popen_kwargs\",\n+        lambda: {\"creationflags\": 0x08000008},\n+    )\n+\n+    def fake_popen(cmd, **kwargs):\n+        popen_calls.append((cmd, kwargs))\n+        return MagicMock()\n+\n+    monkeypatch.setattr(subprocess, \"Popen\", fake_popen)\n+\n+    await runner._launch_detached_restart_command()\n+\n+    assert len(popen_calls) == 1\n+    cmd, kwargs = popen_calls[0]\n+    assert cmd[0] == r\"C:\\Python311\\pythonw.exe\"\n+    assert cmd[-3:] == [\"hermes\", \"gateway\", \"restart\"]\n+    assert kwargs[\"creationflags\"] == 0x08000008\n+\n+\n # ── Shutdown notification tests ──────────────────────────────────────\n \n "]},{"file":"tests/gateway/test_status.py","hunks":["@@ -2,6 +2,7 @@\n \n import json\n import os\n+import sys\n from pathlib import Path\n from types import SimpleNamespace\n ","@@ -1351,6 +1352,7 @@ class TestReadProcessCmdlinePsFallback:\n \n     def test_ps_fallback_when_proc_unavailable(self, monkeypatch):\n         monkeypatch.setattr(status.Path, \"read_bytes\", lambda self: (_ for _ in ()).throw(FileNotFoundError))\n+        monkeypatch.setattr(status, \"_IS_WINDOWS\", False)\n         monkeypatch.setattr(\n             status.subprocess, \"run\",\n             lambda args, **kwargs: SimpleNamespace(returncode=0, stdout=\"/usr/libexec/bluetoothuserd\\n\"),","@@ -1360,6 +1362,7 @@ def test_ps_fallback_when_proc_unavailable(self, monkeypatch):\n \n     def test_ps_fallback_returns_none_on_failure(self, monkeypatch):\n         monkeypatch.setattr(status.Path, \"read_bytes\", lambda self: (_ for _ in ()).throw(FileNotFoundError))\n+        monkeypatch.setattr(status, \"_IS_WINDOWS\", False)\n         monkeypatch.setattr(\n             status.subprocess, \"run\",\n             lambda args, **kwargs: SimpleNamespace(returncode=1, stdout=\"\"),","@@ -1381,6 +1384,7 @@ def fake_read_bytes(self):\n \n     def test_ps_fallback_used_when_proc_returns_empty(self, monkeypatch):\n         monkeypatch.setattr(status.Path, \"read_bytes\", lambda self: b\"\")\n+        monkeypatch.setattr(status, \"_IS_WINDOWS\", False)\n         monkeypatch.setattr(\n             status.subprocess, \"run\",\n             lambda args, **kwargs: SimpleNamespace(returncode=0, stdout=\"python hermes_cli/main.py gateway run\\n\"),","@@ -1388,6 +1392,34 @@ def test_ps_fallback_used_when_proc_returns_empty(self, monkeypatch):\n         result = status._read_process_cmdline(12345)\n         assert \"hermes_cli/main.py\" in result\n \n+    def test_windows_skips_ps_fallback_and_uses_psutil(self, monkeypatch):\n+        monkeypatch.setattr(status.Path, \"read_bytes\", lambda self: (_ for _ in ()).throw(FileNotFoundError))\n+        monkeypatch.setattr(status, \"_IS_WINDOWS\", True)\n+        ps_calls = []\n+        monkeypatch.setattr(\n+            status.subprocess,\n+            \"run\",\n+            lambda args, **kwargs: ps_calls.append((args, kwargs)) or SimpleNamespace(returncode=0, stdout=\"ps should not run\\n\"),\n+        )\n+\n+        class _Proc:\n+            def __init__(self, pid):\n+                self.pid = pid\n+\n+            def cmdline(self):\n+                return [\"pythonw.exe\", \"-m\", \"hermes_cli.main\", \"gateway\", \"run\"]\n+\n+        monkeypatch.setitem(\n+            sys.modules,\n+            \"psutil\",\n+            SimpleNamespace(Process=_Proc),\n+        )\n+\n+        result = status._read_process_cmdline(12345)\n+\n+        assert result == \"pythonw.exe -m hermes_cli.main gateway run\"\n+        assert ps_calls == []\n+\n \n class TestCorruptStatusFiles:\n     \"\"\"A status / pid file holding non-UTF-8 (binary) bytes must read as"]},{"file":"tests/test_hermes_constants.py","hunks":["@@ -2,6 +2,7 @@\n \n import os\n from pathlib import Path\n+from types import SimpleNamespace\n \n import pytest\n ","@@ -611,6 +612,43 @@ def test_npx_fallback_form_accepted(self):\n         assert agent_browser_runnable(\"npx agent-browser\") is True\n         assert agent_browser_runnable(\"/usr/local/bin/npx agent-browser\") is True\n \n+    def test_version_probe_uses_windows_hide_flags(self, tmp_path, monkeypatch):\n+        good = self._stub(tmp_path, \"agent-browser\", \"#!/bin/sh\\necho hi\\n\")\n+        captured = []\n+\n+        def fake_run(cmd, **kwargs):\n+            captured.append((cmd, kwargs))\n+            return SimpleNamespace(returncode=0)\n+\n+        import hermes_cli._subprocess_compat as subprocess_compat\n+        import subprocess as subprocess_mod\n+\n+        monkeypatch.setattr(subprocess_compat, \"windows_hide_flags\", lambda: 0x08000000)\n+        monkeypatch.setattr(subprocess_mod, \"run\", fake_run)\n+\n+        assert agent_browser_runnable(str(good)) is True\n+        assert captured[0][0] == [str(good), \"--version\"]\n+        assert captured[0][1][\"creationflags\"] == 0x08000000\n+\n+\n+    def test_node_tool_probe_uses_windows_hide_flags(self, tmp_path, monkeypatch):\n+        good = self._stub(tmp_path, \"node\", \"#!/bin/sh\\necho v22\\n\")\n+        captured = []\n+\n+        def fake_run(cmd, **kwargs):\n+            captured.append((cmd, kwargs))\n+            return SimpleNamespace(returncode=0)\n+\n+        import hermes_cli._subprocess_compat as subprocess_compat\n+        import subprocess as subprocess_mod\n+\n+        monkeypatch.setattr(subprocess_compat, \"windows_hide_flags\", lambda: 0x08000000)\n+        monkeypatch.setattr(subprocess_mod, \"run\", fake_run)\n+\n+        assert node_tool_runnable(str(good)) is True\n+        assert captured[0][0] == [str(good), \"--version\"]\n+        assert captured[0][1][\"creationflags\"] == 0x08000000\n+\n \n class TestGetHermesDir:\n     \"\"\"Tests for ``get_hermes_dir(new_subpath, old_name)``."]},{"file":"tests/test_windows_subprocess_no_window_flags.py","hunks":["@@ -299,3 +299,29 @@ def fake_run(cmd, **kwargs):\n \n     assert captured[0][0][0] == \"ffmpeg\"\n     assert captured[0][1][\"creationflags\"] == _CREATE_NO_WINDOW\n+\n+def test_tui_slash_worker_hides_python_window(monkeypatch):\n+    from tui_gateway import server\n+\n+    captured = []\n+\n+    class _Proc:\n+        stdin = SimpleNamespace()\n+        stdout = []\n+        stderr = []\n+\n+    def fake_popen(cmd, **kwargs):\n+        captured.append((cmd, kwargs))\n+        return _Proc()\n+\n+    monkeypatch.setattr(server.subprocess, \"Popen\", fake_popen)\n+    monkeypatch.setattr(server.threading, \"Thread\", lambda *a, **k: SimpleNamespace(start=lambda: None))\n+\n+    import hermes_cli._subprocess_compat as subprocess_compat\n+\n+    monkeypatch.setattr(subprocess_compat, \"windows_hide_flags\", lambda: _CREATE_NO_WINDOW)\n+\n+    server._SlashWorker(\"session-key\", \"model-x\")\n+\n+    assert captured[0][0][:3] == [server.sys.executable, \"-m\", \"tui_gateway.slash_worker\"]\n+    assert captured[0][1][\"creationflags\"] == _CREATE_NO_WINDOW"]},{"file":"tests/tools/test_browser_chromium_check.py","hunks":["@@ -76,7 +76,7 @@ class TestCheckBrowserRequirementsChromium:\n \n     def test_local_mode_with_chromium_returns_true(self, monkeypatch, tmp_path):\n         monkeypatch.setattr(bt, \"_is_camofox_mode\", lambda: False)\n-        monkeypatch.setattr(bt, \"_find_agent_browser\", lambda: \"/usr/local/bin/agent-browser\")\n+        monkeypatch.setattr(bt, \"_find_agent_browser\", lambda **_kw: \"/usr/local/bin/agent-browser\")\n         monkeypatch.setattr(bt, \"_requires_real_termux_browser_install\", lambda _: False)\n         monkeypatch.setattr(bt, \"_get_cloud_provider\", lambda: None)\n         monkeypatch.setenv(\"PLAYWRIGHT_BROWSERS_PATH\", str(tmp_path))","@@ -93,7 +93,7 @@ def provider_name(self):\n                 return \"browserbase\"\n \n         monkeypatch.setattr(bt, \"_is_camofox_mode\", lambda: False)\n-        monkeypatch.setattr(bt, \"_find_agent_browser\", lambda: \"/usr/local/bin/agent-browser\")\n+        monkeypatch.setattr(bt, \"_find_agent_browser\", lambda **_kw: \"/usr/local/bin/agent-browser\")\n         monkeypatch.setattr(bt, \"_requires_real_termux_browser_install\", lambda _: False)\n         monkeypatch.setattr(bt, \"_get_cloud_provider\", lambda: FakeProvider())\n         # Point chromium search at an empty dir — should not matter for cloud.","@@ -102,6 +102,23 @@ def provider_name(self):\n \n         assert bt.check_browser_requirements() is True\n \n+    def test_startup_check_uses_lightweight_agent_browser_lookup(self, monkeypatch, tmp_path):\n+        seen = []\n+\n+        def fake_find_agent_browser(**kwargs):\n+            seen.append(kwargs)\n+            return \"/usr/local/bin/agent-browser\"\n+\n+        monkeypatch.setattr(bt, \"_is_camofox_mode\", lambda: False)\n+        monkeypatch.setattr(bt, \"_find_agent_browser\", fake_find_agent_browser)\n+        monkeypatch.setattr(bt, \"_requires_real_termux_browser_install\", lambda _: False)\n+        monkeypatch.setattr(bt, \"_get_cloud_provider\", lambda: None)\n+        monkeypatch.setenv(\"PLAYWRIGHT_BROWSERS_PATH\", str(tmp_path))\n+        (tmp_path / \"chromium-1208\").mkdir()\n+\n+        assert bt.check_browser_requirements() is True\n+        assert seen == [{\"validate\": False}]\n+\n     def test_camofox_mode_does_not_require_chromium(self, monkeypatch, tmp_path):\n         monkeypatch.setattr(bt, \"_is_camofox_mode\", lambda: True)\n         # Even with no chromium on disk, camofox drives its own backend."]},{"file":"tests/tools/test_browser_homebrew_paths.py","hunks":["@@ -222,7 +222,7 @@ def test_termux_requires_real_agent_browser_install_not_npx_fallback(self, monke\n         monkeypatch.setenv(\"PREFIX\", \"/data/data/com.termux/files/usr\")\n         monkeypatch.setattr(\"tools.browser_tool._is_camofox_mode\", lambda: False)\n         monkeypatch.setattr(\"tools.browser_tool._get_cloud_provider\", lambda: None)\n-        monkeypatch.setattr(\"tools.browser_tool._find_agent_browser\", lambda: \"npx agent-browser\")\n+        monkeypatch.setattr(\"tools.browser_tool._find_agent_browser\", lambda **_kw: \"npx agent-browser\")\n \n         assert check_browser_requirements() is False\n ","@@ -231,7 +231,7 @@ class TestRunBrowserCommandTermuxFallback:\n     def test_termux_local_mode_rejects_bare_npx_fallback(self, monkeypatch):\n         monkeypatch.setenv(\"TERMUX_VERSION\", \"0.118.3\")\n         monkeypatch.setenv(\"PREFIX\", \"/data/data/com.termux/files/usr\")\n-        monkeypatch.setattr(\"tools.browser_tool._find_agent_browser\", lambda: \"npx agent-browser\")\n+        monkeypatch.setattr(\"tools.browser_tool._find_agent_browser\", lambda **_kw: \"npx agent-browser\")\n         monkeypatch.setattr(\"tools.browser_tool._get_cloud_provider\", lambda: None)\n \n         result = _run_browser_command(\"task-1\", \"navigate\", [\"https://example.com\"])"]},{"file":"tools/browser_tool.py","hunks":["@@ -2002,7 +2002,15 @@ def _get_session_info(task_id: Optional[str] = None) -> Dict[str, str]:\n \n \n \n-def _find_agent_browser() -> str:\n+def _agent_browser_candidate_present(path: str | None) -> bool:\n+    if not path:\n+        return False\n+    if \" \" in path and path.split()[0].endswith(\"npx\"):\n+        return True\n+    return os.path.exists(path) and (os.name == \"nt\" or os.access(path, os.X_OK))\n+\n+\n+def _find_agent_browser(*, validate: bool = True) -> str:\n     \"\"\"\n     Find the agent-browser CLI executable.\n ","@@ -2041,7 +2049,11 @@ def _find_agent_browser() -> str:\n \n     # Check if it's in PATH (global install)\n     which_result = shutil.which(\"agent-browser\")\n-    if which_result and agent_browser_runnable(which_result):\n+    if which_result and (\n+        agent_browser_runnable(which_result) if validate else _agent_browser_candidate_present(which_result)\n+    ):\n+        if not validate:\n+            return which_result\n         _cached_agent_browser = which_result\n         _agent_browser_resolved = True\n         return which_result","@@ -2051,7 +2063,11 @@ def _find_agent_browser() -> str:\n     extended_path = _merge_browser_path(\"\")\n     if extended_path:\n         which_result = shutil.which(\"agent-browser\", path=extended_path)\n-        if which_result and agent_browser_runnable(which_result):\n+        if which_result and (\n+            agent_browser_runnable(which_result) if validate else _agent_browser_candidate_present(which_result)\n+        ):\n+            if not validate:\n+                return which_result\n             _cached_agent_browser = which_result\n             _agent_browser_resolved = True\n             return which_result","@@ -2068,7 +2084,11 @@ def _find_agent_browser() -> str:\n     local_bin_dir = repo_root / \"node_modules\" / \".bin\"\n     if local_bin_dir.is_dir():\n         local_which = shutil.which(\"agent-browser\", path=str(local_bin_dir))\n-        if local_which and agent_browser_runnable(local_which):\n+        if local_which and (\n+            agent_browser_runnable(local_which) if validate else _agent_browser_candidate_present(local_which)\n+        ):\n+            if not validate:\n+                return local_which\n             _cached_agent_browser = local_which\n             _agent_browser_resolved = True\n             return _cached_agent_browser","@@ -2078,10 +2098,15 @@ def _find_agent_browser() -> str:\n     if not npx_path and extended_path:\n         npx_path = shutil.which(\"npx\", path=extended_path)\n     if npx_path:\n+        if not validate:\n+            return \"npx agent-browser\"\n         _cached_agent_browser = \"npx agent-browser\"\n         _agent_browser_resolved = True\n         return _cached_agent_browser\n \n+    if not validate:\n+        raise FileNotFoundError(\"agent-browser CLI not found\")\n+\n     # Nothing found — try lazy installation before giving up.\n     try:\n         from hermes_cli.dep_ensure import ensure_dependency","@@ -4206,8 +4231,12 @@ def check_browser_requirements() -> bool:\n         return True\n \n     # The agent-browser CLI is required for local launch and cloud-provider flows.\n+    # Tool-schema assembly runs during Desktop startup; do not execute\n+    # ``agent-browser --version`` here, because Windows .cmd shims route through\n+    # cmd.exe and can flash a console before the user invokes any browser tool.\n+    # Actual browser execution paths still validate the candidate before use.\n     try:\n-        browser_cmd = _find_agent_browser()\n+        browser_cmd = _find_agent_browser(validate=False)\n     except FileNotFoundError:\n         return False\n "]},{"file":"tui_gateway/server.py","hunks":["@@ -278,6 +278,8 @@ def __init__(self, session_key: str, model: str):\n             argv += [\"--model\", model]\n \n         self._closed = False\n+        from hermes_cli._subprocess_compat import windows_hide_flags\n+\n         self.proc = subprocess.Popen(\n             argv,\n             stdin=subprocess.PIPE,","@@ -289,6 +291,7 @@ def __init__(self, session_key: str, model: str):\n             # slash_worker runs the Hermes agent → needs provider credentials.\n             # Tier-1 secrets (gateway/GitHub/infra) are still stripped (#29157).\n             env=hermes_subprocess_env(inherit_credentials=[redacted:secret-assignment]\n+            creationflags=windows_hide_flags(),\n         )\n         threading.Thread(target=self._drain_stdout, daemon=True).start()\n         threading.Thread(target=self._drain_stderr, daemon=True).start()\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}