Skip to content

Commit a483aaa

Browse files
hotlongclaude
andcommitted
fix(scripts): spell pnpm flags so a global pnpm 11+ frontend parses them
wip Claude-Session: https://claude.ai/code/session_local_00307fb7-db7a-4ba8-84c3-65a062e8a14d Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0326b32 commit a483aaa

7 files changed

Lines changed: 32 additions & 13 deletions

File tree

‎packages/spec/scripts/check-generated.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,10 @@ function runScript(script: string): { ok: boolean; output: string } {
684684
// the build alone; every gate keeps the caller's environment.
685685
if (script === SPEC_BUILD) delete env.OS_SKIP_DTS;
686686
try {
687-
const output = execSync(`pnpm -s ${script}`, { cwd: pkgRoot, env, stdio: ['ignore', 'pipe', 'pipe'] }).toString();
687+
// `--silent`, never `-s`: a global pnpm 11+/12 `@pnpm/exe` frontend parses the
688+
// argv before handing off to the pinned pnpm and rejects `-s` with exit 2, which
689+
// reads here as every gate stale.
690+
const output = execSync(`pnpm --silent ${script}`, { cwd: pkgRoot, env, stdio: ['ignore', 'pipe', 'pipe'] }).toString();
688691
return { ok: true, output };
689692
} catch (err: any) {
690693
return { ok: false, output: `${err?.stdout?.toString() ?? ''}${err?.stderr?.toString() ?? ''}`.trim() };

‎scripts/build-console.sh‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,18 @@ pushd "$BUILD_ROOT" > /dev/null
321321

322322
# objectui's root package.json may pin packages that aren't available on
323323
# every mirror. Fall back to the public registry just for this install.
324+
#
325+
# The console build needs objectui's devDependencies, so production mode is
326+
# forced OFF: an inherited `npm_config_production=true` or an .npmrc
327+
# `production=true` would otherwise skip them (NODE_ENV=production alone does
328+
# not, under pnpm 10). Spelled `--config.production=false`, never
329+
# `--prod=false`: a global pnpm 11+/12 `@pnpm/exe` frontend parses the argv
330+
# itself before handing off to the version objectui pins, rejects a value on its
331+
# boolean `--prod` and exits 2 without installing anything. The pinned pnpm and
332+
# that frontend both accept this spelling.
324333
NPM_CONFIG_REGISTRY_OVERRIDE="${OBJECTUI_NPM_REGISTRY:-https://registry.npmjs.org}"
325334
npm_config_registry="$NPM_CONFIG_REGISTRY_OVERRIDE" \
326-
pnpm install --frozen-lockfile --prefer-offline --prod=false
335+
pnpm install --frozen-lockfile --prefer-offline --config.production=false
327336

328337
# Build the console's workspace deps via turbo, then the SPA itself directly
329338
# (see DEPS_BUILD_CMD/BUILD_CMD above for why these are split).

‎scripts/check-regen-pending.mjs‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,12 @@ export function gateCouldNotRun(output, exitCode, fromDir, gate = null) {
859859
return null;
860860
}
861861

862+
// `--silent`, never `-s`: a global pnpm 11+/12 `@pnpm/exe` frontend parses the argv
863+
// before handing off to the pinned pnpm and rejects `-s` with exit 2 — every artifact
864+
// would read as stale and every commit would be refused.
862865
function runCheck(script, cwd) {
863866
try {
864-
execSync(`pnpm -s ${script}`, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
867+
execSync(`pnpm --silent ${script}`, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
865868
return { ok: true, output: '', code: 0 };
866869
} catch (err) {
867870
return {
@@ -1396,7 +1399,7 @@ function fixtureSelfTest() {
13961399
/**
13971400
* The pnpm the fixture's stub gate runs under, pinned to the repository's own.
13981401
*
1399-
* `runCheck` spawns every gate with `pnpm -s`, and CI reaches pnpm through
1402+
* `runCheck` spawns every gate with `pnpm --silent`, and CI reaches pnpm through
14001403
* Corepack (`.github/actions/setup-pnpm`). Corepack resolves the version from
14011404
* the project it is invoked IN, so a fixture carrying no `packageManager` field
14021405
* does not inherit this repo's pin and does not get "whatever the machine has"
@@ -1405,8 +1408,10 @@ function fixtureSelfTest() {
14051408
* published that morning: the day `latest` moved to a major whose CLI rejects
14061409
* `-s`, the "clean" stub exited 2 without ever running, and every case that
14071410
* reads the stub's own exit code went red on a tree nobody had touched. It is
1408-
* the FIXTURE that was unpinned, never production — the real hook runs `pnpm -s`
1409-
* in this repository, which is pinned.
1411+
* the FIXTURE that was unpinned, never production — the real hook runs in this
1412+
* repository, which is pinned. A pin does not reach the argv parser of a global
1413+
* pnpm 11+ `@pnpm/exe` frontend, though, which is why the spawn is spelled
1414+
* `--silent` rather than `-s`.
14101415
*
14111416
* Read off the ROOT manifest rather than written as a literal, so the fixture
14121417
* cannot drift from the pnpm this repo pins. The case below asserts both halves,
@@ -1508,7 +1513,7 @@ function fixtureSelfTest() {
15081513
const merge = runHook('stale');
15091514

15101515
// The fixture's OWN prerequisite, asserted before any verdict is read out of a
1511-
// gate's exit code: every case below spawns `pnpm -s` inside this directory, so
1516+
// gate's exit code: every case below spawns `pnpm --silent` inside this directory, so
15121517
// an unpinned fixture grades the registry's `latest` pnpm instead of the one
15131518
// this repository pins, and the failure lands on cases that have nothing to do
15141519
// with pnpm. ⛔ Not `=== rootPackageManager` on its own: were the root manifest

‎scripts/git-merge-regen.mjs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,7 @@ function reconcileOwnership() {
11941194
'a package command filters to its owner',
11951195
ownerRunCommand(DEFAULT_OWNER, 'gen:x') === `pnpm --filter ${DEFAULT_OWNER} gen:x`,
11961196
],
1197-
['a spawn asks for silence', ownerRunCommand(ROOT_OWNER, 'check:x', { silent: true }) === 'pnpm -s check:x'],
1197+
['a spawn asks for silence', ownerRunCommand(ROOT_OWNER, 'check:x', { silent: true }) === 'pnpm --silent check:x'],
11981198
];
11991199

12001200
const failures = cases.filter(([, ok]) => !ok).map(([name]) => name);
@@ -1715,7 +1715,7 @@ function endToEndWorktreeRefusal() {
17151715
const target = REGEN_ARTIFACTS[0].path;
17161716
const gateScript = REGEN_ARTIFACTS[0].check;
17171717

1718-
/* The stub gate, and the pin that keeps it honest. `pnpm -s` resolves its own
1718+
/* The stub gate, and the pin that keeps it honest. `pnpm --silent` resolves its own
17191719
* version from the manifest of the directory it runs in, so a fixture with no
17201720
* `packageManager` grades whatever Corepack resolves as `latest` instead of the
17211721
* pnpm this repository pins — the same trap `check-regen-pending.mjs`'s fixture

‎scripts/pm/dispatch-gates.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9316,7 +9316,7 @@ export function governedReadCensus({ files = null, read = null } = {}) {
93169316
* quoted literal that `resolvePathExpression` refuses by construction, so
93179317
* admitting them would add a scan that cannot return a target: dead code that
93189318
* reads as coverage. Live specimens of the refused class in this tree, both
9319-
* shell-quoted: `pnpm -s ${script}` and `git rev-parse --show-toplevel`.
9319+
* shell-quoted: `pnpm --silent ${script}` and `git rev-parse --show-toplevel`.
93209320
*
93219321
* THE PROGRAM POSITION ONLY — argument 0, plus the elements of an argv ARRAY
93229322
* LITERAL in argument 1. That is where a program path is; an options object is

‎scripts/pm/dispatch-gates.self-test.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8728,7 +8728,7 @@ export function selfTest({ tier = 'full' } = {}) {
87288728
"const r1 = spawnSync(process.execPath, [join(ROOT, TOOL), '--self-test'], { stdio: 'inherit' });", // followed: argv array, component NAMED
87298729
"const r2 = execFileSync('node', [join(ROOT, 'scripts/invoked-as.mjs')]);", // followed: component written out
87308730
"const r3 = spawnSync('git', ['ls-files'], { cwd: ROOT });", // a program that is not in this tree
8731-
'const r4 = execSync(`pnpm -s ${script}`);', // shell form: a command STRING, never scanned
8731+
'const r4 = execSync(`pnpm --silent ${script}`);', // shell form: a command STRING, never scanned
87328732
"const r5 = spawnSync(process.execPath, [join(ROOT, 'package.json')]);", // tracked, but not program text
87338733
"const r6 = spawnSync(process.execPath, [join(ROOT, 'scripts/does-not-exist.mjs')]);", // resolves, untracked
87348734
"const r7 = spawnSync(process.execPath, [join(ROOT, 'scripts/fixture.mjs')]);", // itself: the identity key owns it

‎scripts/regen-artifacts.mjs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -957,11 +957,13 @@ export function ownerDir(owner, workspacePkgs) {
957957
*
958958
* @param {string} owner
959959
* @param {string} script
960-
* @param {{ silent?: boolean }} [options] `silent` adds `-s`, for a spawn rather than advice
960+
* @param {{ silent?: boolean }} [options] `silent` adds `--silent`, for a spawn rather than
961+
* advice — never `-s`, which a global pnpm 11+ `@pnpm/exe` frontend rejects before the
962+
* pinned pnpm ever runs
961963
* @returns {string}
962964
*/
963965
export function ownerRunCommand(owner, script, { silent = false } = {}) {
964-
const s = silent ? ' -s' : '';
966+
const s = silent ? ' --silent' : '';
965967
return owner === ROOT_OWNER ? `pnpm${s} ${script}` : `pnpm${s} --filter ${owner} ${script}`;
966968
}
967969

0 commit comments

Comments
 (0)