fix(devx): pin the regen self-test fixture to the root's packageManager so Corepack never resolves pnpm latest (#15992) - #16002
Merged
os-project-manager merged 1 commit intoSep 5, 2026
Conversation
`check-regen-pending.mjs --self-test` replays the deferred-merge sequence on a throwaway repo and spawns its stub gate with `pnpm -s`. The fixture manifest carried no `packageManager`, and Corepack resolves the version from the project it is invoked in: for an unpinned project that is the registry's `latest` dist-tag, re-resolved every run. When `latest` moved to a pnpm major whose CLI rejects `-s`, the "clean" stub exited 2 without running and the gate went red on every job, on trees nobody had touched. The fixture now copies the ROOT manifest's pin, read at self-test time so it can never drift from the pnpm this repo pins, and one case asserts both halves — the value is a real `pnpm@<version>` pin and it equals the root's — so a root manifest that lost the field cannot make the comparison hold vacuously. Production is untouched: the real hook runs `pnpm -s` in this repository, which is pinned. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M59rPZZFzqhfMUPFqqZTkf
os-project-manager
marked this pull request as ready for review
September 5, 2026 18:18
os-project-manager
enabled auto-merge
September 5, 2026 18:18
This was referenced Sep 5, 2026
This was referenced Sep 5, 2026
os-project-manager
deleted the
claude/issue-15992-regen-selftest-fixture-pin
branch
September 5, 2026 19:14
zhuangjianguo
pushed a commit
that referenced
this pull request
Sep 5, 2026
Picks up #16002 (f50c394), which pins the regen self-test fixture to the root's packageManager and clears the Corepack-store defect that reddened check:merge-driver on this PR and five others. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
zhuangjianguo
pushed a commit
that referenced
this pull request
Sep 5, 2026
…y-posture Picks up #16002, which repairs the check:merge-driver / check-regen-pending.mjs --self-test failure that reddened this PR, origin/main's own push build and five other PRs. Not a change to this card's diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
os-litant
pushed a commit
that referenced
this pull request
Sep 5, 2026
Clears staleness ahead of the contract-review patch round and picks up #16002. Measured before the merge: `pnpm check:merge-driver` was already exit 0 on the pre-merge head, so the branch was not red on that gate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D47qPfEWVPmhguWgBZCi5N
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #15992
Fixes #15994
Related: #15990 (first-filed anchor for the same red check, claimed by another session)
p0 fix-forward for a red
main; the seat lands it ahead of the queue per the main-red convention.The CI symptom
mainhas been red onLint & Repo Gatessince 2026-09-05T17:05Z, and the merge queue has been blocked for every lane. The failing step is Merge-driver wiring gate (pnpm check:merge-driver), insidecheck-regen-pending.mjs --self-test, section "deferred-merge sequence, replayed on a throwaway repo":Reference reading:
pushrun 33979882868, job 101343111648, step at 17:26Z. Every lane whose step executed after ~17:22Z fails identically, and the last pass was amerge_grouprun at ~17:21Z on the same SHA — so the tree was never the cause.Root cause, in three sentences
The self-test replays the deferred-merge sequence on a throwaway repo and spawns its stub gate with
execSync('pnpm -s …'), and the fixture'spackage.jsoncarried nopackageManagerfield. CI reaches pnpm through Corepack (.github/actions/setup-pnpm=corepack enable+corepack install), and Corepack resolves the version from the project it is invoked in — so an unpinned fixture does not inherit this repository's pin and does not get whatever the machine has either: it re-resolves the npmlatestdist-tag on every run.latestmoved topnpm@12.3.4, a major whose CLI rejects-s, so the "clean" stub exited 2 without ever running and every case that reads the stub's own exit code went red on trees nobody had touched.Production was never affected: the real hook runs
pnpm -sin this repository, which is pinned. It was only ever the fixture.The change
One file,
scripts/check-regen-pending.mjs, two hunks:fixtureSelfTest→runHooknow writes the ROOT manifest'spackageManagerinto the fixturepackage.json, read at self-test time from the repository root rather than written as a literal, so the fixture can never drift from the pnpm this repo pins.pnpm@VERSIONpin and that it equals the root's. Both halves are deliberate —=== rootPackageManageralone would compareundefinedtoundefinedif the root manifest ever lost the field, and the fixture would go back to resolvinglatestin silence.Nothing else moves.
execSync('pnpm -s …'), the workflows, the composite actions and every governed surface are untouched; the.git/info/excludeinvariant that keeps the stub out of the index (#9258) is unchanged, since adding a key to that JSON does not make it tracked.The self-test's battery floor is unaffected:
SELF_TEST_BATTERIESfloors each callee at 1 registration, not at an assertion count, so a newcheck()insidefixtureSelfTestneither raises nor lowers it.SELF_TEST_BATTERY_FLOORstays 3.Reproduction — the way CI sees it
The local machine's
pnpmis a plain 10.31.0 global install, not Corepack, which is why the gate passed locally on the broken tree. A PATH shim is what makes the reproduction real:Unfixed tree — red, exactly the CI shape:
Fixed tree — green, against the same Corepack store, which by then had already written
lastKnownGood = 12.3.4:That last detail is the load-bearing one: a store that has already seen 12.x is not repaired by
COREPACK_DEFAULT_TO_LATEST=0, but it is repaired by the pin.Isolated, the mechanism is one command. Unpinned fixture directory:
The same directory with the root pin added: exit 0, no output.
Verification
pnpm check:merge-driver— exit 0, both halves (git-merge-regen --self-test, then✓ check-regen-pending self-test passed.).git-merge-regen.mjswrites no throwaway fixture at all — it only reads the real root manifest — so it was never implicated and stays green.packageManager: rootPackageManager(marker count 1 → 0, blob hash moved off theHEADblob) turns the new line into✗ the fixture pins the ROOT's packageManager …. Restored viagit checkout HEAD -- PATH, proven by an emptygit diff HEADand a file hash byte-identical to theHEADblob.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 33 families; all 33 ran green atb101c2e05. Two (@objectstack/speccheck:docsandcheck:generated) first refused for a missing build artifact in a fresh worktree —json-schema/absent andapi-surfaceread off an unbuiltdist— which is NOT MEASURED, not a red; afterpnpm --filter @objectstack/spec buildboth are exit 0 and the working tree stays clean.--ranreconciliation:33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN.packages/spec/scripts/dist-freshness.test.ts,schema-tree-freshness.test.ts): 2 files, 21 tests, all passing.turbo ls --affectedagainst the merge base reports no packages — the changed path is a root-level script in no workspace, so no packagetest/typecheckis owed.eslint --no-inline-config --format jsonover the changed file reports 1 file linted, 0 errors, 0 warnings. The narrowing excludes nothing, becauseeslint.config.mjsstates of itself that this repo "runs oneeslint.config.mjs, which never enables type-aware linting (noparserOptions.project, no typed@typescript-eslintrules) for ANY file" — with no cross-file type program, this diff cannot move the verdict on any file it does not touch. The repo-widepnpm lintis CI's run.Changeset
None, and
skip-changesetis applied. The diff isscripts/check-regen-pending.mjs— a root-level repo tool in no workspace package, publishing nothing, so there is no user-visible release note it could feed.turbo ls --affectedreturning no packages is the mechanical reading of the same fact.🤖 Generated with Claude Code
https://claude.ai/code/session_01M59rPZZFzqhfMUPFqqZTkf
Generated by Claude Code
Generated by Claude Code