Skip to content

test(windows): set_home helper + sweep ~133 HOME monkeypatch sites (refs #644)#714

Merged
memtomem merged 3 commits intomainfrom
fix/windows-ci-home-monkeypatch-helper
May 2, 2026
Merged

test(windows): set_home helper + sweep ~133 HOME monkeypatch sites (refs #644)#714
memtomem merged 3 commits intomainfrom
fix/windows-ci-home-monkeypatch-helper

Conversation

@memtomem
Copy link
Copy Markdown
Owner

@memtomem memtomem commented May 2, 2026

Summary

Path.home() on Windows reads USERPROFILE first (then HOMEDRIVE+HOMEPATH), so monkeypatch.setenv("HOME", str(tmp_path)) is silently ignored on the runner and tests end up touching the real C:\Users\runneradmin\ instead of tmp_path. Per #644 this was the largest single class of Windows CI failures.

This PR introduces a small set_home(monkeypatch, path) helper in tests/helpers.py that sets both HOME and USERPROFILE (no-op on POSIX, correct on Windows), then sweeps all ~133 HOME monkeypatch sites in packages/memtomem/tests/ to use it. Manual HOME + USERPROFILE pairs that already existed in 5 files (test_context_settings.py, test_web_routes_extended.py, test_web_routes.py, test_context_agents.py, test_server_tools_context_settings_gate.py) are collapsed into single set_home(...) calls — exactly the redundancy that motivated centralizing the helper.

Mechanical, test-only change. No production code touched. ruff check + ruff format --check clean.

What's covered

  • 88 sites in test_init_cmd.py
  • 25 sites in test_web_routes.py (24 HOME-only + 1 manual pair)
  • 4 sites across test_web_routes_extended.py (2 manual pairs collapsed)
  • 4 sites across test_context_settings.py (2 manual pairs collapsed)
  • Manual pairs in test_context_agents.py and test_server_tools_context_settings_gate.py collapsed
  • 11 other test files with single sites (test_cli_index_noop_e2e.py, test_fastembed_cache.py, test_indexing_engine.py, test_lazy_init_acceptance.py, test_runtime_paths.py, test_uninstall_cmd.py, test_web_exclude_guard.py, test_web_hot_reload.py, test_web_routes_context_locks.py, test_web_routes_context_mutators.py, test_web_routes_context_projects.py)

18 files modified, +149 / -149 (1:1 mechanical substitutions). The full sweep makes the helper the only HOME-redirection pattern in the test suite — no two-pattern drift to manage.

Cross-check (BLOCKING per plan)

Source: gh run view 25245215735 --log-failed --job=74028225027 (latest main run after PR #711 / #713 merged, 2026-05-02).

Originally-targeted "auto-discovery" tests:

Test Was failing on Windows? Status after this PR
test_config_overrides.py::test_detect_provider_dirs_excludes_gemini ❌ (false-positive pass) ✅ now exercises invariant correctly
test_config_overrides.py::test_detect_provider_dirs_filters_empty_claude_memory ⚠️ still failing — set_home now redirects discovery, but _bucket() calls categorize_memory_dir() whose forward-slash regex (#316) classifies the backslash path as "user" so the claude-memory bucket stays empty
test_config_overrides.py::test_detect_provider_dirs_finds_claude_plans_and_codex ⚠️ still failing — same #316 root cause
test_init_cmd.py::TestProviderDirsStep::test_write_merges_provider_dirs_into_memory_dirs ❌ (inert HOME patch) ✅ migrated for correctness
test_init_cmd.py::TestIncludeProviderFlag::test_flag_resolves_categories_to_dirs fixed
test_init_cmd.py::TestIncludeProviderFlag::test_flag_silently_skips_unavailable_categories fixed
test_init_cmd.py::TestIncludeProviderFlag::test_no_flag_writes_no_provider_dirs fixed

The 2 still-failing tests need both this PR (USERPROFILE redirect so _detect_provider_dirs looks at tmp_path instead of the runner home) and the #316 production fix (so categorize_memory_dir accepts backslash paths). After #316 lands, these 2 tests should immediately go green on Windows with no further test changes — the migration this PR ships is necessary, just not sufficient on its own.

The full sweep brings ~30 additional HOME-related Windows failures into scope (notably the test_init_cmd.py and test_web_routes.py clusters from #644's symptom report).

Windows CI impact

Metric Before (run 25245215735) After sweep (run 25245680115)
Total Windows failures 105 44
Reduction −61
Auto-discovery failures still pending #316 2

macOS, Ubuntu, lint, typecheck, golden-path, notebooks all green on the sweep run — negative pin held, no POSIX regression. Helper is a no-op on POSIX (stdlib Path.home() ignores USERPROFILE).

Out of scope (explicit follow-ups)

#644 can close on this PR's merge — the helper sweep delivers its full scope (HOME redirect across the whole suite). The 2 lingering _detect_provider_dirs_* tests stay open under #316.

Test plan

  • uv run pytest packages/memtomem/tests/ -m "not ollama" -q — full suite green locally on macOS (3951 passed)
  • uv run ruff check packages/memtomem/tests + ruff format --check packages/memtomem/tests — clean across all 158 files
  • Mypy advisory: no new errors (the 2 pre-existing errors in cli/agent_cmd.py and storage/mixins/schedules.py are unrelated)
  • CI Windows job (informational): 105 → 44 failures (−61); macOS / Ubuntu green with no pass-count delta

🤖 Generated with Claude Code

pandas-studio and others added 3 commits May 2, 2026 15:06
`Path.home()` on Windows reads `USERPROFILE` first (then
`HOMEDRIVE`+`HOMEPATH`), so `monkeypatch.setenv("HOME", str(tmp_path))`
is silently ignored and tests read/write the real runner home. This
manifests as `~/.claude/projects` auto-discovery returning the runner's
real home contents (see #644) and `~/.memtomem/config.json` writes
landing outside `tmp_path`.

Introduce a small `set_home(monkeypatch, path)` helper in
`tests/helpers.py` that sets both `HOME` and `USERPROFILE` (harmless
no-op on POSIX, correct on Windows). Apply to the 7 auto-discovery
callsites that exercise `Path.home()` indirectly:

- `test_config_overrides.py::test_detect_provider_dirs_excludes_gemini`
- `test_config_overrides.py::test_detect_provider_dirs_filters_empty_claude_memory`
- `test_config_overrides.py::test_detect_provider_dirs_finds_claude_plans_and_codex`
- `test_init_cmd.py::TestProviderDirsStep::test_write_merges_provider_dirs_into_memory_dirs`
- `test_init_cmd.py::TestIncludeProviderFlag::test_flag_resolves_categories_to_dirs`
- `test_init_cmd.py::TestIncludeProviderFlag::test_flag_silently_skips_unavailable_categories`
- `test_init_cmd.py::TestIncludeProviderFlag::test_no_flag_writes_no_provider_dirs`

Of the 7, 4 currently fail on the informational Windows job
(filters_empty_claude_memory, finds_claude_plans_and_codex, and the 3
`TestIncludeProviderFlag` tests). The other 3 are migrated for
correctness — `excludes_gemini` was a false-positive pass (assertion
held trivially when `_detect_provider_dirs()` returned empty due to
USERPROFILE redirect), and `write_merges_provider_dirs` had a HOME
monkeypatch that was inert but uses the same auto-discovery shape.

Test-only change. The 130+ other `monkeypatch.setenv("HOME", ...)`
sites across 18 test files (notably 91 in `test_init_cmd.py` and 25 in
`test_web_routes.py`) will be migrated in follow-up PRs to keep this
change axis single (one PR, one change).

Refs #644. Part of the Windows CI green journey (PR 1 #711, PR 2 #713).

Co-Authored-By: Claude <[email protected]>
…me docstring

Per PR #714 review, surface the 5 manual "set both" call sites that
predate this helper so the next contributor sweeping the residual
~130 ``monkeypatch.setenv("HOME", ...)`` sites doesn't re-introduce
the manual pattern.

Refs #644.

Co-Authored-By: Claude <[email protected]>
…t_home helper

Mechanical migration of all remaining HOME-only monkeypatch sites in
packages/memtomem/tests/ to the set_home helper introduced in 9825210.
On Windows, Path.home() reads USERPROFILE first; bare HOME setenv was
silently ignored, leaking real user-home reads in fresh runners.

Sweep covers:
- 88 sites in test_init_cmd.py (HOME-only)
- 25 sites in test_web_routes.py (24 HOME-only + 1 manual HOME+USERPROFILE pair)
- 4 sites across test_web_routes_extended.py (2 manual pairs)
- 4 sites across test_context_settings.py (2 manual pairs)
- Manual HOME+USERPROFILE pairs in test_context_agents.py and
  test_server_tools_context_settings_gate.py collapsed into one set_home call
- Single-site replacements in 11 other test files

Manual pairs (HOME setenv followed by USERPROFILE setenv with the same
value) are collapsed into a single set_home(monkeypatch, path) call,
removing the redundancy that motivated the helper. Helper docstring is
trimmed: the manual call-site list is no longer needed now that the
sweep is complete.

No production code changes. ruff check + format clean. Full impacted
test set (856 tests across the 17 files) passes locally on macOS.

Co-Authored-By: Claude <[email protected]>
@memtomem memtomem changed the title test(windows): set_home helper for HOME→USERPROFILE Windows fix (refs #644, PR 3/N) test(windows): set_home helper + sweep ~133 HOME monkeypatch sites (refs #644) May 2, 2026
@memtomem memtomem merged commit 5ca3cd3 into main May 2, 2026
8 of 9 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators May 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants