From a73bcd248fe8ab31ecb059fa78c69e976988889e Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Wed, 12 Aug 2026 11:47:45 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B3=B5=EA=B0=9C=20=EB=9F=B0=ED=83=80?= =?UTF-8?q?=EC=9E=84=20=ED=94=84=EB=A1=9C=EB=B8=8C=20=EB=B3=B5=EA=B5=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/boot-public-runtime.ps1 | 11 ++- scripts/start-public-runtime.ps1 | 11 ++- ...test_public_runtime_watchdog_provenance.py | 74 +++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/scripts/boot-public-runtime.ps1 b/scripts/boot-public-runtime.ps1 index ff9b33c..8704cd8 100644 --- a/scripts/boot-public-runtime.ps1 +++ b/scripts/boot-public-runtime.ps1 @@ -240,8 +240,15 @@ function Test-VoiceSidecarStack { "--tts-language", "KR", "--timeout-seconds", "5" ) - & $Python @probeArgs 1>$null 2>$null - return $LASTEXITCODE -eq 0 + $previousErrorActionPreference = $ErrorActionPreference + try { + $ErrorActionPreference = "Continue" + & $Python @probeArgs 1>$null 2>$null + $probeExit = $LASTEXITCODE + } finally { + $ErrorActionPreference = $previousErrorActionPreference + } + return $probeExit -eq 0 } Write-BootLog "================ boot start ================" diff --git a/scripts/start-public-runtime.ps1 b/scripts/start-public-runtime.ps1 index 3f5c735..e6c3efe 100644 --- a/scripts/start-public-runtime.ps1 +++ b/scripts/start-public-runtime.ps1 @@ -139,8 +139,15 @@ function Test-VoiceSidecarReady { "--tts-language", $MeloTtsLanguage, "--timeout-seconds", "5" ) - & $Python @probeArgs 1>$null 2>$null - return $LASTEXITCODE -eq 0 + $previousErrorActionPreference = $ErrorActionPreference + try { + $ErrorActionPreference = "Continue" + & $Python @probeArgs 1>$null 2>$null + $probeExit = $LASTEXITCODE + } finally { + $ErrorActionPreference = $previousErrorActionPreference + } + return $probeExit -eq 0 } function Wait-VoiceSidecarReady { diff --git a/scripts/test_public_runtime_watchdog_provenance.py b/scripts/test_public_runtime_watchdog_provenance.py index 86dee61..4807e16 100644 --- a/scripts/test_public_runtime_watchdog_provenance.py +++ b/scripts/test_public_runtime_watchdog_provenance.py @@ -24,6 +24,7 @@ INSTALLER_SOURCE = INSTALLER.read_text(encoding="utf-8") BOOT_SOURCE = BOOT.read_text(encoding="utf-8") BOOT_REGISTER_SOURCE = BOOT_REGISTER.read_text(encoding="utf-8") HIDDEN_TRIGGER_SOURCE = HIDDEN_TRIGGER.read_text(encoding="utf-8") +START_SOURCE = START.read_text(encoding="utf-8") RUNBOOK_SOURCE = RUNBOOK.read_text(encoding="utf-8") LOCAL_DEVELOPMENT_SOURCE = LOCAL_DEVELOPMENT.read_text(encoding="utf-8") @@ -264,6 +265,79 @@ if ($result.Detail -ne 'exact readiness probe failed') { msg=f"stdout={completed.stdout}\nstderr={completed.stderr}", ) + def test_boolean_sidecar_probes_survive_native_stderr_under_powershell_51(self) -> None: + powershell = shutil.which("powershell.exe") + python = shutil.which("python.exe") + if powershell is None or python is None: + self.skipTest("Windows PowerShell 5.1 and Python are required") + + contracts = ( + ( + START_SOURCE[ + START_SOURCE.index("function Test-VoiceSidecarReady") : + START_SOURCE.index("function Wait-VoiceSidecarReady") + ].strip(), + "$result = Test-VoiceSidecarReady -Component 'stt'", + "start", + ), + ( + BOOT_SOURCE[ + BOOT_SOURCE.index("function Test-VoiceSidecarStack") : + BOOT_SOURCE.index('Write-BootLog "================ boot start') + ].strip(), + "$result = Test-VoiceSidecarStack", + "boot", + ), + ) + python_escaped = python.replace("'", "''") + probe_escaped = str(VOICE_PROBE).replace("'", "''") + + with tempfile.TemporaryDirectory() as temporary_directory: + for contract, invocation, role in contracts: + harness = Path(temporary_directory) / f"{role}-probe-contract.ps1" + harness.write_text( + "$ErrorActionPreference = 'Stop'\n" + + f"$Python = '{python_escaped}'\n" + + f"$VoiceSidecarProbe = '{probe_escaped}'\n" + + f"$voiceSidecarProbe = '{probe_escaped}'\n" + + "$WhisperPort = 1\n" + + "$MeloTtsPort = 2\n" + + "$WhisperModel = 'small'\n" + + "$WhisperLanguage = 'ko'\n" + + "$WhisperDevice = 'cpu'\n" + + "$MeloTtsModel = 'melotts-korean'\n" + + "$MeloTtsLanguage = 'KR'\n" + + contract + + "\n" + + invocation + + "\nif ($result) { throw 'unreachable sidecars were accepted' }\n", + encoding="utf-8-sig", + ) + completed = subprocess.run( + [ + powershell, + "-NoLogo", + "-NoProfile", + "-NonInteractive", + "-ExecutionPolicy", + "Bypass", + "-File", + str(harness), + ], + capture_output=True, + text=True, + encoding="utf-8", + errors="replace", + timeout=30, + check=False, + ) + with self.subTest(role=role): + self.assertEqual( + completed.returncode, + 0, + msg=f"stdout={completed.stdout}\nstderr={completed.stderr}", + ) + def test_hidden_trigger_never_executes_a_workspace_script_directly(self) -> None: for expected in ( "VignettePublicRuntimeWatchdog",