57d94dd8dc
Confirmed on native Windows 11 with a real junction and the real startup chain: when the desktop/CLI spawns the backend with HERMES_HOME in the configured (lexical) spelling and --profile / sticky active_profile is in play, _apply_profile_override() re-homes HERMES_HOME through resolve_profile_env(), which resolves the junction under the platform default and returns the PHYSICAL spelling. tools.environments.local is imported after that mutation, so _hermes_repo_root_aliases is built from the physical home, the lexical repo-root spelling written into PYTHONPATH by the launcher (D:\hermes\hermes-agent) is not derivable, and the entry survives stripping (reproduced: cases --profile default / named / sticky active_profile / cross-drive junction all leave it in place; no-profile strips it). Two narrow changes, no heuristics, no new env vars: - hermes_cli/profiles.py::resolve_profile_env: when HERMES_HOME is set, the configured spelling IS the launch root (junction-transparent, physically identical dirs); keep it instead of re-deriving the native default. This is the same producer contract _preserve_hermes_home_path already follows. - tools/environments/local.py::_build_hermes_repo_root_aliases: when the configured home is a profile home (<root>/profiles/<name>), also derive the root spelling lexically (parent of the profiles component, same rule get_default_hermes_root uses) and run the exact-ownership mapping against it, so the launcher's lexical root is recovered after re-home without ever matching arbitrary descendants of HERMES_HOME. Regression test test_profile_rehome_keeps_junction_lexical_alias covers junction + profile re-home + inherited lexical PYTHONPATH end to end.