Completes the test-sharding half of #3197 (Docker-cache half shipped v0.51.177).
Adds pytest-shard 3-way split to tests.yml (3 shards x 3 Python = 9 jobs,
fail-fast: false). pytest-shard is 0-indexed so the matrix uses [0,1,2] — the
original #3197 used [1,2,3] which would have crashed the out-of-range job and
silently skipped shard 0's tests.
Made the suite shard-safe by fixing 4 cross-test state-pollution bugs that
passed sequentially but failed when sharded:
- test_onboarding_mvp: reset onboarding_completed flag (settings.json) in the
autouse fixture; the config-cleanup only cleared config.yaml/.env.
- test_issue693_system_health_panel: invalidate the process-wide password-hash
cache before/after so a prior test's "no password" cache doesn't defeat the
auth-gate assertion.
- test_auth_session_persistence: assert against auth._SESSIONS_FILE (where auth
actually writes) instead of a local _TEST_STATE path that only matched under a
lucky import order.
- test_profile_env_isolation (root cause of the worst leak): stop deleting +
re-importing api.profiles under a temp HERMES_BASE_HOME — that swapped the
module object and poisoned the cached _DEFAULT_HERMES_HOME for every later
test (broke test_title_aux_routing's load_config). Now points the cached path
via monkeypatch.setattr (auto-restored, no module swap).
- conftest: autouse fixture restores HERMES_HOME/HERMES_BASE_HOME after each
test as defense-in-depth against future switch_profile leaks.
Verified: all 3 shards green (6912 passed, 0 failed); full sequential run still
green (6957 passed, 0 failed). Slowest shard ~70s vs ~180s sequential.
CI failed on stage-323 because:
1. mcp_server.py imports the 'mcp' package (optional runtime dep) — only
users who actually run the MCP integration install it. CI runs with
stdlib-only deps (pyyaml + pytest + pytest-timeout).
2. tests/test_mcp_server.py uses pytest.mark.asyncio which requires
pytest-asyncio — not installed in CI.
Fix:
- Add pytest-asyncio to CI install line.
- Try-install mcp; if it fails (Python 3.13 wheel issues, etc.) the test
module uses pytest.importorskip and skips cleanly without breaking the
matrix.
- tests/test_mcp_server.py: add module-level importorskip for both 'mcp'
and 'pytest_asyncio' as a safety net.
Local: 4947/4947 still pass after change.
Runs pytest suite across Python 3.11, 3.12, and 3.13 on ubuntu-latest.
Agent-dependent tests auto-skip via existing conftest logic.
Triggers on PRs targeting master and pushes to master.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>