Dashboard and gateway stop treat a multiplexer-served profile as running via the multiplexer (multiplex parity: surfaces) - #108683
Merged
Merged
Conversation
…ateway as the multiplexer A profile served by the default multiplexer owns no gateway.pid / gateway_state.json, so every surface that reads per-profile identity files called it stopped while the CLI status surfaces (hermes -p X status / gateway status / cron status) said "running via the default-profile multiplexer": - `/api/status?profile=X` and `/api/messaging/platforms?profile=X` reported gateway_running=false / state=None / "gateway_stopped" in the same body that listed X under gateways[].served_profiles. The shared ladder `resolve_gateway_liveness` gains a fourth rung for a named profile_dir: the live default multiplexer that records X in served_profiles IS X's gateway (pid = multiplexer pid, runtime = its record, X's `<X>:<platform>` entries re-keyed to the standalone shape). - `POST /api/gateway/stop?profile=X` spawned `hermes -p X gateway stop`, which printed "No gateway running for this profile" (exit 0) into the action log while the UI flipped to stopped and the multiplexer kept serving X; `/api/gateway/restart?profile=X` spawned a `-p X gateway restart` that only exits 78. start/stop now answer 409 with the multiplexer explanation (one helper shared with the existing start refusal) and restart targets the multiplexer, the process that actually serves X. A `--force`-started separate gateway for X (own pid file) keeps normal per-profile management. - CLI `hermes -p X gateway stop` refuses with exit 78 like run/start/install/restart when X has no gateway of its own, instead of a contradictory exit-0 "not running". Docs: multi-profile-gateways.md §1 and §5 describe stop + the dashboard behaviour.
૮ >ﻌ< ა ci reviewran on 99f49e6 — fix(multiplex): dashboard and
|
This was referenced Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A profile served by the default multiplexer is now reported and managed as running via the multiplexer by the dashboard/Desktop API and by
hermes -p X gateway stop, matching whathermes -p X status/gateway status/cron statusalready said.Symptom → change → behaviour
Live rig: temp HOME,
defaultmultiplexer (api_server on loopback) servingalpha+beta; compared against a standalonehermes -p alpha gateway run.GET /api/status?profile=alphagateway_running: true, pid,state: running, platformsgateway_running: false,pid: null,state: null— in the same body whosegateways[].served_profileslists alphagateway_running: true,pid: <multiplexer>,state: running, alpha's<alpha>:<platform>entries projected as its platformsGET /api/messaging/platforms?profile=alphagateway_running: truegateway_running: false,state: gateway_stopped→ Channels page says "The gateway is not running"gateway_running: truePOST /api/gateway/stop?profile=alphahermes -p alpha gateway stop→ "No gateway running for this profile" exit 0 in the action log; UI flips to stopped, multiplexer keeps serving alpha409with the multiplexer explanation (same helper the existingstartrefusal now uses)POST /api/gateway/restart?profile=alpha(also the post-onboarding restart for Telegram/WhatsApp)hermes -p alpha gateway restart→ exit 78 into the action log, nothing restartedserved_profilesintact)hermes -p alpha gateway stopgateway statuson the same profilehermes gateway stop/restarton the default profile, likerun/start/install/restartRoot cause: a served profile owns no
gateway.pid/gateway_state.json(#97120), so every reader of per-profile identity files called it stopped; only the CLI status paths had been taught aboutserved_profiles.gateway/status.py::resolve_gateway_liveness— 4th rung, scoped requests only: the live default multiplexer whose record lists the profile inserved_profilesis that profile's gateway (source="multiplexer",runtime= its record). Newmultiplexer_liveness_for_profile/profile_platforms_from_multiplexerhelpers;GatewayLiveness.runtimefield.hermes_cli/web_routers/status.py,web_routers/messaging.py— consume the multiplexer runtime, re-keyed to the standalone platform shape.hermes_cli/web_server_gateway.py::_gateway_subcommand—restartfor a served profile drops-p X;multiplexed_profile_refusal(profile, verb)shared by/api/gateway/startand/stop(web_routers/ops.py). A--force-started separate gateway for X (own pid file) keeps normal per-profile management.hermes_cli/gateway.py::_cmd_stop— exit-78 refusal when the profile is served and has no gateway of its own;--allunaffected.website/docs/user-guide/multi-profile-gateways.md§1 and §5.Verified unchanged/already at parity in the same rig (no code change):
hermes -p X status|gateway status|gateway list|cron status|cron list|cron run|profile list|profile show|logs|sessions list,run/start/install/restartexit 78,hermes update --planlists ONEgateway [default](fleet restart hits the multiplexer once),gateway_state.jsonshape (served_profiles+<profile>:<platform>only under the default home), per-profileagent.log/errors.log/gateway.logunderprofiles/X/logsfor X's turns, Desktop ticker standdown (#108428) and shutdown//updatenotices via X's adapter (#107655) on fresh main.Tests
tests/hermes_cli/test_gateway_multiplex_served_record.py+3 invariants (ladder reports served profile running with its platforms and keeps an unserved one stopped; lifecycle verbs target the multiplexer unless the profile runs its own gateway; CLI stop refuses) — red on base (3 failed), green here.tests/hermes_cli/+tests/gateway/: 17610 passed; 2 failures are pre-existing/unrelated (test_update_head_moved_gate::test_update_success_when_head_movesfails on base too;test_session_hygiene::test_hygiene_does_not_wait_ceiling_after_fence_cancelis a load-timing flake, passes in isolation on this tree).Compatibility with #106742
Does not touch
hermes_cli/web_server.py,web_server_lifecycle.py,subcommands/gateway.py,apps/desktop/electron/main.ts,apps/desktop/src/store/profile.ts, ortui_gateway/methods_tools.py. The restart routing is placed inweb_server_gateway.py::_gateway_subcommand, whichweb_server.py::_spawn_gateway_restartalready calls, so #106742's rewrite of that file inherits it without a hunk.Not done
hermes -p Xaction-child env) — owned by another lane.hermes gateway statuson a manually-run default profile lists unrelated gateway PIDs from other HERMES_HOMEs (_scan_gateway_pidsdefault-profile branch accepts anygateway runwithout-p/HERMES_HOME=in argv). Pre-existing and identical in standalone; not a parity bug.Infographic