One Resolution, Many Realities: A Checkpoint on uv's Guarantees
At this point, uv can be understood as a chain rather than a collection of commands: project intent is turned into a conditional dependency graph, the graph is matched to a Python runtime and available artifacts, and the result is synchronized into an environment. This checkpoint connects those ideas around one practical judgment. When a project works on one machine but fails on another, the reader should be able to identify which layer changed and choose a response that addresses that layer instead of changing versions at random.
The distinction is important because “the dependencies resolve” is only one statement about a much longer path. A lockfile can be current while a target platform lacks a wheel. A wheel can be available while the wrong interpreter is selected. An environment can contain the right packages while a command is run without synchronizing it. uv's coordination is most useful when these outcomes remain distinguishable.
The same request passes through different gates
Start with a project that declares a dependency and supports several Python versions. The declaration expresses a range of acceptable choices. The lockfile records the choices uv accepted, including the conditions under which one choice applies. The interpreter supplies one concrete Python version and platform. The artifact—whether a pre-built wheel or the result of a source build—must fit that interpreter. Only then can synchronization materialize the package in the project environment.
These are not interchangeable descriptions of success. The declaration can be valid even when no compatible solution exists. The resolution can be valid even when a wheel is missing for a deployment target. The artifact can be usable while the environment is stale. The environment can be correct while a command selects a different Python interpreter. Each transition has its own owner and failure signal.
The project owns the declared support range and dependency constraints. uv's resolver owns the search for versions that satisfy those constraints and the marker conditions. The package publisher owns the available wheels and source distribution. The target platform determines which wheel tags match. The sync operation owns the final changes to the environment. A useful diagnosis follows those ownership boundaries.
The graph also explains why a lockfile should not be read as a flat list of packages. A package entry may be connected to a marker region, and the applicable artifact depends on the concrete interpreter and platform. The environment is a materialization of those choices, not a second independent resolution. If a user looks only at package names, they lose the conditions that decide whether a particular machine can use them.
A small hypothetical example makes the gates visible. Suppose a project supports Python 3.9 through 3.13 and asks for a package whose newer releases require Python 3.10 or later. A universal resolution may choose an older release for the lower Python region and a newer release for later versions. That is a successful resolution because the lockfile describes both conditions. If the same project also depends on a package that publishes only Linux wheels, the lock may remain valid while a macOS installation fails.