In Resolver#resolve, the edge walk dedups with next if resolved.key?(id) (and queue << edge_decl unless resolved.key?(...)) — see lib/dev/deps/resolver.rb.
When two packages both depend on C with different constraints (a diamond), whoever reaches C first pins it, and the second edge is dropped without verifying that the pinned version satisfies its constraint. reject_conflicts only inspects the input declarations, never transitive edges.
Today this is unreachable in practice — ficsit is the only integration reporting resolved edges, and its trees are shallow — but it is a correctness gap that grows with every integration that gains transitivity support.
Fix direction: accumulate constraints per PackageId during the walk and raise loudly when a pinned version violates a later edge's constraint. A satisfying-version re-solve or full backtracking is a separate, bigger step.
Related (future): cross-integration edges for subproject / dev-as-an-ecosystem resolution — DependencyEdge currently carries only a name, and the walk stamps the declaring dep's integration onto every edge.
In
Resolver#resolve, the edge walk dedups withnext if resolved.key?(id)(andqueue << edge_decl unless resolved.key?(...)) — seelib/dev/deps/resolver.rb.When two packages both depend on C with different constraints (a diamond), whoever reaches C first pins it, and the second edge is dropped without verifying that the pinned version satisfies its constraint.
reject_conflictsonly inspects the input declarations, never transitive edges.Today this is unreachable in practice — ficsit is the only integration reporting resolved edges, and its trees are shallow — but it is a correctness gap that grows with every integration that gains transitivity support.
Fix direction: accumulate constraints per
PackageIdduring the walk and raise loudly when a pinned version violates a later edge's constraint. A satisfying-version re-solve or full backtracking is a separate, bigger step.Related (future): cross-integration edges for subproject / dev-as-an-ecosystem resolution —
DependencyEdgecurrently carries only a name, and the walk stamps the declaring dep's integration onto every edge.