Skip to content

chore: migrate to Corepack-managed Yarn 4#1109

Merged
tomcasaburi merged 6 commits intomasterfrom
codex/chore/yarn4-corepack
Mar 19, 2026
Merged

chore: migrate to Corepack-managed Yarn 4#1109
tomcasaburi merged 6 commits intomasterfrom
codex/chore/yarn4-corepack

Conversation

@tomcasaburi
Copy link
Member

@tomcasaburi tomcasaburi commented Mar 19, 2026

Summary

  • pin the app to Yarn 4 via Corepack
  • remove reliance on global Yarn Classic
  • align CI, docs, and contributor setup with plain yarn
  • fix Vercel preview installs to use the Yarn 4 install command

Testing

  • yarn install --immutable
  • yarn build
  • yarn type-check
  • yarn lint
  • yarn test --run
  • vercel build

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 localStorage mock may also subtly change test behavior.

Overview
Migrates the project to Corepack-managed Yarn 4 by pinning packageManager: yarn@4.13.0, adding .nvmrc (Node 22.12.0) and .yarnrc.yml, and updating docs/agent workflows to consistently use corepack yarn for installs and verification.

Updates CI and release workflows to corepack enable and use yarn install --immutable, adjusts Vercel to install/build via Corepack, and tweaks .gitignore for Yarn-managed directories.

Adds Vitest setupFiles (vitest.setup.ts) to provide a stable localStorage mock during tests.

Written by Cursor Bugbot for commit 50301fb. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Chores

    • Standardized package management to use Yarn 4 with Corepack across development, CI/CD, and deployment environments
    • Pinned Node.js version to 22.12.0
  • Documentation

    • Updated contributor setup guides to reflect new tooling requirements and initialization steps
  • Tests

    • Enhanced test environment with improved localStorage support for testing purposes

@vercel
Copy link

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
5chan Ready Ready Preview, Comment Mar 19, 2026 7:04am

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

Migration 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

Cohort / File(s) Summary
Documentation & Skill Guides
.codex/skills/..., .cursor/skills/..., AGENTS.md, docs/agent-playbooks/hooks-setup.md, public/llms.txt
Updated Yarn command invocations to use corepack yarn instead of yarn. Modified guidance for dependency installation, build, lint, type-check, and audit operations.
GitHub Actions Workflows
.github/workflows/ci.yml, .github/workflows/release.yml
Added corepack enable step after setup-node in all jobs. Replaced yarn install --frozen-lockfile with yarn install --immutable while preserving network timeout, concurrency, and retry logic.
Configuration Files
.yarnrc.yml, .nvmrc, .gitignore, package.json
Added Yarn version pinning (.yarnrc.yml with nodeLinker: node-modules), Node.js version specification (.nvmrc: 22.12.0). Updated .gitignore to use .yarn/* with explicit unignore patterns. Added packageManager: yarn@4.13.0 to package.json and changed dependency source from git commit ref to tarball URL.
Package Scripts
package.json, vercel.json, README.md, scripts/agent-hooks/...
Replaced all yarn invocations with corepack yarn across build, test, and dependency management scripts. Updated Vercel install/build commands and shell hook scripts (yarn-install.sh, verify.sh). Changed lockfile flag from --frozen-lockfile to --immutable.
Test Infrastructure
vitest.config.ts, vitest.setup.ts
Added setupFiles: ['./vitest.setup.ts'] to Vitest configuration. Created new setup file implementing in-memory localStorage mock using a shared Map with redefined Storage.prototype methods and properties for test environments.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hop along with Corepack's might,
Yarn's version locked up tight,
Storage mocked for tests so bright,
Workflows humming—all is right! ✨🧶

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: migrating the project to use Corepack-managed Yarn 4 instead of globally installed Yarn.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/chore/yarn4-corepack
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟡 Minor

Coding guideline violation: Use exact version, not ^.

As per coding guidelines, package.json must 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 | 🟡 Minor

Coding 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 | 🟡 Minor

Coding 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 | 🟡 Minor

Coding 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-time corepack enable), but this template uses corepack yarn install. For contributor-facing docs, using plain yarn commands 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 install here 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 install instead of corepack yarn install to 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 enable once, then use yarn. But this line uses corepack yarn install. For consistency, consider using plain yarn install here 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 install to align with the guidance at Line 74 that plain yarn works after corepack 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 plain yarn commands for consistency.

The skill uses corepack yarn prefix throughout, but the PR's main documentation (README.md, AGENTS.md) uses plain yarn commands after a one-time corepack enable. For agent playbooks that run after the environment is already set up, plain yarn commands would be more concise and consistent.

That said, using corepack yarn explicitly 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

📥 Commits

Reviewing files that changed from the base of the PR and between e0fa1ca and 15df2e5.

⛔ Files ignored due to path filters (1)
  • yarn.lock is 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.yml
  • AGENTS.md
  • README.md
  • docs/agent-playbooks/hooks-setup.md
  • package.json
  • public/llms.txt
  • scripts/agent-hooks/verify.sh
  • scripts/agent-hooks/yarn-install.sh
  • vercel.json
  • vitest.config.ts
  • vitest.setup.ts

Comment on lines +5 to +72
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,
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.ts

Repository: bitsocialnet/5chan

Length of output: 2341


🏁 Script executed:

cat -n vitest.setup.ts

Repository: 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",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

@tomcasaburi tomcasaburi merged commit 8cced0f into master Mar 19, 2026
5 checks passed
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

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",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

@tomcasaburi tomcasaburi deleted the codex/chore/yarn4-corepack branch March 19, 2026 07:51
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.

1 participant