From 8895adf24cf95549c6de58d9fd9e7ca22c1ce13b Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Sun, 9 Aug 2026 01:54:27 +0900 Subject: [PATCH] fix: decode harness git output as utf-8 --- scripts/execute.py | 6 ++++-- tests/test_execute.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/scripts/execute.py b/scripts/execute.py index 25e5232..953a7a6 100644 --- a/scripts/execute.py +++ b/scripts/execute.py @@ -58,7 +58,7 @@ class StepExecutor: """Phase 디렉토리 안의 step들을 순차 실행하는 하네스.""" MAX_RETRIES = 3 - FEAT_MSG = "feat({phase}): step {num} — {name}" + FEAT_MSG = "feat({phase}): step {num} - {name}" CHORE_MSG = "chore({phase}): step {num} output" TZ = timezone(timedelta(hours=9)) @@ -112,7 +112,9 @@ class StepExecutor: def _run_git(self, *args) -> subprocess.CompletedProcess: cmd = ["git"] + list(args) - return subprocess.run(cmd, cwd=self._root, capture_output=True, text=True) + return subprocess.run( + cmd, cwd=self._root, capture_output=True, text=True, encoding="utf-8" + ) def _checkout_branch(self): branch = f"feat-{self._phase_name}" diff --git a/tests/test_execute.py b/tests/test_execute.py index 8b0f216..de9d7c1 100644 --- a/tests/test_execute.py +++ b/tests/test_execute.py @@ -34,3 +34,28 @@ def test_invoke_codex_uses_utf8_for_unicode_prompt(tmp_path, monkeypatch): assert "Euler–Bernoulli 보" in invocation["kwargs"]["input"] assert invocation["kwargs"]["encoding"] == "utf-8" + + +def test_run_git_decodes_output_as_utf8(tmp_path, monkeypatch): + invocation = {} + + def capture_run(command, **kwargs): + invocation["command"] = command + invocation["kwargs"] = kwargs + return subprocess.CompletedProcess(command, 0, stdout="", stderr="") + + monkeypatch.setattr(execute.subprocess, "run", capture_run) + executor = object.__new__(execute.StepExecutor) + executor._root = str(tmp_path) + + executor._run_git("status", "--short") + + assert invocation["kwargs"]["encoding"] == "utf-8" + + +def test_feature_commit_message_is_windows_console_safe(): + message = execute.StepExecutor.FEAT_MSG.format( + phase="linear-static-3d-euler-beam", num=0, name="requirements-baseline" + ) + + message.encode("cp949")