Support hosted and vendored PDM patches - #243
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Leftover PDM lock blocks live PyPI redirects
- PDM rewriter now only runs when pdm.lock is the active lock file (uv.lock not present), preventing stale pdm.lock from blocking uv.lock/requirements.txt patches.
You can send follow-ups to the cloud agent here.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7547658. Configure here.
607e20f to
bf281e1
Compare
Review + hardening: rebased onto main, 14 correctness fixes, full real-PDM matrixI ran an adversarial multi-agent review of this PR and a full real-PDM compatibility Rebase + cleanup
Defects found by testing + fixed (verified against real PDM 0.12–2.29)
Correctness fixes from the review (adversarially verified)
Evidence
Bugbot's HIGH ("leftover pdm.lock blocks live redirects") is resolved: the |
bf281e1 to
f292ffb
Compare
Adds hosted PDM redirects and refactors the vendored PDM backend onto one validated `pdm.lock` rewriter (`utils/pdm_lock.rs`). Hosted `scan --mode hosted` rewrites the target `[[package]]` to the hosted wheel URL + patched SHA-256 (`redirect_pdm_lock_package`); vendored wires the same unit to a committed wheel. Both support the legacy `[metadata.files]` table and `extras` entries, preserve line endings and non-canonical spacing, are idempotent, and leave `pyproject.toml` / `content_hash` untouched. Supported lock formats are `2` (PDM 0.12-1.4) and `4.3`-`4.5.1` (PDM 2.8+); `3.1` / `4.0`-`4.2` (PDM 1.8-2.7) and unknown formats are refused before any write. Hardening beyond the original change: - Hosted lock-only checkouts are discovered and redirected: the lock inventory now reads `pdm.lock` (discovery-only, mirroring poetry). Vendored keeps refusing a lock-only checkout since PDM installs into `__pypackages__`, which the crawler does not probe. - A re-scan after an external `pdm lock` rebases the ledger's edits onto the relocked text. PDM un-patches AND may reflow line endings (CRLF -> LF) on relock, so for the pdm edit kind the rebase adopts the fresh `original` (the relocked registry fragment); poetry's relock keeps the patch and keeps its older original, so its path is unchanged. - When several Python lockfiles coexist, `uv.lock` and `poetry.lock` drive hosted PyPI redirects ahead of `pdm.lock`; a leftover `pdm.lock` neither blocks a live redirect nor is falsely attested. The same predicate gates the redirect dispatch and the hosted confirmation filter. Adds byte-exact `pdm-native` fixtures and CLI-level hosted regression tests (lock-only redirect + attest + rollback, legacy `[metadata.files]`, and relock-reflow convergence). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Documents hosted PDM support (ecosystems.md, hosted-production-e2e.md, CLI_CONTRACT.md new codes, CHANGELOG) and adds the per-release matrix: docs/testing/pdm-compatibility.md with a generated table, scripts/backtest-pdm.py (real PDM releases via uv, hosted/vendored/agent, installed-byte verification, tamper rejection, relock convergence, rollback), and .github/workflows/pdm-compatibility.yml (Linux/Windows/macOS). Measured 0.12-2.29 across 17 shapes x 3 modes: 523 pass, 268 refused as expected (identity-losing 3.1/4.0-4.2, forked two-version locks, non-default lock filenames), 46 unsupported (`__pypackages__` agent/vendored, a documented layout limitation), 0 failures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A 12-finder review (42 confirmed findings) plus a real-PDM verification pass
surfaced correctness gaps beyond the initial three. Fixes, each verified
against real PDM binaries:
Confirmation / attestation (false-success class):
- Refuse a lock whose `strategy` lacks `inherit_metadata` (lock_version
4.4.1/4.5.x) — PDM 2.12-2.23 re-resolves such a lock and cannot match a
rewritten `url`/`path` source (CandidateNotFound); read the 4.3 boolean
strategy spelling (`cross_platform`/`static_urls`) that PDM 2.8-2.9 write.
- A `pdm.lock` refusal now vetoes the sibling pypi rewriters only for a package
the lock CONTAINS but refuses, never one it simply lacks (which a
`requirements.txt`/pylock legitimately installs) — the old veto silently
dropped those redirects.
- An inactive `pdm.lock` (a `uv.lock`/`poetry.lock` drives) no longer feeds the
substring confirmation probe, so an untouched uv/poetry project cannot report
a bogus `redirected: 1`.
- Emit `redirect_pdm_stale_install_risk` for PDM < 2.11 locks (2/4.3/4.4), which
do not reinstall over an already-installed same-version package.
- A marker/multi-target lock holding one package at several versions is refused
with an accurate, ordering-independent message (hosted and vendored).
Vendored integrity:
- Refuse a symlinked `pdm.lock` before wire/revert (the rename-over would
replace the link and strand its target) — mirrors the uv/hosted guards.
- Require a real sha256 in the pre-flight hash guard so a non-sha256 lock is
refused before the wheel is built.
- Refuse a `pdm add`/partial-relock unit that kept the patched hash but lost the
vendored `path`, so a stale patched hash is never recorded as the registry
original.
- Supersede a prior Socket-hosted `url` (rotated token / new uuid, same origin
and wheel leaf) in place instead of refusing it as foreign.
- Fix the version-mismatch refusal to print the plain version, not `Some("…")`.
Fragments / keys:
- Give the recorded package fragment a trailing boundary so a lock_version-2
pristine fragment is not a prefix of the rewritten one (replay convergence).
- Key legacy `[metadata.files]` by PDM's `safe_name().lower()` (dots preserved),
so dotted-name packages in format-2 locks are found.
Docs: PDM 2.8.0 writes an indistinguishable `4.3` lock but shares the
identity-loss bug, so the supported floor is 2.8.1; the docker vendored e2e
awk counter now matches the inline `files` shape.
Adds unit tests for the strategy gate, multi-version fork, URL supersede,
dotted-name key, absent-package veto skip, stale advisory, symlink guard and
the non-sha256 pre-flight refusal.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f292ffb to
b9408d9
Compare
Rebased onto
|


