diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd90271c3..6585d8b8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,7 +252,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" diff --git a/.github/workflows/cli-ci.yml b/.github/workflows/cli-ci.yml index da3961e8c..18584c91e 100644 --- a/.github/workflows/cli-ci.yml +++ b/.github/workflows/cli-ci.yml @@ -82,7 +82,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -98,7 +97,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -115,7 +113,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -131,7 +128,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -148,7 +144,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -164,7 +159,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -191,7 +185,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -206,7 +199,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" @@ -228,7 +220,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 6cc3c7f02..6f3bd3566 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -32,7 +32,6 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare pnpm@latest --activate - name: Cache pnpm store uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 @@ -42,7 +41,7 @@ jobs: restore-keys: pnpm-${{ runner.os }}- - name: Install dependencies - run: pnpm install --frozen-lockfile=false --ignore-scripts + run: pnpm install --no-frozen-lockfile --ignore-scripts - name: Install cli dependencies # cli/ is a self-contained project (own lockfile, not a pnpm workspace diff --git a/cli/package.json b/cli/package.json index a9b00d0cd..be97ab781 100644 --- a/cli/package.json +++ b/cli/package.json @@ -35,15 +35,7 @@ "engines": { "node": ">=22.12" }, - "packageManager": "pnpm@10.14.0", - "pnpm": { - "overrides": { - "fast-uri": ">=3.1.2", - "picomatch": ">=4.0.4", - "postcss": ">=8.5.10", - "qs": ">=6.15.2" - } - }, + "packageManager": "pnpm@12.3.4", "bundleBudgetKB": 598, "scripts": { "build": "tsup && node scripts/check-bundle-size.mjs", diff --git a/cli/pnpm-lock.yaml b/cli/pnpm-lock.yaml index ad13873fc..1a4e96127 100644 --- a/cli/pnpm-lock.yaml +++ b/cli/pnpm-lock.yaml @@ -1,3 +1,104 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.3.4 + version: 12.3.4 + +packages: + + '@pnpm/exe.darwin-arm64@12.3.4': + resolution: {integrity: sha512-PAyUol8T1+/+ViOiXAt51ECA+QnfXCqz6foL4bW+LsoX0NcVd5XVEM2mRQu+LV4oc7uRz9zf9U0P+XFfuQeDAw==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.3.4': + resolution: {integrity: sha512-fxP9JCk0Cdye+ePuj+GJJLMUMTqHGWRdb1dtv4How876uQ2ehxvenpgiYAir/ceO9PsYUZkFTtyZdx+rRu5QOA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.linux-arm64-musl@12.3.4': + resolution: {integrity: sha512-FBOt0/7ye6O6q4AllVV5QMviB6qE6fqkeczV/+MDWQsmo+QJrlfsh6X7CpH/tClVpBZEyIbjpUoT8bNhCYBxEg==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.3.4': + resolution: {integrity: sha512-t71AVA7LRqiKTyZ5xMYaZc2n5DfdpMbfokZuiIOXHBOM03ECnF0t4iYwaBDqJgVjlKYUOwaF/bRQajGNA4cJ4w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.3.4': + resolution: {integrity: sha512-RPmk7Jb/aYaFvL2iyDN/AtMY+hUEsue732WmXpcuQ9tBpMnGyA5py7Z3+e+qmQaJ0zY/4ni9jJiyPBQHujmv6w==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.3.4': + resolution: {integrity: sha512-2ZqOlSPkfwX1h5cR+FPiWf8+F+2hZT/3TvhUK5sigHqwaQCIiq8R7CGxhndKs63JtcLi2a1Qpo+wX/EoyfjyJQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.3.4': + resolution: {integrity: sha512-ANyrHqyqco6SXBysUTRF74itDyyraea7IbFsKFdNXTjcFnfycTDx37EwuhdpPYFNSIh2JhUG4fByclsRfiHX7w==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.3.4': + resolution: {integrity: sha512-WH/KqBPY/hq2Tb7SgQltEZytimcjgKRaCRL/aM9CI0c67iKc5TVmHUhIiL3Ux9FB4bWn36i6XewUcScQI+zG8w==} + cpu: [x64] + os: [win32] + + pnpm@12.3.4: + resolution: {integrity: sha512-lhqkH7B32joEpEHZ+OFevAyW2o73ELLrZ7+e58sGEOq9SPH9hfUc/+c4RnhfoPh8VqOocqHYk/hEZ0G1zORUVw==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.darwin-arm64@12.3.4': + optional: true + + '@pnpm/exe.darwin-x64@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64@12.3.4': + optional: true + + '@pnpm/exe.linux-x64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-x64@12.3.4': + optional: true + + '@pnpm/exe.win32-arm64@12.3.4': + optional: true + + '@pnpm/exe.win32-x64@12.3.4': + optional: true + + pnpm@12.3.4: + optionalDependencies: + '@pnpm/exe.darwin-arm64': 12.3.4 + '@pnpm/exe.darwin-x64': 12.3.4 + '@pnpm/exe.linux-arm64': 12.3.4 + '@pnpm/exe.linux-arm64-musl': 12.3.4 + '@pnpm/exe.linux-x64': 12.3.4 + '@pnpm/exe.linux-x64-musl': 12.3.4 + '@pnpm/exe.win32-arm64': 12.3.4 + '@pnpm/exe.win32-x64': 12.3.4 + +--- lockfileVersion: '9.0' settings: diff --git a/cli/pnpm-workspace.yaml b/cli/pnpm-workspace.yaml index 96039eab1..b03326216 100644 --- a/cli/pnpm-workspace.yaml +++ b/cli/pnpm-workspace.yaml @@ -5,3 +5,20 @@ # # Empty on purpose - cli/ has its own lockfile and installs alone. packages: [] + +# Moved here from `package.json`'s own `pnpm` field, which pnpm 12 stopped reading: +# "The 'pnpm' field in package.json is no longer read by pnpm". Left there, these four +# security floors were silently ignored while the lockfile still recorded them, which is +# the ERR_PNPM_LOCKFILE_CONFIG_MISMATCH every `cli` install answered with. +overrides: + fast-uri: '>=3.1.2' + picomatch: '>=4.0.4' + postcss: '>=8.5.10' + qs: '>=6.15.2' + +# pnpm refuses a dependency's install scripts unless it is named here, and pnpm 12 makes +# that refusal a hard error rather than a warning: `ERR_PNPM_IGNORED_BUILDS`. Measured by +# running the install, never guessed - these are the packages pnpm 12 named itself. +allowBuilds: + esbuild: true + lefthook: true diff --git a/kanban/package.json b/kanban/package.json index 9af64b776..76b8d5456 100644 --- a/kanban/package.json +++ b/kanban/package.json @@ -6,7 +6,7 @@ "engines": { "node": ">=22.12" }, - "packageManager": "pnpm@10.14.0", + "packageManager": "pnpm@12.3.4", "scripts": { "test": "vitest run", "test:watch": "vitest", diff --git a/kanban/pnpm-lock.yaml b/kanban/pnpm-lock.yaml index e3ec3e5e2..af74a64ac 100644 --- a/kanban/pnpm-lock.yaml +++ b/kanban/pnpm-lock.yaml @@ -1,3 +1,104 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.3.4 + version: 12.3.4 + +packages: + + '@pnpm/exe.darwin-arm64@12.3.4': + resolution: {integrity: sha512-PAyUol8T1+/+ViOiXAt51ECA+QnfXCqz6foL4bW+LsoX0NcVd5XVEM2mRQu+LV4oc7uRz9zf9U0P+XFfuQeDAw==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.3.4': + resolution: {integrity: sha512-fxP9JCk0Cdye+ePuj+GJJLMUMTqHGWRdb1dtv4How876uQ2ehxvenpgiYAir/ceO9PsYUZkFTtyZdx+rRu5QOA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.linux-arm64-musl@12.3.4': + resolution: {integrity: sha512-FBOt0/7ye6O6q4AllVV5QMviB6qE6fqkeczV/+MDWQsmo+QJrlfsh6X7CpH/tClVpBZEyIbjpUoT8bNhCYBxEg==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.3.4': + resolution: {integrity: sha512-t71AVA7LRqiKTyZ5xMYaZc2n5DfdpMbfokZuiIOXHBOM03ECnF0t4iYwaBDqJgVjlKYUOwaF/bRQajGNA4cJ4w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.3.4': + resolution: {integrity: sha512-RPmk7Jb/aYaFvL2iyDN/AtMY+hUEsue732WmXpcuQ9tBpMnGyA5py7Z3+e+qmQaJ0zY/4ni9jJiyPBQHujmv6w==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.3.4': + resolution: {integrity: sha512-2ZqOlSPkfwX1h5cR+FPiWf8+F+2hZT/3TvhUK5sigHqwaQCIiq8R7CGxhndKs63JtcLi2a1Qpo+wX/EoyfjyJQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.3.4': + resolution: {integrity: sha512-ANyrHqyqco6SXBysUTRF74itDyyraea7IbFsKFdNXTjcFnfycTDx37EwuhdpPYFNSIh2JhUG4fByclsRfiHX7w==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.3.4': + resolution: {integrity: sha512-WH/KqBPY/hq2Tb7SgQltEZytimcjgKRaCRL/aM9CI0c67iKc5TVmHUhIiL3Ux9FB4bWn36i6XewUcScQI+zG8w==} + cpu: [x64] + os: [win32] + + pnpm@12.3.4: + resolution: {integrity: sha512-lhqkH7B32joEpEHZ+OFevAyW2o73ELLrZ7+e58sGEOq9SPH9hfUc/+c4RnhfoPh8VqOocqHYk/hEZ0G1zORUVw==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.darwin-arm64@12.3.4': + optional: true + + '@pnpm/exe.darwin-x64@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64@12.3.4': + optional: true + + '@pnpm/exe.linux-x64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-x64@12.3.4': + optional: true + + '@pnpm/exe.win32-arm64@12.3.4': + optional: true + + '@pnpm/exe.win32-x64@12.3.4': + optional: true + + pnpm@12.3.4: + optionalDependencies: + '@pnpm/exe.darwin-arm64': 12.3.4 + '@pnpm/exe.darwin-x64': 12.3.4 + '@pnpm/exe.linux-arm64': 12.3.4 + '@pnpm/exe.linux-arm64-musl': 12.3.4 + '@pnpm/exe.linux-x64': 12.3.4 + '@pnpm/exe.linux-x64-musl': 12.3.4 + '@pnpm/exe.win32-arm64': 12.3.4 + '@pnpm/exe.win32-x64': 12.3.4 + +--- lockfileVersion: '9.0' settings: diff --git a/kanban/pnpm-workspace.yaml b/kanban/pnpm-workspace.yaml index 58105b003..b962c9299 100644 --- a/kanban/pnpm-workspace.yaml +++ b/kanban/pnpm-workspace.yaml @@ -1,3 +1,9 @@ # See cli/pnpm-workspace.yaml. This stops pnpm searching upward and treating the # repository root as this project's workspace. packages: [] + +# pnpm refuses a dependency's install scripts unless it is named here, and pnpm 12 makes +# that refusal a hard error rather than a warning: `ERR_PNPM_IGNORED_BUILDS`. Measured by +# running the install, never guessed - these are the packages pnpm 12 named itself. +allowBuilds: + esbuild: true diff --git a/lefthook.yml b/lefthook.yml index 121da7528..f48509960 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -162,13 +162,18 @@ pre-commit: cli-typecheck: # The CLI type-checks `kanban/` too, so that folder's dependencies must be # resolvable. Install them only when they are missing, to keep the hook fast. - # `--ignore-workspace` because the repository root declares one (for pnpm's - # build allowlist); without the flag pnpm resolves kanban to that root, finds - # it lists no members, reports "Already up to date" and installs nothing — - # leaving this step to fail on a sibling package it was meant to repair. + # + # `--ignore-workspace` was here so pnpm would not resolve kanban to the + # repository root, find it lists no members, report "Already up to date" and + # install nothing. `kanban/pnpm-workspace.yaml` now stops that upward search on + # its own — that is the whole reason the file exists — and the flag had turned + # harmful: it discards that same file, and with it the `allowBuilds` entry pnpm + # needs to run esbuild's install script. Measured in the real layout under + # pnpm 12.3.4, a root workspace above and kanban's own file present: without the + # flag the install exits 0, with it, ERR_PNPM_IGNORED_BUILDS. glob: "{cli,kanban}/**" run: | - [ -d kanban/node_modules ] || (cd kanban && pnpm install --frozen-lockfile --ignore-workspace) + [ -d kanban/node_modules ] || (cd kanban && pnpm install --frozen-lockfile) cd cli && pnpm typecheck pre-push: diff --git a/package.json b/package.json index b8415249e..17eba7439 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "sdlc-automation", "prompt-engineering" ], + "packageManager": "pnpm@12.3.4", "engines": { "node": ">=22.12" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8002bb9d4..24ff1ec21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3 +1,104 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.3.4 + version: 12.3.4 + +packages: + + '@pnpm/exe.darwin-arm64@12.3.4': + resolution: {integrity: sha512-PAyUol8T1+/+ViOiXAt51ECA+QnfXCqz6foL4bW+LsoX0NcVd5XVEM2mRQu+LV4oc7uRz9zf9U0P+XFfuQeDAw==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.3.4': + resolution: {integrity: sha512-fxP9JCk0Cdye+ePuj+GJJLMUMTqHGWRdb1dtv4How876uQ2ehxvenpgiYAir/ceO9PsYUZkFTtyZdx+rRu5QOA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.linux-arm64-musl@12.3.4': + resolution: {integrity: sha512-FBOt0/7ye6O6q4AllVV5QMviB6qE6fqkeczV/+MDWQsmo+QJrlfsh6X7CpH/tClVpBZEyIbjpUoT8bNhCYBxEg==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.3.4': + resolution: {integrity: sha512-t71AVA7LRqiKTyZ5xMYaZc2n5DfdpMbfokZuiIOXHBOM03ECnF0t4iYwaBDqJgVjlKYUOwaF/bRQajGNA4cJ4w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.3.4': + resolution: {integrity: sha512-RPmk7Jb/aYaFvL2iyDN/AtMY+hUEsue732WmXpcuQ9tBpMnGyA5py7Z3+e+qmQaJ0zY/4ni9jJiyPBQHujmv6w==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.3.4': + resolution: {integrity: sha512-2ZqOlSPkfwX1h5cR+FPiWf8+F+2hZT/3TvhUK5sigHqwaQCIiq8R7CGxhndKs63JtcLi2a1Qpo+wX/EoyfjyJQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.3.4': + resolution: {integrity: sha512-ANyrHqyqco6SXBysUTRF74itDyyraea7IbFsKFdNXTjcFnfycTDx37EwuhdpPYFNSIh2JhUG4fByclsRfiHX7w==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.3.4': + resolution: {integrity: sha512-WH/KqBPY/hq2Tb7SgQltEZytimcjgKRaCRL/aM9CI0c67iKc5TVmHUhIiL3Ux9FB4bWn36i6XewUcScQI+zG8w==} + cpu: [x64] + os: [win32] + + pnpm@12.3.4: + resolution: {integrity: sha512-lhqkH7B32joEpEHZ+OFevAyW2o73ELLrZ7+e58sGEOq9SPH9hfUc/+c4RnhfoPh8VqOocqHYk/hEZ0G1zORUVw==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.darwin-arm64@12.3.4': + optional: true + + '@pnpm/exe.darwin-x64@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-arm64@12.3.4': + optional: true + + '@pnpm/exe.linux-x64-musl@12.3.4': + optional: true + + '@pnpm/exe.linux-x64@12.3.4': + optional: true + + '@pnpm/exe.win32-arm64@12.3.4': + optional: true + + '@pnpm/exe.win32-x64@12.3.4': + optional: true + + pnpm@12.3.4: + optionalDependencies: + '@pnpm/exe.darwin-arm64': 12.3.4 + '@pnpm/exe.darwin-x64': 12.3.4 + '@pnpm/exe.linux-arm64': 12.3.4 + '@pnpm/exe.linux-arm64-musl': 12.3.4 + '@pnpm/exe.linux-x64': 12.3.4 + '@pnpm/exe.linux-x64-musl': 12.3.4 + '@pnpm/exe.win32-arm64': 12.3.4 + '@pnpm/exe.win32-x64': 12.3.4 + +--- lockfileVersion: '9.0' settings: diff --git a/scripts/validate-yaml.mjs b/scripts/validate-yaml.mjs index 043bcc4a0..57aab56a5 100755 --- a/scripts/validate-yaml.mjs +++ b/scripts/validate-yaml.mjs @@ -2,14 +2,20 @@ // Validates YAML syntax using the repository's Node dependency, avoiding Python in hooks. import { readFile } from "node:fs/promises"; -import { load } from "js-yaml"; +import { loadAll } from "js-yaml"; const files = process.argv.slice(2).filter((file) => file !== "--"); const errors = []; for (const file of files) { try { - load(await readFile(file, "utf8"), { filename: file }); + // `loadAll`, not `load`: a YAML stream may hold several documents, and `load` + // rejects one that does with "expected a single document in the stream". pnpm 12 + // writes exactly that shape - a lockfile whose first document carries + // `packageManagerDependencies` and whose second carries the lockfile itself - so + // `load` reported three valid files as broken. What this checks is syntax; how + // many documents a file holds is not a syntax error. + loadAll(await readFile(file, "utf8"), null, { filename: file }); } catch (error) { errors.push(`${file}: ${error.message}`); }