Skip to content

deps(docs): restore the caret on react-dom now that Dependabot groups the pair - #276

Merged
os-bill merged 1 commit into
mainfrom
claude/issue-238-react-dom-caret
Sep 8, 2026
Merged

deps(docs): restore the caret on react-dom now that Dependabot groups the pair#276
os-bill merged 1 commit into
mainfrom
claude/issue-238-react-dom-caret

Conversation

@os-bill

@os-bill os-bill commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes #238

apps/docs/package.json declared the two halves of a peer-coupled pair in different shapes — react floating on ^19.2.7, react-dom pinned exact at 19.2.7. This restores the caret on react-dom.

Why the pin can go

The pin was a deliberate, bounded workaround: react-dom@X peer-requires react@^X, react was out of that card's scope, and a caret on react-dom resolved upward and broke the peer check. .github/dependabot.yml now carries a react group with both react and react-dom patterns, so the pair arrives as one PR and moves together — the mechanism the pin was standing in for.

Nothing is broken today; both halves resolve to 19.2.7. The defect is that the asymmetry reads as intentional while the thing that would catch a drift does not fire: a future non-frozen install can float react up while react-dom stays pinned, the peer range ^19.2.7 permits it, no tool complains, and React itself requires the pair to match. Keeping both the group and the pin is belt-and-braces — not wrong, but it hides which mechanism is load-bearing.

What changed — two lines, one per file

$ git diff --stat 87880ba
 apps/docs/package.json | 2 +-
 pnpm-lock.yaml         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

pnpm install --lockfile-only after the manifest edit moves exactly one lockfile line:

39c39
<         specifier: 19.2.7
---
>         specifier: ^19.2.7

The resolved version does not move — react-dom stays version: 19.2.7(react@19.2.7), and react stays 19.2.7. This is a specifier shape change, not a version bump. The diff reproduces the measurement taken on PR #236 byte for byte, so the premise the card was dispatched on still holds on 87880ba.

Gates run locally, each with its own verdict

  • pnpm install --frozen-lockfile --lockfile-only — exit 0, Done in 1.2s. This is CI's first step and the one a lockfile edit can break.
  • node .github/scripts/check-node-floor.mjs --self-test — exit 0, 17 rule case(s), 24 satisfies case(s) and 18 range case(s) — every rule demonstrated able to fail.
  • node .github/scripts/check-node-floor.mjs — exit 0, Every declared floor clears what the dependency tree requires, and the declarations agree. Run because this gate reads pnpm-lock.yaml as text, so it is directly implicated by the file this PR edits. It reports 430 engines blocks scanned and a required floor of 22.0.0, unchanged.

The frozen-lockfile green was ablated rather than trusted, since a validator observed only green is indistinguishable from one that cannot go red. Mutating the manifest specifier to ^19.9.9 (confirmed on disk: blob 9bc55e3 to 9cb316a, injected-marker count 1, removed-marker count 0) took that check to exit 1 with ERR_PNPM_OUTDATED_LOCKFILE ... react-dom (lockfile: ^19.2.7, manifest: ^19.9.9) — which also independently confirms the committed lockfile now carries ^19.2.7. Restoring from HEAD reproduced blob 9bc55e3 exactly, git diff HEAD empty, and the check returned to exit 0.

The docs build, zh-Hant, locale-surface, Worker packaging and Worker size gates are CI's on this PR; they need a full install and the built .next tree.

Worker bundle

pnpm-lock.yaml is one of deploy-docs.yml's trigger paths, so merging this deploys the docs site — that path is CI-gated now with a post-deploy live smoke check and auto-rollback. The build job also weighs the Worker on every pull request against the 61440 KiB budget. A specifier-only change that moves no resolved version should not move that reading at all; the figure this PR's gate actually reports is quoted in a comment below rather than asserted here in advance.

Scope

apps/docs/package.json and pnpm-lock.yaml only — no other file is touched. .github/workflows/ci.yml is deliberately untouched (a sibling card is in flight on it). No dependency is upgraded. This repo has no changeset flow, so there is no changeset.

Generated by Claude Code in session session_01ChPQM8jamxLUfUAxwFpJ8S (durable attribution in prose, since a later body edit rewrites the footer link below).


Generated by Claude Code

… the pair

`apps/docs/package.json` declared the two halves of a peer-coupled pair in
different shapes: `react` floating on `^19.2.7`, `react-dom` pinned exact at
`19.2.7`. The pin was a deliberate, bounded workaround — `react-dom@X`
peer-requires `react@^X`, `react` was out of that card's scope, and a caret on
`react-dom` resolved upward and broke the peer check.

`.github/dependabot.yml` now groups `react` and `react-dom` under one `react`
group, so the two arrive as a single PR and move together. That is the
mechanism the pin was standing in for, so the pin has outlived its reason.

Keeping both is belt-and-braces: not wrong, but it hides which mechanism is
load-bearing, and it leaves an asymmetry that reads as intentional while the
thing that would catch a drift does not fire — a future non-frozen install can
float `react` up while `react-dom` stays put, the peer range `^19.2.7` permits
it, no tool complains, and React itself requires the pair to match.

Specifier shape only. No version moves: `pnpm install --lockfile-only` changes
exactly one lockfile line, `specifier: 19.2.7` to `specifier: ^19.2.7`, and the
resolved `version: 19.2.7(react@19.2.7)` is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ChPQM8jamxLUfUAxwFpJ8S

os-bill commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

What the Worker size gate reported on this PR

Run 34248195235, job build, step Worker bundle fits the size budget — conclusion success:

Total Upload: 58549.05 KiB / gzip: 8799.33 KiB

### Worker bundle size — within budget

| | KiB | % of limit |
|:--|--:|--:|
| measured | 58549.05 | 89.34 % |
| budget | 61440 | 93.75 % |
| Cloudflare limit | 65536 | 100 % |

Headroom to budget: 2890.95 KiB  ·  headroom to the limit: 6986.95 KiB

Against a same-tree baseline

main has not moved since this branch was cut, so this PR's merge ref is 87880ba plus the two lines above. 87880ba's own push run (#417, job 102095970086) reported Headroom to budget: 2887.58 KiB, which is 58552.42 KiB against the same 61440 KiB budget.

So the reading moved -3.37 KiB (-0.006 %), and the percentage of the limit is unchanged at 89.34 %. Reporting it rather than absorbing it, since the card asked for any movement — but it is not claimed as caused by this change, and it should not be read that way: no resolved dependency version moves here, so the installed graph is identical.

The reading has drift of the same order on inputs that provably cannot differ. ci.yml's own calibration comment records 58553.98 KiB at 0e26657f, and git diff --stat 0e26657f 87880ba is one file — .github/workflows/ci.yml, which cannot enter the bundle — yet those two readings differ by 1.56 KiB. Filed as #277 (observation, unassigned, not blocking).

The figure the dispatch quoted (~58554 KiB, 89.35 %) is that 0e26657f calibration figure, not a main @ 87880ba measurement; the same-tree baseline is the 58552.42 KiB above.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

react-dom's exact pin outlived its reason — revert it to a caret now that the Dependabot group exists

1 participant