Skip to content

fix(cli): add CREATE_BREAKAWAY_FROM_JOB to windows_hide_flags() - #55613

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-55604-hide-flags-breakaway
Closed

fix(cli): add CREATE_BREAKAWAY_FROM_JOB to windows_hide_flags()#55613
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-55604-hide-flags-breakaway

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds CREATE_BREAKAWAY_FROM_JOB to windows_hide_flags() so that subprocess calls made from inside an Electron / Tauri Windows Job Object remain hidden. Without this flag, CREATE_NO_WINDOW alone is silently ignored by the OS and every subprocess spawn produces a visible cmd.exe window flash.

The constant (_CREATE_BREAKAWAY_FROM_JOB = 0x01000000) already exists in the file and is already used by windows_detach_flags() for the same reason — it was simply missing from the hide-only variant.

Related Issue

Fixes #55604

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • hermes_cli/_subprocess_compat.py: Added | _CREATE_BREAKAWAY_FROM_JOB to windows_hide_flags() return value; updated docstring to explain why the flag is needed.
  • tests/tools/test_windows_native_support.py: Added test_windows_hide_flags_includes_breakaway_from_job — regression guard that verifies the breakaway bit is set and DETACHED_PROCESS is absent (which would break capture_output).

How to Test

  1. Run python -m pytest tests/tools/test_windows_native_support.py::TestSubprocessCompatHelpers::test_windows_hide_flags_includes_breakaway_from_job -xvs — should pass.
  2. Run python -m pytest tests/test_windows_subprocess_no_window_flags.py -q — all 15 existing tests should still pass (they mock windows_hide_flags so are unaffected by the implementation change).
  3. On a Windows machine with Electron Desktop (Hermes One): navigate to the "About" page — no cmd.exe windows should flash.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 — POSIX path returns 0 (correct no-op); Windows path verified via monkeypatched IS_WINDOWS in tests

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — docstring updated in windows_hide_flags()
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — POSIX path unchanged (returns 0); only Windows path affected
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Without this flag, CREATE_NO_WINDOW alone is silently ignored when the
parent process lives inside a Windows Job Object (Electron, Tauri, etc.).
Every subprocess spawn produces a visible cmd.exe window flash.

The constant already exists in the file and is used by
windows_detach_flags() for the same reason — it was simply missing
from the hide-only variant.

Fixes NousResearch#55604
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard platform/windows Native Windows-specific behavior or breakage sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows labels Jun 30, 2026

@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: LGTM

Fixes a real Windows issue: when Electron/Tauri spawns child processes inside a Windows Job Object, CREATE_NO_WINDOW alone is silently ignored and a visible cmd.exe window flashes for every subprocess. Adding CREATE_BREAKAWAY_FROM_JOB prevents the child from being re-parented into the job.

Looks Good

  • One-line fix with clear documentation explaining the Windows Job Object interaction
  • Regression test verifies both flags are present AND that DETACHED_PROCESS is NOT included (which would break capture_output)
  • Docstring updated with the new flag's purpose

Reviewed by Hermes Agent

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the focused Windows investigation. The proposed flag bundle needs a native-Windows reproduction before it is safe to salvage.

Problems

  • hermes_cli/_subprocess_compat.py:201 would add CREATE_BREAKAWAY_FROM_JOB to every hidden synchronous spawn, but current main documents that restrictive Job Objects can reject that flag and only detached callers have the retry-without-breakaway path (hermes_cli/_subprocess_compat.py:138-144, :156-183).
  • Maintainer commit d3d621f7c / PR #53853 reverted the preceding popup-fix sweep because it did not fix the observed Windows symptom and required identifying the actual flashing spawn leg first.
  • Helper-only coverage is incomplete: direct CREATE_NO_WINDOW sites remain in tools/code_execution_tool.py:1353 and hermes_cli/kanban_db.py:8077.

Suggested changes

  • Capture the flashing executable and parent spawn on native Windows, then fix that verified path.
  • Keep breakaway scoped to a path that genuinely needs Job Object escape and use the existing fallback pattern when it can be denied.

Automated hermes-sweeper review.


``CREATE_BREAKAWAY_FROM_JOB`` is included so that child processes
spawned inside an Electron / Tauri Windows Job Object are not
forcibly re-parented into the job — without this flag,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CREATE_BREAKAWAY_FROM_JOB can be denied by restrictive Job Objects; current main documents that at lines 138-144 and only retries detached spawns without this bit. Adding it here makes every short-lived hidden spawn subject to that failure with no fallback. Please first reproduce the actual flashing spawn on native Windows and scope any breakaway behavior to that path.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Closing after the class-level fix in PR #70205 (merged as 0dbf639) — the premise here doesn't hold against Win32 semantics, and the underlying symptom is addressed at a different layer.

Two problems with adding CREATE_BREAKAWAY_FROM_JOB to windows_hide_flags():

  1. Job objects don't affect console/window creation. CREATE_NO_WINDOW is not "silently ignored inside a job object" — jobs govern process lifetime and limits, not console allocation. The flag that actually neutralizes CREATE_NO_WINDOW is DETACHED_PROCESS (documented in the Process Creation Flags spec), and the real cause of the Electron/desktop flashes was the parent being console-less (GUI-subsystem pythonw.exe / DETACHED daemons), so every console-subsystem child had to allocate its own visible console. That's fixed at the root: commit aa2ae36 launches the desktop backend as hidden-console python, and fix(windows): hidden-console daemons — extend the parent-console flash fix to every detached spawn path #70205 extends the same to all detached daemon paths.

  2. Breakaway on every short-lived spawn is harmful. windows_hide_flags() feeds ~40 synchronous capture-output call sites. In a job that doesn't set JOB_OBJECT_LIMIT_BREAKAWAY_OK, CREATE_BREAKAWAY_FROM_JOB makes CreateProcess fail with ERROR_ACCESS_DENIED — and none of those sites have a retry, so probes and helpers would start crashing in restrictive Windows Terminal/container/kiosk configs. Short-lived children being torn down with the parent's job is also the desired behavior for helpers.

If a flash persists at a specific spawn site on current main, that's worth a fresh issue with the process name from the flash — it would point at a leg the parent-console fix doesn't cover. Thanks for digging into the Windows spawn behavior.

@teknium1 teknium1 closed this Jul 23, 2026
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 P2 Medium — degraded but workaround exists platform/windows Native Windows-specific behavior or breakage sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

windows_hide_flags() missing CREATE_BREAKAWAY_FROM_JOB — cmd.exe windows flash in Electron desktop apps (Hermes One, etc.)

4 participants