Skip to content

fix(profiles): align main-process HOME with subprocess HOME within a profile (#27250)#27260

Open
xxxigm wants to merge 3 commits into
NousResearch:mainfrom
xxxigm:fix/27250-profile-home-alignment
Open

fix(profiles): align main-process HOME with subprocess HOME within a profile (#27250)#27260
xxxigm wants to merge 3 commits into
NousResearch:mainfrom
xxxigm:fix/27250-profile-home-alignment

Conversation

@xxxigm

@xxxigm xxxigm commented May 17, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Aligns the main Hermes Python process's HOME with the per-profile HOME that tool subprocesses already see, so a single active profile no longer carries two competing HOME values.

In Docker (and any install where ${HERMES_HOME}/home/ exists) the situation was:

  • Main process: HOME=/opt/data (from the image's useradd -d /opt/data hermes).
  • Tool subprocesses: HOME=/opt/data/home/ (injected by _make_run_env, _sanitize_subprocess_env, code_execution_tool).

That made paths like ~/.ssh, ~/.gitconfig, ~/.config/gh and ~/workspace resolve to different directories depending on whether the agent or a child tool expanded them — exactly the ambiguity reported in #27250.

After this PR the invariant requested in the issue holds:

main process HOME == subprocess HOME       (within one profile)
profile A HOME    != profile B HOME        (across profiles)

Activation is directory-gated (only fires when ${HERMES_HOME}/home/ actually exists), and HERMES_PRESERVE_HOST_HOME=1 is provided as an escape hatch for callers that depend on the historical split-HOME behaviour.

Related Issue

Closes #27250.

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

  • hermes_constants.py — new align_main_process_home_with_subprocess() (idempotent, import-safe). When get_subprocess_home() returns a path, sets os.environ["HOME"] (and USERPROFILE on Windows so Path.home() follows) to the same per-profile directory. Skips when HERMES_PRESERVE_HOST_HOME=1. Also adds a small _truthy_env helper. get_subprocess_home() docstring updated to point at the new function; behaviour unchanged (still a pure read).
  • hermes_cli/main.py — invokes the alignment right after _apply_profile_override() finalises HERMES_HOME and before any subsequent module-level code caches Path.home(). Wrapped in try/except so a bug here can never block hermes from booting.
  • tests/test_main_process_home_alignment.py — 36 new regression tests:
    • TestAlignmentActivationGates — 4 cases (no-op when HERMES_HOME unset, no-op when home/ subdir missing, aligns when both present, idempotent).
    • TestPreserveHostHomeOptOut — 14 cases parametrised over truthy/falsy values for HERMES_PRESERVE_HOST_HOME.
    • TestProfileIsolation — 2 cases (two profiles get different homes; main HOME equals subprocess HOME within one profile — the core issue invariant).
    • TestSubprocessEnvStillAligned — 3 cases (_make_run_env / _sanitize_subprocess_env agree with aligned main HOME; opt-out keeps the split behaviour).
    • TestPathHomeAgreement — 1 POSIX case asserting Path.home() and os.path.expanduser("~") follow the aligned HOME.
    • TestGetSubprocessHomeStillPureRead — 1 case pinning that get_subprocess_home() itself never mutates env.
  • website/docs/reference/environment-variables.md — documents the new HERMES_PRESERVE_HOST_HOME flag.
  • website/docs/user-guide/profiles.md — new "Per-profile HOME for tools and the agent" subsection under How it works, explaining both halves of the alignment and the opt-out flag.

How to Test

  1. Check out this branch and ensure .venv is set up: python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[all,dev]"
  2. Run the new tests on their own:
    scripts/run_tests.sh tests/test_main_process_home_alignment.py -v
    
    Expected: 36 passed.
  3. Run the full HOME / profile suite to confirm no cross-file regressions:
    scripts/run_tests.sh tests/test_main_process_home_alignment.py tests/test_subprocess_home_isolation.py
    
    Expected: 76 passed.
  4. Manual smoke (Docker / profile mode):
    • In a container with HERMES_HOME=/opt/data and /opt/data/home/ present:
      hermes  # any subcommand
      # Inside Python: import os; from pathlib import Path; print(os.environ["HOME"], Path.home())
      # Inside a tool subprocess (e.g. terminal): echo $HOME
      
      Both should print /opt/data/home.
    • Set HERMES_PRESERVE_HOST_HOME=1 and re-run: main process keeps /opt/data, subprocesses still get /opt/data/home (historical split behaviour preserved).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(profiles): ..., test(profiles): ..., docs(profiles): ...)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (no unrelated commits)
  • I've run scripts/run_tests.sh tests/test_main_process_home_alignment.py tests/test_subprocess_home_isolation.py and all tests pass
  • I've added tests for my changes (36 new regression tests covering activation gates, opt-out, profile isolation, subprocess agreement, Path.home() agreement, and the historical pure-read invariant)
  • I've tested on my platform: macOS 15.2 (Darwin 24.6.0), Python 3.12

Documentation & Housekeeping

  • I've updated relevant documentation (website/docs/reference/environment-variables.md and website/docs/user-guide/profiles.md)
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A (env-var only, no config-yaml surface)
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — Windows also gets USERPROFILE aligned so Path.home() follows; POSIX Path.home() reads HOME directly so setting os.environ["HOME"] is sufficient there
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A (no tool schema change)

Screenshots / Logs

$ scripts/run_tests.sh tests/test_main_process_home_alignment.py -v
36 passed in 1.87s

$ scripts/run_tests.sh tests/test_main_process_home_alignment.py tests/test_subprocess_home_isolation.py -q
76 passed in 3.05s

xxxigm added 3 commits May 17, 2026 11:17
…profile

Pull the Hermes Python process's own HOME (and USERPROFILE on Windows so
Path.home() follows) over to the same per-profile directory subprocesses
already use, so a single active profile never has two competing HOME
values. Activation is gated on {HERMES_HOME}/home/ existing on disk and
honours HERMES_PRESERVE_HOST_HOME=1 as an escape hatch for the historical
split-HOME behaviour. Profile isolation is unchanged — different profiles
still resolve to different homes. Issue NousResearch#27250.
…rch#27250

36 regression tests for align_main_process_home_with_subprocess: activation
gates (directory-driven, HERMES_HOME-driven), idempotency, the
HERMES_PRESERVE_HOST_HOME opt-out (parametrised truthy/falsy values),
profile-level isolation, Path.home()/expanduser agreement on POSIX, and
that _make_run_env / _sanitize_subprocess_env keep producing the same
HOME as the aligned main process.
Update the environment-variables reference with the new
HERMES_PRESERVE_HOST_HOME flag and add a "Per-profile HOME for tools and
the agent" section to the profiles user guide explaining why a single
profile no longer carries two competing HOME values. Issue NousResearch#27250.
@xxxigm xxxigm force-pushed the fix/27250-profile-home-alignment branch from 2ca6c14 to aee4b9d Compare May 17, 2026 04:20
@cardtest15-coder

This comment was marked as spam.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/agent Core agent loop, run_agent.py, prompt builder area/docker Docker image, Compose, packaging area/config Config system, migrations, profiles labels May 17, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing PR: #27259 addresses the same issue (#27250) with a similar approach. Maintainers should pick one.

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 area/docker Docker image, Compose, packaging comp/agent Core agent loop, run_agent.py, prompt builder comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docker/profile mode should avoid different HOME values between Hermes process and tool subprocesses

3 participants