findPythonForRoot ended in findSystemPython(), so a checkout with no
in-tree venv/.venv produced a PATH Python. Two designed refusals were
therefore unreachable: readSourceUpdate's `!managed && !probe.python`
guard (checkout-source.ts) and StateDbPreflight's `string | null` python
plus its "Python not found" throw (state-db-preflight.ts). Both were
written expecting null and could never see it.
A PATH Python can import a checkout while lacking its selected
dependencies, which is the failure the checkout-source comment already
names, so a failed read became a wrong answer instead of a refusal:
the update probe, the state.db pre-flight and the source backend all
ran under an interpreter nothing selected. PM deletes the in-tree
venv/.venv once a generation is committed, making null the ordinary
answer for a managed install — its callers resolve the installation
launcher instead, and the backend ladder falls through to its next rung.
resolveSourcePython owns the decision (override, then the checkout's own
venv, else null) and findPythonForRoot keeps its signature, so the four
call sites are unchanged. findSystemPython stays for the uninstaller,
whose interpreter choice is a separate, deliberate one for a locked venv.