Skip to content

fix(profile): detect service-managed gateway status - #20488

Open
LeonSGP43 wants to merge 1 commit into
NousResearch:mainfrom
LeonSGP43:fix/profile-gateway-status-systemd
Open

fix(profile): detect service-managed gateway status#20488
LeonSGP43 wants to merge 1 commit into
NousResearch:mainfrom
LeonSGP43:fix/profile-gateway-status-systemd

Conversation

@LeonSGP43

Copy link
Copy Markdown
Contributor

Summary

  • keep the existing profile-scoped gateway.pid check as the fast path
  • fall back to the shared gateway runtime snapshot with HERMES_HOME temporarily scoped to the profile being displayed
  • use service-manager state for the fallback so profile list/show can detect systemd/launchd gateways without attributing unrelated gateway PIDs to the wrong profile
  • add regression coverage for the service-managed no-pid-file path

Closes #20254

Verification

  • scripts/run_tests.sh tests/hermes_cli/test_profiles.py -k gateway_running_check
  • scripts/run_tests.sh tests/hermes_cli/test_profiles.py

Non-goals

  • does not change gateway start/stop/install behavior
  • does not attempt to infer profile ownership for arbitrary manual gateway processes without a pid file

@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 labels May 6, 2026
@austinpickett
austinpickett requested a review from Copilot May 18, 2026 14:52

@austinpickett austinpickett left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please use PULL_REQUEST_TEMPLATE.md

Copilot AI 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.

Pull request overview

Fixes #20254 by teaching profile status reporting to recognize service-managed (systemd/launchd) gateways. The existing per-profile gateway.pid lookup is kept as a fast path; when no pid file is found, _check_gateway_running temporarily scopes HERMES_HOME to the profile being inspected and consults get_gateway_runtime_snapshot() so service-managed gateways are correctly reported by hermes profile list/show.

Changes:

  • Add a service-manager fallback in hermes_cli/profiles._check_gateway_running when the profile's gateway.pid is absent.
  • Temporarily scope HERMES_HOME to the target profile around the snapshot call so get_service_name() resolves the right systemd unit.
  • Add regression test (test_gateway_running_check_uses_runtime_snapshot_fallback) and update the existing tests to mock the new snapshot dependency.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
hermes_cli/profiles.py Adds the service-manager runtime-snapshot fallback inside _check_gateway_running, with HERMES_HOME save/restore.
tests/hermes_cli/test_profiles.py Mocks get_gateway_runtime_snapshot in the existing tests and adds a regression test verifying the no-pid-file service fallback path and HERMES_HOME restoration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/profiles.py
Comment on lines +364 to 377
try:
from hermes_cli.gateway import get_gateway_runtime_snapshot
previous_home = os.environ.get("HERMES_HOME")
os.environ["HERMES_HOME"] = str(profile_dir)
try:
snapshot = get_gateway_runtime_snapshot()
return bool(getattr(snapshot, "service_running", False))
finally:
if previous_home is None:
os.environ.pop("HERMES_HOME", None)
else:
os.environ["HERMES_HOME"] = previous_home
except Exception:
return False
Comment thread hermes_cli/profiles.py
Comment on lines +366 to +375
previous_home = os.environ.get("HERMES_HOME")
os.environ["HERMES_HOME"] = str(profile_dir)
try:
snapshot = get_gateway_runtime_snapshot()
return bool(getattr(snapshot, "service_running", False))
finally:
if previous_home is None:
os.environ.pop("HERMES_HOME", None)
else:
os.environ["HERMES_HOME"] = previous_home
Comment thread hermes_cli/profiles.py
Comment on lines 355 to 377
try:
from gateway.status import get_running_pid
return get_running_pid(profile_dir / "gateway.pid", cleanup_stale=False) is not None
if (
get_running_pid(profile_dir / "gateway.pid", cleanup_stale=False)
is not None
):
return True
except Exception:
pass
try:
from hermes_cli.gateway import get_gateway_runtime_snapshot
previous_home = os.environ.get("HERMES_HOME")
os.environ["HERMES_HOME"] = str(profile_dir)
try:
snapshot = get_gateway_runtime_snapshot()
return bool(getattr(snapshot, "service_running", False))
finally:
if previous_home is None:
os.environ.pop("HERMES_HOME", None)
else:
os.environ["HERMES_HOME"] = previous_home
except Exception:
return False

@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 targeting the service-managed no-PID path; current main still has a related systemd gap.

Problems

  • hermes_cli/profiles.py:368 temporarily writes os.environ["HERMES_HOME"]. That environment is process-global, so another dashboard/request thread can observe the displayed profile and use the wrong home. hermes_constants.py:23-35 provides set_hermes_home_override() specifically for per-task scoping without mutating the environment.
  • The new test validates that global mutation rather than proving the profile-specific service probe is isolated.

Suggested changes

  • Scope get_gateway_runtime_snapshot() with set_hermes_home_override(str(profile_dir)) and reset its token in finally.
  • Add coverage that the snapshot resolves the target profile while an independent context retains its original home.

Automated hermes-sweeper review.

Comment thread hermes_cli/profiles.py
from hermes_cli.gateway import get_gateway_runtime_snapshot
previous_home = os.environ.get("HERMES_HOME")
os.environ["HERMES_HOME"] = str(profile_dir)
try:

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.

os.environ is shared by every thread. Please use hermes_constants.set_hermes_home_override(str(profile_dir)) and reset its token in finally; this scopes the snapshot to this operation without exposing another profile to concurrent dashboard/request work.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state 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 area/profiles Multi-profile isolation, HERMES_HOME scoping labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists 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-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

profile list/show reports Gateway stopped when host-side systemd gateway is running

5 participants