Skip to content

fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint - #53829

Merged
teknium1 merged 1 commit into
mainfrom
fix/footgun-capture-invariant
Jun 27, 2026
Merged

fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint#53829
teknium1 merged 1 commit into
mainfrom
fix/footgun-capture-invariant

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #53791 correcting the false invariant Gille flagged in review: the Windows footgun checker treated capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a console. That's wrong — stream redirection controls where a child's output goes, not whether a console is allocated. From a console-less parent (Desktop/Electron, pythonw.exe, a detached gateway/cron) a console-subsystem child still flashes a window even when fully captured.

Changes

  • scripts/check-windows-footguns.py — capture/redirect/check_output is no longer a blanket safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git, gh, npm, node, python, uv, ffmpeg, docker, powershell, …); calls to those are flagged even when captured. Non-flashing programs keep the capture exemption, so the rule stays comprehensive without flipping ~271 POSIX-only/dynamic calls red. Calls routed through _subprocess_compat.run/popen are inherently safe (the wrapper carries the flag).
  • Routed 35 genuine flashing spawns (git/gh/npm/uv/ffmpeg/docker probes in banner, doctor, kanban_db, checkpoint_manager, coding_context, mem0, …) through the _subprocess_compat.run/popen chokepoint added in fix(windows): stop terminal-window popups from background spawns #53810 — the durable fix, not per-site annotations. cmd.exe /c start stays # windows-footgun: ok (intentional window).
  • Tests updated to the corrected invariant (test_flags_flashing_programs_even_when_captured), plus CONTRIBUTING.md rule Add support for Atropos Agentic RL environments (requires branch tool… #17 rewritten.

Validation

Before After
Captured git/npm spawn from GUI parent treated SAFE (wrong) flagged → routed to chokepoint
Genuine flashing sites fixed 0 35 (via wrapper)
Noise (POSIX-only/dynamic) not flagged (capture still exempt for non-flashing)
check-windows-footguns.py --all n/a ✓ clean (709 files)
Rule tests 24 32 pass
tests/agent/ regression 4859 pass

Builds on the wrapper chokepoint from #53810: "no visible terminal" is structural for these spawns, not a per-call-site rule that gets forgotten.

Infographic

capture-not-no-window

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/footgun-capture-invariant vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11528 on HEAD, 11526 on base (🆕 +2)

🆕 New issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:3014: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

✅ Fixed issues (1):

Rule Count
invalid-assignment 1
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

Unchanged: 6070 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

…wns through chokepoint

Follow-up to #53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from #53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule #17 to the corrected invariant.
@teknium1
teknium1 force-pushed the fix/footgun-capture-invariant branch from 044b863 to 6177a62 Compare June 27, 2026 21:20
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint platform/windows Native Windows-specific behavior or breakage sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-automation Sweeper risk: may affect CI, automerge, label sync, or maintainer automation P2 Medium — degraded but workaround exists labels Jun 27, 2026
@teknium1
teknium1 merged commit 2ecca1e into main Jun 27, 2026
30 checks passed
@teknium1
teknium1 deleted the fix/footgun-capture-invariant branch June 27, 2026 21:49
teknium1 added a commit that referenced this pull request Jun 27, 2026
…53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (#53829)"

This reverts commit 2ecca1e.

* Revert "fix(windows): stop terminal-window popups from background spawns (#53810)"

This reverts commit 5db1430.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (#53791)"

This reverts commit ef17cd2.
lpaiu-cs added a commit to lpaiu-cs/hermes-agent that referenced this pull request Jun 28, 2026
…ch#53853 revert

The first cut routed these probes through _subprocess_compat.run/popen (the
NousResearch#53810 chokepoint), but NousResearch#53853 reverted NousResearch#53791/NousResearch#53810/NousResearch#53829 — so those calls
would now AttributeError on main (the wrappers are gone; windows_hide_flags()
survived). Switch the two sites to pass creationflags=windows_hide_flags()
directly, the same surviving-helper approach NousResearch#53892 took post-revert.

Also drop the now-moot footgun changes: the console-spawn rule was reverted, so
adding tui_gateway to its --all roots no longer buys anything (and would only
surface unrelated, hasattr-guarded signal handlers in entry.py). Net change is
now just the two gateway probe sites + the test, which asserts the no-window
flag is passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pai-scaffolde pushed a commit to pai-scaffolde/hermes-agent that referenced this pull request Jun 28, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule #17 to the corrected invariant.
pai-scaffolde pushed a commit to pai-scaffolde/hermes-agent that referenced this pull request Jun 28, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 2ecca1e.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 5db1430.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit ef17cd2.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit bc1c8f2.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 40591a4.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit c2eab69.
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 2ecca1e.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 5db1430.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit ef17cd2.
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 710ac05.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 3db485a.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit 80b090d.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 12aa1c3.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit ec5d0c1.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit d0ffccd.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 2ecca1e.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 5db1430.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit ef17cd2.
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…wns through chokepoint (NousResearch#53829)

Follow-up to NousResearch#53791 addressing review feedback: the footgun checker treated
capture_output=/stdout=/stderr=/check_output as proof a subprocess can't pop a
Windows console. That invariant is false — stream redirection controls where a
child's output goes, not whether a console is allocated. From a console-less
parent (Desktop/Electron, pythonw.exe, detached gateway/cron) a console-subsystem
child still flashes a window even when fully captured.

- check-windows-footguns.py: capture/redirect/check_output is no longer a blanket
  safe-pass. Added _WINDOWS_FLASHING_PROGRAMS (git/gh/npm/node/python/uv/ffmpeg/
  docker/powershell/…); calls to those are flagged even when captured. Non-flashing
  programs keep the capture exemption (no 271-site noise). _subprocess_compat.run/
  popen calls are inherently safe (wrapper injects CREATE_NO_WINDOW).
- Routed the 35 genuine flashing git/gh/npm/uv/ffmpeg/docker spawns through the
  _subprocess_compat.run/popen chokepoint (Brooklyn's wrapper from NousResearch#53810) — the
  durable fix, not per-site annotations. cmd.exe /c start stays # ok (intentional).
- Updated tests + CONTRIBUTING.md rule NousResearch#17 to the corrected invariant.
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…Research#53810 NousResearch#53829 (NousResearch#53853)

* Revert "fix(windows): capture is not a no-window boundary; route flashing spawns through chokepoint (NousResearch#53829)"

This reverts commit 2ecca1e.

* Revert "fix(windows): stop terminal-window popups from background spawns (NousResearch#53810)"

This reverts commit 5db1430.

* Revert "fix(windows): stop subprocess console-window popups + add CI guard (NousResearch#53791)"

This reverts commit ef17cd2.
Oc2cO pushed a commit to Oc2cO/hermes-agent that referenced this pull request Aug 16, 2026
…revert d3d621f

Root cause of the persisting desktop console flash: commit d3d621f bulk-
reverted three earlier windows-hide fix PRs (NousResearch#53791/NousResearch#53810/NousResearch#53829) across
~40 files in June; only a handful were individually re-fixed afterward.
This restores creationflags=windows_hide_flags() (or
windows_detach_popen_kwargs() for the one long-running Popen in
raft/adapter.py) on every remaining Windows-reachable subprocess/asyncio
spawn found by a full-repo audit:

cli.py (24 sites: worktree/branch-resolution helpers on the `hermes -w`
startup path), kanban_db.py (6, gateway boot/orphan-reconcile),
gateway/run.py (2, asyncio create_subprocess_exec/shell), clipboard.py (4),
claw.py (2), mcp_catalog.py, dep_ensure.py, doctor.py, setup.py, dump.py,
webhook.py, raft/adapter.py, managed_uv.py (11), mem0/_setup.py (7),
honcho/client.py, iron_proxy.py (7), environments/docker.py (19),
environments/ssh.py (11), uninstall.py, plugins_cmd.py, profiles.py,
secret_sources/{bitwarden,onepassword}.py, discord/voice_mixer.py,
contributor_audit.py, profile_distribution.py.

Deliberately left visible (interactive/foreground by design): editor
launches, `claude setup-token` OAuth login, relaunch.py's self-relaunch,
and anything gated to non-Windows-only code paths (service_manager.py's
s6-overlay branch, command.py's secret helper, profile-tui.py's pty
import). Verified via ast.parse + py_compile on every changed file and a
live import check on all touched non-CLI modules.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists platform/windows Native Windows-specific behavior or breakage sweeper:risk-automation Sweeper risk: may affect CI, automerge, label sync, or maintainer automation 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.

2 participants