From 49ccca0014ff04274be526071658c4ab346b1c2f Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 2 Nov 2026 03:18:00 +0100 Subject: [PATCH 1/3] rfc(pnpr): split packuments and platform variants details from the implementation Co-Authored-By: Claude Opus 5.5 --- pnpr/text/0000-platform-variants.md | 10 +++++++--- pnpr/text/0000-split-packuments.md | 16 ++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/pnpr/text/0000-platform-variants.md b/pnpr/text/0000-platform-variants.md index 97710ce..4d4336c 100644 --- a/pnpr/text/0000-platform-variants.md +++ b/pnpr/text/0000-platform-variants.md @@ -435,8 +435,11 @@ For example, variant A can list `linux-x64` and `darwin-arm64-napi9`, while B lists `linux-x64-napi8` and `darwin-arm64`. Linux with N-API 9 must prefer B; macOS arm64 with N-API 9 must prefer A. No single ordering of A and B works. Reuse the resolution type and matching utilities, but extend the selector for -these records; older runtime lockfiles retain their existing selection behavior. -The required lockfile version marker distinguishes the new semantics. +these records. The selector chooses its rule from each variant's resolution: a +runtime's `binary` archives keep first-match selection, and a package's +registry or tarball variants are ranked. It needs no version check; the +lockfile version marker is needed only so older releases do not rewrite a +lockfile without its variants. For example: @@ -526,7 +529,8 @@ Six changes to the lockfile and its interpretation are needed: - `targets` gain the floor and ABI fields from the tag table. - The selector ranks the best matching target of every variant at install time, independently of serialization order, instead of stopping at the first - match. The lockfile version distinguishes this from existing runtime entries. + match. Runtime entries, whose variants are `binary` archives, keep + first-match selection. - A `fallback` resolution holds the primary archive. It is absent when the version has no primary. - `VariationsResolution` gains an optional `revision` (including `0` for diff --git a/pnpr/text/0000-split-packuments.md b/pnpr/text/0000-split-packuments.md index 61234f0..780a494 100644 --- a/pnpr/text/0000-split-packuments.md +++ b/pnpr/text/0000-split-packuments.md @@ -180,6 +180,10 @@ by its `manifest`, not by its `integrity`. ### Publish times +Publish times that the document coarsens, as npm's abbreviated document does, +are coarsened relative to the package's last publish, never the current time, so +the document changes only when the package is published to. + A minimum release age filters versions by their publish time before it picks one, but it only needs to know whether a version is younger than the cutoff. So an entry carries its time only if the version was published within @@ -334,10 +338,10 @@ manifests. Below it, every entry has one: leaving manifests out saves little there and would cost a request for every package whose resolution picks an older version. The prototype used 64 KiB of serialized JSON. -Once a package's document crosses the threshold, it stays split, even if it -shrinks below it again (after an unpublish, for example). A document that -flips between the two near the threshold would change for clients on every -publish, for no saving. pnpr records the decision with the package. +pnpr decides from the document on every read and records nothing. A publish only +grows the document, so it cannot flip it back below the threshold; only an +unpublish, or a removed deprecation or tag, can, and clients read both forms the +same way. ### Client behavior @@ -499,8 +503,8 @@ one function every pick goes through. 1. pnpr: serve the new format under the new media type with `Vary: Accept`, with the likely-picks rule, a configurable threshold, and a configurable - publish-time window of at least 30 days (30 by default), and record that a - package is split. + publish-time window of at least 30 days (30 by default), deciding the split + from the document on every read. 2. pnpr: serve release records at `/+r` for every accepted revision, with immutable caching, and remove `dist.pnpr`, `variants`, any variant declarations pnpr stores with a version, From a813b7d044299fa929df34ae91da329159f673f1 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 2 Nov 2026 03:18:12 +0100 Subject: [PATCH 2/3] rfc(pnpr): rewrap the split packuments implementation step Co-Authored-By: Claude Opus 5.5 --- pnpr/text/0000-split-packuments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pnpr/text/0000-split-packuments.md b/pnpr/text/0000-split-packuments.md index 780a494..06b78a0 100644 --- a/pnpr/text/0000-split-packuments.md +++ b/pnpr/text/0000-split-packuments.md @@ -503,8 +503,8 @@ one function every pick goes through. 1. pnpr: serve the new format under the new media type with `Vary: Accept`, with the likely-picks rule, a configurable threshold, and a configurable - publish-time window of at least 30 days (30 by default), deciding the split - from the document on every read. + publish-time window of at least 30 days (30 by default), deciding the + split from the document on every read. 2. pnpr: serve release records at `/+r` for every accepted revision, with immutable caching, and remove `dist.pnpr`, `variants`, any variant declarations pnpr stores with a version, From 69edaa41d9577322ef5690b4fdad928e133870c8 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 2 Nov 2026 07:20:40 +0100 Subject: [PATCH 3/3] docs(pnpr): scope sorted variants to packages, let a publish shrink a document Co-Authored-By: Claude Opus 5.5 --- pnpr/text/0000-platform-variants.md | 10 ++++++---- pnpr/text/0000-split-packuments.md | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/pnpr/text/0000-platform-variants.md b/pnpr/text/0000-platform-variants.md index 4d4336c..7ad22b8 100644 --- a/pnpr/text/0000-platform-variants.md +++ b/pnpr/text/0000-platform-variants.md @@ -425,10 +425,12 @@ unchanged across revisions is stored once. ### Lockfile pnpm records a package with variants using the existing `variations` -resolution shape, extended with the selection rule above. Serialize variants -in byte order of their derived tags for a platform-neutral lockfile; array -order does not choose the archive. At install time, evaluate every variant's -best matching target for the actual host and rank those matches. +resolution shape, extended with the selection rule above. Serialize a +package's variants in byte order of their derived tags for a platform-neutral +lockfile; array order does not choose its archive. At install time, evaluate +every variant's best matching target for the actual host and rank those +matches. A runtime's `binary` variants keep their written order, which their +first-match selection depends on. The current first-match implementation cannot express this rule for all hosts. For example, variant A can list `linux-x64` and `darwin-arm64-napi9`, while B diff --git a/pnpr/text/0000-split-packuments.md b/pnpr/text/0000-split-packuments.md index 06b78a0..573d1f0 100644 --- a/pnpr/text/0000-split-packuments.md +++ b/pnpr/text/0000-split-packuments.md @@ -182,7 +182,7 @@ by its `manifest`, not by its `integrity`. Publish times that the document coarsens, as npm's abbreviated document does, are coarsened relative to the package's last publish, never the current time, so -the document changes only when the package is published to. +time passing never changes the document; only a write to the package does. A minimum release age filters versions by their publish time before it picks one, but it only needs to know whether a version is younger than the @@ -338,10 +338,11 @@ manifests. Below it, every entry has one: leaving manifests out saves little there and would cost a request for every package whose resolution picks an older version. The prototype used 64 KiB of serialized JSON. -pnpr decides from the document on every read and records nothing. A publish only -grows the document, so it cannot flip it back below the threshold; only an -unpublish, or a removed deprecation or tag, can, and clients read both forms the -same way. +pnpr decides from the document on every read and records nothing. A document +can cross the threshold in either direction: a publish after a long gap can +shrink it, by dropping the publish times that fall out of the window, and so can +an unpublish or a removed deprecation or tag. Clients read both forms the same +way. ### Client behavior @@ -545,7 +546,8 @@ version has its manifest), an older pnpm sharing the home directory, and a froze install that reads no metadata. Also test the 30-day release-age boundary, a larger policy rejected when consuming this format, and time-based cutoffs on either side of `timesSince`, including the documented approximation for an -older cutoff. None of these cases fetches a second document for timestamps. +older cutoff, and a publish after a long gap that takes a document back below +the threshold. None of these cases fetches a second document for timestamps. ## Prior Art