diff --git a/tests/conftest.py b/tests/conftest.py index a1d0a034c5..00644ab7e6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -264,6 +264,12 @@ _HERMES_BEHAVIORAL_VARS = frozenset({ "HERMES_VOICE", "HERMES_VOICE_TTS", "HERMES_YOLO_MODE", + # Injected into subprocess envs by the terminal tool (_make_run_env), so + # any test run launched FROM a Hermes agent session inherits them and + # hermes_constants home-resolution helpers prefer them over monkeypatched + # HOME (test_subprocess_home_isolation red locally, green on CI). + "HERMES_REAL_HOME", + "TERMINAL_HOME_MODE", "HERMES_INTERACTIVE", "HERMES_QUIET", "HERMES_TOOL_PROGRESS", diff --git a/tests/hermes_cli/test_noninteractive_git.py b/tests/hermes_cli/test_noninteractive_git.py index 1150ab6111..2b8e48b814 100644 --- a/tests/hermes_cli/test_noninteractive_git.py +++ b/tests/hermes_cli/test_noninteractive_git.py @@ -84,6 +84,16 @@ def test_git_clone_against_auth_remote_fails_fast(tmp_path: Path): thread.start() try: t0 = time.monotonic() + env = noninteractive_git_env() + # noninteractive_git_env deliberately leaves GIT_ASKPASS/SSH_ASKPASS + # alone so a user's WORKING helper can still authenticate. This test + # asserts the no-helper fail-fast path, so strip them — otherwise a + # dev shell's VS Code askpass helper (GIT_ASKPASS=...askpass.sh) + # blocks waiting on the editor and the clone times out locally. + for var in ("GIT_ASKPASS", "SSH_ASKPASS", "VSCODE_GIT_ASKPASS_NODE", + "VSCODE_GIT_ASKPASS_MAIN", "VSCODE_GIT_ASKPASS_EXTRA_ARGS", + "VSCODE_GIT_IPC_HANDLE"): + env.pop(var, None) proc = subprocess.run( ["git", "clone", f"http://127.0.0.1:{port}/private.git", str(tmp_path / "dest")], @@ -91,7 +101,7 @@ def test_git_clone_against_auth_remote_fails_fast(tmp_path: Path): text=True, timeout=30, stdin=subprocess.DEVNULL, - env=noninteractive_git_env(), + env=env, ) elapsed = time.monotonic() - t0 assert proc.returncode != 0 diff --git a/tests/tools/test_modal_sandbox_fixes.py b/tests/tools/test_modal_sandbox_fixes.py index 6238f4710e..89878150dc 100644 --- a/tests/tools/test_modal_sandbox_fixes.py +++ b/tests/tools/test_modal_sandbox_fixes.py @@ -391,10 +391,19 @@ class TestDockerHostBindApproval: config permanently allowlists e.g. "delete in root path" the guard under test silently approves and the assertions flip. CI never has such an allowlist, making this a local-only flake. + + Same import-time freeze applies to ``_YOLO_MODE_FROZEN``: it reads + HERMES_YOLO_MODE off the environment when the module is imported at + collection time, before conftest's per-test env blanking runs. A test + run launched from a --yolo Hermes session (or any shell exporting + HERMES_YOLO_MODE=1) freezes True and every guard auto-approves. + Reset it explicitly so the tests exercise the guard, not the bypass. """ import tools.approval as A monkeypatch.setattr(A, "_permanent_approved", set()) monkeypatch.setattr(A, "_session_approved", {}) + monkeypatch.setattr(A, "_YOLO_MODE_FROZEN", False) + monkeypatch.setattr(A, "_get_approval_mode", lambda: "manual") def test_host_bound_docker_requires_approval(self, monkeypatch): """Host-bound Docker dangerous command escalates instead of bypassing."""