LLM Description written by Codex:gpt-6-astra
Hosted PDM scans did not produce a confirmed redirect, while vendored scans rejected historical lock formats and CRLF files. Both modes now share a validated source-and-integrity rewriter with legacy metadata.files support, base/extras entries, byte-preserving edits, idempotency and exact rollback. Conflicting sources, ambiguous package entries, malformed strategies and unsupported schemas are refused before files change. Failed PDM rewrites cannot be reported as successful through a generic manifest rewrite.
The native compatibility matrix covers every stable PDM major family (0.x, 1.x, 2.x), with thirteen releases spanning the lock-format transitions. PDM 0.12.3 supports both modes with
pdm sync; the CLI warns about its upstream freshness bug, which can cause ordinary install to regenerate some locks. PDM 1.15.5 and 2.0–2.7 lose URL/path candidate identity in native dependency lookup, so their schemas refuse safely without changing inputs. PDM 2.8.2 through 2.29.2 pass both patch modes. Unknown future formats also refuse.Validation:
75476589b04f1d66d0d92a747ccbb7dc79673067commit.Note
Medium Risk
Changes how Python lockfiles are rewritten and how hosted scans attest PyPI patches when
pdm.lockis present; incorrect confirmation or lock edits could affect supply-chain enforcement, though the design is fail-closed with extensive tests.Overview
Adds PDM (
pdm.lock) to hosted registry redirects and aligns vendored PDM wiring with the same lock rewriter.A shared
pdm_lockmodule validates supported lock versions/strategies, rewrites wheelurl/pathand file hashes (including legacy[metadata.files]and extras variants), preserves line endings, and produces fragment edits for replay. Hosted scan collectspdm.lockand only confirms PyPI patches whenconfirmed_pdm_uuidssays the PDM rewrite fully landed; refused PDM uuids are excluded like pnpm/cargo.The redirect pipeline runs PDM first and drops overrides that PDM refused before other ecosystems run. Vendor
pypi_pdmdrops bespoke text splicing in favor ofrewrite_pdm_lock/pdm_lock_edits, broadens supported lock formats (with fail-closed refusal for untested versions), treats legacy[tool.pdm.*-dependencies]as direct deps, and handles CRLF/non-canonical spacing via span-based edits. Replay groupsredirect_pdm_lock_packagewith other PyPI edits. Byte-exactpdm-nativelock fixtures and.gitattributes-textrules back the matrix.Reviewed by Cursor Bugbot for commit 7547658. Configure here.