chore: migrate to Corepack-managed Yarn 4#1109
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughMigration from direct Yarn invocation to Corepack-managed Yarn 4.13.0 across documentation, CI/CD workflows, package scripts, and test infrastructure. Changes add Corepack enable steps, update Yarn commands, modify lockfile constraint flags, and implement localStorage mocking for tests. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
package.json (4)
21-21:⚠️ Potential issue | 🟡 MinorCoding guideline violation: Use exact version, not
^.As per coding guidelines,
package.jsonmust pin exact dependency versions (package@x.y.z), never^or~.🔧 Suggested fix
- "@vercel/analytics": "^1.6.1", + "@vercel/analytics": "1.6.1",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 21, The dependency entry for "@vercel/analytics" in package.json uses a caret range "^1.6.1" which violates the guideline to pin exact versions; update the version string for "@vercel/analytics" from "^1.6.1" to the exact "1.6.1" so the package is pinned (ensure any related lockfile is updated/committed after changing the package.json).
171-171:⚠️ Potential issue | 🟡 MinorCoding guideline violation in resolutions: Use exact version.
🔧 Suggested fix
- "baseline-browser-mapping": "^2.9.11", + "baseline-browser-mapping": "2.9.11",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 171, The resolutions entry currently pins "baseline-browser-mapping" with a caret ("^2.9.11"), violating the guideline to use exact versions; update the resolutions (or dependencies/resolutions section where "baseline-browser-mapping" is declared) to use the exact version string "2.9.11" (remove the leading caret) so the package is locked to that exact version.
186-186:⚠️ Potential issue | 🟡 MinorCoding guideline violation in resolutions: Use exact version.
🔧 Suggested fix
- "diff": "^8.0.3", + "diff": "8.0.3",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 186, The resolutions entry uses a caret range ("diff": "^8.0.3") which violates the guideline to pin exact versions; update the resolutions key so the package "diff" is pinned to the exact version "8.0.3" (remove the caret) so tools reading package.json and any lockfile enforcement use the exact "diff" version rather than a range.
129-129:⚠️ Potential issue | 🟡 MinorCoding guideline violation: Use exact version, not
^.Same issue - use exact version pinning.
🔧 Suggested fix
- "@typescript/native-preview": "^7.0.0-dev.20251226.1", + "@typescript/native-preview": "7.0.0-dev.20251226.1",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 129, Replace the caret-pinned dependency entry "@typescript/native-preview": "^7.0.0-dev.20251226.1" in package.json with an exact version string (remove the leading '^' so it reads "@typescript/native-preview": "7.0.0-dev.20251226.1"); after changing the dependency, regenerate the lockfile (npm/yarn/pnpm) so the lock reflects the exact pin to keep installs deterministic.
🧹 Nitpick comments (5)
.codex/skills/readme/SKILL.md (2)
157-158: Inconsistent with other documentation in this PR.The README.md and AGENTS.md use
yarn install(after a one-timecorepack enable), but this template usescorepack yarn install. For contributor-facing docs, using plainyarncommands after enabling Corepack is cleaner and aligns with the PR's stated goal to "use the plain yarn command backed by Corepack-managed Yarn 4."Consider keeping
yarn installhere for consistency with the rest of the PR.♻️ Suggested change for consistency
-corepack yarn install +yarn install🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.codex/skills/readme/SKILL.md around lines 157 - 158, Replace the inconsistent command string "corepack yarn install" in SKILL.md with "yarn install" so it matches the rest of the PR; locate the line containing the literal `corepack yarn install` and update it to `yarn install` (keeping the surrounding code block/backticks intact).
711-712: Same inconsistency in troubleshooting section.Same feedback as above - consider using
yarn installinstead ofcorepack yarn installto match the conventions in README.md and AGENTS.md.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.codex/skills/readme/SKILL.md around lines 711 - 712, Update the troubleshooting command that currently uses "corepack yarn install" to use "yarn install" for consistency with README.md and AGENTS.md; locate the occurrence of the command string (e.g., the line containing "rm -rf node_modules && corepack yarn install") in SKILL.md and replace it with "rm -rf node_modules && yarn install" so the docs follow the same convention.AGENTS.md (2)
30-30: Minor inconsistency with Line 74 guidance.Line 74 states to run
corepack enableonce, then useyarn. But this line usescorepack yarn install. For consistency, consider using plainyarn installhere since the Task Router assumes the environment is already set up per the Package and Dependency Rules.♻️ Suggested change
-| `package.json` changed | Run `corepack yarn install` to keep `yarn.lock` in sync | +| `package.json` changed | Run `yarn install` to keep `yarn.lock` in sync |🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AGENTS.md` at line 30, Replace the inconsistent instruction that currently reads "`package.json` changed | Run `corepack yarn install` to keep `yarn.lock` in sync`" with a consistent entry using plain yarn, e.g. change the action to "Run `yarn install` to keep `yarn.lock` in sync" so it aligns with the guidance on Line 74 that `corepack enable` is run once and subsequent commands use `yarn`.
181-181: Same minor inconsistency in Common Commands.Consider using
yarn installto align with the guidance at Line 74 that plainyarnworks aftercorepack enable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AGENTS.md` at line 181, Replace the inconsistent command "corepack yarn install" in the Common Commands section with "yarn install" (or simply "yarn") so it aligns with the guidance referenced earlier (the note that plain "yarn" works after corepack enable); locate the occurrence of "corepack yarn install" in AGENTS.md and update that line to "yarn install" for consistency..cursor/skills/fix-merge-conflicts/SKILL.md (1)
39-54: Consider using plainyarncommands for consistency.The skill uses
corepack yarnprefix throughout, but the PR's main documentation (README.md, AGENTS.md) uses plainyarncommands after a one-timecorepack enable. For agent playbooks that run after the environment is already set up, plainyarncommands would be more concise and consistent.That said, using
corepack yarnexplicitly is also valid and ensures Corepack is invoked even if not previously enabled - this is a reasonable defensive choice for conflict resolution scenarios.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.cursor/skills/fix-merge-conflicts/SKILL.md around lines 39 - 54, Update .cursor/skills/fix-merge-conflicts/SKILL.md to use plain yarn commands for consistency with the README and AGENTS.md: replace occurrences of the "corepack yarn" prefix with plain "yarn" (e.g. the validation command block should be "yarn build && yarn lint && yarn type-check" and the install step "yarn install"), and keep a short parenthetical note near the top that Corepack can be enabled once (e.g. "run `corepack enable` if Corepack isn't set up") so the defensive "corepack yarn" option is documented but not used inline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@vitest.setup.ts`:
- Around line 5-72: The current setup mutates Storage.prototype via storageProto
and uses a single shared Map storageState, causing all storage instances (e.g.,
localStorage and future sessionStorage) to share state; replace this by
implementing a createStorageMock() factory that creates an isolated storage
state and methods (getItem, setItem, removeItem, clear, key, length) per
instance instead of mutating storageProto or relying on storageState, then
assign its returned object to localStorageMock and to globalThis.localStorage
(and window.localStorage when present) so each storage instance remains
independent and prototype mutation is avoided.
---
Outside diff comments:
In `@package.json`:
- Line 21: The dependency entry for "@vercel/analytics" in package.json uses a
caret range "^1.6.1" which violates the guideline to pin exact versions; update
the version string for "@vercel/analytics" from "^1.6.1" to the exact "1.6.1" so
the package is pinned (ensure any related lockfile is updated/committed after
changing the package.json).
- Line 171: The resolutions entry currently pins "baseline-browser-mapping" with
a caret ("^2.9.11"), violating the guideline to use exact versions; update the
resolutions (or dependencies/resolutions section where
"baseline-browser-mapping" is declared) to use the exact version string "2.9.11"
(remove the leading caret) so the package is locked to that exact version.
- Line 186: The resolutions entry uses a caret range ("diff": "^8.0.3") which
violates the guideline to pin exact versions; update the resolutions key so the
package "diff" is pinned to the exact version "8.0.3" (remove the caret) so
tools reading package.json and any lockfile enforcement use the exact "diff"
version rather than a range.
- Line 129: Replace the caret-pinned dependency entry
"@typescript/native-preview": "^7.0.0-dev.20251226.1" in package.json with an
exact version string (remove the leading '^' so it reads
"@typescript/native-preview": "7.0.0-dev.20251226.1"); after changing the
dependency, regenerate the lockfile (npm/yarn/pnpm) so the lock reflects the
exact pin to keep installs deterministic.
---
Nitpick comments:
In @.codex/skills/readme/SKILL.md:
- Around line 157-158: Replace the inconsistent command string "corepack yarn
install" in SKILL.md with "yarn install" so it matches the rest of the PR;
locate the line containing the literal `corepack yarn install` and update it to
`yarn install` (keeping the surrounding code block/backticks intact).
- Around line 711-712: Update the troubleshooting command that currently uses
"corepack yarn install" to use "yarn install" for consistency with README.md and
AGENTS.md; locate the occurrence of the command string (e.g., the line
containing "rm -rf node_modules && corepack yarn install") in SKILL.md and
replace it with "rm -rf node_modules && yarn install" so the docs follow the
same convention.
In @.cursor/skills/fix-merge-conflicts/SKILL.md:
- Around line 39-54: Update .cursor/skills/fix-merge-conflicts/SKILL.md to use
plain yarn commands for consistency with the README and AGENTS.md: replace
occurrences of the "corepack yarn" prefix with plain "yarn" (e.g. the validation
command block should be "yarn build && yarn lint && yarn type-check" and the
install step "yarn install"), and keep a short parenthetical note near the top
that Corepack can be enabled once (e.g. "run `corepack enable` if Corepack isn't
set up") so the defensive "corepack yarn" option is documented but not used
inline.
In `@AGENTS.md`:
- Line 30: Replace the inconsistent instruction that currently reads
"`package.json` changed | Run `corepack yarn install` to keep `yarn.lock` in
sync`" with a consistent entry using plain yarn, e.g. change the action to "Run
`yarn install` to keep `yarn.lock` in sync" so it aligns with the guidance on
Line 74 that `corepack enable` is run once and subsequent commands use `yarn`.
- Line 181: Replace the inconsistent command "corepack yarn install" in the
Common Commands section with "yarn install" (or simply "yarn") so it aligns with
the guidance referenced earlier (the note that plain "yarn" works after corepack
enable); locate the occurrence of "corepack yarn install" in AGENTS.md and
update that line to "yarn install" for consistency.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4317c82f-ba21-4ca9-b3c7-8f0393a2530d
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (19)
.codex/skills/fix-merge-conflicts/SKILL.md.codex/skills/readme/SKILL.md.cursor/skills/fix-merge-conflicts/SKILL.md.cursor/skills/readme/SKILL.md.github/workflows/ci.yml.github/workflows/release.yml.gitignore.nvmrc.yarnrc.ymlAGENTS.mdREADME.mddocs/agent-playbooks/hooks-setup.mdpackage.jsonpublic/llms.txtscripts/agent-hooks/verify.shscripts/agent-hooks/yarn-install.shvercel.jsonvitest.config.tsvitest.setup.ts
| Object.defineProperties(storageProto, { | ||
| clear: { | ||
| configurable: true, | ||
| enumerable: false, | ||
| value: function clear() { | ||
| storageState.clear(); | ||
| }, | ||
| writable: true, | ||
| }, | ||
| getItem: { | ||
| configurable: true, | ||
| enumerable: false, | ||
| value: function getItem(key: string) { | ||
| const normalizedKey = String(key); | ||
| return storageState.has(normalizedKey) ? storageState.get(normalizedKey) ?? null : null; | ||
| }, | ||
| writable: true, | ||
| }, | ||
| key: { | ||
| configurable: true, | ||
| enumerable: false, | ||
| value: function key(index: number) { | ||
| return Array.from(storageState.keys())[index] ?? null; | ||
| }, | ||
| writable: true, | ||
| }, | ||
| length: { | ||
| configurable: true, | ||
| enumerable: true, | ||
| get() { | ||
| return storageState.size; | ||
| }, | ||
| }, | ||
| removeItem: { | ||
| configurable: true, | ||
| enumerable: false, | ||
| value: function removeItem(key: string) { | ||
| storageState.delete(String(key)); | ||
| }, | ||
| writable: true, | ||
| }, | ||
| setItem: { | ||
| configurable: true, | ||
| enumerable: false, | ||
| value: function setItem(key: string, value: string) { | ||
| storageState.set(String(key), String(value)); | ||
| }, | ||
| writable: true, | ||
| }, | ||
| }); | ||
|
|
||
| const localStorageMock = Object.create(storageProto) as Storage; | ||
|
|
||
| Object.defineProperty(globalThis, 'localStorage', { | ||
| configurable: true, | ||
| enumerable: true, | ||
| value: localStorageMock, | ||
| writable: true, | ||
| }); | ||
|
|
||
| if (typeof window !== 'undefined') { | ||
| Object.defineProperty(window, 'localStorage', { | ||
| configurable: true, | ||
| enumerable: true, | ||
| value: localStorageMock, | ||
| writable: true, | ||
| }); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the setup implementation and pinpoint prototype + backing-state usage.
sed -n '1,160p' vitest.setup.ts
rg -n -C2 'const storageState = new Map|Storage\.prototype|Object\.defineProperties\(storageProto|sessionStorage|localStorage' vitest.setup.tsRepository: bitsocialnet/5chan
Length of output: 2341
🏁 Script executed:
cat -n vitest.setup.tsRepository: bitsocialnet/5chan
Length of output: 2206
Avoid mutating Storage.prototype; instead create isolated mock instances.
The code mutates Storage.prototype directly (line 3) and backs all storage methods with a single storageState Map (line 1). While only localStorage is currently defined, this pattern creates tight coupling and makes it error-prone to add sessionStorage later—any new storage created from the same prototype would share the backing state, breaking isolation.
The proposed refactor using a createStorageMock() factory ensures each storage instance has its own isolated state and avoids prototype mutation entirely, which is safer and more maintainable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@vitest.setup.ts` around lines 5 - 72, The current setup mutates
Storage.prototype via storageProto and uses a single shared Map storageState,
causing all storage instances (e.g., localStorage and future sessionStorage) to
share state; replace this by implementing a createStorageMock() factory that
creates an isolated storage state and methods (getItem, setItem, removeItem,
clear, key, length) per instance instead of mutating storageProto or relying on
storageState, then assign its returned object to localStorageMock and to
globalThis.localStorage (and window.localStorage when present) so each storage
instance remains independent and prototype mutation is avoided.
| "prebuild": "yarn sync:directories && yarn generate:assets", | ||
| "prestart": "yarn sync:directories && yarn generate:assets", | ||
| "prebuild": "corepack yarn sync:directories && corepack yarn generate:assets", | ||
| "prestart": "corepack yarn sync:directories && corepack yarn generate:assets", |
There was a problem hiding this comment.
Yarn 4 won't auto-run prebuild/prestart lifecycle scripts
High Severity
Yarn 4 intentionally does not execute arbitrary pre<script> and post<script> lifecycle hooks for user-defined scripts. The prebuild and prestart scripts (which run sync:directories and generate:assets) will be silently skipped when running yarn build or yarn start. The build and start scripts need to explicitly invoke these steps inline, since only standard lifecycle hooks like postinstall are auto-triggered in Yarn 4.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| "test:coverage": "vitest run --coverage.enabled --coverage.provider=istanbul --coverage.reporter=text --coverage.reporter=json --coverage.reporter=json-summary --coverage.reportsDirectory=./coverage", | ||
| "test:coverage:changed": "vitest run --changed master --coverage.enabled --coverage.provider=istanbul --coverage.reporter=text --coverage.reporter=json --coverage.reporter=json-summary --coverage.reportsDirectory=./coverage", | ||
| "retest:quality": "yarn test && yarn build && yarn lint && yarn type-check && yarn doctor", | ||
| "retest:quality": "corepack yarn test && corepack yarn build && corepack yarn lint && corepack yarn type-check && corepack yarn doctor", |
There was a problem hiding this comment.
Redundant corepack yarn prefix inside package.json scripts
Low Severity
All package.json scripts that invoke sub-scripts now use corepack yarn <script> (e.g., prebuild, prestart, electron:*, retest:quality). When Yarn 4 runs a script, it already places its own binary on the PATH, so yarn inside scripts already resolves to Yarn 4. The corepack prefix is redundant, adds an extra process-resolution step per invocation, and creates inconsistency with CI workflows which correctly use plain yarn build, yarn test, etc. after corepack enable. The PR description itself states the goal is to "align CI, docs, and contributor setup with plain yarn", yet these scripts do the opposite. Plain yarn calls inside package.json scripts would be sufficient and consistent.


Summary
yarnTesting
Note
Medium Risk
Medium risk because it changes the repo’s package manager pinning and install semantics across CI/release/Vercel, which can break builds if Yarn/Corepack versions or lockfile expectations differ. The added Vitest
localStoragemock may also subtly change test behavior.Overview
Migrates the project to Corepack-managed Yarn 4 by pinning
packageManager: yarn@4.13.0, adding.nvmrc(Node22.12.0) and.yarnrc.yml, and updating docs/agent workflows to consistently usecorepack yarnfor installs and verification.Updates CI and release workflows to
corepack enableand useyarn install --immutable, adjusts Vercel to install/build via Corepack, and tweaks.gitignorefor Yarn-managed directories.Adds Vitest
setupFiles(vitest.setup.ts) to provide a stablelocalStoragemock during tests.Written by Cursor Bugbot for commit 50301fb. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Chores
Documentation
Tests