[GH-ISSUE #4841] [Bug] Hermes named-user home overrides plan registration in a different relative directory #3009

Closed
opened 2026-10-31 00:34:46 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @xu91102 on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4841

Before submitting

  • Searched open/closed issues and PRs, including Hermes path/profile reports.
  • Only self-owned temporary configuration roots were used; paths below are reduced placeholders.

Observed behavior

On freshly fetched/built main 3fa972af7c7cb6cf014ffc426bdf7130dc6f2fd2, HERMES_HOME=~<current-login>/... is treated as a relative pathname. setup --client hermes --dry-run --json plans registration and the skill under <REA working directory>/~<login>/..., rather than the user's actual home. doctor --client hermes --skill --json says the client/skill is missing.

The same existing configuration selected by an absolute HERMES_HOME reports healthy (exit0), including its installed skill identity. The native named-home variant reports unhealthy (exit1). The wrong-target setup was a dry run only; no wrong-directory write or third-party data loss is claimed.

Reproduction and controls actually run

  1. Create an isolated config root beneath the current account's real home, with config.yaml containing mcp_servers: {}. Use a separate disposable HOME/USERPROFILE.
  2. Set HERMES_HOME to that absolute config root and run node scripts/rea.mjs setup --client hermes --yes --json. This returned ready/exit0 and wrote only the controlled config/skill destinations. doctor --client hermes --skill --json then returned healthy/exit0.
  3. Change only HERMES_HOME to the equivalent ~<login>/<same-home-relative-suffix>. Run the same doctor and a setup dry run. Doctor returned Requested client hermes was not detected plus missing skill identity; the plan targeted the working directory's literal ~<login> child for both configuration and skill.

For an independent client control, I executed the actual, unmodified, stdlib-only get_process_hermes_home() from NousResearch/hermes-agent's hermes_constants.py (Git blob 30252854c2e584131873ddb7a414eb52ba6845c2) using Python3.11 and the same named-home override. It resolved exactly to the absolute control directory. _expand_hermes_home uses Python os.path.expanduser(os.path.expandvars(path)). This was a real production path-resolver call, not a full installed Hermes agent session or model invocation.

Expected behavior and impact

A supported home override must select the same config and skill destinations in setup, doctor and uninstall. Expand a known named-user home using actual OS account identity, or explicitly refuse an unresolved form before any write plan; do not silently configure a different relative directory. A valid MCP registration is otherwise missed and approval would target a location the client does not read.

Root and duplicate check

HermesClientHome.expandedDirectory expands variables and handles only ~, ~/... (and the Windows separator variant), then calls resolve() on other input. A named-user tilde therefore becomes a literal working-directory path.

This is distinct from #1521/#1528's sticky profile selection, #3939/#4145's nested override/sticky-root semantics, and #3320/#3785's YAML aliases. I read #3939 and the actual current #4145/#3785 production diffs: #4145 has no production delta and #3785 edits YAML alias ownership; neither resolves named-user homes. Open/closed searches for named/tilde Hermes paths found no same-root fix.

Environment and scope

Node24.18.0, macOS27.0.1 arm64, source build at the SHA above. Self-owned controlled config roots and real filesystem setup/doctor/dry-run results; current Hermes production resolver executed independently. Full Hermes MCP/agent/model execution, native Windows/Linux and other OS account homes are NOT RUN. The original real account files and unrelated services were untouched.

Local fix and verification

Prepared in xu91102/rea@cbb2005c. The shared path owner expands the current POSIX account using OS identity; other named forms require an absolute HERMES_HOME before any write. Existing profile behavior is retained.

Final independent Standards/Spec review passed. Actual compiled CLI and an additional seven calls from the locally installed tarball verified aligned setup/doctor/skill paths, idempotent repeat, exact preservation of unrelated settings, uninstall and refusal before writes. Full installed Hermes agent/model/MCP-client integration and native Windows/Linux remain NOT RUN. No upstream PR has been created.

Main correction and delivery status

Maintainer commit c555caad6 fixes the same shared Hermes path owner under the maintainer author, and the maintainer closed this issue. I read its complete three-file diff. My existing fork branch is now read-only HOLD and will not be submitted as a duplicate. I have no upstream PR or CI for this fix. The main commit has no explicit adaptation statement or my author credit; I have not established that it adopted my fork patch.

My earlier 53 distinct passing checks and seven installed-tarball CLI lifecycle calls remain evidence for my original frozen fork baseline. I have not run the new main commit, the maintainer-reported 113 checks or its measurements, and do not transfer those results or claim complete equivalence to my additional controls. Full installed Hermes agent/model/MCP-client and native Windows/Linux remain NOT RUN.

Originally created by @xu91102 on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4841 ### Before submitting - [x] Searched open/closed issues and PRs, including Hermes path/profile reports. - [x] Only self-owned temporary configuration roots were used; paths below are reduced placeholders. ### Observed behavior On freshly fetched/built main `3fa972af7c7cb6cf014ffc426bdf7130dc6f2fd2`, `HERMES_HOME=~<current-login>/...` is treated as a relative pathname. `setup --client hermes --dry-run --json` plans registration and the skill under `<REA working directory>/~<login>/...`, rather than the user's actual home. `doctor --client hermes --skill --json` says the client/skill is missing. The same existing configuration selected by an absolute `HERMES_HOME` reports healthy (exit0), including its installed skill identity. The native named-home variant reports unhealthy (exit1). The wrong-target setup was a dry run only; no wrong-directory write or third-party data loss is claimed. ### Reproduction and controls actually run 1. Create an isolated config root beneath the current account's real home, with `config.yaml` containing `mcp_servers: {}`. Use a separate disposable HOME/USERPROFILE. 2. Set HERMES_HOME to that absolute config root and run `node scripts/rea.mjs setup --client hermes --yes --json`. This returned `ready`/exit0 and wrote only the controlled config/skill destinations. `doctor --client hermes --skill --json` then returned healthy/exit0. 3. Change only HERMES_HOME to the equivalent `~<login>/<same-home-relative-suffix>`. Run the same doctor and a setup dry run. Doctor returned `Requested client hermes was not detected` plus missing skill identity; the plan targeted the working directory's literal `~<login>` child for both configuration and skill. For an independent client control, I executed the actual, unmodified, stdlib-only `get_process_hermes_home()` from NousResearch/hermes-agent's `hermes_constants.py` (Git blob `30252854c2e584131873ddb7a414eb52ba6845c2`) using Python3.11 and the same named-home override. It resolved exactly to the absolute control directory. `_expand_hermes_home` uses Python `os.path.expanduser(os.path.expandvars(path))`. This was a real production path-resolver call, not a full installed Hermes agent session or model invocation. ### Expected behavior and impact A supported home override must select the same config and skill destinations in setup, doctor and uninstall. Expand a known named-user home using actual OS account identity, or explicitly refuse an unresolved form before any write plan; do not silently configure a different relative directory. A valid MCP registration is otherwise missed and approval would target a location the client does not read. ### Root and duplicate check `HermesClientHome.expandedDirectory` expands variables and handles only `~`, `~/...` (and the Windows separator variant), then calls `resolve()` on other input. A named-user tilde therefore becomes a literal working-directory path. This is distinct from #1521/#1528's sticky profile selection, #3939/#4145's nested override/sticky-root semantics, and #3320/#3785's YAML aliases. I read #3939 and the actual current #4145/#3785 production diffs: #4145 has no production delta and #3785 edits YAML alias ownership; neither resolves named-user homes. Open/closed searches for named/tilde Hermes paths found no same-root fix. ### Environment and scope Node24.18.0, macOS27.0.1 arm64, source build at the SHA above. Self-owned controlled config roots and real filesystem setup/doctor/dry-run results; current Hermes production resolver executed independently. Full Hermes MCP/agent/model execution, native Windows/Linux and other OS account homes are NOT RUN. The original real account files and unrelated services were untouched. ### Local fix and verification Prepared in [xu91102/rea@cbb2005c](https://github.com/xu91102/rea/commit/cbb2005c18851617271be53e615e6e835d248468). The shared path owner expands the current POSIX account using OS identity; other named forms require an absolute HERMES_HOME before any write. Existing profile behavior is retained. Final independent Standards/Spec review passed. Actual compiled CLI and an additional seven calls from the locally installed tarball verified aligned setup/doctor/skill paths, idempotent repeat, exact preservation of unrelated settings, uninstall and refusal before writes. Full installed Hermes agent/model/MCP-client integration and native Windows/Linux remain NOT RUN. No upstream PR has been created. ### Main correction and delivery status Maintainer commit [`c555caad6`](https://github.com/morluto/rea/commit/c555caad6558e801e99155cb199ba12d11aa7826) fixes the same shared Hermes path owner under the maintainer author, and the maintainer closed this issue. I read its complete three-file diff. My existing fork branch is now read-only HOLD and will not be submitted as a duplicate. I have no upstream PR or CI for this fix. The main commit has no explicit adaptation statement or my author credit; I have not established that it adopted my fork patch. My earlier 53 distinct passing checks and seven installed-tarball CLI lifecycle calls remain evidence for my original frozen fork baseline. I have not run the new main commit, the maintainer-reported 113 checks or its measurements, and do not transfer those results or claim complete equivalence to my additional controls. Full installed Hermes agent/model/MCP-client and native Windows/Linux remain NOT RUN.
Author
Owner

@gongfpp commented on GitHub (Oct 17, 2026):

Hi — I can investigate a narrowly scoped fix for HERMES_HOME=~user/..., preserving the existing ~, ~/..., and absolute-path behavior, with isolated setup/doctor/uninstall regression coverage.

Before changing code, could maintainers confirm the intended contract: should a known named-user home be expanded, or should unresolved ~user input fail closed with a diagnostic instead of being treated as a relative path? I also found open PR #4145, which updates Hermes home documentation and tests/acceptance/setup/hermesClientSetup.test.ts but does not change the resolver. @hichipli, are you planning to cover this issue there, or can we coordinate the shared test file separately?

I reviewed merged #1528's resolver changes; they cover sticky-profile selection/validation, not this named-user home expansion case. I'll hold implementation until the expected behavior and any overlap are clear.

<!-- gh-comment-id:6237385409 --> @gongfpp commented on GitHub (Oct 17, 2026): Hi — I can investigate a narrowly scoped fix for `HERMES_HOME=~user/...`, preserving the existing `~`, `~/...`, and absolute-path behavior, with isolated setup/doctor/uninstall regression coverage. Before changing code, could maintainers confirm the intended contract: should a known named-user home be expanded, or should unresolved `~user` input fail closed with a diagnostic instead of being treated as a relative path? I also found open PR #4145, which updates Hermes home documentation and `tests/acceptance/setup/hermesClientSetup.test.ts` but does not change the resolver. @hichipli, are you planning to cover this issue there, or can we coordinate the shared test file separately? I reviewed merged #1528's resolver changes; they cover sticky-profile selection/validation, not this named-user home expansion case. I'll hold implementation until the expected behavior and any overlap are clear.
Author
Owner

@hichipli commented on GitHub (Oct 17, 2026):

Thanks for checking, @gongfpp! #4145 only covers the nested-home docs and tests, so I’m not planning to cover ~user there. Happy to coordinate on the shared test file.

I also saw @xu91102 has a local fix linked in the issue description, so worth checking with them first to avoid doubling up.

<!-- gh-comment-id:6239961273 --> @hichipli commented on GitHub (Oct 17, 2026): Thanks for checking, @gongfpp! #4145 only covers the nested-home docs and tests, so I’m not planning to cover `~user` there. Happy to coordinate on the shared test file. I also saw @xu91102 has a local fix linked in the issue description, so worth checking with them first to avoid doubling up.
Author
Owner

@morluto commented on GitHub (Oct 17, 2026):

Fixed on main in c555caad6.

The shared Hermes path owner now expands the current named POSIX account using OS account identity, independently of caller HOME/USERPROFILE. Repeated separators preserve that home prefix. Unresolved names and Windows named forms require an absolute HERMES_HOME before exposing a writable configuration or skill path. Setup, doctor, skill selection and uninstall reuse this owner; existing sticky-profile handling is retained.

Validation: 113 checks across seven files pass, including a compiled CLI setup → doctor → repeat setup → uninstall workflow over an owned profile under the actual account home, with a separate disposable caller home. Environment-variable expansion, repeated slashes, backup preservation, unrelated configuration and refusal before writes have controls. In an isolated unchanged checkout, all five new checks fail and 44 existing checks pass; the final repeated-slash controls also fail there. Static/docs/discovery1559 and pre-push checks pass. Both scoped source reviews are clear.

Twelve small completed setup dry runs compare absolute and named overrides. Warm two-repeat medians, baseline → fix: absolute elapsed1.244→1.253s, CPU1.318→1.311s, sampled process-family peak RSS533.7→529.2MB; named elapsed1.247→1.259s, CPU1.312→1.308s, RSS531.4→531.1MB. Complete reply cl100k estimates: absolute3187→3187 (raw replies identical), named3175→3187; selected CLI request17, progress0. First-process runs are separate from alternating warm repeats. No significance, speedup, true-cold, npm-resolution or whole-agent cost claim.

Research checked the current Hermes expansion owner, Python expanduser semantics and Node userInfo documentation, with DeepWiki as context. Scope: native macOS, real owned configuration/skill files, static Windows/Linux branch controls. Full installed Hermes agent/model/MCP-client integration, native Windows/Linux and unavailable OS account lookup are NOT RUN. No provider software was installed; heavy tests/profiling remain stopped.

<!-- gh-comment-id:6241248279 --> @morluto commented on GitHub (Oct 17, 2026): Fixed on `main` in `c555caad6`. The shared Hermes path owner now expands the current named POSIX account using OS account identity, independently of caller HOME/USERPROFILE. Repeated separators preserve that home prefix. Unresolved names and Windows named forms require an absolute HERMES_HOME before exposing a writable configuration or skill path. Setup, doctor, skill selection and uninstall reuse this owner; existing sticky-profile handling is retained. Validation: 113 checks across seven files pass, including a compiled CLI setup → doctor → repeat setup → uninstall workflow over an owned profile under the actual account home, with a separate disposable caller home. Environment-variable expansion, repeated slashes, backup preservation, unrelated configuration and refusal before writes have controls. In an isolated unchanged checkout, all five new checks fail and 44 existing checks pass; the final repeated-slash controls also fail there. Static/docs/discovery1559 and pre-push checks pass. Both scoped source reviews are clear. Twelve small completed setup dry runs compare absolute and named overrides. Warm two-repeat medians, baseline → fix: absolute elapsed1.244→1.253s, CPU1.318→1.311s, sampled process-family peak RSS533.7→529.2MB; named elapsed1.247→1.259s, CPU1.312→1.308s, RSS531.4→531.1MB. Complete reply cl100k estimates: absolute3187→3187 (raw replies identical), named3175→3187; selected CLI request17, progress0. First-process runs are separate from alternating warm repeats. No significance, speedup, true-cold, npm-resolution or whole-agent cost claim. Research checked the [current Hermes expansion owner](https://github.com/NousResearch/hermes-agent/blob/main/hermes_constants.py), Python expanduser semantics and Node userInfo documentation, with DeepWiki as context. Scope: native macOS, real owned configuration/skill files, static Windows/Linux branch controls. Full installed Hermes agent/model/MCP-client integration, native Windows/Linux and unavailable OS account lookup are NOT RUN. No provider software was installed; heavy tests/profiling remain stopped.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3009
No description provided.