Files
hermes-agent/tests/tools/test_cron_not_interactive.py
teknium1 04fcf9159c fix: keep api_server approval bridge and cron self-scheduling after presence strip
Widening the _presence() clearing from single-query to every unattended
context also cleared is_ask for platform=api_server. That surface answers
approvals through the /v1/runs bridge (approval.request ->
POST /v1/runs/{id}/approval), so a dangerous command that used to park in
waiting_for_approval became an instant BLOCK with no approval.request.
Restrict the clearing to single-query + cron, where nobody can answer.

Stripping HERMES_INTERACTIVE/HERMES_GATEWAY_SESSION/HERMES_EXEC_ASK from
the external worker env also made check_cronjob_requirements() False, so
the cronjob toolset vanished for every job on a managed-systemd gateway
even with cron.allow_agent_scheduling: true. Accept the existing
HERMES_CRON_SESSION marker (set by run_one_job's context) as well.

Review finding: _presence() over-widening broke the /v1/runs approval bridge; env strip hid the cronjob toolset in external workers.
2026-09-15 03:56:17 -07:00

42 lines
1.8 KiB
Python

"""Unattended approval contexts never resolve as interactive (#110932).
A gateway sets HERMES_EXEC_ASK=1 at startup and hands its environ to every external cron
worker; interactive launches export HERMES_INTERACTIVE=1. Inside cron nobody can answer the
card, so ``_presence()`` must clear the trio and let the gate resolve from
``approvals.cron_mode``. Unattended platforms are NOT cleared: api_server answers via the
``/v1/runs`` approval bridge, which needs ``is_ask`` intact.
"""
import pytest
from tools import approval as approval_mod
@pytest.fixture
def leaked_presence(monkeypatch):
monkeypatch.setenv("HERMES_INTERACTIVE", "1")
monkeypatch.setenv("HERMES_EXEC_ASK", "1")
monkeypatch.setenv("HERMES_GATEWAY_SESSION", "1")
monkeypatch.delenv("HERMES_CRON_SESSION", raising=False)
monkeypatch.delenv("HERMES_SINGLE_QUERY_SESSION", raising=False)
monkeypatch.delenv("HERMES_SESSION_PLATFORM", raising=False)
def test_cron_context_clears_leaked_presence(monkeypatch, leaked_presence):
monkeypatch.setenv("HERMES_CRON_SESSION", "1")
_, is_cli, is_gateway, is_ask = approval_mod._presence()
assert (is_cli, is_gateway, is_ask) == (False, False, False)
def test_interactive_session_keeps_presence(monkeypatch, leaked_presence):
_, is_cli, is_gateway, is_ask = approval_mod._presence()
assert (is_cli, is_gateway, is_ask) == (True, True, True)
def test_api_server_platform_keeps_exec_ask_for_runs_approval_bridge(monkeypatch, leaked_presence):
"""api_server resolves approvals via ``approval.request`` → ``POST /v1/runs/{id}/approval``;
clearing ``is_ask`` there would turn every dangerous command into an instant BLOCK."""
monkeypatch.setenv("HERMES_SESSION_PLATFORM", "api_server")
_, _, _, is_ask = approval_mod._presence()
assert is_ask is True