v0.1.23 — Windows now first-class on CI
This release lights up Windows as a gating CI platform. Issue #302 ran a multi-week ladder (#303–#319, #321) shaking out Windows-specific bugs across the cli, the file-IO utilities, the surfacing feedback store, and ~10 test sites that assumed POSIX-shaped HOME / file-mode / monotonic-clock semantics. With every rung green, #320 PATCHed main's required-status-checks to require lint (windows-latest) + test (windows-latest) — Windows is now first-class supported, not an informational matrix axis. There are no new features; v0.1.23 is the first wheel published with Windows officially under CI gate.
User-visible fixes
-
#303 —
_run_claude_mcpsubprocess now pins UTF-8 on Windows.subprocess.runwas inheriting the system codepage (cp949on Korean locale,cp1252on Western European), so any MCP discovery output containing non-ASCII bytes (server names, descriptions, tool docstrings) decoded as mojibake andmms add --from-clients/mms importeither raisedUnicodeDecodeErroror silently round-tripped garbled strings into the registry. Now pinsencoding=\"utf-8\"+errors=\"replace\"explicitly. POSIX behavior unchanged. -
#307 —
utils/fileioretriesos.replaceon Windows transientWinError 5.os.replace(tmp, dest)is the atomic-write substrate under every TOML write in mms (registry.toml,import_state.toml,stm_proxy.json, surfacing feedback store, pending store) and the proxy metrics DB rotation. On Windows it intermittently raisesPermissionError: [WinError 5]when an antivirus or indexer briefly holds the destination open. The replace path now retries up to 5 times with 10ms exponential backoff (~310ms cap) before re-raising. POSIX hits the success path on the first attempt — zero behavior change. -
#314 —
mms add --argstokenizer is now backslash-safe on Windows.shlex.spliton POSIX consumes\as escape, which destroys path separators in--args \"C:\\path\\to\\server.exe --port 1234\"(you getC:pathtoserver.exe). The cli now branches onsys.platform == \"win32\"and passesposix=False, matching cmd.exe / PowerShell semantics. -
#316 — surfacing feedback store recent ordering is deterministic on tied
created_at.feedback_store.recent(limit=N)previously relied on insertion order until two rows shared the samecreated_atUnix timestamp, at which point SQLite'sORDER BY created_at DESCbecame implementation-defined. POSIXtime.time()provides nanosecond resolution; Windows ticks at ~15.6ms, so two writes inside one operation routinely tied. Query now sorts by(created_at DESC, rowid DESC). Surfaced via Windows but is platform-agnostic correctness.
CI / test infra (no behavior change)
- #304 + #320 —
windows-latestmatrix axis added to lint + test workflows, then promoted from informational to required onmain. - #305, #310 —
set_hometest helper that round-tripsUSERPROFILE(the env var Windows actually consults). - #306 — NTFS mode-bit assertions
skipif'd on Windows (NTFS doesn't track POSIX mode bits). - #309, #312, #313 — unified test platform-detection on
sys.platform == \"win32\". - #315 — UTF-8
read_textintest_qa_round3(was using system codepage default). - #317, #319 — sleep above Windows monotonic tick floor in
pending_store.touchand compression-key TTL tests. - #318, #321 — reader thread tolerates
PermissionErrorfrom #307's retry window + 1ms yield per iteration so the reader doesn't starve the writer's retry budget under Windows' coarser scheduler.
PyPI: https://pypi.org/project/memtomem-stm/0.1.23/
Full diff: v0.1.22...v0.1.23