{"repo":"NousResearch/hermes-agent","public_id":"22351","display_label":"Cron origin misidentified as live gateway sender","summary":"These items address a bug where cron delivery origin was incorrectly seeding or being treated as a live gateway sender identity, affecting tool access-control and session context variables.","subsystem":null,"counts":{"members":3,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":22382,"merged_at":"2026-05-09T07:57:27+00:00"},"resolution":{"state":"resolved","by":"pr-22382"},"freshness":{"state":"verified","last_verified_at":"2026-05-09T07:57:27+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.6666666666666666},"fix_edges":[{"issue_number":22351,"pr_number":22382,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-05-09T07:57:27+00:00"}],"members":[{"kind":"issue","number":22351,"title":"Cron delivery origin should not seed live gateway sender identity for tool access-control","url":null,"state":"closed"},{"kind":"pr","number":22356,"title":"fix(cron): do not treat delivery origin as live gateway sender identity","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"dbafa083b","number":0},{"kind":"pr","value":"#22382","number":22382},{"kind":"pr","value":"#22351","number":22351}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":22382,"title":"fix(cron): do not seed HERMES_SESSION_* contextvars from cron origin (salvage of #22356)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["cron/scheduler.py","scripts/release.py"],"fix_hunks":[{"file":"cron/scheduler.py","hunks":["@@ -1204,10 +1204,31 @@ def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]:\n     # don't clobber each other's targets (os.environ is process-global).\n     from gateway.session_context import set_session_vars, clear_session_vars, _VAR_MAP\n \n+    # Cron execution is an internal scheduler context, not a live inbound\n+    # gateway message. Do not seed HERMES_SESSION_* contextvars from the\n+    # stored ``origin`` (which is delivery routing metadata, not a sender\n+    # identity). Several tool consumers branch on these vars during job\n+    # execution and would otherwise behave as if a real user from the\n+    # origin chat was driving the agent:\n+    #   - tools/terminal_tool.py: background-process notification routing\n+    #     (notify_on_complete / watch_patterns) reads HERMES_SESSION_PLATFORM\n+    #     and HERMES_SESSION_CHAT_ID to populate watcher_platform / chat_id,\n+    #     which would route completion notifications to the origin chat\n+    #     instead of via HERMES_CRON_AUTO_DELIVER_* below.\n+    #   - tools/tts_tool.py: picks Opus vs MP3 based on\n+    #     HERMES_SESSION_PLATFORM == \"telegram\".\n+    #   - tools/skills_tool.py + agent/prompt_builder.py: per-platform\n+    #     skill-disable lists and the system-prompt cache key both consume\n+    #     HERMES_SESSION_PLATFORM.\n+    #   - tools/send_message_tool.py: mirror source labelling and the\n+    #     send_message gate read HERMES_SESSION_PLATFORM.\n+    # Cron output delivery itself reads job[\"origin\"] directly via\n+    # _resolve_origin(job) and the HERMES_CRON_AUTO_DELIVER_* vars set\n+    # below, so clearing HERMES_SESSION_* here does not affect delivery.\n     _ctx_tokens = set_session_vars(\n-        platform=origin[\"platform\"] if origin else \"\",\n-        chat_id=str(origin[\"chat_id\"]) if origin else \"\",\n-        chat_name=origin.get(\"chat_name\", \"\") if origin else \"\",\n+        platform=\"\",\n+        chat_id=\"\",\n+        chat_name=\"\",\n     )\n     _cron_delivery_vars = (\n         \"HERMES_CRON_AUTO_DELIVER_PLATFORM\","]},{"file":"scripts/release.py","hunks":["@@ -909,6 +909,7 @@\n     \"[redacted:email]\": \"firefly\",  # PR #18123 salvage of #16660 (ContextVars)\n     \"[redacted:email]\": \"WuTianyi123\",  # PR #20275 salvage of #13723 (feishu markdown)\n     \"[redacted:email]\": \"hanzckernel\",  # PR #20311 (api-server approval events)\n+    \"[redacted:email]\": \"oferlaor\",  # PR #22356 salvage (cron origin sender identity)\n     # pander: empty email, salvaged via PR #19665 from #16126 by @ms-alan\n }\n \n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}