From a0a0c10ffe1301a15608def8b0dcc50d942a9940 Mon Sep 17 00:00:00 2001 From: Jared Scott Date: Thu, 27 Aug 2026 20:57:12 +0800 Subject: [PATCH 1/2] chore(pnpm): prepare pnpm 12 upgrade Pin pnpm 12 and its platform artifacts, migrate CI to the verified native setup action, and keep tooling documentation in sync. Co-Authored-By: Codex Signed-off-by: Jared Scott --- .claude/agents/recce-pr-verifier.md | 2 +- .claude/skills/address-dependabot/skill.md | 2 +- .github/copilot-instructions.md | 6 +- .github/instructions/frontend-instructions.md | 10 +- .github/workflows/address-dependabot.yaml | 16 ++- .github/workflows/nightly.yaml | 16 ++- .github/workflows/release-ui.yaml | 22 ++-- .github/workflows/release.yaml | 16 ++- .github/workflows/tests-js.yaml | 52 +++++---- .github/workflows/tests-python.yaml | 34 ++++-- .pre-commit-config.yaml | 2 + CLAUDE.md | 2 +- Makefile | 6 +- docs/KNOWLEDGE_BASE.md | 2 +- docs/frontend.md | 2 +- js/CLAUDE.md | 10 +- js/README.md | 2 +- js/package.json | 2 +- js/pnpm-lock.yaml | 101 ++++++++++++++++++ 19 files changed, 238 insertions(+), 67 deletions(-) diff --git a/.claude/agents/recce-pr-verifier.md b/.claude/agents/recce-pr-verifier.md index b7dc9c9ee..09b27e4aa 100644 --- a/.claude/agents/recce-pr-verifier.md +++ b/.claude/agents/recce-pr-verifier.md @@ -95,7 +95,7 @@ uv run pytest tests/test_foo.py --cov=recce.module --cov-report=term-missing ### Frontend (TypeScript) — only if `js/` changed -For frontend tooling specifics (pnpm v11 quirks, Biome config, style conventions), see **[`js/CLAUDE.md`](../../js/CLAUDE.md)**. +For frontend tooling specifics (pnpm v12 quirks, Biome config, style conventions), see **[`js/CLAUDE.md`](../../js/CLAUDE.md)**. ```bash cd js diff --git a/.claude/skills/address-dependabot/skill.md b/.claude/skills/address-dependabot/skill.md index a82a01cee..b9a41767c 100644 --- a/.claude/skills/address-dependabot/skill.md +++ b/.claude/skills/address-dependabot/skill.md @@ -50,7 +50,7 @@ digraph address_dependabot { This repo contains `@datarecce/ui`, a **published npm package** consumed by external projects. Its `dependencies` field is a contract with consumers. This shapes how dependency updates are applied. -For frontend tooling context (pnpm v11 `strictDepBuilds`/`allowBuilds`, Biome migration on bump, Node.js 26 via `nave`), reference **[`js/CLAUDE.md`](../../../js/CLAUDE.md)** before applying npm updates. +For frontend tooling context (pnpm v12 `strictDepBuilds`/`allowBuilds`, Biome migration on bump, Node.js 26 via `nave`), reference **[`js/CLAUDE.md`](../../../js/CLAUDE.md)** before applying npm updates. ### The Three Zones diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c284d8503..b1b06d109 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,6 @@ # Recce Copilot Instructions -> Claude Code and other agents using `CLAUDE.md` should also consult **[`js/CLAUDE.md`](../js/CLAUDE.md)** for frontend tooling specifics (pnpm commands, Biome, Vitest, `@datarecce/ui` publishing, pnpm v11 `strictDepBuilds`/`allowBuilds`, style conventions). This file remains the canonical Copilot context. +> Claude Code and other agents using `CLAUDE.md` should also consult **[`js/CLAUDE.md`](../js/CLAUDE.md)** for frontend tooling specifics (pnpm commands, Biome, Vitest, `@datarecce/ui` publishing, pnpm v12 `strictDepBuilds`/`allowBuilds`, style conventions). This file remains the canonical Copilot context. ## Project Overview @@ -86,7 +86,7 @@ below: ```bash cd js -pnpm install # Uses pnpm 11, NOT npm or yarn +pnpm install # Uses pnpm 12, NOT npm or yarn ``` **Development Server:** @@ -218,7 +218,7 @@ recce/ ``` js/ -├── package.json # pnpm 11, Node >=26.5.0, React 19, Next.js 16 +├── package.json # pnpm 12, Node >=26.5.0, React 19, Next.js 16 ├── tsconfig.json # TypeScript config ├── next.config.js # Next.js config (output: 'export') ├── app/ # OSS Next.js App Router shell (routes/layout only) diff --git a/.github/instructions/frontend-instructions.md b/.github/instructions/frontend-instructions.md index 6ff5eb069..20dc6c4c3 100644 --- a/.github/instructions/frontend-instructions.md +++ b/.github/instructions/frontend-instructions.md @@ -4,7 +4,7 @@ applyTo: "js/**/*.ts,js/**/*.tsx,js/**/*.js,js/**/*.jsx,js/**/*.json,js/**/*.mjs # Frontend Build Instructions (js/ Directory) -> This file is the **Copilot-targeted** frontend guide (scoped via `applyTo:` frontmatter). Claude Code and other agents using `CLAUDE.md` should consult **[`js/CLAUDE.md`](../../js/CLAUDE.md)** for the equivalent guidance — both should stay in sync on tooling specifics (pnpm v11, Biome, `@datarecce/ui` publishing, style conventions). +> This file is the **Copilot-targeted** frontend guide (scoped via `applyTo:` frontmatter). Claude Code and other agents using `CLAUDE.md` should consult **[`js/CLAUDE.md`](../../js/CLAUDE.md)** for the equivalent guidance — both should stay in sync on tooling specifics (pnpm v12, Biome, `@datarecce/ui` publishing, style conventions). ## Critical Frontend Build Requirements @@ -27,7 +27,7 @@ pnpm run build ## Package Manager - MUST use pnpm ```bash -# CORRECT - Always use pnpm (version 11) +# CORRECT - Always use pnpm (version 12) pnpm install pnpm dev pnpm run build @@ -87,7 +87,7 @@ pnpm run clean ## Tech Stack - **Node.js >=26.5.0** - JavaScript runtime (required) -- **pnpm 11** - Package manager (NOT npm or yarn) +- **pnpm 12** - Package manager (NOT npm or yarn) - **Next.js 16** - React framework with App Router - **React 19.2** - UI library with new JSX transform - **React DOM 19.2** - React renderer @@ -130,7 +130,7 @@ js/ **package.json:** - Requires Node.js >=26.5.0 -- Uses pnpm@11.1.1 as package manager (pinned via Corepack) +- Uses pnpm@12.0.0 as package manager (pinned via Corepack) - Key scripts: - `dev`: Start development server with Turbopack - `build`: Clean, build Next.js, move to ../recce/data @@ -225,7 +225,7 @@ pnpm test # Watch mode **What it checks:** 1. Node.js 26.5.0 setup from `js/.nvmrc` -2. pnpm 11 installation +2. pnpm 12 installation 3. Dependency install with frozen lockfile 4. Biome linting (`pnpm lint`) 5. Production build (`pnpm run build`) diff --git a/.github/workflows/address-dependabot.yaml b/.github/workflows/address-dependabot.yaml index 04fc41013..ce8e89539 100644 --- a/.github/workflows/address-dependabot.yaml +++ b/.github/workflows/address-dependabot.yaml @@ -41,9 +41,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Install frontend dependencies working-directory: ./js diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index f42017b52..8d2f23817 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -40,9 +40,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Install dependencies run: | diff --git a/.github/workflows/release-ui.yaml b/.github/workflows/release-ui.yaml index 30723713a..14af29ab1 100644 --- a/.github/workflows/release-ui.yaml +++ b/.github/workflows/release-ui.yaml @@ -44,18 +44,28 @@ jobs: # For workflow_run, checkout the same ref that triggered the parent workflow ref: ${{ github.event.workflow_run.head_sha || github.sha }} - - uses: pnpm/action-setup@v6 - with: - version: 11.1.1 - - name: Setup Node.js 26 uses: actions/setup-node@v7 with: node-version-file: 'js/.nvmrc' # Node 26 includes npm 11+ with OIDC support - cache: 'pnpm' - cache-dependency-path: js/pnpm-lock.yaml registry-url: 'https://registry.npmjs.org' + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 + with: + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" + - name: Verify npm version run: | NPM_VERSION=$(npm --version) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1f2881124..3163a36cd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -27,9 +27,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Install dependencies run: | diff --git a/.github/workflows/tests-js.yaml b/.github/workflows/tests-js.yaml index 42b972da3..1284cc297 100644 --- a/.github/workflows/tests-js.yaml +++ b/.github/workflows/tests-js.yaml @@ -23,23 +23,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 - run_install: false + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml - - name: Get pnpm store directory - shell: bash + - name: Verify pnpm version + working-directory: ./js run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - uses: actions/cache@v4 - name: Setup pnpm cache - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Install dependencies working-directory: ./js @@ -60,23 +58,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 - run_install: false + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml - - name: Get pnpm store directory - shell: bash + - name: Verify pnpm version + working-directory: ./js run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - uses: actions/cache@v4 - name: Setup pnpm cache - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Install dependencies working-directory: ./js diff --git a/.github/workflows/tests-python.yaml b/.github/workflows/tests-python.yaml index 3f9eb3d95..e647b122c 100644 --- a/.github/workflows/tests-python.yaml +++ b/.github/workflows/tests-python.yaml @@ -74,10 +74,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 - run_install: false + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Build frontend assets run: make build-frontend @@ -117,10 +128,21 @@ jobs: with: node-version-file: 'js/.nvmrc' - - uses: pnpm/action-setup@v6 + - name: Set up pnpm + uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 with: - version: 11.1.1 - run_install: false + package-json-file: js/package.json + install: false + cache: true + cache-dependency-path: js/pnpm-lock.yaml + + - name: Verify pnpm version + working-directory: ./js + run: | + expected=$(node -p "require('./package.json').packageManager.match(/^pnpm@([^+]+)/)[1]") + actual=$(pnpm --version) + echo "pnpm version: $actual" + test "$actual" = "$expected" - name: Build frontend assets run: make build-frontend diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4c7089fb..2b983f286 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,6 +6,8 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml + # pnpm 12 lockfiles are valid multi-document YAML streams. + exclude: ^js/pnpm-lock\.yaml$ - id: check-added-large-files exclude: ^uv\.lock$ diff --git a/CLAUDE.md b/CLAUDE.md index 431f2d60d..1ae6109ba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,7 @@ ## Quick Reference → `docs/KNOWLEDGE_BASE.md` - Architecture, code patterns, frontend structure, testing, debugging -→ `js/CLAUDE.md` - Frontend conventions and tooling (Node.js 26 via `nave`, Biome, Vitest, pnpm v11 +→ `js/CLAUDE.md` - Frontend conventions and tooling (Node.js 26 via `nave`, Biome, Vitest, pnpm v12 quirks, Storybook imports, CSS color format, rem vs px, shell vs shared code) ## Working Preferences diff --git a/Makefile b/Makefile index c96bdc035..16de8a1a4 100644 --- a/Makefile +++ b/Makefile @@ -94,8 +94,10 @@ test-tox-python-versions: @tox run-parallel -e 3.10,3.11,3.12,3.13 install-frontend-requires: -# Install pnpm if not installed - @command -v pnpm || npm install -g pnpm +# Install Corepack if needed, then provision the pnpm version pinned by js/package.json + @command -v corepack >/dev/null || npm install -g corepack@latest + @corepack enable + @cd js && corepack install @cd js && pnpm install dev: install-frontend-requires diff --git a/docs/KNOWLEDGE_BASE.md b/docs/KNOWLEDGE_BASE.md index cd9251fd8..a4e08a6e0 100644 --- a/docs/KNOWLEDGE_BASE.md +++ b/docs/KNOWLEDGE_BASE.md @@ -21,7 +21,7 @@ Separation of concerns across models, APIs, tasks, adapters, and state. Import r Monorepo with `@datarecce/ui` shared package. OSS app (`js/app/`) stays thin; shared components, hooks, and API clients live in `js/packages/ui/`. → `docs/frontend.md` (structure, import rules, build process) -→ `js/CLAUDE.md` (tooling: pnpm, Biome, Vitest, @datarecce/ui publishing, style conventions, pnpm v11 quirks) +→ `js/CLAUDE.md` (tooling: pnpm, Biome, Vitest, @datarecce/ui publishing, style conventions, pnpm v12 quirks) ## Testing diff --git a/docs/frontend.md b/docs/frontend.md index 601f19d12..13529738b 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1,6 +1,6 @@ # Frontend Structure -> For frontend tooling specifics (pnpm commands, Biome, Vitest, `@datarecce/ui` publishing, pnpm v11 `strictDepBuilds`/`allowBuilds`, and style conventions), see **[`js/CLAUDE.md`](../js/CLAUDE.md)**. This document focuses on monorepo structure, package boundaries, and the build pipeline. +> For frontend tooling specifics (pnpm commands, Biome, Vitest, `@datarecce/ui` publishing, pnpm v12 `strictDepBuilds`/`allowBuilds`, and style conventions), see **[`js/CLAUDE.md`](../js/CLAUDE.md)**. This document focuses on monorepo structure, package boundaries, and the build pipeline. ## Monorepo Layout diff --git a/js/CLAUDE.md b/js/CLAUDE.md index de808b43e..60420668e 100644 --- a/js/CLAUDE.md +++ b/js/CLAUDE.md @@ -46,17 +46,19 @@ When updating frontend deps: Packages requiring overrides (exist in multiple `package.json`): `@emotion/react`, `@mui/material`, `@tanstack/react-query`, `@xyflow/react`, `axios`, `date-fns`, `lodash`, `tailwindcss`, `typescript`, `vitest`. -## pnpm v11 — strictDepBuilds + allowBuilds +## pnpm v12 — strictDepBuilds + allowBuilds -The repo runs on pnpm v11.1.1 (since DRC-3439, 2026-05-13). Four non-obvious behaviors: +The repo runs on pnpm v12.0.0 (since 2026-08-27). Five non-obvious behaviors: 1. **`strictDepBuilds: true` is on by default.** Any transitive package with a `postinstall` script that isn't explicitly listed in `pnpm-workspace.yaml#allowBuilds` will cause `pnpm install --frozen-lockfile` to hard-fail in CI with `ERR_PNPM_IGNORED_BUILDS`. When a new dep triggers this, add it to `allowBuilds` as `true` (run its postinstall) or `false` (acknowledge it exists, do NOT run postinstall). 2. **Local repro requires CI parity.** Use `CI=true pnpm install --frozen-lockfile` to match CI exactly. The `--ignore-scripts` flag will MASK this failure — do not use it as a verification path. -3. **pnpm 11 silently appends placeholder lines.** If you run `pnpm install` in a non-TTY context and it hits an ignored build, pnpm appends `: set this to true or false` to `pnpm-workspace.yaml#allowBuilds`. Always `git status` after running install — never commit these placeholders. +3. **Never accept generated `allowBuilds` placeholders.** If a non-TTY install discovers an ignored build, inspect `pnpm-workspace.yaml#allowBuilds` for `: set this to true or false`. Always run `git status` after an install and replace any placeholder with a reviewed boolean decision before committing. -4. **`packageManager` must be exact semver.** Corepack rejects ranges like `pnpm@11`. Pin the full `pnpm@11.x.y+sha512.` via `corepack use pnpm@11.x.y` (note the `.` separator between `sha512` and the hash — not `:`). +4. **`packageManager` must be exact semver.** Do not use ranges or dist-tags such as `pnpm@12`, `latest`, or `next-12`. Pin the full `pnpm@12.x.y+sha512.` via `corepack use pnpm@12.x.y` (note the `.` separator between `sha512` and the hash — not `:`). + +5. **The lockfile pins pnpm's platform executables.** Changing `packageManager` requires regenerating `pnpm-lock.yaml` so its leading `packageManagerDependencies` document records pnpm and every supported platform package with integrity hashes. CI's frozen install rejects a mismatched pin. GitHub Actions must read the version from `js/package.json` through the SHA-pinned `pnpm/setup` action rather than duplicate the version in workflow YAML. Canonical `allowBuilds` examples live in recce-cloud-infra: - `recce-cloud-infra/recce-cloud/pnpm-workspace.yaml` diff --git a/js/README.md b/js/README.md index d59c2f503..4342ee3c6 100644 --- a/js/README.md +++ b/js/README.md @@ -5,7 +5,7 @@ nave install "$(cat .nvmrc)" nave use "$(cat .nvmrc)" ``` -2. pnpm +2. pnpm 12 (the exact version is pinned in `package.json`) ``` npm install -g corepack@latest diff --git a/js/package.json b/js/package.json index e0610c328..153175ded 100644 --- a/js/package.json +++ b/js/package.json @@ -8,7 +8,7 @@ "engines": { "node": ">=26.5.0" }, - "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a", + "packageManager": "pnpm@12.0.0+sha512.9e2e3dc3911995868dc94b8175c217c27e95408fa03b4a22749778f2b34f773b77cdd3b39ede8171b22fcd53be6a35342e9fac9948a68ef58df6488ce89a7e67", "scripts": { "dev": "next dev --turbopack", "build": "next build && cp -R out/. ../recce/data/ && rm -rf out", diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index d460bf6ff..1d6707e9c 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -1,3 +1,104 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.0.0 + version: 12.0.0 + +packages: + + '@pnpm/exe.darwin-arm64@12.0.0': + resolution: {integrity: sha512-sqeoPfVMIfQhbwzDrKraXY2ynyuWClFqzvfImzAS/yczEru1m5SGvQ9kgFPDvQzJZ9AetedgJeDZC6qYvH8/tQ==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.0.0': + resolution: {integrity: sha512-Quc3J6c9cGTy+LDgz1cLVgCNOU9IERuyAlDoEj0DCilKqvo50Jx1GV8k74iwn4J9fFSKkm8JrwNvtTDj3uWnUA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.linux-arm64-musl@12.0.0': + resolution: {integrity: sha512-EVWd3OTmgsMFhXx69b5JxIzoabG9Ma7m4OeTaf0ZKBzMnfYi8u21NDQo92ToMrdYL5dYDDCHsyYIjXzk+d0HhA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.0.0': + resolution: {integrity: sha512-cXHHW8M4rAPsYNkKZO9WVcpLLK55i9EaIsZPfIqUuY2eopd5LqnFyBge54HCh1GC0yCX8ySn0hYIi+4OyAEoDg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.0.0': + resolution: {integrity: sha512-UcXwMdFjly0mpddkGigHKTxe27IMv2fUK4IWW/MHmJ3yMguxXmkwNlEI4aE+G1HO2TLo20uNEUWD4ymLe/DaCQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.0.0': + resolution: {integrity: sha512-6Rsl+zEWMOmus7v7/9J3OE8EMvHyNAfxYmDfmhQG4J0985OuT3G3Ho9NSGHjkBn4aU4bgklWifRhe1HX8dUSyw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.0.0': + resolution: {integrity: sha512-O5F76A4oVFrpDGdFxEszRIThOSBfjHdH5c006gR+7UTCfiXrukr1XfqPungUI1DXcSR5gb9jBsPQqQZOAoOOxw==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.0.0': + resolution: {integrity: sha512-5dKFajIEWJ1ai+KHXFJvskY6vchbunmLwSUV2ywbLymcmJjfY5XJVpgzPCyIoVCMVG0zHorr66+hM8h8b3aRfQ==} + cpu: [x64] + os: [win32] + + pnpm@12.0.0: + resolution: {integrity: sha512-ni49w5EZlYaNyUuBdcIXwn6VQI+gO0oidJd48rNPdzt3zdOznt6BcbIvzVO+ajU0Lp+smUimjvWN9kiM6Jp+Zw==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.darwin-arm64@12.0.0': + optional: true + + '@pnpm/exe.darwin-x64@12.0.0': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.0.0': + optional: true + + '@pnpm/exe.linux-arm64@12.0.0': + optional: true + + '@pnpm/exe.linux-x64-musl@12.0.0': + optional: true + + '@pnpm/exe.linux-x64@12.0.0': + optional: true + + '@pnpm/exe.win32-arm64@12.0.0': + optional: true + + '@pnpm/exe.win32-x64@12.0.0': + optional: true + + pnpm@12.0.0: + optionalDependencies: + '@pnpm/exe.darwin-arm64': 12.0.0 + '@pnpm/exe.darwin-x64': 12.0.0 + '@pnpm/exe.linux-arm64': 12.0.0 + '@pnpm/exe.linux-arm64-musl': 12.0.0 + '@pnpm/exe.linux-x64': 12.0.0 + '@pnpm/exe.linux-x64-musl': 12.0.0 + '@pnpm/exe.win32-arm64': 12.0.0 + '@pnpm/exe.win32-x64': 12.0.0 + +--- lockfileVersion: '9.0' settings: From 09db057d9086ea3fea6359a41536f2f667c33c28 Mon Sep 17 00:00:00 2001 From: Jared Scott Date: Mon, 14 Sep 2026 10:42:03 +0800 Subject: [PATCH 2/2] chore(pnpm): update package manager to 12.4.1 Refresh the Corepack integrity pin and all 14 platform executables while retaining the application dependency graph. Document release-note impacts from pnpm 12.1 through 12.4.1. Co-Authored-By: Claude Signed-off-by: Jared Scott --- .github/instructions/frontend-instructions.md | 2 +- js/CLAUDE.md | 12 +- js/package.json | 2 +- js/pnpm-lock.yaml | 131 +++++++++++++----- 4 files changed, 107 insertions(+), 40 deletions(-) diff --git a/.github/instructions/frontend-instructions.md b/.github/instructions/frontend-instructions.md index 20dc6c4c3..518ea02f1 100644 --- a/.github/instructions/frontend-instructions.md +++ b/.github/instructions/frontend-instructions.md @@ -130,7 +130,7 @@ js/ **package.json:** - Requires Node.js >=26.5.0 -- Uses pnpm@12.0.0 as package manager (pinned via Corepack) +- Uses pnpm@12.4.1 as package manager (pinned via Corepack) - Key scripts: - `dev`: Start development server with Turbopack - `build`: Clean, build Next.js, move to ../recce/data diff --git a/js/CLAUDE.md b/js/CLAUDE.md index 60420668e..7e9701a07 100644 --- a/js/CLAUDE.md +++ b/js/CLAUDE.md @@ -48,7 +48,7 @@ Packages requiring overrides (exist in multiple `package.json`): `@emotion/react ## pnpm v12 — strictDepBuilds + allowBuilds -The repo runs on pnpm v12.0.0 (since 2026-08-27). Five non-obvious behaviors: +The repo runs on pnpm v12.4.1 (updated 2026-09-14). Five non-obvious behaviors: 1. **`strictDepBuilds: true` is on by default.** Any transitive package with a `postinstall` script that isn't explicitly listed in `pnpm-workspace.yaml#allowBuilds` will cause `pnpm install --frozen-lockfile` to hard-fail in CI with `ERR_PNPM_IGNORED_BUILDS`. When a new dep triggers this, add it to `allowBuilds` as `true` (run its postinstall) or `false` (acknowledge it exists, do NOT run postinstall). @@ -60,6 +60,16 @@ The repo runs on pnpm v12.0.0 (since 2026-08-27). Five non-obvious behaviors: 5. **The lockfile pins pnpm's platform executables.** Changing `packageManager` requires regenerating `pnpm-lock.yaml` so its leading `packageManagerDependencies` document records pnpm and every supported platform package with integrity hashes. CI's frozen install rejects a mismatched pin. GitHub Actions must read the version from `js/package.json` through the SHA-pinned `pnpm/setup` action rather than duplicate the version in workflow YAML. +Release notes reviewed for this pin: [12.1](https://pnpm.io/blog/releases/12.1), +[12.2–12.3](https://pnpm.io/blog/releases/12.2-12.3), and +[12.4 / 12.4.1](https://pnpm.io/blog/releases/12.4). +The first install after 12.4 refetches registry metadata because cache keys now +include the full registry URL; the package store remains reusable. Version 12.4.1 +also fixes filesystem copy fallbacks, workspace dependency links, and install +scripts whose side effects live outside their package directory. Verify both +fresh and repeat frozen installs when updating the pin. Python dependencies +continue to use uv; pnpm's experimental Python/Cargo support is opt-in. + Canonical `allowBuilds` examples live in recce-cloud-infra: - `recce-cloud-infra/recce-cloud/pnpm-workspace.yaml` - `recce-cloud-infra/recce_instance_launcher/recce_agent/pnpm-workspace.yaml` diff --git a/js/package.json b/js/package.json index 088f88d96..88a5cb15f 100644 --- a/js/package.json +++ b/js/package.json @@ -8,7 +8,7 @@ "engines": { "node": ">=26.5.0" }, - "packageManager": "pnpm@12.0.0+sha512.9e2e3dc3911995868dc94b8175c217c27e95408fa03b4a22749778f2b34f773b77cdd3b39ede8171b22fcd53be6a35342e9fac9948a68ef58df6488ce89a7e67", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "scripts": { "dev": "next dev --turbopack", "build": "next build && cp -R out/. ../recce/data/ && rm -rf out", diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 138aa0224..d04c7b1a5 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -7,96 +7,153 @@ importers: configDependencies: {} packageManagerDependencies: pnpm: - specifier: 12.0.0 - version: 12.0.0 + specifier: 12.4.1 + version: 12.4.1 packages: - '@pnpm/exe.darwin-arm64@12.0.0': - resolution: {integrity: sha512-sqeoPfVMIfQhbwzDrKraXY2ynyuWClFqzvfImzAS/yczEru1m5SGvQ9kgFPDvQzJZ9AetedgJeDZC6qYvH8/tQ==} + '@pnpm/exe.android-arm64@12.4.1': + resolution: {integrity: sha512-/HwsqXMSmlOfgtV9+O0ratzjV6Vd/8n1hh4rGHpCGmDURvt52MwZxdbhyxP4K03ZfvgSDvotFPr8O+RzE5Eu8A==} + cpu: [arm64] + os: [android] + + '@pnpm/exe.android-x64@12.4.1': + resolution: {integrity: sha512-+l74Qb4c2YjOzNKHXJLg+1wr8xHM1ckkUhnU5KRUK9TJqiiczt6yeTZqqzHIlJ8i6pAoj5V0OJevDRwnQKLgrQ==} + cpu: [x64] + os: [android] + + '@pnpm/exe.darwin-arm64@12.4.1': + resolution: {integrity: sha512-6rkZkT3iGfaxknUdGHraqSWFvTa6N0ajAHluv9Ax0GRWs0sIcGNiFhDopv6xSZCsJZmG483aNS/b6UEDy3blfw==} cpu: [arm64] os: [darwin] - '@pnpm/exe.darwin-x64@12.0.0': - resolution: {integrity: sha512-Quc3J6c9cGTy+LDgz1cLVgCNOU9IERuyAlDoEj0DCilKqvo50Jx1GV8k74iwn4J9fFSKkm8JrwNvtTDj3uWnUA==} + '@pnpm/exe.darwin-x64@12.4.1': + resolution: {integrity: sha512-Vb1CHlR88HghC1qUxjxjs82zQSXnXacPD+btG2CmG8Q/hBU7Q0/b2YWJKSQqZXicunV5khFtfTlAwJddV9RkYA==} cpu: [x64] os: [darwin] - '@pnpm/exe.linux-arm64-musl@12.0.0': - resolution: {integrity: sha512-EVWd3OTmgsMFhXx69b5JxIzoabG9Ma7m4OeTaf0ZKBzMnfYi8u21NDQo92ToMrdYL5dYDDCHsyYIjXzk+d0HhA==} + '@pnpm/exe.freebsd-x64@12.4.1': + resolution: {integrity: sha512-iT3iHz3Nl0Sxxj7UPOtZ/aQ81AFsQhjoeWMAlPkSRO04gsgDGAXv3UYxOFaesMWsfNxaGn0A+CITbuCHFF66FA==} + cpu: [x64] + os: [freebsd] + + '@pnpm/exe.linux-arm64-musl@12.4.1': + resolution: {integrity: sha512-aBooZfNXM5f+OGUgCAMFWpE/kAhsWfvmqIyMtHy6zl3aNxyInWrcY/Saln/UElzo7lZWMC0Yktroxd/2J26lNQ==} cpu: [arm64] os: [linux] libc: [musl] - '@pnpm/exe.linux-arm64@12.0.0': - resolution: {integrity: sha512-cXHHW8M4rAPsYNkKZO9WVcpLLK55i9EaIsZPfIqUuY2eopd5LqnFyBge54HCh1GC0yCX8ySn0hYIi+4OyAEoDg==} + '@pnpm/exe.linux-arm64@12.4.1': + resolution: {integrity: sha512-TlOdacTTP09BgcMvwWBFRsu8VAjfwqwnslBj+XSq1JFM3ck4f3k+1O/747EuctxZxs3/o785b6Q3s7Pd92Ptsg==} cpu: [arm64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-x64-musl@12.0.0': - resolution: {integrity: sha512-UcXwMdFjly0mpddkGigHKTxe27IMv2fUK4IWW/MHmJ3yMguxXmkwNlEI4aE+G1HO2TLo20uNEUWD4ymLe/DaCQ==} + '@pnpm/exe.linux-ppc64@12.4.1': + resolution: {integrity: sha512-r/ab/MlIBo75oizUP5ITiziCCrnXz4SJwfErLQ+603AshB+Yq7xTMCoMtzTSCAMu6aaymIKkAFtZvd2J75Wq0w==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-riscv64@12.4.1': + resolution: {integrity: sha512-C/D1QWdKMiB8+wv/spl1rGITFUuqC+aI/fb6h8NB5sqxsOaGXeYc/g891oCuzggHn6SODk9p+I09hI76x/cMNw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-s390x@12.4.1': + resolution: {integrity: sha512-nxz5zD4yXt94uzbStDk0QTPKW+aE92hH1b5tFXK9ctB1HE9Xcq1vjTiA2LsZMFC6p4gdu5OwQeFqYNAVGa6QlA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.4.1': + resolution: {integrity: sha512-5AwgFdGhVUg2kIweYGfxzSLEHiIG77PQhZAkXC3TwofQHsu1Wr+TrV5/rNX2PopFnHRzuE581zoB8F6Wle32yg==} cpu: [x64] os: [linux] libc: [musl] - '@pnpm/exe.linux-x64@12.0.0': - resolution: {integrity: sha512-6Rsl+zEWMOmus7v7/9J3OE8EMvHyNAfxYmDfmhQG4J0985OuT3G3Ho9NSGHjkBn4aU4bgklWifRhe1HX8dUSyw==} + '@pnpm/exe.linux-x64@12.4.1': + resolution: {integrity: sha512-FJOZuuuQMhp0oLzBtcKkLXknBI92hfkmSnlKc47vfin4HrmfID5khY2lGekL9tCzk1cpR+HShEw/meFl+nHtzQ==} cpu: [x64] os: [linux] libc: [glibc] - '@pnpm/exe.win32-arm64@12.0.0': - resolution: {integrity: sha512-O5F76A4oVFrpDGdFxEszRIThOSBfjHdH5c006gR+7UTCfiXrukr1XfqPungUI1DXcSR5gb9jBsPQqQZOAoOOxw==} + '@pnpm/exe.win32-arm64@12.4.1': + resolution: {integrity: sha512-OO7eKBL9S+xk5hRy+JUUZSNJknGuGe3GEUffsrlC2LbqKF02g+VX1anGIzSbJDvkkdnpJhSlxF5AUz2JzJu2Jw==} cpu: [arm64] os: [win32] - '@pnpm/exe.win32-x64@12.0.0': - resolution: {integrity: sha512-5dKFajIEWJ1ai+KHXFJvskY6vchbunmLwSUV2ywbLymcmJjfY5XJVpgzPCyIoVCMVG0zHorr66+hM8h8b3aRfQ==} + '@pnpm/exe.win32-x64@12.4.1': + resolution: {integrity: sha512-x7gJHZgHo6hp354xCYA2NvoFzYJkHwovt2kVsUBK5EmXULLcP51JGMq09CX+5FRFJUZFKoXjLu3mZWmfP7o6PQ==} cpu: [x64] os: [win32] - pnpm@12.0.0: - resolution: {integrity: sha512-ni49w5EZlYaNyUuBdcIXwn6VQI+gO0oidJd48rNPdzt3zdOznt6BcbIvzVO+ajU0Lp+smUimjvWN9kiM6Jp+Zw==} + pnpm@12.4.1: + resolution: {integrity: sha512-LoHjmdc/6DkNqyXgaqeIq3pZCCSNL1o3D4K0gRR6ano2e/gEj5pv22Rg8hpm8FQt7bi5TKLIcjWWdBkgsWVtTA==} engines: {node: '>=18.*'} hasBin: true snapshots: - '@pnpm/exe.darwin-arm64@12.0.0': + '@pnpm/exe.android-arm64@12.4.1': + optional: true + + '@pnpm/exe.android-x64@12.4.1': + optional: true + + '@pnpm/exe.darwin-arm64@12.4.1': + optional: true + + '@pnpm/exe.darwin-x64@12.4.1': + optional: true + + '@pnpm/exe.freebsd-x64@12.4.1': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.4.1': + optional: true + + '@pnpm/exe.linux-arm64@12.4.1': optional: true - '@pnpm/exe.darwin-x64@12.0.0': + '@pnpm/exe.linux-ppc64@12.4.1': optional: true - '@pnpm/exe.linux-arm64-musl@12.0.0': + '@pnpm/exe.linux-riscv64@12.4.1': optional: true - '@pnpm/exe.linux-arm64@12.0.0': + '@pnpm/exe.linux-s390x@12.4.1': optional: true - '@pnpm/exe.linux-x64-musl@12.0.0': + '@pnpm/exe.linux-x64-musl@12.4.1': optional: true - '@pnpm/exe.linux-x64@12.0.0': + '@pnpm/exe.linux-x64@12.4.1': optional: true - '@pnpm/exe.win32-arm64@12.0.0': + '@pnpm/exe.win32-arm64@12.4.1': optional: true - '@pnpm/exe.win32-x64@12.0.0': + '@pnpm/exe.win32-x64@12.4.1': optional: true - pnpm@12.0.0: + pnpm@12.4.1: optionalDependencies: - '@pnpm/exe.darwin-arm64': 12.0.0 - '@pnpm/exe.darwin-x64': 12.0.0 - '@pnpm/exe.linux-arm64': 12.0.0 - '@pnpm/exe.linux-arm64-musl': 12.0.0 - '@pnpm/exe.linux-x64': 12.0.0 - '@pnpm/exe.linux-x64-musl': 12.0.0 - '@pnpm/exe.win32-arm64': 12.0.0 - '@pnpm/exe.win32-x64': 12.0.0 + '@pnpm/exe.android-arm64': 12.4.1 + '@pnpm/exe.android-x64': 12.4.1 + '@pnpm/exe.darwin-arm64': 12.4.1 + '@pnpm/exe.darwin-x64': 12.4.1 + '@pnpm/exe.freebsd-x64': 12.4.1 + '@pnpm/exe.linux-arm64': 12.4.1 + '@pnpm/exe.linux-arm64-musl': 12.4.1 + '@pnpm/exe.linux-ppc64': 12.4.1 + '@pnpm/exe.linux-riscv64': 12.4.1 + '@pnpm/exe.linux-s390x': 12.4.1 + '@pnpm/exe.linux-x64': 12.4.1 + '@pnpm/exe.linux-x64-musl': 12.4.1 + '@pnpm/exe.win32-arm64': 12.4.1 + '@pnpm/exe.win32-x64': 12.4.1 --- lockfileVersion: '9.0'