docs(releasing): distinguish npm replication lag from a failed publish - #101
Merged
Merged
Conversation
Both lessons come from the 2026-09-10 release of all 9 packages (run 34495769507), the first end-to-end publish this workflow has actually done. New section, placed BEFORE the failure playbook so the "did it even fail?" question gets asked first: npm replication lags a publish by up to ~5 minutes, and a lagging package is indistinguishable from a failed one. Seven packages were queryable within seconds; ultimatedarktowerdisplay@2.0.0 took ~3 minutes and ultimatedarktowerrelay-shared@1.0.2 took ~5. For that window the repo looked exactly like a partial failure -- green workflow, git tags pushed for all nine, two packages 404ing on npm -- and it was the SAME two package families as the real July 2026 partial failure, which makes the false positive very convincing. The fix is to read Changesets' own success manifest from the run log rather than trusting a single registry query: a package listed under "packages published successfully" with a matching "New tag:" line was accepted by npm. Section adds the exact `gh run view --log` incantation and a poll-don't-single-shot curl, plus a warning never to re-run a publish or bump a version off one 404, since the version is already taken on npm's side and retrying burns a number for nothing. Also softens the NPM_TOKEN allow-list claim, which was too strong. It said the granular-token failure "fires every time a new published package joins the monorepo". It did not fire here: ultimatedarktowerrelay-cli@0.2.0, a brand-new name never before on npm (the log even shows `Received 404 for npm info`), published cleanly on the first attempt alongside eight existing packages. So the current token is either not package-scoped or was already broadened. Now framed as the first hypothesis when a new package's publish fails, rather than a blocker to fix pre-emptively -- the old wording would send a future session to npmjs.com to solve a problem it does not have. Claude-Session: https://claude.ai/code/session_01Br4DeujSD86Rj6uxYuTC2r
ChessMess
added a commit
that referenced
this pull request
Sep 11, 2026
Audited 2026-09-10 after noticing only 1 of 9 published packages had ever
produced a provenance attestation -- 71 versions, 7 attested, all of them
ultimatedarktowerboard.
Nothing in the repo explains it. repository fields, publishConfig, prepack
hooks and NPM_CONFIG_PROVENANCE are identical across all nine, and the release
log shows no provenance error, warning or skip. The cause is npm-side: Trusted
Publisher is a PER-PACKAGE setting naming an exact repo + workflow file. When
the OIDC claim (workflow_ref: .github/workflows/release.yml) does not match the
package's entry, or no entry exists, npm cannot mint the attestation and
silently falls back to the NPM_TOKEN auth the workflow also supplies.
Checking all nine found two distinct faults, and the second was the common one:
- No entry at all -- six packages (game-data, relay-{client,core,shared},
mcp-server, relay-cli). Never configured.
- Stale entry -- two packages. ultimatedarktower named publish.yml, deleted
2026-07-11; ultimatedarktowerdisplay named ChessMess/UltimateDarkTowerDisplay,
the archived pre-consolidation repo.
board was the only correct one, configured 2026-07-12 -- the day after the
workflow rename -- which is why it alone produced provenance.
The new section records the diagnosis path (registry, not repo: count attested
versions, then decode a working attestation to see which workflow produced it),
the exact field values that work, and two traps found while fixing it: entries
are immutable so a wrong one must be deleted and re-created, and Environment
must be left blank because release.yml declares no environment key -- filling it
in breaks the claim match silently. Also notes npm permits multiple entries per
package, so a correct one can be added alongside a stale one without deleting
anything, which matters because every write costs a 2FA security-key tap.
Closes the loop on the replication-lag section added in #101: that one was about
misreading a good publish as failed, this one is about a publish that really is
missing something and never says so.
Claude-Session: https://claude.ai/code/session_01Br4DeujSD86Rj6uxYuTC2r
ChessMess
added a commit
that referenced
this pull request
Sep 11, 2026
Audited 2026-09-10 after noticing only 1 of 9 published packages had ever
produced a provenance attestation -- 71 versions, 7 attested, all of them
ultimatedarktowerboard.
Nothing in the repo explains it. repository fields, publishConfig, prepack
hooks and NPM_CONFIG_PROVENANCE are identical across all nine, and the release
log shows no provenance error, warning or skip. The cause is npm-side: Trusted
Publisher is a PER-PACKAGE setting naming an exact repo + workflow file. When
the OIDC claim (workflow_ref: .github/workflows/release.yml) does not match the
package's entry, or no entry exists, npm cannot mint the attestation and
silently falls back to the NPM_TOKEN auth the workflow also supplies.
Checking all nine found two distinct faults, and the second was the common one:
- No entry at all -- six packages (game-data, relay-{client,core,shared},
mcp-server, relay-cli). Never configured.
- Stale entry -- two packages. ultimatedarktower named publish.yml, deleted
2026-07-11; ultimatedarktowerdisplay named ChessMess/UltimateDarkTowerDisplay,
the archived pre-consolidation repo.
board was the only correct one, configured 2026-07-12 -- the day after the
workflow rename -- which is why it alone produced provenance.
The new section records the diagnosis path (registry, not repo: count attested
versions, then decode a working attestation to see which workflow produced it),
the exact field values that work, and two traps found while fixing it: entries
are immutable so a wrong one must be deleted and re-created, and Environment
must be left blank because release.yml declares no environment key -- filling it
in breaks the claim match silently. Also notes npm permits multiple entries per
package, so a correct one can be added alongside a stale one without deleting
anything, which matters because every write costs a 2FA security-key tap.
Closes the loop on the replication-lag section added in #101: that one was about
misreading a good publish as failed, this one is about a publish that really is
missing something and never says so.
Claude-Session: https://claude.ai/code/session_01Br4DeujSD86Rj6uxYuTC2r
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documentation only. Both lessons come from the 2026-09-10 release of all 9 packages (run 34495769507) — the first end-to-end publish this workflow has actually performed.
New section — confirm a publish actually failed before debugging it
Placed before the existing failure playbook, so the "did it even fail?" question gets asked first.
npm replication lags a publish by up to ~5 minutes, and a lagging package is indistinguishable from a failed one:
ultimatedarktowerdisplay@2.0.0ultimatedarktowerrelay-shared@1.0.2For that window the repo looked exactly like a partial failure — green workflow, git tags pushed for all nine, two packages 404ing. And it was the same two package families as the real July 2026 partial failure, which makes the false positive genuinely convincing.
The fix: read Changesets’ own success manifest from the run log rather than trusting one registry query. A package listed under
packages published successfullywith a matchingNew tag:line was accepted by npm. The section adds the exactgh run view --logincantation, a poll-don’t-single-shotcurl, and a warning to never re-run a publish or bump a version off a single 404 — the version is already taken on npm’s side, so retrying burns a number for nothing.Softened the
NPM_TOKENallow-list claimThe old wording said the granular-token failure "fires every time a new published package joins the monorepo." That is too strong, and I acted on it this session — I flagged
relay-clias a near-certain blocker before merging.It didn’t fire.
ultimatedarktowerrelay-cli@0.2.0— a brand-new name never before on npm (the log even showsReceived 404 for npm info "ultimatedarktowerrelay-cli") — published cleanly on the first attempt, alongside eight existing packages. So the current token is either not package-scoped or was already broadened.Now framed as the first hypothesis when a new package’s publish fails, rather than a blocker to fix pre-emptively. The old wording would send a future session to npmjs.com to solve a problem it doesn’t have.
https://claude.ai/code/session_01Br4DeujSD86Rj6uxYuTC2r