{"repo":"NousResearch/hermes-agent","public_id":"1631","display_label":"Stale PID and argv in gateway_state.json","summary":"These issues and fixes address gateway_state.json retaining outdated PID and argv metadata after gateway restarts or binary path changes. The associated fixes aim to refresh that runtime metadata on each status write.","subsystem":"gateway","counts":{"members":4,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":22674},"resolution":{"state":"partially_resolved","by":"pr-22674"},"freshness":{"state":"verified","last_verified_at":"2026-05-09T18:08:24+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.3933333333333333},"fix_edges":[{"issue_number":22560,"pr_number":22674,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":1631,"title":"[Bug]: gateway_state.json retains stale PID after gateway restart","url":null,"state":"closed"},{"kind":"issue","number":22560,"title":"[Bug]: gateway_state.json reports stale argv after upstream binary path changes","url":null,"state":"closed"},{"kind":"pr","number":22579,"title":"fix(gateway): refresh runtime argv metadata","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#22674","number":22674}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":22674,"title":"fix(gateway): refresh runtime argv metadata on every status write (salvage #22579)","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["gateway/status.py","tests/gateway/test_status.py"],"fix_hunks":[{"file":"gateway/status.py","hunks":["@@ -482,10 +482,12 @@ def write_runtime_status(\n     \"\"\"Persist gateway runtime health information for diagnostics/status.\"\"\"\n     path = _get_runtime_status_path()\n     payload = _read_json_file(path) or _build_runtime_status_record()\n+    current_record = _build_pid_record()\n     payload.setdefault(\"platforms\", {})\n-    payload.setdefault(\"kind\", _GATEWAY_KIND)\n-    payload[\"pid\"] = os.getpid()\n-    payload[\"start_time\"] = _get_process_start_time(os.getpid())\n+    payload[\"kind\"] = current_record[\"kind\"]\n+    payload[\"pid\"] = current_record[\"pid\"]\n+    payload[\"argv\"] = current_record[\"argv\"]\n+    payload[\"start_time\"] = current_record[\"start_time\"]\n     payload[\"updated_at\"] = _utc_now_iso()\n \n     if gateway_state is not _UNSET:"]},{"file":"tests/gateway/test_status.py","hunks":["@@ -287,6 +287,30 @@ def test_write_runtime_status_overwrites_stale_pid_on_restart(self, tmp_path, mo\n         assert payload[\"pid\"] == os.getpid(), \"PID should be overwritten, not preserved via setdefault\"\n         assert payload[\"start_time\"] != 1000.0, \"start_time should be overwritten on restart\"\n \n+    def test_write_runtime_status_overwrites_stale_argv_on_restart(self, tmp_path, monkeypatch):\n+        \"\"\"Regression: gateway_state.json must not keep the previous launch argv.\"\"\"\n+        monkeypatch.setenv(\"HERMES_HOME\", str(tmp_path))\n+\n+        state_path = tmp_path / \"gateway_state.json\"\n+        state_path.write_text(json.dumps({\n+            \"pid\": 99999,\n+            \"start_time\": 1000.0,\n+            \"kind\": \"hermes-gateway\",\n+            \"argv\": [\"/old/path/hermes\", \"gateway\", \"run\"],\n+            \"platforms\": {},\n+            \"updated_at\": \"2025-01-01T00:00:00Z\",\n+        }))\n+\n+        monkeypatch.setattr(status.sys, \"argv\", [\"/new/path/hermes\", \"gateway\", \"run\"])\n+        monkeypatch.setattr(status, \"_get_process_start_time\", lambda pid: 2000)\n+\n+        status.write_runtime_status(gateway_state=\"running\")\n+\n+        payload = status.read_runtime_status()\n+        assert payload[\"argv\"] == [\"/new/path/hermes\", \"gateway\", \"run\"]\n+        assert payload[\"pid\"] == os.getpid()\n+        assert payload[\"start_time\"] == 2000\n+\n     def test_write_runtime_status_records_platform_failure(self, tmp_path, monkeypatch):\n         monkeypatch.setenv(\"HERMES_HOME\", str(tmp_path))\n \n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}