Repository navigation
chore(deps): pnpm 11.21.0, and why the pin stops short of 12 - #310
Merged
Merged
Conversation
The bump is free: `packageManager` only, no lockfile byte changes, no build byte changes, `--frozen-lockfile` is a no-op, 206/206, typecheck 0. Gotcha 30 records why 12 is not the answer yet, measured against 12.0.0-rc.3 on the branch behind #309. Everything here works under it, including a byte-identical build across all 1975 files. What does not work is pnpm 10.11.1 — the version gotcha 29 records the Workers Builds image running — reading the lockfile pnpm 12 writes: ERR_PNPM_BROKEN_LOCKFILE the lockfile is broken: expected a single document in the stream, but found more It is a `---` YAML document separator, and `lockfileVersion` stays '9.0', so one upstream line could retire the whole objection. Production would still build only because pnpm reads `packageManager` before it opens the lockfile and downloads the pinned binary, which parses its own format. That makes every production install depend on a single registry fetch with no fallback, and being two majors behind is the milder failure. The rule worth keeping past this instance: check that the BUILD IMAGE can read what your package manager WRITES, not just that your own install works. A lockfile is an interchange format between two machines on different versions, and "it installs here" tests one of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
aadhar-sh | 1b66b49 | Aug 10 2026, 07:11 PM |
This was referenced Aug 10, 2026
oddharsh
added a commit
that referenced
this pull request
Aug 12, 2026
…stops rotting (#348) The dictionary sets are the one build input no build step may produce. A returning visitor holds whatever `/a/` asset and page production served them last, offers its hash, and earns a delta only if those exact bytes are committed here. build.mjs cannot derive that from source, so the sets are committed, and committing them is a step someone has to remember. Nobody remembered since #178 on 2026-07-30, 161 commits back. ## What was broken Every dictionary-carrying shell asset production serves was missing from `www/a-dict`: nav.1c6af07b, luna.1523f4f6, hoist.d9081560, tooltip.5dad2389, lens.88fba28b. Main built its six shell deltas against #178's candidates, which no living browser holds, so a returning visitor took plain brotli on the render-blocking path. After the roll, against the bytes browsers actually hold: | | stale | rolled | |---|--:|--:| | `luna` delta | 7,781 B (no match, plain br) | **155 B** | | `nav` delta | 5,973 B (no match, plain br) | **1,113 B** | Per-page deltas went 121,288 B over 92 to 74,337 B over 94, because the snapshots now match live pages rather than pages from twelve days ago. ## Why dcz:check said PASS the whole time Its shell probe picks an a-dict candidate that is NOT the live hash, offers it, and asserts dcz comes back. build.mjs builds a delta for every a-dict entry, so that is true by construction; the probe reads the live hash only to exclude it. It is the same self-agreeing shape as the Markdown-twin test in gotcha 24 and the page tier's old snapshot probe in gotcha 20. `live shell is covered by a-dict` asks the question a returning visitor asks: are the bytes THEY hold covered? Bases with no a-dict history are skipped, since a new asset cannot have a dictionary until it has been served once. Byte-compared, not filename-compared, because 8 hex of a sha256 is not the digest the browser keys on. Advisory on purpose: like infra:check's edge tier it reads production, so making it required would deadlock the release that would clear it. ## Why it can now run unattended `shell:roll` adopted from `.build/www/a`, which forced it to run from the deployed commit. `--live` (`pnpm run dict:roll`) reads production instead, the same way the page half has since gotcha 20. Adopting from a build can only capture THIS commit's shell, so a release that goes by without a roll is unrecoverable, and on an unramped tree it adopts bytes nobody holds while evicting one still in use (KEEP is 3). Whatever is live is protected from the prune. It refuses outright if production reads empty, since an empty read hands the prune an empty `current` set, which is exactly when it is free to evict what browsers are holding. `.github/workflows/dictionary-roll.yml` runs it nightly and opens a PR when anything moved. It holds no Cloudflare credential: `--live` is plain HTTPS and the PR goes out on GITHUB_TOKEN. It cannot merge, because `main` takes zero bypass actors and that property is the whole release model. ## CLAUDE.md Two paragraphs described a `.github/workflows/ramp.yml` running the ramp from a scoped environment secret. Verified 2026-08-12: no such workflow in any commit, the environments are `copilot` and `production` rather than the canary/full pair, and the only repo secret is the six-read-scope CLOUDFLARE_API_TOKEN. What landed on 2026-08-06 was the release-guard rewrite alone. Both blocks are relabelled as a PLAN rather than deleted, since the reasoning about where a secret lives is still right. Also corrected: "not urgent, a dictionary 11 days stale still gave 87-93%" is true of a STALE dictionary and false of an ABSENT one. The page tier degrades to the family corpus at ~26%; the shell tier has no fallback. ## Drive-by Four workflows bootstrapped pnpm@11.20.0 while package.json has pinned 11.21.0 since #310 two days ago, each under a comment calling package.json the source of truth. Behaviour-neutral (self-switching is on by default, so 11.21.0 already ran every time), but the gap stops being harmless the moment it crosses a major: pnpm 12 ships a native CLI that an older pnpm cannot exec, which is gotcha 30. A contract test now pins every workflow's bootstrap to package.json, and counts what it checked so a regex that stops matching cannot pass silently. Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com>
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.
Two things: the free bump, and the note explaining why the expensive one is parked.
The bump
packageManageronly. No lockfile byte changes and no build byte changes.pnpm install --frozen-lockfileAlready up to date, no-oppnpm run typecheckGotcha 30: why not 12
Measured against
12.0.0-rc.3on the branch behind #309, which stays a draft.Everything here works under pnpm 12, including a byte-identical build across all 1975 files. What doesn't work is pnpm 10.11.1 — the version gotcha 29 records the Workers Builds image running — reading the lockfile pnpm 12 writes:
It's a
---YAML document separator, andlockfileVersionstays'9.0', so one upstream line could retire the whole objection.Production would still build, for exactly one reason: pnpm reads
packageManagerbefore it opens the lockfile, downloads the pinned binary, and that binary parses its own format. So adopting 12 makes every production install depend on a single registry fetch with no fallback. Run the build image withmanage-package-manager-versionsoff, or lose that fetch, and it's holding a lockfile it cannot parse. Two majors behind is the milder failure.The rule worth keeping past this instance: check that the build image can read what your package manager writes, not just that your own install works. A lockfile is an interchange format between two machines on different versions, and "it installs here" tests one of them.
The contrast between the two changes is the point: a patch bump inside a major is free here, and the major is not.
🤖 Generated with Claude Code