From 5a2a2092fb9cabd503829f094513d6700a0b1540 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 18:25:55 +0000 Subject: [PATCH] fix(scripts): check-regen-pending --self-test no longer spawns its stubs through an ambient package manager The fixture wrote its gate stub into a mkdtemp directory under tmpdir() and ran it as `pnpm -s check:spec-changes`. That directory declares no `packageManager` and has no parent manifest to inherit one from, so the verdict was decided by whatever launcher resolved there rather than by the tree. Measured against CI's own Corepack store: `.github/actions/setup-pnpm` materialises the pinned pnpm and writes no `lastKnownGood.json`, so in a directory with no pin Corepack ignores the pin and resolves pnpm's `latest` dist-tag instead. That is pnpm 12, whose CLI rejects `-s` outright (`error: unexpected argument '-s' found`, exit 2). Every stub then collapsed to "the gate exited non-zero", which the script correctly grades as `stale`, so exactly the cases whose expected outcome was not stale went red -- byte identically on an innocent PR and on origin/main's own push build. The gate now takes its launcher from `OS_REGEN_GATE_LAUNCHER`, which production leaves unset (`pnpm -s`, unchanged) and the fixture points at a launcher it writes itself: it reads the named script out of the manifest at cwd and runs the body under /bin/sh with argv0 `sh`, the same producer and the same diagnostic shapes the classifier already anchors on. No case is skipped, disabled or relaxed; two cases are ADDED, asserting that a hostile pnpm first on PATH leaves both the `stale` and the `clean` readings byte-identical. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ --- scripts/check-regen-pending.mjs | 130 +++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 4 deletions(-) diff --git a/scripts/check-regen-pending.mjs b/scripts/check-regen-pending.mjs index 93af08f21a..cc541d6204 100755 --- a/scripts/check-regen-pending.mjs +++ b/scripts/check-regen-pending.mjs @@ -67,7 +67,7 @@ import { execFileSync, execSync, spawnSync } from 'node:child_process'; import { appendFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; -import { dirname, join, resolve } from 'node:path'; +import { delimiter, dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { PENDING_MARKER, entryForPath, ownerDir, ownerOf, ownerRunCommand } from './regen-artifacts.mjs'; @@ -90,6 +90,39 @@ const SPEC_DIR = join(REPO_ROOT, 'packages/spec'); */ const GATE_CWD_OVERRIDE = process.env.OS_REGEN_GATE_CWD || null; +/** + * The launcher the gates are spawned THROUGH. Production leaves this unset and + * every gate runs as `pnpm -s