From 49c48507f2bfe06b85e3ce6ef5c130251120ce98 Mon Sep 17 00:00:00 2001 From: Boyd Cohen Date: Sun, 23 Aug 2026 16:38:33 -0600 Subject: [PATCH 1/4] Re-measure after the dist-tag move: latest is now 1.0.0-rc.21 Committed alone, ahead of the copy change, because npmLatest is compared by several markers and mixing the two makes the copy commit unreviewable. npmLatest 1.0.0-rc.12 -> 1.0.0-rc.21 npmLatestExports now includes resolutionPayload The withdrawal band is unchanged: resolutionPayload is still absent from rc.9 through rc.12. What changed is that latest no longer points inside it. --- results/engine-payload-exports.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/results/engine-payload-exports.json b/results/engine-payload-exports.json index 1ee14f3..18a8cf3 100644 --- a/results/engine-payload-exports.json +++ b/results/engine-payload-exports.json @@ -19,7 +19,7 @@ "versionCount" ], "computedAgainstRegistryState": { - "npmLatest": "1.0.0-rc.12", + "npmLatest": "1.0.0-rc.21", "npmRc": "1.0.0-rc.21", "versionCount": 26 }, @@ -33,7 +33,7 @@ } }, "package": "@observer-protocol/policy-engine", - "npmLatest": "1.0.0-rc.12", + "npmLatest": "1.0.0-rc.21", "npmRc": "1.0.0-rc.21", "versionCount": 26, "withdrawals": { @@ -56,7 +56,8 @@ "npmLatestExports": [ "evaluationVerdictPayload", "lapsePayload", - "refusalPayload" + "refusalPayload", + "resolutionPayload" ], "versions": [ { From 81a4ff2663e91d302da64cc7244bf2309d94b1eb Mon Sep 17 00:00:00 2001 From: Boyd Cohen Date: Sun, 23 Aug 2026 16:39:55 -0600 Subject: [PATCH 2/4] Section 02 swapped: a resolution record now checks with the version the page tells you to install All six parts in one commit, because no ordering buys anything and part 4 without parts 1-3 is green and wrong. No check reads the words, so writing them together is the only thing that makes the set atomic. 1 heading "You cannot check a resolution record with the version this page tells you to install" becomes "A resolution record now checks ... It did not, for four releases." 2 consequence sentence 1 "The version npm install serves does not export it" becomes "serves exports it. For four releases it did not." 3 consequence sentence 2 the reader-cannot-check sentence becomes the record of who could and who could not: the 122 signed resolution records were always rebuildable by someone who installed @rc, and were not by someone who followed the instruction on this page. 4 marker, both sites latest-does-not-export -> latest-exports 5 "What to do about it" it told a reader to accept the gap and said the gap closes when latest moves past the band. It has. The paragraph now says nothing needs doing and why the page stays pinned to latest regardless. 6 npmLatest spans 1.0.0-rc.12 -> 1.0.0-rc.21, both THE FOUR-RELEASE GAP IS RECORDED, NOT DELETED. The section stays because a section that vanishes when a defect clears leaves a reader unable to tell a page that was always right from a page that was corrected. resolutionPayload was still absent from rc.9 through rc.12 and the withdrawal still appears in no changelog; what changed is which release a reader receives. Verified in the INDEX before committing, per CONVENTIONS 18: all six present in the staged bytes, the old heading gone, and zero occurrences of the old marker or the old span value. --- verify.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/verify.html b/verify.html index c9718ee..6454ac7 100644 --- a/verify.html +++ b/verify.html @@ -352,12 +352,12 @@

There is no verifier for a PolicyEvaluationCredent
-

You cannot check a resolution record with the version this page tells you to install.

-

An approval resolution is the record of a human decision, signed at both ends: the routing and the outcome. Rebuilding its signed bytes needs resolutionPayload. The version npm install serves does not export it.

-

Read out of every published tarball rather than out of a release note: resolutionPayload was exported at 1.0.0-rc.8, withdrawn across 4 consecutive releases, 1.0.0-rc.9 through 1.0.0-rc.12, and restored at 1.0.0-rc.13. npm's latest tag sits inside that band, at 1.0.0-rc.12, which is the version this page documents and the version the install line above gives you.

-

So a reader following this page's own instructions cannot check a resolution, and until now the page did not say so. That is worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. We hold 122 signed resolution records that a reader on 1.0.0-rc.12 has no route to.

+

A resolution record now checks with the version this page tells you to install. It did not, for four releases.

+

An approval resolution is the record of a human decision, signed at both ends: the routing and the outcome. Rebuilding its signed bytes needs resolutionPayload. The version npm install serves exports it. For four releases it did not.

+

Read out of every published tarball rather than out of a release note: resolutionPayload was exported at 1.0.0-rc.8, withdrawn across 4 consecutive releases, 1.0.0-rc.9 through 1.0.0-rc.12, and restored at 1.0.0-rc.13. npm's latest tag sits inside that band, at 1.0.0-rc.21, which is the version this page documents and the version the install line above gives you.

+

The 122 signed resolution records this estate holds were always rebuildable by someone who installed @rc; what they were not was rebuildable by someone who followed the instruction on this page. That is worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. We hold 122 signed resolution records that a reader on 1.0.0-rc.21 has no route to.

The withdrawal appears in no changelog. The package's own release notes record neither the removal nor the restoration, so nothing but the tarballs could have told you. That is why the figures in this paragraph are read from a measurement in results/ and compared against npm on every build, instead of being typed here where nothing could contradict them.

-

What to do about it. Installing @rc gets you a version that exports it, and that is a different package from the one this site documents, so we are not going to tell you it is the same thing. This site stays pinned to what latest serves, because a page that documents a version nobody receives is the failure this whole surface is written against. The gap closes when latest moves past the band.

+

What to do about it. Nothing. The version this page documents and the version its install line gives you both rebuild a resolution record, because npm’s latest tag now points past the withdrawal band rather than inside it. This site stays pinned to what latest serves, for the same reason it did while that was the broken version: a page that documents a version nobody receives is the failure this whole surface is written against.

From b2c5c910fad6dbfcc91db3c36aa10798be4f75de Mon Sep 17 00:00:00 2001 From: Boyd Cohen Date: Sun, 23 Aug 2026 16:44:37 -0600 Subject: [PATCH 3/4] The six parts were not all of them: two sentences and a figure declaration The held plan enumerated six parts and named the two dependents that must change with them. IT MISSED TWO SENTENCES, ON TWO PAGES, AND ONE OF THEM WAS INSIDE THE SECTION BEING SWAPPED. verify.html "We hold 122 signed resolution records that a reader on 1.0.0-rc.21 has no route to." That is the failure the whole mechanism was built to prevent, in the one place it was supposed to be watched: the data-measured SPAN inside the sentence updated itself to rc.21 while the SENTENCE inverted in meaning and did not. Part 6 moved the span. Nothing moved the words around it. index.html "A further 122 resolution records are rebuildable at some published version but not at the one npm install serves." Both rewritten. The count is now 0 and both pages say so in the past tense, with the four-release history kept rather than deleted. RE-MEASURED signed-record-coverage against the stores, which are reachable: resolution.rebuildableAtNpmLatest false -> true notRebuildableAtNpmLatest kinds [resolution] count 122 -> kinds [] count 0 neverRebuildable UNCHANGED, instructed and report, 3089, 27.0%. No route at ANY version, so the tag move cannot touch it. AND THE CHECK CAUGHT ME DROPPING A DECLARED FIGURE. Rewriting index.html removed the kinds span, and check-measured-figures refused: "Dropping a measured claim must not be something an edit does quietly." Correct. The kinds list is now empty because the count is 0, so there is no class name to show and the declaration's own reason -- a count with no class name cannot be acted on -- no longer has a subject. Removed in this commit with that reason recorded, which is what the check's message asks for. The count declaration is KEPT AT ZERO rather than dropped: a page that stops citing a figure when it clears cannot show a reader that it ever was not zero. --- index.html | 2 +- results/signed-record-coverage.json | 20 +++++++++----------- scripts/measured-figures.json | 16 +++++++--------- verify.html | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/index.html b/index.html index a5f0c5b..eafc6cf 100644 --- a/index.html +++ b/index.html @@ -1147,7 +1147,7 @@

The register, stated plainly.

Signed records an outside party can rebuild
-
Of 11,432 signed records across 13 record stores we hold, written between 2026-08-05 and 2026-08-15, 3,089 of them (27.0%) cannot be checked by anyone. They are instructed, report records, and no version of the engine ever published rebuilds their signed bytes, so there is nothing to verify a signature against. This is not a version pin and it is not a gap that a reader can work around by installing something else: those records carry a signature that no counterparty, and no one here, can check. Principle 04 below says the evidence is portable or it isn't evidence. For better than a quarter of what we sign, it isn't. A further 122 resolution records are rebuildable at some published version but not at the one npm install serves; section 04 of /verify carries that. Every figure in this row is read from results/ and fails the build if the copy and the measurement disagree.
+
Of 11,432 signed records across 13 record stores we hold, written between 2026-08-05 and 2026-08-15, 3,089 of them (27.0%) cannot be checked by anyone. They are instructed, report records, and no version of the engine ever published rebuilds their signed bytes, so there is nothing to verify a signature against. This is not a version pin and it is not a gap that a reader can work around by installing something else: those records carry a signature that no counterparty, and no one here, can check. Principle 04 below says the evidence is portable or it isn't evidence. For better than a quarter of what we sign, it isn't. A second class, resolution records, was rebuildable at some published version but not at the one npm install served, for four releases. That count is now 0; section 02 of /verify carries what happened. Every figure in this row is read from results/ and fails the build if the copy and the measurement disagree.
27.0% unverifiable
diff --git a/results/signed-record-coverage.json b/results/signed-record-coverage.json index 98d6857..d05ad1f 100644 --- a/results/signed-record-coverage.json +++ b/results/signed-record-coverage.json @@ -14,7 +14,7 @@ "no reader sees. A figure that announces it is unchecked where nobody reads the", "announcement is a marker doing no work, so the announcement is now in the artifact." ], - "measuredOn": "2026-08-16", + "measuredOn": "2026-08-23", "provenance": { "corpusHalf": { "fields": [ @@ -25,7 +25,7 @@ "signedRange", "headline.neverRebuildable" ], - "measuredOn": "2026-08-16", + "measuredOn": "2026-08-23", "over": "13 store file(s) under ~/op-artifacts", "reDerivable": false, "why": "The stores are working artifacts outside this repository. CI cannot reach them, so these figures are a DATED MEASUREMENT and nothing re-confirms them. The per-file sha256 list below exists so a later run can prove it measured the same population." @@ -36,12 +36,12 @@ "headline.notRebuildableAtNpmLatest" ], "computedAgainstRegistryState": { - "npmLatest": "1.0.0-rc.12", + "npmLatest": "1.0.0-rc.21", "source": "results/engine-payload-exports.json", "thatFileMeasuredOn": "2026-08-23" }, "reDerivable": true, - "why": "These depend on which symbols npm's `latest` exports, which is public and is re-read by check-measured-figures.mjs on every run. THEY GO FALSE WHEN THE `latest` DIST-TAG MOVES, without this file being touched. If npm latest is not 1.0.0-rc.12, treat every field listed here as stale." + "why": "These depend on which symbols npm's `latest` exports, which is public and is re-read by check-measured-figures.mjs on every run. THEY GO FALSE WHEN THE `latest` DIST-TAG MOVES, without this file being touched. If npm latest is not 1.0.0-rc.21, treat every field listed here as stale." } }, "storesRoot": "~/op-artifacts", @@ -102,7 +102,7 @@ "total": 122, "rebuildRoute": "resolutionPayload", "rebuildableEver": true, - "rebuildableAtNpmLatest": false + "rebuildableAtNpmLatest": true } ], "headline": { @@ -116,12 +116,10 @@ "note": "No published version of the package rebuilds these. Not fragile, not version-pinned: unverifiable by anyone, permanently, on the evidence of every version published to date." }, "notRebuildableAtNpmLatest": { - "kinds": [ - "resolution" - ], - "count": 122, - "percentOfSigned": "1.1%", - "note": "Rebuildable at some published version but NOT at 1.0.0-rc.12, which is what npm install serves a reader today." + "kinds": [], + "count": 0, + "percentOfSigned": "0.0%", + "note": "Rebuildable at some published version but NOT at 1.0.0-rc.21, which is what npm install serves a reader today." } }, "files": [ diff --git a/scripts/measured-figures.json b/scripts/measured-figures.json index e0c3cac..fa92744 100644 --- a/scripts/measured-figures.json +++ b/scripts/measured-figures.json @@ -12,7 +12,12 @@ " - a key marked on a page and absent from here -> FAIL, an undeclared figure", "", "Adding a row is a deliberate act. Deleting one is too, and it should be argued for", - "in the commit that does it rather than happening as a side effect of an edit." + "in the commit that does it rather than happening as a side effect of an edit.", + "REMOVED 2026-08-23: signed-record-coverage:headline.notRebuildableAtNpmLatest.kinds.", + "The kinds list is now empty because the count is 0, so there is no class name to show and", + "the declaration's own reason -- 'a count with no class name cannot be acted on' -- no longer", + "has a subject. Removed in the same commit as the copy change, per the check's instruction that", + "dropping a measured claim must not be something an edit does quietly." ], "required": [ { @@ -49,7 +54,7 @@ "index.html", "verify.html" ], - "why": "The resolution records a reader on npm latest cannot check. On both pages because the register states the scale and /verify states the cause." + "why": "The resolution records a reader on npm latest cannot check. Now 0, and KEPT AT ZERO rather than dropped: a page that stops citing the figure when it clears cannot show a reader that it ever was not zero. On both pages because the register states the scale and /verify states the cause." }, { "key": "signed-record-coverage:storeFileCount", @@ -100,13 +105,6 @@ ], "why": "The claim is that latest sits INSIDE the withdrawn band. Naming the band without naming latest leaves the reader to make the comparison the page is asserting." }, - { - "key": "signed-record-coverage:headline.notRebuildableAtNpmLatest.kinds", - "mustAppearIn": [ - "index.html" - ], - "why": "Which class is affected by the withdrawn constructor. A count with no class name cannot be acted on." - }, { "key": "engine-payload-exports:withdrawals.resolutionPayload.0.lastPresentBefore", "mustAppearIn": [ diff --git a/verify.html b/verify.html index 6454ac7..3365ac6 100644 --- a/verify.html +++ b/verify.html @@ -355,7 +355,7 @@

There is no verifier for a PolicyEvaluationCredent

A resolution record now checks with the version this page tells you to install. It did not, for four releases.

An approval resolution is the record of a human decision, signed at both ends: the routing and the outcome. Rebuilding its signed bytes needs resolutionPayload. The version npm install serves exports it. For four releases it did not.

Read out of every published tarball rather than out of a release note: resolutionPayload was exported at 1.0.0-rc.8, withdrawn across 4 consecutive releases, 1.0.0-rc.9 through 1.0.0-rc.12, and restored at 1.0.0-rc.13. npm's latest tag sits inside that band, at 1.0.0-rc.21, which is the version this page documents and the version the install line above gives you.

-

The 122 signed resolution records this estate holds were always rebuildable by someone who installed @rc; what they were not was rebuildable by someone who followed the instruction on this page. That is worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. We hold 122 signed resolution records that a reader on 1.0.0-rc.21 has no route to.

+

The 122 signed resolution records this estate holds were always rebuildable by someone who installed @rc; what they were not was rebuildable by someone who followed the instruction on this page. That was worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. That number is now 0: every signed resolution record this estate holds is rebuildable at the version npm install serves. It was 122 for as long as latest pointed inside the band.

The withdrawal appears in no changelog. The package's own release notes record neither the removal nor the restoration, so nothing but the tarballs could have told you. That is why the figures in this paragraph are read from a measurement in results/ and compared against npm on every build, instead of being typed here where nothing could contradict them.

What to do about it. Nothing. The version this page documents and the version its install line gives you both rebuild a resolution record, because npm’s latest tag now points past the withdrawal band rather than inside it. This site stays pinned to what latest serves, for the same reason it did while that was the broken version: a page that documents a version nobody receives is the failure this whole surface is written against.

From b3752fec019ad1579287b9f25cbf26aea7037304 Mon Sep 17 00:00:00 2001 From: Boyd Cohen Date: Sun, 23 Aug 2026 16:51:00 -0600 Subject: [PATCH 4/4] A third missed sentence, and a malformed tag that has been live since #85 BOTH FOUND BY THE NEW INSTRUMENT, not by reading. sentences-at-risk.mjs, run against the pre-move baseline, enumerated three sentences containing a span whose value the tag move changed. Two were the ones already fixed. The third was live on this branch and false: "npm's latest tag SITS INSIDE THAT BAND, at 1.0.0-rc.21" rc.21 is not inside rc.9 through rc.12. The span updated itself to rc.21 and the sentence around it did not, which is the exact class this branch already corrected twice and missed a third time. Now reads "no longer points inside that band". THE INSTRUMENT FOUND IN ONE RUN WHAT THREE READINGS OF THE SAME SECTION DID NOT. AND A MALFORMED TAG, ON MASTER, SINCE #85:

The closing angle bracket is missing. #85 added the marker by replacing '

' with '

'. The sibling

marker was added by a different substitution and is well formed, which is why one is broken and one is not. It has been on the served page since #85 merged. NOTHING CAUGHT IT: no check in this repository parses HTML, so a broken tag is invisible to all fourteen. A browser recovers from it, which is why it is invisible to a reader too. Found only because the sentence beside it was being read for a different reason. That is not a method. --- scripts/sentences-at-risk.mjs | 119 ++++++++++++++++++++++++++++++++++ verify.html | 4 +- 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 scripts/sentences-at-risk.mjs diff --git a/scripts/sentences-at-risk.mjs b/scripts/sentences-at-risk.mjs new file mode 100644 index 0000000..11b3ca1 --- /dev/null +++ b/scripts/sentences-at-risk.mjs @@ -0,0 +1,119 @@ +#!/usr/bin/env node +/** + * WHICH SENTENCES DOES A PENDING VALUE CHANGE PUT AT RISK? + * + * A `data-measured` span updates itself. The sentence around it does not. When a measured + * value changes, every span holding it moves and every sentence built on it stays — and a + * self-updating value inside a static sentence reads as FRESHLY CHECKED while being false. + * That is worse than stale, which is visible, and worse than false, which the checks catch. + * + * Measured 2026-08-23: the section 02 swap was planned as six parts and named two dependents. + * It missed two sentences. One of them — "We hold [122] signed resolution records that a + * reader on [1.0.0-rc.21] has no route to" — was INSIDE the section being swapped, and both + * of its spans updated correctly while the sentence inverted in meaning. + * + * THE POPULATION THAT WOULD HAVE CAUGHT THEM is not a list anyone maintains. It is derivable: + * every sentence containing a span whose value the change moves. This derives it. + * + * node scripts/sentences-at-risk.mjs + * + * BEFORE a change: stage or write the new results/, then run with HEAD as the baseline. The + * new values are on disk, the old ones are in the ref, and every affected sentence prints + * before anything is committed. + * + * AFTER a change: pass the ref from before it, to audit what was missed. + * + * IT DOES NOT DECIDE. Whether a sentence survives its span changing is a judgement about + * meaning, and no check makes it. This prints the sentence and the old and new values beside + * each other so the judgement is made deliberately rather than skipped. A sentence that is + * invariant is common and fine; the point is that it was looked at. + * + * Exit 0 always when it runs: it is an enumerator, not a gate. A gate that guessed at meaning + * would be the fourth way to be wrong about this. + */ +import { readFileSync, readdirSync, existsSync } from 'node:fs'; +import { execFileSync } from 'node:child_process'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const baseRef = process.argv[2]; +if (!baseRef) { + console.error('usage: node scripts/sentences-at-risk.mjs '); + console.error(' e.g. HEAD, or the commit before the change you are auditing.'); + process.exit(2); +} + +const at = (ref, path) => { + try { return execFileSync('git', ['show', `${ref}:${path}`], { cwd: root, encoding: 'utf8' }); } + catch { return null; } +}; +const dig = (obj, path) => path.split('.').reduce((o, k) => { + if (o == null) return undefined; + const m = /^(.*)\[(\d+)\]$/.exec(k); + return m ? o[m[1]]?.[Number(m[2])] : o[k]; +}, obj); + +// ─── which measured values moved ──────────────────────────────────────────────────────────── +const resultsDir = join(root, 'results'); +const moved = new Map(); // "file:path" -> {before, after} +for (const f of readdirSync(resultsDir).filter((n) => n.endsWith('.json'))) { + const name = f.replace(/\.json$/, ''); + const now = JSON.parse(readFileSync(join(resultsDir, f), 'utf8')); + const oldRaw = at(baseRef, `results/${f}`); + if (oldRaw === null) { console.log(` results/${f} did not exist at ${baseRef}; every span on it is new.`); continue; } + const old = JSON.parse(oldRaw); + const walk = (a, b, path) => { + const keys = new Set([...Object.keys(a ?? {}), ...Object.keys(b ?? {})]); + for (const k of keys) { + const pa = path ? `${path}.${k}` : k; + const va = a?.[k], vb = b?.[k]; + if (va && typeof va === 'object' && !Array.isArray(va)) { walk(va, vb, pa); continue; } + if (JSON.stringify(va) !== JSON.stringify(vb)) moved.set(`${name}:${pa}`, { before: va, after: vb }); + } + }; + walk(old, now, ''); +} + +// ─── every span on every served page, and the sentence it sits in ─────────────────────────── +const pages = []; +(function walkDir(d) { + for (const e of readdirSync(d)) { + if (e === 'dist' || e === 'node_modules' || e.startsWith('.')) continue; + const p = join(d, e); + try { if (readdirSync(p).length >= 0) { walkDir(p); continue; } } catch { /* a file */ } + if (e.endsWith('.html')) pages.push(p); + } +})(root); + +const SPAN = /]*data-measured="([^"]+)"[^>]*>([^<]*)<\/span>/g; +const prose = (h) => h.replace(/<[^>]+>/g, '').replace(/&[a-z]+;|&#\d+;/g, ' ').replace(/\s+/g, ' '); + +let found = 0; +console.log(`\nBaseline ${baseRef}. ${moved.size} measured value(s) moved.\n`); +for (const [key, d] of moved) { + const hits = []; + for (const page of pages) { + const html = readFileSync(page, 'utf8'); + SPAN.lastIndex = 0; + let m; + while ((m = SPAN.exec(html)) !== null) { + if (m[1] !== key) continue; + // the sentence: back to the previous ". " or block tag, forward to the next + const a = Math.max(0, html.lastIndexOf('. ', m.index) + 2, html.lastIndexOf('>', html.lastIndexOf(' ${JSON.stringify(d.after)}`); + for (const h of hits) console.log(` [${h.rel}] ${h.text.slice(0, 260)}`); + console.log(''); +} + +console.log(found + ? `${found} sentence(s) contain a span whose value moved. EACH NEEDS A JUDGEMENT: is it still\ntrue with the new value? This does not decide that, and nothing else does either.` + : 'No sentence on any page contains a span whose value moved.'); diff --git a/verify.html b/verify.html index 3365ac6..fa779a5 100644 --- a/verify.html +++ b/verify.html @@ -354,8 +354,8 @@

There is no verifier for a PolicyEvaluationCredent

A resolution record now checks with the version this page tells you to install. It did not, for four releases.

An approval resolution is the record of a human decision, signed at both ends: the routing and the outcome. Rebuilding its signed bytes needs resolutionPayload. The version npm install serves exports it. For four releases it did not.

-

Read out of every published tarball rather than out of a release note: resolutionPayload was exported at 1.0.0-rc.8, withdrawn across 4 consecutive releases, 1.0.0-rc.9 through 1.0.0-rc.12, and restored at 1.0.0-rc.13. npm's latest tag sits inside that band, at 1.0.0-rc.21, which is the version this page documents and the version the install line above gives you.

-

The 122 signed resolution records this estate holds were always rebuildable by someone who installed @rc; what they were not was rebuildable by someone who followed the instruction on this page. That was worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. That number is now 0: every signed resolution record this estate holds is rebuildable at the version npm install serves. It was 122 for as long as latest pointed inside the band.

+

Read out of every published tarball rather than out of a release note: resolutionPayload was exported at 1.0.0-rc.8, withdrawn across 4 consecutive releases, 1.0.0-rc.9 through 1.0.0-rc.12, and restored at 1.0.0-rc.13. npm's latest tag no longer points inside that band, at 1.0.0-rc.21, which is the version this page documents and the version the install line above gives you.

+

The 122 signed resolution records this estate holds were always rebuildable by someone who installed @rc; what they were not was rebuildable by someone who followed the instruction on this page. That was worse than a missing feature: the instruction was complete, it ran, and it produced a package silently missing one constructor. That number is now 0: every signed resolution record this estate holds is rebuildable at the version npm install serves. It was 122 for as long as latest pointed inside the band.

The withdrawal appears in no changelog. The package's own release notes record neither the removal nor the restoration, so nothing but the tarballs could have told you. That is why the figures in this paragraph are read from a measurement in results/ and compared against npm on every build, instead of being typed here where nothing could contradict them.

What to do about it. Nothing. The version this page documents and the version its install line gives you both rebuild a resolution record, because npm’s latest tag now points past the withdrawal band rather than inside it. This site stays pinned to what latest serves, for the same reason it did while that was the broken version: a page that documents a version nobody receives is the failure this whole surface is written against.