anchor.diff:                  let nodesToRemove = ResizeArray()
                   for node in parent.ChildNodes do
                       if node.Name = "dependency" then
  -                        let packageName =
  -                            match node.Attributes.["id"] with null -> "" | x -> x.InnerText
  -                        let packName = PackageName packageName
  +                        let packName = attr "id" node |> Option.map PackageName
  +                        let versionRange = attr "version" node |> Option.bind VersionRequirement.TryParse
  +
                           // Ignore unknown packages, see https://github.com/fsprojects/Paket/issues/2694
  -                        // TODO: Add some version sanity check here.
                           // Assert that the version we remove it not newer than what we have in our resolution!
                           if known.Contains packName
                              && not (projectReferences.Contains packageName)
                              && not (directDeps.Contains (PackageName packageName)) then
  +                        match packName with
  +                        | Some IndirectDependency ->
                               nodesToRemove.Add node |> ignore
  +                        | Some UnknownDependency -> ()
  +                        | Some (DirectDependency ((GroupName(grp, _)) as g, (PackageName.PackageName(pkg, _) as p))) ->
  +                            match versionRange with
  +                            | Some versionRange ->
  +                                match (g, p), versionRange with
  +                                | MatchesRange -> ()
  +                                | LockRangeNotFound ->
  +                                    printfn "Couldn't find a version range for package '%s' in group '%s', is this package in your paket.dependencies file?" pkg grp
  +                                    ()
  +                                | NeedsRangeUpdate newVersionRange ->
  +                                    let nugetVersionRangeString = newVersionRange.FormatInNuGetSyntax()
  +                                    node.Attributes.["version"].InnerText <- nugetVersionRangeString
  +                            | None ->
  +                                ()
  +                        | None ->
  +                            raise (Exception(sprintf "Could not read dependency id for package node %O" node))
   
                   if nodesToRemove.Count = 0 then
                       for node in parent.ChildNodes do traverse node
  
positive.code:             use fileStream = File.Open (nuspecFile, FileMode.Create)
              doc.Save fileStream
  
      static member FixNuspecs (projectFile: ProjectFile, referencesFile: ReferencesFile, nuspecFileList:string list) =
          let deps = Dependencies.Locate(Path.GetDirectoryName(referencesFile.FileName))
          let locked = deps.GetLockFile()
          let projectReferences =
              projectFile.GetAllReferencedProjects(onlyWithOutput = true, cache = PackProcessCache.empty)
              |> List.map (fun proj -> proj.NameWithoutExtension)
              |> Set.ofList
  
          // NuGet has thrown away "group" association, so this is best effort.
          let known =
  
negative.code:             if not (File.Exists nuspecFile) then
                  failwithf "Specified file '%s' does not exist." nuspecFile
  
          let projectReferencedDeps =
              referencesFile.Groups
              |> Seq.collect (fun (KeyValue(group, packages)) -> packages.NugetPackages |> Seq.map (fun p -> group, p))
  
          let groupsForProjectReferencedDeps =
              projectReferencedDeps
              |> Seq.map (fun (grp, pkg) -> pkg.Name, grp)
              |> Seq.groupBy fst
              |> Seq.map (fun (key, items) -> key, (items |> Seq.map snd |> List.ofSeq))
              |> Map.ofSeq
  
          let allDepsFilePackages =
              depsFile.Groups
              |> Seq.map (fun (KeyValue(g, p)) -> g, p.Packages)
  
          let allDepsFilePackageRequirements =
              allDepsFilePackages
              |> Seq.collect (fun (group, packages) ->
                  let depsFileRanges = depsFile.Groups.[group].Packages |> List.map (fun p -> p.Name, p.VersionRequirement) |> Map.ofList
                  packages
                  |> Seq.choose (fun p ->
                      match depsFileRanges.TryFind p.Name with
                      | Some req -> Some ((group, p.Name), req)
                      | None -> None
                  )
              )
              |> Map.ofSeq
  
          let allLockFileResolvedVersions =
              allDepsFilePackages
              |> Seq.collect (fun (group, packages) ->
                  let lockGroup = locked.Groups.[group].Resolution
                  packages
                  |> Seq.choose (fun p ->
                      lockGroup.TryFind p.Name
                      |> Option.map (fun p -> (group, p.Name), p.Version)
                  )
              )
              |> Map.ofSeq
  
          let lockedPackageVersionRequirements =
              projectReferencedDeps
              |> Seq.map (fun (grp, pkg) -> grp, pkg.Name)
              |> Seq.choose (fun groupAndPackage -> match allDepsFilePackageRequirements.TryFind groupAndPackage with | Some r -> Some(groupAndPackage, r) | None -> None)
              |> Seq.map (fun (groupAndPackage, versionRequirement) ->
                  match allLockFileResolvedVersions |> Map.tryFind groupAndPackage with
                  | Some lockedVersion -> groupAndPackage, adjustRangeToLockedVersion versionRequirement lockedVersion
                  | None -> groupAndPackage, versionRequirement
              )
              |> Map.ofSeq
  
  //        printfn "=====\ndirectDeps\n====="
  //        for (grp, pkg) in projectReferencedDeps do printfn "%A ==> %A" grp pkg.Name
  //        printfn ""
  
          let (|IndirectDependency|DirectDependency|UnknownDependency|) (p: PackageName) =
              if not (known.Contains p)
              then UnknownDependency
              else
                  match groupsForProjectReferencedDeps.TryFind p with
                  | None -> IndirectDependency
                  | Some [] -> IndirectDependency
                  | Some [group] -> DirectDependency (group, p)
                  | Some (firstGroup::_) -> DirectDependency (firstGroup, p)
  
  //        printfn "=====\nlocked\n====="
  //        for dep in lockedPackageVersionRequirements do printfn "%O" dep
  //        printfn ""
  
          let (|MatchesRange|NeedsRangeUpdate|LockRangeNotFound|) (groupAndPackage: (GroupName * PackageName), nuspecVersionRequirement: VersionRequirement) =
  
              match lockedPackageVersionRequirements.TryFind groupAndPackage with
              | Some lockedFileRange ->
                  if lockedFileRange = nuspecVersionRequirement
                  then MatchesRange
                  else NeedsRangeUpdate lockedFileRange
              | None -> LockRangeNotFound
  
          for nuspecFile in nuspecFileList do
              let nuspecText = File.ReadAllText nuspecFile
  