Skip to content

feat(gateway): add YAML-only user-systemd scope - #76786

Closed
kortylokai-web wants to merge 1 commit into
NousResearch:mainfrom
kortylokai-web:feat/gateway-systemd-scope
Closed

feat(gateway): add YAML-only user-systemd scope#76786
kortylokai-web wants to merge 1 commit into
NousResearch:mainfrom
kortylokai-web:feat/gateway-systemd-scope

Conversation

@kortylokai-web

Copy link
Copy Markdown

What does this PR do?

Adds a YAML-only gateway.systemd_scope setting for Linux deployments that run independent Hermes roots with the same profile names.

The scope is validated and composed into the existing deterministic unit name as hermes-gateway-<scope>[-<profile>]. Missing or null preserves the current service names. Scoped services are user-systemd only, and existing units must persist a canonical HERMES_HOME matching the active root before Hermes may replace, control, or remove them.

Full uninstall also keeps its standalone-process cleanup without terminating service-managed gateway PIDs, including a service PID that changes during discovery. Inconclusive service-manager discovery fails closed before the standalone termination sweep. A configured scope is rejected before the direct full-uninstall path can mutate a system-scoped unit.

Related Issue

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added the nullable gateway.systemd_scope config key and conservative validation in hermes_cli/config_defaults.py and hermes_cli/gateway.py.
  • Composed scoped unit names without changing legacy names when the setting is absent.
  • Added canonical HERMES_HOME ownership checks before scoped unit replacement, control, and deletion.
  • Rejected scoped system services at the existing central user-scope guard, including direct full-uninstall cleanup.
  • Protected full uninstall's standalone gateway sweep from service-managed PIDs, service PID churn, and incomplete service-manager discovery.
  • Added focused lifecycle, ownership, naming, and platform-boundary tests.
  • Documented the public YAML setting in cli-config.yaml.example and website/docs/user-guide/messaging/index.md.

How to Test

  1. Run the focused systemd-scope tests:

    python -m pytest tests/hermes_cli/test_gateway_systemd_scope.py -q

    Expected: 35 tests pass.

  2. Run the affected gateway, profile, and uninstall suites:

    python -m pytest tests/hermes_cli/test_gateway.py tests/hermes_cli/test_gateway_service.py tests/hermes_cli/test_gateway_service_paths.py tests/hermes_cli/test_profiles.py tests/hermes_cli/test_uninstall_dry_run.py tests/hermes_cli/test_uninstall_node_symlinks.py tests/hermes_cli/test_gui_uninstall.py -q

    Expected: 137 tests pass.

  3. Run lint and cross-platform guards:

    ruff check hermes_cli/config_defaults.py hermes_cli/gateway.py hermes_cli/profiles.py hermes_cli/uninstall.py tests/hermes_cli/test_gateway_systemd_scope.py
    python scripts/check-windows-footguns.py --diff main
    git diff --check main

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
    • Fresh full-suite comparison (209730507 vs. 0a62610f1): 23,951 passed / 65 failed vs. 23,915 passed / 66 failed; both had the same 11 collection/import/timeout files, and the only failure delta was one unrelated test that passed on the candidate retry. The remaining 35-pass delta is the new scope suite.
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Linux, with automated user- and system-scope lifecycle coverage

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — cli-config.yaml.example and the messaging guide
  • I've updated cli-config.yaml.example if I added/changed config keys
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A; no architecture or workflow changes
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — Windows behavior is unchanged, incomplete launchd discovery also fails closed for the destructive standalone sweep, and the Windows guard passes
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A; no tool behavior changed

Screenshots / Logs

N/A — no UI changes.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 2, 2026
@teknium1

teknium1 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for the careful lifecycle and ownership analysis.

This automated hermes-sweeper review found that current main already provides the isolation this PR targets:

  • hermes_cli/gateway.py:1727-1752 assigns a deterministic short hash for an arbitrary HERMES_HOME; it only uses a bare profile name for profiles beneath the one default Hermes root.
  • hermes_cli/gateway.py:1798-1808 incorporates that suffix into the gateway service name.
  • website/docs/user-guide/messaging/index.md:596-598 documents that distinct HERMES_HOME installations receive distinct systemd service names and that gateway commands target the active root.

As a result, independent roots with the same profile name already avoid the reported unit collision on current main. Closing as implemented on main.

@teknium1 teknium1 closed this Aug 2, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:implemented-on-main Sweeper: behavior already present on current main sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants