test: isolate state-dir probes from user state#6305
Conversation
e0d6aa0 to
71c4778
Compare
|
| Filename | Overview |
|---|---|
| tests/test_issue4449_state_dir_contract.py | Strengthens subprocess environment isolation by adding a mandatory platform_home parameter, clearing additional inherited env vars (HERMES_BASE_HOME, HERMES_WEBUI_TEST_STATE_DIR, HERMES_WEBUI_DEFAULT_WORKSPACE, HERMES_CONFIG_PATH), and adding a sentinel mutation regression test; logic is correct and consistent across all four callers. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant T as Test (pytest process)
participant H as _state_dir_for_env
participant S as Subprocess (api.config)
participant FS as Filesystem (tmp_path)
T->>T: Create platform_home and sentinel settings.json
T->>T: monkeypatch HERMES_WEBUI_DEFAULT_WORKSPACE
T->>H: _platform_default_state_dir(platform_home)
H->>H: "env = dict(os.environ)"
H->>H: Override HOME, USERPROFILE, LOCALAPPDATA to platform_home
H->>H: Pop HERMES_HOME, HERMES_BASE_HOME, HERMES_WEBUI_DEFAULT_WORKSPACE etc.
H->>S: subprocess.run probe
S->>FS: Read settings.json only
S-->>H: Print resolved STATE_DIR
H-->>T: Return Path(STATE_DIR)
T->>FS: Read settings.json
T->>T: Assert bytes unchanged
T->>T: Assert STATE_DIR equals settings_file parent
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant T as Test (pytest process)
participant H as _state_dir_for_env
participant S as Subprocess (api.config)
participant FS as Filesystem (tmp_path)
T->>T: Create platform_home and sentinel settings.json
T->>T: monkeypatch HERMES_WEBUI_DEFAULT_WORKSPACE
T->>H: _platform_default_state_dir(platform_home)
H->>H: "env = dict(os.environ)"
H->>H: Override HOME, USERPROFILE, LOCALAPPDATA to platform_home
H->>H: Pop HERMES_HOME, HERMES_BASE_HOME, HERMES_WEBUI_DEFAULT_WORKSPACE etc.
H->>S: subprocess.run probe
S->>FS: Read settings.json only
S-->>H: Print resolved STATE_DIR
H-->>T: Return Path(STATE_DIR)
T->>FS: Read settings.json
T->>T: Assert bytes unchanged
T->>T: Assert STATE_DIR equals settings_file parent
Reviews (1): Last reviewed commit: "test: isolate state-dir probes from user..." | Re-trigger Greptile
…6180) + state-dir test isolation (#6305) (#6332) * fix: catch unhandled exception in POST /api/updates/check (defensive hardening) (#6180) * fix: generate non-empty approval_id when gateway approval.request omits it (#6008) (#6168) * chore: mark update-check try/except as defensive-only guard, drop #6086 linkage Per maintainer review, the try/except wrapper is defense-in-depth only — it does NOT fix #6086 (root cause is signal/process-group reaping). Updated log message and added inline comment to make this explicit. Leave #6086 open. * test: isolate state-dir probes from user state * docs(changelog): stamp #6168 approval_id, #6180 update-check guard, #6305 test isolation --------- Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> Co-authored-by: webtecnica <webtecnica@users.noreply.github.com> Co-authored-by: pxxD1998 <214340659+pxxD1998@users.noreply.github.com> Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
|
Shipped in exp-v0.52.117 (experimental channel) via release #6332. Thanks @pxxD1998! 🎉 The Gate: full pytest suite (13443 passed / 0 failed), Codex regression gate |
Thinking Path
api.configin fresh subprocesses.HERMES_HOMEandHERMES_WEBUI_STATE_DIR, but still inherited the pytest workspace override while using the platform user home.settings.json.Contract Routing
Task type: test-isolation bug fix; no intentional product-contract change.
Touched areas:
tests/test_issue4449_state_dir_contract.pyRelevant public docs:
AGENTS.mdCONTRIBUTING.mddocs/CONTRACTS.mdTESTING.mdScope boundaries:
Evidence needed before claiming done:
settings.jsonremains byte-for-byte unchanged.What Changed
HOME,USERPROFILE, andLOCALAPPDATAinside the child environment.settings.jsonbyte-for-byte, including%LOCALAPPDATA%\hermes\webuion native Windows.json.dumpsso the sentinel remains valid on Windows paths.Why It Matters
A test that only intends to inspect
STATE_DIRmust never read or reconcile pytest defaults into real user state. The isolation now models a normal install without touching the operator's home on Linux, macOS, or Windows.Verification
settings.jsonrewritten with the pytest workspace (1 failed, 3 passed)../scripts/test.sh tests/test_issue4449_state_dir_contract.py tests/test_pytest_state_isolation.py tests/test_issue2698_isolated_hermes_home.py tests/test_bootstrap_foreground.py -q78 passedruff check tests/test_issue4449_state_dir_contract.pyruff format --check tests/test_issue4449_state_dir_contract.pypython scripts/ruff_lint.py --diff origin/mastergit diff --check./scripts/test.sh13348 passed, 104 skipped, 1 xfailed, 2 xpassed, 34 subtests passedtest_issue4685_post_compression_context_metering.py: importing the external Hermes Agentagent.context_compressorsaw an incompleteagent.auxiliary_clientstub and could not importcall_llm. The same failure occurred in both isolated PR worktrees and is outside this test-only diff.Risks / Follow-ups
Model Used
gpt-5.6-solmedium