fix: Support pnpm per-workspace lockfiles in turbo prune (#12067)
## Summary
- Fixes `turbo prune` failing with "no workspace found in lockfile" when
pnpm is configured with `shared-workspace-lockfile=false` (#3541)
- Adds a lockfile-test fixture (`pnpm-per-workspace-lockfile`) that
reproduces the scenario
## Problem
When pnpm's `.npmrc` has `shared-workspace-lockfile=false`, each
workspace gets its own `pnpm-lock.yaml` instead of a single root-level
lockfile. Turbo only looked for a root lockfile, so it either couldn't
find it or found one that only contained the root's importers.
## Approach
1. **`.npmrc` parsing** — `NpmRc` now reads `shared-workspace-lockfile`
2. **Lockfile merging** —
`PnpmLockfile::merge_per_workspace_lockfiles()` takes per-workspace
lockfiles, re-keys their `"."` importers to the workspace's relative
path (e.g. `apps/web`), and merges all packages/snapshots into a unified
lockfile
3. **Discovery** — `PackageManager::read_lockfile()` checks `.npmrc` for
pnpm, and when per-workspace lockfiles are detected, discovers workspace
dirs via globs and merges their lockfiles
4. **Prune output cleanup** — The pruned output always uses a shared
lockfile, so stale per-workspace lockfiles are removed from copied
workspace directories and `.npmrc` is rewritten to
`shared-workspace-lockfile=true`
## Testing
To verify manually, build turbo and run against the new fixture:
```
cargo build
# Copy fixture to a temp dir, git init, then:
turbo prune web
# Should succeed and produce a merged lockfile in out/
```
Rust unit tests cover `.npmrc` parsing and the lockfile merge logic.