fix(codex-runtime): de-dup [plugins.X] tables and stop leaking HERMES_HOME into config.toml (#26250)#26260
Merged
kshitijk4poor merged 2 commits intoMay 15, 2026
Conversation
…_HOME into config.toml Builds on @steezkelly's Bug A fix (NousResearch#25857, top-level default_permissions via _insert_managed_block_at_top_level) by addressing the other two config-corruption bugs described in NousResearch#26250: Bug B (duplicate [plugins.X] tables) - Codex itself writes [plugins."<name>@<marketplace>"] tables to config.toml when the user runs `codex plugins enable` directly, before hermes-agent's managed block exists. On the next migrate run, _query_codex_plugins() re-discovers the same plugins via plugin/list and render_codex_toml_section() re-emits them inside the managed block. Codex's strict TOML parser then rejects the duplicate table header on startup. - Add _strip_unmanaged_plugin_tables() that drops [plugins.*] tables from the user-content portion of the file. Only run it when plugin/list succeeded — if the RPC failed we can't re-emit and must preserve the user's tables. plugin/list is the source of truth when it answers. Bug C (HERMES_HOME pytest-tempdir leak into ~/.codex/config.toml) - _build_hermes_tools_mcp_entry() read HERMES_HOME directly from os.environ, so a sibling pytest's monkeypatch.setenv("HERMES_HOME", tmp_path) silently burned a transient pytest tempdir into the user's real ~/.codex/config.toml. After pytest reaped the tempdir, every codex-routed hermes-tools tool call failed silently. - Derive HERMES_HOME from get_hermes_home() (the canonical resolver that goes through the profile-aware path) and refuse to emit obvious test-tempdir paths via _looks_like_test_tempdir() as belt-and-suspenders for any other callsite that forgets to patch migrate(). - test_enable_succeeds_when_codex_present in test_codex_runtime_switch.py invoked the real migrate() (no mock), writing to Path.home() / .codex using whatever HERMES_HOME the running pytest session had set. Add the same migrate patch the other apply() tests already use, so the suite stops touching the user's real ~/.codex/config.toml. E2E verification (replicating the issue's repro): - Pre-state config.toml with user [mcp_servers.omx_team_run] + codex-installed [plugins."tasks@openai-curated"], HERMES_HOME="/private/var/folders/.../pytest-of-.../..." - On origin/main: tomllib refuses to load the result with "Cannot declare ('plugins', 'tasks@openai-curated') twice" AND the pytest-tempdir HERMES_HOME is burned in. - On this branch: file parses cleanly, default_permissions is top-level, exactly one [plugins."tasks@openai-curated"] table inside the managed block, no HERMES_HOME in the MCP env. 7 new regression tests covering all three bugs + the test-leak guard. `bash scripts/run_tests.sh tests/hermes_cli/test_codex_runtime_*.py` — 95 passed, 0 failed. Closes NousResearch#26250
7b5d651 to
7ab5aee
Compare
6 tasks
1 task
This was referenced May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the three independent bugs in
hermes codex-runtime migratereported in #26250. Each one corrupts~/.codex/config.tomlin a way that crashes codex on next startup with a TOML parse error.This PR builds on @steezkelly's #25857 (Bug A — top-level
default_permissionsvia_insert_managed_block_at_top_level) by cherry-picking it onto currentmainand then adding fixes for Bugs B and C with regression tests.Bugs fixed
default_permissionslands inside a previous[mcp_servers.X]table on re-rendermigrate()appended the managed block after pre-existing user tables, so the root key got scoped to the wrong table.[plugins."<name>@<marketplace>"]tables duplicated when codex itself installed plugins before hermes' migrate ran[plugins.*]tables outside the managed block survive_strip_existing_managed_block(), then_query_codex_plugins()reports the same plugins and we re-emit them inside the managed block. Result: duplicate table headers → codex's strict TOML parser rejects the file._strip_unmanaged_plugin_tables()drops[plugins.*]tables from the user-content portion of the file, but only whenplugin/listsucceeded — otherwise we'd silently lose plugins we can't re-emit.plugin/listis the source of truth when it answers.HERMES_HOMEfromos.environleaks pytest-tempdir paths into the user's real~/.codex/config.toml_build_hermes_tools_mcp_entry()reados.environ["HERMES_HOME"]at migrate time. A sibling pytest'smonkeypatch.setenv("HERMES_HOME", tmp_path)therefore burned a transient pytest tempdir path into the user's actual codex config; once pytest reaped the tempdir, every codex-routed hermes-tools call failed silently.HERMES_HOMEfromget_hermes_home()(canonical profile-aware resolver) and refuse to emit obvious test-tempdir paths via_looks_like_test_tempdir()as belt-and-suspenders. Also patchtest_enable_succeeds_when_codex_presentto mockmigrate()so the suite stops touching the user's real~/.codex/.E2E verification (reproduces the issue's exact pre-state)
On
origin/main:On this branch:
Test plan
bash scripts/run_tests.sh tests/hermes_cli/test_codex_runtime_plugin_migration.py tests/hermes_cli/test_codex_runtime_switch.py # 95 passed in 1.76s7 new regression tests:
TestStripUnmanagedPluginTables(4 tests): unit + end-to-end migrate dedup + preservation whenplugin/listfails.TestHermesHomeLeakGuard(4 tests): tempdir detector positive/negative + e2e pytest-tempdir refusal + real-path passthrough.test_enable_succeeds_when_codex_presentnow patchesmigrate()(closes the test-leak path).Attribution
c21f649e2from fix(codex-runtime): keep migrated root keys top-level #25857 with author preserved (Steve Kelly).Closes #26250