fix(update): reload config's import surface before config in the in-place updater - #90554
fix(update): reload config's import surface before config in the in-place updater#90554liuhao1024 wants to merge 1 commit into
Conversation
…lace updater hermes update runs in the PRE-pull Python process. After the pull, _reload_config_modules force-reloads config — but importlib.reload re-executes config's module-level `from X import Y` against the CACHED X in sys.modules. When d0132b5 added `from hermes_cli.cli_output import line_input` to config.py, an updater process whose cached cli_output predated the symbol died with "cannot import name 'line_input'" and aborted the gateway auto-restart (NousResearch#90535) — the checkout and venv were healthy; only the mixed-generation sys.modules was broken. Reload every hermes_cli module config imports at module level (colors, secret_prompt, cli_output, route_identity, default_soul, personality) BEFORE config itself, with the dependency ordering documented. All six are leaf modules with no hermes_cli imports of their own, so the order among them is free but all must precede config.
|
Architecture note for review: this PR is a valid tactical repair for #90535, but it should not be treated as closure of the mixed-generation updater class tracked by #90145. Reloading config's current import surface reduces today's failure modes; it does not establish that the mutation-bearing post-pull import graph is wholly generation-coherent. A future dependency edge can recreate the same N/N+1 Please preserve the distinction in merge/closure semantics:
Interlocks: #90145 (generation authority) and #90144 (proof scope must cover the actual execution/mutation graph). |
|
One additional acceptance note from the packaged-artifact side of the same architecture: this tactical reload fix should be validated against the post-update runtime users actually execute, not only against the helper’s reload list. The important chain is That does not expand this PR’s implementation scope; it clarifies why the existing #90535/#90145 architecture residue must remain open after this manifestation is repaired. #89875, #88233, and #82450 are the corresponding bundle/native/install precedents: earlier-stage success is evidence, not acceptance of the final executable artifact. |
|
Thanks for both notes — the boundaries are clear and I agree with them. To confirm my understanding: this PR only repairs the enumerated import surface of One concrete question on merge semantics: the body currently says |
|
Yes—please switch #90535 is not limited to the single Suggested wording:
This PR can merge as tactical containment, but it should not auto-close #90535. |
|
Please switch the body to non-closing semantics: #90535 itself states the broader invariant (“An update should not execute newly pulled modules against stale cached dependencies”) and names a fresh subprocess as the stronger direction. This PR proves the enumerated Exact-head CI Closure-sweep receipt: I attempted to make the body-only change directly, but GitHub rejected PR metadata mutation with |
andrexibiza
left a comment
There was a problem hiding this comment.
Re-reviewed exact head c3019206a94e1fa4fb82144fc242babab4ea78b3 after the merge-semantics correction. The PR now uses a non-closing Refs #90535, accurately scopes itself to the enumerated hermes_cli.config import surface, and preserves #90535/#90145/#90144 as the coherent-generation closure owners. Exact-head CI 32336809924, Docker 32336809325, and Nix 32336809309 are all green. No remaining code-review blocker for this tactical containment slice.
What does this PR do?
hermes updateruns in the PRE-pull Python process, and after the pull_reload_config_modules()force-reloadshermes_cli.configfrom disk. Butimportlib.reloadre-executes config's module-levelfrom X import Yagainst the cachedXinsys.modules. When d0132b5 addedfrom hermes_cli.cli_output import line_inputtoconfig.py, an updater process whose cachedcli_outputpredated the symbol died withcannot import name 'line_input'and aborted the gateway auto-restart — the checkout and venv were healthy; only the mixed-generationsys.moduleswas broken (#90535).The fix reloads every
hermes_climodule thatconfigimports at module level (colors,secret_prompt,cli_output,route_identity,default_soul,personality) beforeconfigitself, with the dependency ordering documented in the docstring. All six are leaf modules with nohermes_cliimports of their own, so the order among them is free but all must precedeconfig. This covers not just thecli_output/line_inputinstance but any future symbol added to config's import surface.Related Issue
Refs #90535 — addresses the current
configimport-surface manifestation; coherent-generation post-pull orchestration remains open under #90535 / #90145 / #90144 (intentionally non-closing per review).Type of Change
Changes Made
hermes_cli/update_cmd.py—_reload_config_modules()now reloads config's module-level import surface (six leaf modules) in dependency order beforeconfig; docstring documents the cached-Xmechanism and the [Bug]: in-place update reloads new config against stale cli_output, aborting gateway restart #90535 failuretests/hermes_cli/test_update_stale_dashboard.py— two regression tests: (1) the reload list covers the import surface and each entry reloads strictly beforehermes_cli.config; (2) the [Bug]: in-place update reloads new config against stale cli_output, aborting gateway restart #90535 reproduction shape — a cachedcli_outputstripped ofline_inputregains the symbol from disk after the reload passHow to Test
python -m pytest tests/hermes_cli/test_update_stale_dashboard.py -q— should pass (37 passed, 2 skipped), including the two new testspython -m pytest tests/hermes_cli/test_cmd_update.py tests/hermes_cli/test_update_yes_flag.py -q— should pass (no collateral damage to the update suites; 78 passed combined)cli_outputmissing from the reload list / stale symbol not restored); with the fix, all greenChecklist