Skip to content

emrg: add emrg stop command to kill all emrg processes (daemon/TUI/GUI) - #808

Merged
argszero merged 1 commit into
masterfrom
feature/emrg-stop-command
Aug 16, 2026
Merged

emrg: add emrg stop command to kill all emrg processes (daemon/TUI/GUI)#808
argszero merged 1 commit into
masterfrom
feature/emrg-stop-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Host request (from the host's own session on 2026-08-15): add an emrg stop command that checks all open emrg TUI / GUI / server processes and stops them all — graceful stop first, force-kill any stragglers to make sure nothing is left running. The Windows installer pre-stop script (stop-emrg.cmd) now calls it first.

Changes

  • emrg/main.py — new emrg stop subcommand:
    • daemon: reuses the existing _stop_daemon() (protocol shutdown → ping-pid SIGTERM fallback)
    • POSIX clients: ps -axww scan matching python -m emrg (TUI), python -m emrg.server (daemon, in case protocol stop missed it), and EMRG.app (macOS GUI); SIGTERM → ~3s grace → SIGKILL. Lookalike modules (-m emrg.serverless, -m emrgx) are explicitly NOT matched. The running CLI's own pid is excluded.
    • Windows clients: mirrors stop-emrg.cmd steps [1]/[2] — taskkill /IM EMRG.exe graceful then unconditional /F fallback, plus PowerShell CIM command-line filter for python.exe -m emrg excluding emrg.server
  • bin/stop-emrg.cmd — new step [0] calls emrg stop (installed launcher path preferred, PATH fallback, missing command → continue without error for first-time installs)
  • tests/test_main.py — parser test + _match_emrg_client / _scan_emrg_client_pids unit tests covering positive and negative states
  • tests/test_installer_stop.py — step [0] wiring test (runs before step [1], both launcher and PATH paths, falls through to :step1)
  • Agent.md — test count sync 825→834

Verification

  • uv run pytest tests/833 passed, 1 skipped (CRLF + doc-count guards included)
  • uv run python -c "from emrg.client.app import run_client" → OK
  • uv run python -m emrg --help → shows stop command

…GUI)

Host request (session 2026-08-15T08:44): add an `emrg stop` command that
checks all open emrg TUI/GUI/server processes and stops them all; graceful
stop first, force-kill stragglers. stop-emrg.cmd step [0] now calls it
first (skips cleanly when the emrg command is absent on first-time install).

- emrg/__main__.py: `emrg stop` subcommand + _stop_all() — daemon via
  existing _stop_daemon(); POSIX clients via ps -axww scan (TUI `-m emrg`,
  daemon `-m emrg.server`, macOS EMRG.app), SIGTERM → 3s grace → SIGKILL;
  Windows clients via taskkill EMRG.exe (graceful + unconditional /F) and
  PowerShell CIM command-line filter (python.exe -m emrg, excluding
  emrg.server). Own pid excluded so the running CLI survives.
- bin/stop-emrg.cmd: new step [0] calls `emrg stop` (installed launcher
  preferred, PATH fallback, missing command → continue without error).
- tests: parser + matcher/scan unit tests (positive/negative states,
  lookalikes -m emrg.serverless / -m emrgx rejected), step [0] wiring test.
- Agent.md doc-count sync 825→834.
@pm25coder

Copy link
Copy Markdown
Contributor

Tested this PR end-to-end on Windows (branch head 419b79a):

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle (R1948)

Reviewed the full diff with fresh eyes:

  • emrg/main.py_match_emrg_client regex -m\s+emrg(\.server)?(\s|$) correctly rejects lookalike modules (emrg.serverless, emrgx, emrg.gui — after emrg/(.server) a whitespace-or-end anchor is required). Own-pid exclusion prevents emrg stop from killing its own CLI. POSIX path: ps scan → SIGTERM → ~3s grace → SIGKILL; scanning after daemon stop also catches any daemon a still-alive TUI respawned in the race window. Windows path mirrors stop-emrg.cmd steps [1]/[2] (unconditional /F fallback per host 2026-08-10 lesson).
  • bin/stop-emrg.cmd step [0] — best-effort by design: installed launcher preferred, PATH fallback, missing command → continue without error (first-time install); an old installed emrg.cmd stop (no subcommand) exits non-zero but the script does not gate on it → falls through to the robust steps [1]-[4], so no version-safety regression.
  • Tests — matcher/scan positive+negative states, CRLF guard, doc-count guard all green (833 passed + 1 skipped locally); CI test + test-windows pass on this PR.

One minor note (non-blocking): POSIX-sourced GUI as python -m emrg.gui would not match the regex — not a real invocation path (GUI launches via Electron / EMRG.app / EMRG.exe), so acceptable.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle (R1950)

Second independent-cycle review. Re-verified the working state of the change:

  • The matcher (_match_emrg_client) correctly anchors module boundaries (-m\s+emrg(\.server)?(\s|$)), so lookalike module names (emrg.serverless, emrgx, emrg.gui) are rejected — covered by negative tests.
  • _scan_emrg_client_pids excludes the caller's own pid and tolerates malformed ps lines.
  • _stop_pids SIGTERM → 3s grace → SIGKILL leaves no stragglers; POSIX scan runs after daemon stop, catching daemons respawned by still-alive TUIs in the race window.
  • stop-emrg.cmd step [0] is best-effort: old launchers (no stop subcommand) fail non-fatally and fall through to the robust steps [1]-[4]; first-time installs without the command continue cleanly.
  • CI: test + test-windows both pass on this PR; mergeable CLEAN.

No blocking issues.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed the full diff fresh this cycle:

  • _match_emrg_client — the -m\s+emrg(\.server)?(\s|$) regex is correctly anchored: whitespace-or-end after emrg/(.server) rejects lookalikes (emrg.serverless, emrgx, emrgistry), and the EMRG.app substring covers the macOS GUI. Negative-state tests cover module-like flags (-X dev) so no false positives.
  • _scan_emrg_client_pids — parses ps -axww -o pid=,command=, excludes own pid so emrg stop never kills itself; scanning after _stop_daemon() also catches a daemon a still-alive TUI respawned in the race window.
  • _stop_windows_clients — mirrors stop-emrg.cmd steps [1]/[2]: graceful GUI stop then unconditional /F fallback (host 2026-08-10T01:27:07Z lesson), TUI via PowerShell CIM command-line filter (wmic-free, Win11 24H2+ safe, excludes emrg.server).
  • stop-emrg.cmd step [0] — best-effort: installed launcher preferred, PATH fallback, missing command → continue without error (first-time install); an old emrg.cmd stop (no subcommand) exiting non-zero is not gated on, so no version-safety regression.
  • Tests — matcher positive+negative, scan parse/exclusion, step [0] ordering + no-%VAR% block guard, CRLF guard; doc count synced; CI test + test-windows both green.

No blocking issues.

@argszero
argszero merged commit 820e033 into master Aug 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants