diff --git a/hermes_cli/update_cmd_maint.py b/hermes_cli/update_cmd_maint.py index d5b3ea68dd..2413d96d2d 100644 --- a/hermes_cli/update_cmd_maint.py +++ b/hermes_cli/update_cmd_maint.py @@ -27,10 +27,12 @@ _UPDATE_RUNTIME_RELOAD_MODULES = "hermes_constants", "tools.environments.local", #: Modules EXECUTING the update survive the purge: evicting them buys nothing (running frames #: keep them alive) and reloading them mid-flight is the one genuinely unsafe move. -#: ``hermes_logging`` is protected for a different reason: its queue listener, handler list and -#: ``_logging_initialized`` flag are module globals, so a fresh copy starts a SECOND -#: QueueListener over the same log files while the first one keeps running. -_STALE_PURGE_PROTECTED = frozenset({"hermes_cli", "hermes_cli.main", "hermes_logging"}) +#: Two root modules carry process-wide identity state and are refreshed in place by +#: ``_reload_updated_runtime_modules`` instead: ``hermes_logging`` (a fresh copy starts a SECOND +#: QueueListener over the same log files while the first keeps running) and ``hermes_constants`` +#: (its ``_HERMES_HOME_OVERRIDE`` ContextVar — a token taken through the old module cannot reset a +#: fresh module's var, and an override set before the purge would silently vanish). +_STALE_PURGE_PROTECTED = frozenset({"hermes_cli", "hermes_cli.main", "hermes_logging", "hermes_constants"}) #: The updater's own module family (``update_cmd*``, ``update_receipt``, ``update_inventory``, #: ``update_lock``, ...) is protected as a prefix: these hold per-run state — the open receipt diff --git a/tests/hermes_cli/test_update_config_reload_tools_config.py b/tests/hermes_cli/test_update_config_reload_tools_config.py index 59842d7548..03feb631c1 100644 --- a/tests/hermes_cli/test_update_config_reload_tools_config.py +++ b/tests/hermes_cli/test_update_config_reload_tools_config.py @@ -70,9 +70,9 @@ def test_update_migration_survives_stale_module_missing_call_time_symbol(tmp_pat def test_update_migration_import_failure_after_purge_prints_fallback(tmp_path, monkeypatch, capsys): - """The purge evicts ``hermes_cli.*`` but not root modules (``hermes_constants``, ...), so the - post-purge ``from hermes_cli.config import ...`` re-executes NEW config.py against OLD root - modules and can raise ImportError. That must print the 'run hermes config migrate' fallback and + """The purge protects ``hermes_constants`` (identity-bearing ContextVar state), so the + post-purge ``from hermes_cli.config import ...`` re-executes NEW config.py against that OLD + root module and can raise ImportError. That must print the 'run hermes config migrate' fallback and return — not escape and abort the rest of post-update maintenance (fleet restart).""" home = tmp_path / "flat-home" home.mkdir()