{"repo":"NousResearch/hermes-agent","public_id":"17049","display_label":"Windows subprocess Unicode encoding errors and fixes","summary":"These issues and pull requests concern UnicodeDecodeError crashes on Windows when subprocess output uses non-UTF-8 locale encodings (e.g., cp1251, GBK). The members propose various fixes including explicit UTF-8 encoding, errors='replace' fallbacks, and environment variable overrides across multiple components.","subsystem":"acp","counts":{"members":47,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":18,"merged_prs":5,"attempt_prs":24},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":17435},"resolution":{"state":"partially_resolved","by":"pr-17435,pr-38334,pr-70850,pr-70875"},"freshness":{"state":"verified","last_verified_at":"2026-07-24T22:47:12+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.05313598519888989},"fix_edges":[{"issue_number":17049,"pr_number":17435,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":37423,"pr_number":71014,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":38172,"pr_number":38334,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":38633,"pr_number":70875,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":39029,"pr_number":70875,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":39029,"pr_number":71014,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":42384,"pr_number":70875,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":42785,"pr_number":70875,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":46099,"pr_number":71014,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":47939,"pr_number":70875,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":52649,"pr_number":70850,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":53137,"pr_number":70850,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":53428,"pr_number":70875,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":60760,"pr_number":70850,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":60760,"pr_number":70875,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":60760,"pr_number":71014,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":61595,"pr_number":70850,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":63686,"pr_number":70850,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false}],"members":[{"kind":"issue","number":17049,"title":"[Bug]: UnicodeDecodeError and AttributeError in Windows gateway process scanning","url":null,"state":"closed"},{"kind":"issue","number":31420,"title":"[Bug] Windows: subprocess env missing PYTHONUTF8=1 causes UnicodeEncodeError on non-ASCII output in CP936/legacy locales","url":null,"state":"closed"},{"kind":"issue","number":38172,"title":"Windows: hermes gateway status emits UnicodeDecodeError on localized schtasks output","url":null,"state":"closed"},{"kind":"issue","number":39029,"title":"Windows: UnicodeDecodeError in subprocess._readerthread — cp1251 can't decode byte 0x98","url":null,"state":"closed"},{"kind":"issue","number":45140,"title":"[Bug]: UnicodeDecodeError in copilot_acp_client.py _stdout_reader on Windows","url":null,"state":"closed"},{"kind":"issue","number":47939,"title":"[Bug]: BUG_WINDOWS_UNICODE_SUBPROCESS","url":null,"state":"closed"},{"kind":"issue","number":49491,"title":"UnicodeDecodeError-on-Windows-doctor","url":null,"state":"closed"},{"kind":"issue","number":49492,"title":"Bug-Windows-UnicodeDecodeError-doctor","url":null,"state":"closed"},{"kind":"issue","number":49496,"title":"hermes doctor crashes with UnicodeDecodeError on Chinese Windows GBK locale","url":null,"state":"closed"},{"kind":"issue","number":49499,"title":"hermes doctor crashes with UnicodeDecodeError on Chinese Windows GBK locale","url":null,"state":"closed"},{"kind":"issue","number":52649,"title":"Windows: Gateway crashes with UnicodeDecodeError (cp950) in _readerthread — causes zombie cycle every ~580s","url":null,"state":"closed"},{"kind":"issue","number":53137,"title":"fix: TUI gateway crash on Windows - UnicodeDecodeError in subprocess _readerthread","url":null,"state":"closed"},{"kind":"issue","number":53428,"title":"subprocess.run(text=True) without encoding param triggers GBK crash on Chinese Windows (21 locations)","url":null,"state":"closed"},{"kind":"issue","number":55020,"title":"Windows Chinese locale (GBK) causes subprocess._readerthread UnicodeDecodeError crash","url":null,"state":"closed"},{"kind":"issue","number":57238,"title":"Bug: GBK encoding crash on Chinese Windows[Bug] GBK encoding crash in terminal tool on Chinese Windows (cp936)","url":null,"state":"closed"},{"kind":"issue","number":60760,"title":"[Windows] Detached gateway crashes with `UnicodeDecodeError: 'gbk'` when a spawned child process emits UTF-8 output","url":null,"state":"closed"},{"kind":"issue","number":61595,"title":"[Windows] subprocess._readerthread crashes with UnicodeDecodeError on GBK output","url":null,"state":"closed"},{"kind":"issue","number":63686,"title":"Windows CJK locale: UnicodeDecodeError in _SlashWorker crashes gateway (text=True defaults to GBK)","url":null,"state":"closed"},{"kind":"pr","number":17073,"title":"fix(gateway): handle wmic UnicodeDecodeError gracefully","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#17074","number":17074},{"kind":"pr","value":"#17049","number":17049}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":17074,"title":"Fix UnicodeDecodeError in Windows wmic process scanning  #17049","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"cf83982da","number":0},{"kind":"pr","value":"#17049","number":17049}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":17123,"title":"fix(update): protect dashboard wmic scan against UnicodeDecodeError on Windows non-UTF-8 locales (#17049)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#17435","number":17435}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":17252,"title":"fix(gateway): handle wmic encoding errors on Windows non-English locales","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#17435","number":17435}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":17271,"title":"fix(gateway): add errors='replace' to subprocess.run for Windows wmic compatibility","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#17435","number":17435},{"kind":"pr","value":"#17049","number":17049}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":17435,"title":"fix(windows): decode wmic output with explicit encoding to survive non-UTF-8 locales (#17049)","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["hermes_cli/gateway.py","hermes_cli/main.py","scripts/release.py","tests/hermes_cli/test_update_stale_dashboard.py"],"fix_hunks":[{"file":"hermes_cli/gateway.py","hunks":["@@ -279,9 +279,11 @@ def _matches_current_profile(command: str) -> bool:\n                 [\"wmic\", \"process\", \"get\", \"ProcessId,CommandLine\", \"/FORMAT:LIST\"],\n                 capture_output=True,\n                 text=True,\n+                encoding=\"utf-8\",\n+                errors=\"ignore\",\n                 timeout=10,\n             )\n-            if result.returncode != 0:\n+            if result.returncode != 0 or result.stdout is None:\n                 return []\n             current_cmd = \"\"\n             for line in result.stdout.split(\"\\n\"):"]},{"file":"hermes_cli/main.py","hunks":["@@ -5274,12 +5274,20 @@ def _warn_stale_dashboard_processes() -> None:\n \n     try:\n         if sys.platform == \"win32\":\n+            # wmic may emit text in the system code page (for example cp936\n+            # on zh-CN systems), not UTF-8. In text mode, subprocess output\n+            # decoding depends on Python's configuration (locale-dependent\n+            # by default, or UTF-8 in UTF-8 mode). The important protection\n+            # here is errors=\"ignore\": it prevents a reader-thread\n+            # UnicodeDecodeError from leaving result.stdout=None and turning\n+            # the later .split() into an AttributeError (#17049).\n             result = subprocess.run(\n                 [\"wmic\", \"process\", \"get\", \"ProcessId,CommandLine\",\n                  \"/FORMAT:LIST\"],\n                 capture_output=True, text=True, timeout=10,\n+                encoding=\"utf-8\", errors=\"ignore\",\n             )\n-            if result.returncode != 0:\n+            if result.returncode != 0 or result.stdout is None:\n                 return\n             current_cmd = \"\"\n             for line in result.stdout.split(\"\\n\"):"]},{"file":"scripts/release.py","hunks":["@@ -263,6 +263,7 @@\n     \"[redacted:email]\": \"Bartok9\",\n     \"[redacted:email]\": \"CruxExperts\",\n     \"[redacted:email]\": \"LeonSGP43\",\n+    \"[redacted:email]\": \"Kailigithub\",\n     \"[redacted:email]\": \"vlwkaos\",\n     \"[redacted:email]\": \"Tranquil-Flow\",\n     \"[redacted:email]\": \"mcndjxlefnd\","]},{"file":"tests/hermes_cli/test_update_stale_dashboard.py","hunks":["@@ -175,3 +175,55 @@ def test_grep_lines_ignored(self, capsys):\n         output = capsys.readouterr().out\n         assert \"PID 99999\" not in output\n         assert \"PID 12345\" in output\n+\n+\n+class TestWindowsWmicEncoding:\n+    \"\"\"Regression tests for #17049 — the Windows wmic branch must not crash\n+    `hermes update` on non-UTF-8 system locales (e.g. cp936 on zh-CN).\n+    \"\"\"\n+\n+    def test_wmic_invoked_with_utf8_ignore_errors(self, monkeypatch):\n+        \"\"\"The wmic subprocess.run call must pass encoding='utf-8' and\n+        errors='ignore' so the subprocess reader thread cannot raise\n+        UnicodeDecodeError on non-UTF-8 wmic output.\"\"\"\n+        monkeypatch.setattr(sys, \"platform\", \"win32\")\n+        with patch(\"subprocess.run\") as mock_run:\n+            # Provide a minimal valid wmic /FORMAT:LIST response.\n+            mock_run.return_value = MagicMock(\n+                returncode=0,\n+                stdout=(\n+                    \"CommandLine=python -m hermes_cli.main dashboard\\n\"\n+                    \"ProcessId=12345\\n\"\n+                ),\n+                stderr=\"\",\n+            )\n+            _warn_stale_dashboard_processes()\n+\n+        assert mock_run.called, \"subprocess.run was not invoked\"\n+        kwargs = mock_run.call_args.kwargs\n+        assert kwargs.get(\"encoding\") == \"utf-8\", (\n+            \"encoding kwarg must be 'utf-8' so wmic output is decoded \"\n+            \"deterministically rather than via the implicit reader-thread \"\n+            \"default that crashes on non-UTF-8 locales (#17049).\"\n+        )\n+        assert kwargs.get(\"errors\") == \"ignore\", (\n+            \"errors kwarg must be 'ignore' so undecodable bytes don't take \"\n+            \"down the reader thread (#17049).\"\n+        )\n+\n+    def test_wmic_returns_none_stdout_does_not_crash(self, monkeypatch, capsys):\n+        \"\"\"If subprocess.run returns successfully but stdout is None — which\n+        is what Python 3.11 leaves behind when the reader thread silently\n+        crashed on UnicodeDecodeError before this fix landed — the warning\n+        must short-circuit instead of raising AttributeError on\n+        ``None.split('\\\\n')`` and aborting `hermes update` (#17049).\"\"\"\n+        monkeypatch.setattr(sys, \"platform\", \"win32\")\n+        with patch(\"subprocess.run\") as mock_run:\n+            mock_run.return_value = MagicMock(\n+                returncode=0, stdout=None, stderr=\"\"\n+            )\n+            # Must not raise.\n+            _warn_stale_dashboard_processes()\n+\n+        output = capsys.readouterr().out\n+        assert \"dashboard process\" not in output\n"]}]},{"kind":"pr","number":38186,"title":"fix(gateway): decode schtasks output with locale encoding on Windows (#38172)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"973decc05","number":0},{"kind":"commit","value":"df848bd2d","number":0},{"kind":"pr","value":"#38334","number":38334},{"kind":"pr","value":"#38172","number":38172}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":38187,"title":"fix(cli/windows): decode schtasks output with locale encoding to silence UnicodeDecodeError (#38172)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"973decc05048f1d6fe990d5d6457e80389d5f1c5","number":0},{"kind":"pr","value":"#38172","number":38172}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":38334,"title":"fix(gateway): decode schtasks output with locale encoding on Windows (#38172)","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["hermes_cli/gateway_windows.py","tests/hermes_cli/test_gateway_windows.py"],"fix_hunks":[{"file":"hermes_cli/gateway_windows.py","hunks":["@@ -29,6 +29,7 @@\n from __future__ import annotations\n \n import ctypes\n+import locale\n import os\n import re\n import shlex","@@ -52,6 +53,20 @@\n _TASK_DESCRIPTION = \"Hermes Agent Gateway - Messaging Platform Integration\"\n \n \n+def _schtasks_encoding() -> str:\n+    \"\"\"Best-effort console encoding for decoding ``schtasks.exe`` output.\n+\n+    On localized Windows (e.g. Chinese), ``schtasks`` emits text in the OEM/ANSI\n+    code page rather than UTF-8. Decoding with the wrong codec raised\n+    ``UnicodeDecodeError`` inside ``subprocess``' reader threads. Prefer the\n+    locale's preferred encoding and fall back to UTF-8.\n+    \"\"\"\n+    try:\n+        return locale.getpreferredencoding(False) or \"utf-8\"\n+    except Exception:\n+        return \"utf-8\"\n+\n+\n # ---------------------------------------------------------------------------\n # Platform guard\n # ---------------------------------------------------------------------------","@@ -112,6 +127,12 @@ def _exec_schtasks(args: list[str]) -> tuple[int, str, str]:\n             [schtasks, *args],\n             capture_output=True,\n             text=True,\n+            # Localized Windows emits schtasks output in the console code page,\n+            # not UTF-8. Decode with the locale encoding and replace undecodable\n+            # bytes so a non-UTF-8 status line never surfaces a UnicodeDecodeError\n+            # traceback from subprocess' reader threads (issue #38172).\n+            encoding=_schtasks_encoding(),\n+            errors=\"replace\",\n             timeout=_SCHTASKS_TIMEOUT_S,\n             # CREATE_NO_WINDOW avoids a flashing console window when the CLI\n             # is itself hosted in a TUI. See tools/browser_tool.py for the"]},{"file":"tests/hermes_cli/test_gateway_windows.py","hunks":["@@ -29,6 +29,49 @@ def test_schtasks_fallback_does_not_hide_unknown_errors():\n     assert gateway_windows._should_fall_back(1, \"ERROR: The system cannot find the file specified.\") is False\n \n \n+def test_schtasks_encoding_falls_back_to_utf8(monkeypatch):\n+    \"\"\"A broken/empty locale must not leave us without a decoder (issue #38172).\"\"\"\n+\n+    monkeypatch.setattr(gateway_windows.locale, \"getpreferredencoding\", lambda *a, **k: \"\")\n+    assert gateway_windows._schtasks_encoding() == \"utf-8\"\n+\n+    def _boom(*args, **kwargs):\n+        raise RuntimeError(\"locale exploded\")\n+\n+    monkeypatch.setattr(gateway_windows.locale, \"getpreferredencoding\", _boom)\n+    assert gateway_windows._schtasks_encoding() == \"utf-8\"\n+\n+\n+def test_exec_schtasks_decodes_with_replace_errors(monkeypatch):\n+    \"\"\"schtasks output must be decoded with errors='replace' so localized\n+    (non-UTF-8) bytes never surface a UnicodeDecodeError traceback (#38172).\"\"\"\n+\n+    captured: dict[str, object] = {}\n+\n+    class _FakeCompleted:\n+        returncode = 0\n+        stdout = \"ok\"\n+        stderr = \"\"\n+\n+    def fake_run(cmd, **kwargs):\n+        captured[\"cmd\"] = cmd\n+        captured.update(kwargs)\n+        return _FakeCompleted()\n+\n+    monkeypatch.setattr(gateway_windows, \"_assert_windows\", lambda: None)\n+    monkeypatch.setattr(gateway_windows.shutil, \"which\", lambda name: r\"C:\\\\Windows\\\\System32\\\\schtasks.exe\")\n+    monkeypatch.setattr(gateway_windows.subprocess, \"run\", fake_run)\n+\n+    code, out, err = gateway_windows._exec_schtasks([\"/Query\", \"/TN\", \"Hermes_Gateway\"])\n+\n+    assert (code, out, err) == (0, \"ok\", \"\")\n+    assert captured[\"errors\"] == \"replace\", \"schtasks output must decode with errors='replace'\"\n+    assert isinstance(captured[\"encoding\"], str) and captured[\"encoding\"], (\n+        \"an explicit non-empty encoding must be passed to subprocess.run\"\n+    )\n+    assert captured[\"text\"] is True\n+\n+\n def test_build_gateway_argv_uses_base_pythonw_for_uv_venv_launcher(monkeypatch, tmp_path):\n     \"\"\"Avoid uv's venv pythonw launcher because it respawns console python.exe.\"\"\"\n \n"]}]},{"kind":"pr","number":39539,"title":"fix(windows): tolerate localized taskkill decode errors","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"0f732cb3d6","number":0},{"kind":"pr","value":"#70875","number":70875},{"kind":"pr","value":"#55339","number":55339},{"kind":"pr","value":"#60741","number":60741},{"kind":"pr","value":"#60751","number":60751}],"category":"uncategorized","implication":"needs_llm"},"merged":false},{"kind":"pr","number":45099,"title":"fix(tools): add errors='replace' to subprocess.","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#71014","number":71014},{"kind":"pr","value":"#70875","number":70875}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":45144,"title":"fix(windows): set UTF-8 encoding for Copilot ACP subprocess","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#45099","number":45099},{"kind":"pr","value":"#45099","number":45099},{"kind":"pr","value":"#45099","number":45099}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":47951,"title":"fix(environments): pass encoding='utf-8' errors='replace' to all text-mode Popen calls","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#45099","number":45099},{"kind":"pr","value":"#45099","number":45099},{"kind":"pr","value":"#45099","number":45099}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":47993,"title":"fix(subprocess): add UTF-8 encoding to _popen_bash for Windows (#47939)","url":null,"state":"closed","close_reason":{"category":"uncategorized","implication":"needs_llm"},"merged":false},{"kind":"pr","number":48838,"title":"fix(cli): tolerate undecodable alias lookup output","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"c89481db5ec2400e936de6ac402c89e7a39cfe19","number":0},{"kind":"pr","value":"#53428","number":53428}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":48839,"title":"fix(cli): default Windows subprocess text decoding","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#48838","number":48838}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":49510,"title":"fix(doctor): decode subprocess output as UTF-8 on non-UTF-8 (GBK) locales","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"38b67a345","number":0}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":49512,"title":"fix(doctor): pin utf-8/replace decoding for captured subprocesses","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#49510","number":49510},{"kind":"pr","value":"#49499","number":49499},{"kind":"pr","value":"#49510","number":49510}],"category":"superseded_by_pr","implication":"superseded"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":49564,"title":"fix(cli): add encoding to subprocess calls in doctor (#49499)","url":null,"state":"closed","close_reason":{"category":"uncategorized","implication":"needs_llm"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":53460,"title":"fix: add encoding=utf-8, errors=replace to all subprocess text=True calls (#53428)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#54220","number":54220},{"kind":"pr","value":"#54236","number":54236},{"kind":"pr","value":"#53892","number":53892},{"kind":"pr","value":"#54417","number":54417}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":53549,"title":"fix: add encoding='utf-8' to subprocess calls with text=True","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#54220","number":54220},{"kind":"pr","value":"#54236","number":54236},{"kind":"pr","value":"#53892","number":53892},{"kind":"pr","value":"#54417","number":54417}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":55339,"title":"fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#70875","number":70875},{"kind":"pr","value":"#60751","number":60751}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":60832,"title":"fix(windows): force utf8 for detached gateway","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#70850","number":70850},{"kind":"pr","value":"#70875","number":70875},{"kind":"pr","value":"#71014","number":71014}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":61978,"title":"fix: harden tui_gateway subprocess reads against Windows locale UnicodeDecodeError (#53137)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#70850","number":70850}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":63716,"title":"fix(tui): decode slash worker streams as UTF-8","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"ead23aadb9","number":0},{"kind":"pr","value":"#70850","number":70850},{"kind":"pr","value":"#52700","number":52700},{"kind":"pr","value":"#61978","number":61978}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":68546,"title":"fix(doctor): decode subprocess output as utf-8","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"0f732cb3d6","number":0},{"kind":"pr","value":"#70875","number":70875},{"kind":"pr","value":"#55339","number":55339},{"kind":"pr","value":"#60741","number":60741},{"kind":"pr","value":"#60751","number":60751}],"category":"uncategorized","implication":"needs_llm"},"merged":false},{"kind":"pr","number":70850,"title":"fix(windows): utf-8 subprocess decode across the desktop backend — salvage #61978 + widen to sibling sites","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["hermes_cli/banner.py","hermes_cli/web_server.py","tests/tui_gateway/test_subprocess_encoding.py","tui_gateway/compute_host.py","tui_gateway/host_supervisor.py","tui_gateway/server.py"]},{"kind":"pr","number":70875,"title":"fix(windows): close out the text-mode subprocess decode bug class — salvage #55339/#60741/#60751 + full sweep + linter","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["agent/anthropic_adapter.py","agent/context_references.py","agent/copilot_acp_client.py","agent/lsp/install.py","agent/proxy_sources/iron_proxy.py","agent/secret_sources/base.py","agent/secret_sources/bitwarden.py","agent/shell_hooks.py","agent/skill_preprocessing.py","agent/trace_upload.py","agent/transports/codex_app_server.py","batch_runner.py","cli.py","contributors/emails/[redacted:email]","contributors/emails/[redacted:email]","gateway/platforms/base.py","gateway/platforms/webhook.py","gateway/platforms/webhook_filters.py","gateway/run.py","gateway/shutdown_forensics.py","gateway/status.py","hermes_cli/_early_recovery.py","hermes_cli/claw.py","hermes_cli/clipboard.py","hermes_cli/copilot_auth.py","hermes_cli/doctor.py","hermes_cli/dump.py","hermes_cli/gateway.py","hermes_cli/kanban_db.py","hermes_cli/main.py","hermes_cli/managed_uv.py","hermes_cli/onepassword_secrets_cli.py","hermes_cli/plugins_cmd.py","hermes_cli/profiles.py","hermes_cli/secrets_cli.py","hermes_cli/service_manager.py","hermes_cli/setup.py","hermes_cli/tools_config.py","hermes_cli/uninstall.py","hermes_cli/web_git.py","hermes_cli/windows_ssh_runtime.py","optional-skills/creative/kanban-video-orchestrator/scripts/monitor.py","plugins/google_meet/audio_bridge.py","plugins/google_meet/cli.py","plugins/google_meet/meet_bot.py","plugins/memory/byterover/__init__.py","plugins/memory/honcho/client.py","plugins/memory/mem0/_setup.py","plugins/platforms/photon/adapter.py","plugins/platforms/telegram/adapter.py","plugins/platforms/whatsapp/adapter.py","plugins/web/ddgs/provider.py","scripts/check-windows-footguns.py","scripts/ci/lockfile_diff.py","scripts/ci/publish_e2e_evidence.py","scripts/contributor_audit.py","scripts/iso-certify.py","scripts/profile-tui.py","scripts/release.py","scripts/run_tests_parallel.py","skills/creative/comfyui/scripts/auto_fix_deps.py","skills/creative/comfyui/scripts/hardware_check.py","skills/productivity/docx/scripts/accept_changes.py","skills/productivity/docx/scripts/office/validators/redlining.py","skills/productivity/google-workspace/scripts/google_api.py","skills/productivity/powerpoint/scripts/office/validators/redlining.py","skills/productivity/powerpoint/scripts/thumbnail.py","skills/productivity/xlsx/scripts/recalc.py","tests/gateway/test_status.py","tests/gateway/test_webhook_integration.py","tests/gateway/test_whatsapp_connect.py","tests/hermes_cli/test_update_autostash.py","tests/scripts/test_footgun_subprocess_encoding.py","tests/test_windows_subprocess_no_window_flags.py","tests/tools/test_docker_environment.py","tests/tools/test_subprocess_utf8_encoding.py","tools/browser_tool.py","tools/checkpoint_manager.py","tools/computer_use/cua_backend.py","tools/computer_use/permissions.py","tools/environments/base.py","tools/environments/docker.py","tools/environments/local.py","tools/environments/singularity.py","tools/environments/ssh.py","tools/lazy_deps.py","tools/process_registry.py","tools/skills_hub.py","tools/tirith_security.py","tools/transcription_tools.py","tools/tts_tool.py","tools/voice_mode.py"]},{"kind":"pr","number":71014,"title":"fix(windows): residual encoding gaps — MCP stdio, gateway update file-I/O, STT/TTS, desktop spawn, bootstrap ver-stub","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["apps/desktop/electron/backend-env.test.ts","apps/desktop/electron/backend-env.ts","gateway/dead_targets.py","gateway/delivery.py","gateway/platforms/qqbot/adapter.py","gateway/run.py","gateway/slash_commands.py","gateway/status.py","hermes_bootstrap.py","plugins/platforms/discord/adapter.py","plugins/platforms/feishu/adapter.py","plugins/platforms/google_chat/adapter.py","plugins/platforms/google_chat/oauth.py","plugins/platforms/telegram/adapter.py","plugins/platforms/whatsapp/adapter.py","tests/gateway/test_gateway_utf8_encoding.py","tests/test_hermes_bootstrap.py","tests/tools/test_mcp_stdio_encoding_handler.py","tools/mcp_tool.py","tools/transcription_tools.py","tools/tts_tool.py"]}],"trust":{"default_tier":"verified","includes_suggested":false}}