07ee4a2ec8
* fix: Windows path handling in search_files rg calls and patch escape drift Two related Windows failures from a live session (Windows 10, git-bash terminal backend, winget-installed native ripgrep): 1. search_files was unusable on drive-letter paths. _escape_shell_arg rewrites C:\... to the MSYS form /c/... so bash builtins resolve it, but rg is a native Windows binary and Hermes disables MSYS argument conversion for its bash subprocesses (MSYS_NO_PATHCONV=1 / MSYS2_ARG_CONV_EXCL=*, see _apply_windows_msys_bash_env_defaults) — so nothing ever translated /c/... back and every search failed with 'The system cannot find the path specified. (os error 3)'. Fix: new _escape_native_tool_arg emits the forward-slash NATIVE form (C:/Users/...), which native binaries accept, bash passes through untouched, and MSYS builds also handle. Applied to the six rg call sites (content search, --files search x2, zero-match probe x3); the grep fallback keeps the MSYS form since MSYS grep wants it. 2. The patch tool silently doubled backslash runs when tool-call args arrived JSON-escaped one extra time (file had \ where old_string had \\). Similarity strategies (context_aware) matched the region anyway and wrote new_string verbatim, corrupting every backslash run (reproduced: 6 backslashes on the line became 12). _detect_escape_drift now also blocks when every backslash run in old_string is exactly twice its counterpart in the matched region and new_string repeats the doubling — with guardrails so exact matches, intentional backslash edits, model-corrected new_strings, and single weak-signal runs all still apply. Blocking returns the standard escape-drift guidance so the model re-reads and retries with correct counts. Tests: TestEscapeNativeToolArg (5 cases, including an end-to-end _search_with_rg command capture) and TestBackslashDoublingDrift (6 cases). The 8 pre-existing failures in tests/tools/test_file_operations.py on a Windows host (umask/symlink POSIX assumptions) are identical on unmodified main and unrelated. * fix: shell linters get native Windows paths too (node C:\c\... double-prefix) Same class as the rg fix: LINTERS commands (python -m py_compile, node --check, npx tsc, go vet, rustfmt) invoke native Windows binaries, but _check_lint interpolated the MSYS /c/... form. node resolves that as C:\c\Users\... (double-prefixed), so on Windows hosts every .js write reported a phantom ENOENT lint failure that could mask real syntax errors (issue #84303). Route the {file} arg through _escape_native_tool_arg like the rg call sites. Regression test asserts node --check receives 'C:/...' and never '/c/...'.