Skip to content

a2a_fleet/spawners: inject HERMES_HOME explicitly into child env (profile-misroute risk) #98

Description

@Interstellar-code

Summary

get_hermes_home() (hermes_constants.py:67-101) has a guard that warns once on stderr when HERMES_HOME is unset while a non-default profile is sticky-active:

[HERMES_HOME fallback] HERMES_HOME is unset but active profile is 'hermes-switch'.
Falling back to ~/.hermes, which is the DEFAULT profile — not 'hermes-switch'.
Any data this process writes will land in the wrong profile. The subprocess
spawner should pass HERMES_HOME explicitly (see issue #18594).

The guard correctly detects the misroute but does not prevent it — the fix it recommends ("the subprocess spawner should pass HERMES_HOME explicitly") is not yet implemented. Process correctness currently depends on ambient inheritance.

Why it matters

When HERMES_HOME is unset, a child process under active profile hermes-switch silently resolves its home to ~/.hermes (the default profile) and any data it writes (state, tokens, transcripts, fleet.yaml edits) lands in the wrong profile.

Current state (observed 2026-06-03)

  • The dashboard launchd plist (ai.hermes.dashboard) does set HERMES_HOME=/Users/rohits/.hermes, so the live service is fine.
  • The a2a_fleet receiver spawner (cc_deploy.py:719-724, mirrored in oc/codex/agy deploy) builds child_env = dict(os.environ) and launches with env=child_env. It inherits HERMES_HOME if the parent (gateway) has it, but never sets it explicitly — so a parent lacking it propagates the misroute to the receiver, which then writes .hermes/ artifacts under the wrong profile root.
  • Any bare invocation of hermes code without HERMES_HOME (e.g. a manual python -c, a cron/CI step, a future spawner that constructs a clean env) hits the fallback.

Repro

# active profile is non-default (e.g. hermes-switch), HERMES_HOME unset:
unset HERMES_HOME
python -c "import hermes_constants as h; print(h.get_hermes_home())"
# -> stderr warning + returns ~/.hermes (DEFAULT), not the active profile root

Proposed fix

Make spawners that launch hermes code inject HERMES_HOME explicitly into the child env so the child lands in the same profile regardless of ambient env:

child_env = dict(os.environ)
child_env["HERMES_HOME"] = str(get_hermes_home())   # pin profile for the child

Apply at every subprocess spawn site that runs hermes code — starting with the a2a_fleet receiver launchers (cc/oc/codex/agy _launch_receiver paths), and audit other subprocess/Popen sites. Optionally promote the one-shot stderr warning to also fire when a spawner is about to launch without HERMES_HOME set.

Notes

  • #18594 referenced in the warning text is an internal observation id, not a GitHub issue — this issue tracks the real fix.
  • Severity: Medium — silent profile misroute; no current production impact (dashboard plist sets the var), but receiver spawns and ad-hoc invocations are exposed.

Env: hermes-agent main (post v2026.6.2.4), a2a_fleet v0.8.6.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions