From 2db47cc9fb35ee8b5864f59fa8f8018e471e5140 Mon Sep 17 00:00:00 2001 From: fabiantax Date: Mon, 14 Sep 2026 13:30:49 +0200 Subject: [PATCH] fix(cron): strip interactive presence vars from external worker env Gateway sets HERMES_EXEC_ASK=1 (interactive launches set HERMES_INTERACTIVE / HERMES_GATEWAY_SESSION) at runtime; systemd-run cron workers inherited them, _is_interactive_cli() then bypassed approvals.cron_mode for terminal and every run hung on a pending card nobody could answer (fab-swarm #105: ms197 lane left 6 claims stranded, 10-30s hangs). Local mitigation; upstream report to follow. --- cron/scheduler.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cron/scheduler.py b/cron/scheduler.py index d9c6ae21c6..f7474e387e 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -3261,6 +3261,18 @@ def _launch_external_cron_worker(job: dict) -> bool: finally: _reset_fire_secret_scope(fire_scope_tokens) worker_env = systemd_user_bus_env(worker_env) + # Cron workers are unattended: presence vars inherited from a gateway that + # set them at runtime (start_gateway sets HERMES_EXEC_ASK; interactive + # launches set the rest) invert the approval gate — `_is_interactive_cli()` + # sees HERMES_INTERACTIVE=1 and `approvals.cron_mode` is never consulted for + # `terminal`, so the run hangs 10-30s on a pending card nobody can answer + # (measured 2026-09-14: ms197 cron left 6 claims stranded; fab-swarm #105). + for _presence_var in ( + "HERMES_INTERACTIVE", + "HERMES_GATEWAY_SESSION", + "HERMES_EXEC_ASK", + ): + worker_env.pop(_presence_var, None) try: process = subprocess.Popen( dispatch.argv,