c6a71294b6
Two gaps left every Windows git-checkout install unable to recover from the exact failure state #83569 reports: 1. Self-lock detection. _detect_venv_python_processes() always excludes the calling process by design — a CLI hermes update IS the venv python. An updater that had already imported a native venv extension (the canonical one being cryptography.hazmat.bindings._rust, mapped while hermes_cli.main resolved external secret sources) passed every preflight and then died mid-sync with os error 5 when uv tried to rewrite the mapped .pyd, stranding the venv half-updated. A new preflight now refuses the sync before touching the checkout, writes the update-incomplete marker so the next fresh launch completes the install, and exits 2. Verified on a live Windows 11 host: after importing hermes_cli.main, tasklist /m _rust.pyd shows the .pyd mapped in the caller, and a peer process cannot open it read-write (Permission denied) — while a rename succeeds, matching how uv/pip actually fail (truncate+write, not rename). 2. Early-recovery install path. _early_recovery._run_repair_install used sys.executable -m pip unconditionally. Windows git checkouts install on a uv-managed base interpreter (python-build-standalone), whose EXTERNALLY-MANAGED marker makes plain pip abort with externally-managed-environment — the repair no-oped and the venv stayed broken. The repair now detects the PEP 668 marker, prefers uv pip install with VIRTUAL_ENV pointed at the project venv, and falls back to pip --break-system-packages when no uv binary exists. Both fixes ship with subprocess/unit regressions (sabotage-verified): the new tests fail on pre-fix code and pass with it. Complements #77517, which keeps the updater from importing cryptography in the first place; this PR is the defence-in-depth when any future path loads it anyway. Fixes #83569