From 1ee96a9dd7989ae9e2b92d8f79cc7e92506b5a74 Mon Sep 17 00:00:00 2001 From: Julie Yaunches Date: Wed, 10 Jun 2026 15:40:09 -0400 Subject: [PATCH] fix(hermes): detect wrapped gateway argv Refs #4981 --- agents/hermes/start.sh | 2 +- test/e2e/test-hermes-root-entrypoint-smoke.sh | 2 +- test/hermes-start.test.ts | 22 ++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/agents/hermes/start.sh b/agents/hermes/start.sh index 5b2b0c7047..c7d47b2e5b 100755 --- a/agents/hermes/start.sh +++ b/agents/hermes/start.sh @@ -304,7 +304,7 @@ cmdline_is_hermes_gateway() { local cmdline=" $1 " case "$cmdline" in - *"/hermes gateway run "* | *" hermes gateway run "*) return 0 ;; + *"/hermes gateway run "* | *" hermes gateway run "* | *"/hermes.real gateway run "* | *" hermes.real gateway run "*) return 0 ;; esac return 1 } diff --git a/test/e2e/test-hermes-root-entrypoint-smoke.sh b/test/e2e/test-hermes-root-entrypoint-smoke.sh index 59eaf01006..81e9269ecd 100755 --- a/test/e2e/test-hermes-root-entrypoint-smoke.sh +++ b/test/e2e/test-hermes-root-entrypoint-smoke.sh @@ -149,7 +149,7 @@ assert_runtime_layout() { assert_gateway_process() { local container="$1" assert_container_sh "$container" "Hermes gateway process is not running as gateway user" \ - "ps -eo user=,args= | awk '\$1 == \"gateway\" && index(\$0, \"hermes gateway run\") { found = 1 } END { exit found ? 0 : 1 }'" + "ps -eo user=,args= | awk '\$1 == \"gateway\" && (index(\$0, \"hermes gateway run\") || index(\$0, \"hermes.real gateway run\")) { found = 1 } END { exit found ? 0 : 1 }'" assert_container_sh "$container" "start log does not show gateway privilege separation" \ "grep -F \"hermes gateway launched as 'gateway' user\" /tmp/nemoclaw-start.log" } diff --git a/test/hermes-start.test.ts b/test/hermes-start.test.ts index ca31ec1cd9..c7b7b5c777 100644 --- a/test/hermes-start.test.ts +++ b/test/hermes-start.test.ts @@ -382,6 +382,7 @@ function lstatIfPresent(entry: string): fs.Stats | null { function runHermesGatewayRuntimeCleanup(opts: { liveGateway?: boolean; + liveGatewayArgv?: string[]; orphanSocat?: boolean; orphanDashboardSocat?: boolean; staleLock?: boolean; @@ -430,7 +431,11 @@ function runHermesGatewayRuntimeCleanup(opts: { if (opts.stalePid !== false) fs.writeFileSync(runtimePid, "999999\n"); if (opts.staleLock !== false) fs.writeFileSync(runtimeLock, "stale lock"); if (opts.liveGateway) { - writeFakeProcCmdline(procRoot, 123, ["/usr/local/bin/hermes", "gateway", "run"]); + writeFakeProcCmdline( + procRoot, + 123, + opts.liveGatewayArgv ?? ["/usr/local/bin/hermes", "gateway", "run"], + ); } if (opts.orphanSocat) { writeFakeProcCmdline(procRoot, 456, [ @@ -1068,6 +1073,21 @@ describe("agents/hermes/start.sh gateway runtime cleanup", () => { expect(run.killLog).toBe(""); expect(run.result.stderr).toContain("Existing Hermes gateway process detected"); }); + + it("preserves Hermes runtime state when the wrapped gateway execs hermes.real", () => { + const run = runHermesGatewayRuntimeCleanup({ + liveGateway: true, + liveGatewayArgv: ["/usr/local/bin/hermes.real", "gateway", "run"], + orphanSocat: true, + }); + + expect(run.result.status).toBe(0); + expect(run.runtimePidExists).toBe(true); + expect(run.runtimeLockExists).toBe(true); + expect(run.legacyPidIsSymlink).toBe(true); + expect(run.killLog).toBe(""); + expect(run.result.stderr).toContain("Existing Hermes gateway process detected"); + }); }); function runShieldsUpRuntimeEnv(opts: { locked: boolean; presetValue?: string }) {