fix: Keep pnpm patches with version range keys during prune (#13307)
### Why
pnpm supports semver ranges in `patchedDependencies` keys (e.g.
`next@<=16.2.9`), but `turbo prune` silently dropped them: the patch key
disappeared from the pruned lockfile, the patch file was not copied, and
the entry was stripped from `package.json` / `pnpm-workspace.yaml`. The
pruned repo then installed unpatched dependencies.
Fixes #13301
### What
`PnpmLockfile::prune_patches` now retains a patch when its key's version
part is a semver range matching a pruned package's resolved version, in
addition to the existing exact `name@version` and version-less `name`
lookups.
### How
- Lookup order per pruned package: exact key, then range key, then
version-less key, mirroring pnpm's exact > range > name-only precedence.
- Bare-version keys (`foo@1.0.0`) are excluded from range matching since
pnpm treats them as exact, while Rust's `VersionReq` would treat them as
caret ranges.
- The v5/v6 patch-hash check applies to range matches the same as exact
matches.
- No downstream changes needed: `package_json_patch_paths`,
`patch_paths_for_keys`, and `prune_workspace_patches` compare the same
key strings/paths, which now survive in the pruned lockfile.
To test: unit tests cover range/scoped/non-matching/bare-version keys,
and a new integration test
(`test_prune_docker_keeps_version_range_patches`) runs `turbo prune
--docker` end-to-end with `is-number@<=7.0.0` and asserts the lockfile
key, `package.json` entry, and patch file all land in the pruned output.
Alternatively, follow the repro at
https://github.com/Netail/repro-turbo-version-range-patches.