One uv sync, Fully Traced
1. Discover desired and actual state
The project command loads workspace metadata, Python requirements, settings, lock mode, interpreter, and the existing environment. This is mostly ordinary owned data and borrowing; async becomes important when discovery reaches the network, subprocesses, or locks.
2. Lock the environment before mutation
sync
acquires the environment lock before the resolve-and-install path. Separate uv
processes may populate the shared cache, but must not concurrently rewrite the
same site-packages.
3. Produce or validate the lock
Lock modes encode frozen, locked, dry-run, and write behavior. The resolver drives a PubGrub-like decision process while metadata requests execute concurrently. Resolution is coordination-heavy CPU work fed by asynchronous evidence, not a parallel search that may accept inconsistent branches.
4. Derive an installation plan
Installed distributions, the resolution, reinstall policy, and cache state are compared to classify packages as already satisfied, removable, cached, or remote. Planning is separated from mutation so diagnostics and dry-run can describe the intended transition.
5. Prepare missing artifacts
Preparer
starts distribution futures together. Downloads and builds are limited deeper
in the database by shared semaphores. The largest artifacts start first to
reduce the long tail.
6. Apply under exclusive target ownership
uv removes obsolete packages and installs prepared wheels using links, reflinks, or copies from its archive cache. Temporary files and renames avoid publishing partially written cache entries; the environment lock protects the multi-file target transition.