Skip to content

fix(windows): harden gateway scheduled task - #45610

Merged
teknium1 merged 2 commits into
NousResearch:mainfrom
lEWFkRAD:fix/windows-gateway-reboot-survival
Jun 23, 2026
Merged

fix(windows): harden gateway scheduled task#45610
teknium1 merged 2 commits into
NousResearch:mainfrom
lEWFkRAD:fix/windows-gateway-reboot-survival

Conversation

@lEWFkRAD

@lEWFkRAD lEWFkRAD commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Makes the Windows gateway Scheduled Task actually survive reboot/login by closing all three root causes in [Windows] Gateway does not survive reboot - .cmd wrapper killed by console control event + schtasks missing critical XML settings #45599, not just the schtasks-settings one.
  • Creates the task from XML with a logon delay, StartWhenAvailable, battery-safe settings, no 72-hour execution limit, and a RestartOnFailure policy (root cause Support passing morph snapshot id #2).
  • Resolves the detached uv-venv pythonw in the generated wrapper so the launcher does not respawn a console python.exe (root cause #2c).
  • Runs the task through a console-less wscript.exe -> pythonw.exe launcher instead of cmd.exe, so the logon-time CTRL_CLOSE_EVENT can no longer reap the gateway with STATUS_CONTROL_C_EXIT / 0xC000013A (root cause Terminal tool #1 - the one that produced the reported LastTaskResult after every reboot). RestartOnFailure cannot catch 0xC000013A (Windows treats it as a user cancel), so the console has to be eliminated at the source rather than retried.

Why the .vbs launcher
wscript.exe and pythonw.exe are both GUI-subsystem executables with no console, so the Scheduled Task action receives no console control events at logon. The .vbs sets HERMES_HOME / PYTHONIOENCODING / HERMES_GATEWAY_DETACHED / VIRTUAL_ENV / PYTHONPATH on the WScript.Shell process (chaining onto any runtime PYTHONPATH, mirroring the cmd wrapper's ;%PYTHONPATH%) and Runs pythonw directly, window style 0, async. The .cmd wrapper is kept for the Startup-folder fallback and direct /Run paths, so this is a single, scoped change to the reboot path.

Related Issue
Fixes #45599

Type of Change

  • Bug fix

Changes Made

  • Added _build_gateway_vbs_script() + _quote_vbs_string() (mirrors _build_gateway_cmd_script; reuses _resolve_detached_python).
  • _write_task_script() now also renders <task>.vbs next to <task>.cmd.
  • Scheduled Task <Exec> action now runs wscript.exe //B //Nologo "<vbs>" instead of cmd.exe /d /c "<cmd>".
  • Added regression tests for the console-less launcher, spaced-path quoting, runtime PYTHONPATH chaining, the VBScript quoter, and the wscript action in the install XML.

How to Test

  • (Windows) python -m pytest tests/hermes_cli/test_gateway_windows.py
  • python -m ruff check hermes_cli/gateway_windows.py tests/hermes_cli/test_gateway_windows.py
  • python -m py_compile hermes_cli/gateway_windows.py tests/hermes_cli/test_gateway_windows.py
  • python scripts/check-windows-footguns.py hermes_cli/gateway_windows.py tests/hermes_cli/test_gateway_windows.py
  • git diff --check

Checklist

  • Tests added/updated
  • Targeted tests pass (39 passed)
  • Lint passes (ruff)
  • Whitespace check passes
  • Windows footgun scan passes

Screenshots / Logs
Targeted suite:

39 passed in tests/hermes_cli/test_gateway_windows.py

Live wscript.exe -> pythonw.exe smoke test on Windows 11 (launcher built with the new _quote_vbs_string); the child process reported:

{
  "has_console": false,
  "HERMES_HOME": "C:\\Hermes Home",
  "HERMES_GATEWAY_DETACHED": "1",
  "VIRTUAL_ENV": "C:\\venv",
  "PYTHONPATH": "C:\\repo root",
  "cwd": "C:\\dev",
  "argv": ["...\\probe.py", "smoke-arg"]
}

has_console: false is the direct evidence that no console is allocated for the launcher or the gateway, so the logon CTRL_CLOSE_EVENT that produced 0xC000013A can no longer be delivered to it. Env (including spaced values) and cwd all propagate correctly.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Windows gateway hardening: replaces fragile schtasks /TR quoting with a clean Task Scheduler XML definition, adds restart-on-failure policy (PT1M, 999 retries), 30s logon delay, and proper cleanup of temp XML files. Correctly uses LeastPrivilege run level. Test coverage added for uv-safe base pythonw detection. No issues found.


Reviewed by Hermes Agent

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists labels Jun 13, 2026
The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lEWFkRAD

Copy link
Copy Markdown
Contributor Author

Approved by tonydwb. Clean Windows gateway task hardening with proper cleanup and restart policy. Ready for merge.

@lEWFkRAD

Copy link
Copy Markdown
Contributor Author

Approved by tonydwb. Windows-specific scope, safe standalone change.

@teknium1
teknium1 merged commit 433db17 into NousResearch:main Jun 23, 2026
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 24, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause NousResearch#1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kpadilha pushed a commit to kpadilha/hermes-agent that referenced this pull request Jun 24, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pai-scaffolde pushed a commit to pai-scaffolde/hermes-agent that referenced this pull request Jun 28, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause NousResearch#1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause NousResearch#1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause NousResearch#1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeff <jeffrobodie@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nekwo added a commit to nekwo/hermes-agent that referenced this pull request Aug 10, 2026
…om silently running the gateway in a killable console

hermes update's launcher refresh rewrites gateway.cmd + gateway.vbs and
reasons that "the task /TR points at a stable script path, so rewriting the
files retargets it with no schtasks call and no UAC". That holds only when
the registered action already names the .vbs. A task registered before
NousResearch#45610 names the .cmd — a cmd.exe launch that owns a VISIBLE console
window — and no amount of file rewriting changes that. So the exact class of
install the refresh was written to rescue keeps a console-window gateway
forever, and nothing ever says so.

That is not cosmetic. The gateway dies with STATUS_CONTROL_C_EXIT
(0xC000013A) the moment the window is closed or the console process group
takes a stray control broadcast, and the ONLOGON-only trigger leaves it down
until the next login. Observed live: a fully healthy boot (Telegram
connected, cron job run) followed by a silent death, with `hermes gateway
status` reporting nothing but a bare `Last Run Result: -1073741510`.

Re-registering the action needs schtasks /Create (elevation), which the
update path deliberately avoids — so the fix is to make the condition
legible rather than to mutate it behind the operator's back:

* gateway_windows._task_action_is_console_less() classifies a schtasks dump
  by which launcher path the action names. Locale-independent on purpose:
  Windows translates the field labels, never the paths.
* gateway_windows.task_action_is_console_less() probes the live
  registration; None for absent/unreadable/unrecognised so unknown is never
  reported as broken.
* `hermes gateway status` names the cause next to the exit code an operator
  is already staring at.
* the post-update refresh says it too, with the elevated command to run.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows] Gateway does not survive reboot - .cmd wrapper killed by console control event + schtasks missing critical XML settings

5 participants