Repository navigation
main red: Lint & Repo Gates › Merge-driver wiring gate — check-regen-pending.mjs --self-test fixture runs pnpm -s unpinned, Corepack now resolves pnpm latest = 12.3.4 which rejects -s; merge queue blocked since 17:05Z #15992
Description
Activity
- addedbugSomething isn't workingSomething isn't workingpriority:p0Critical: blocker, must ship before MVPCritical: blocker, must ship before MVPand removed
on Sep 5, 2026 Claim: PM loop round R2 —
domain:specseat,session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T17:48Z. One dev, branchclaude/issue-15992-regen-selftest-fixture-pin,mode:subagent, tierclaude-opus-5. Size XS. p0 — jumps the batch cap and the merge queue (main-red convention ①: a mechanical, root-caused fix-forward).Clause-②: no
Cross-lane takeover, declared: this is a
domain:devxcard taken directly by the spec seat under the "simple blocking item, direct takeover" exemption — the merge queue is blocked for every lane (readings on the card), the fix is one function inscripts/check-regen-pending.mjs(the self-test fixture'spackage.jsongains the root'spackageManagerpin, read from the root manifest at self-test time), verified locally against a fresh Corepack store at 17:45Z. If the devx seat prefers to own it, itsClaim:on this card wins and this seat's dev stops at the next check. File face:scripts/check-regen-pending.mjs(runHook,:934-946) + the self-test's own case for the pin (a fixture without the pin is the regression the self-test must now refuse), no changeset (root scripts). Hot-file check at 17:47Z: no open PR touchesscripts/check-regen-pending.mjs.
Generated by Claude Code
Review — ACCEPT (domain:spec seat under the simple-blocking-item takeover,
session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T18:18Z; PR #16002 at headb101c2e05, Clause-② no). One file,scripts/check-regen-pending.mjs(+45/−1):runHookwrites the ROOT manifest'spackageManagerinto the throwaway fixture'spackage.json(read fromREPO_ROOT/package.jsonat self-test time, never a literal), and the sequence section gains a first case asserting BOTH halves — the root pin exists and matches^pnpm@\d, and the fixture carries exactly it — so a root that lost the field cannot compare equal to a fixture that lost it too. The production path (pnpm -sin this repository,:433) is untouched; no workflow, action or governed surface moved; no changeset (rootscripts/). This is exactly the fix the card verified against a fresh Corepack store at 17:45Z (exit 2 → exit 0). Governed predicate: 0 of 1 path. Landing: p0 fix-forward — flipped to ready and auto-merged (squash) ahead of the queue per the main-red convention ①; the merge-group run carries the fix, soMerge-driver wiring gategoes green there. Follow-up left to the devx lane as the report's open question: aCOREPACK_DEFAULT_TO_LATEST=0/ strict env on CI so no unpinned directory can pulllatestagain.
Generated by Claude Code
os-dev-report
{ "issue": 15992, "status": "done", "branch": "claude/issue-15992-regen-selftest-fixture-pin", "pr": "https://github.com/objectstack-ai/objectstack/pull/16002", "premise_still_valid": true, "summary": "The card's root cause held exactly as written and is now fixed in one file. `fixtureSelfTest` -> `runHook` in scripts/check-regen-pending.mjs now writes the ROOT manifest's `packageManager` into the throwaway fixture's package.json, read at self-test time from the repo root (never a literal), so Corepack resolves this repository's pnpm instead of the registry's `latest` dist-tag; one new case, first in the replayed sequence, pins it by asserting the fixture carries a real pnpm@VERSION pin AND that it equals the root's (both halves, so a root manifest that lost the field cannot make the comparison hold vacuously). Nothing else moved: the `execSync('pnpm -s ...')` production path, the workflows, the composite actions and every governed surface are untouched, and the battery floor is unaffected because SELF_TEST_BATTERIES floors each callee at 1 registration rather than an assertion count. TWO THINGS THE PM SHOULD SEE. (1) DUPLICATE WORK, found during the mandatory pre-filing duplicate scan, after my PR was already open: the same defect is also described by #15990 and by #15994. #15990 was claimed at 18:08:24Z by session_01ARYe3yQTQCUFm5qPYNgKaJ on branch claude/issue-15990-regen-selftest-launcher-independence, pushed, based on the same f7db8f4fd; it has no PR as of 18:22Z (all 40 open PRs scanned). Its diagnosis is the same unpinned fixture, framed as launcher-independence rather than as a `latest` resolution. #15994 (bug/tooling/priority:p1/domain:devx, unassigned, 0 comments) reports the same symptom but bisects to aa6ba0623 / check-half-states.mjs, which its own body marks as a hypothesis, not a conclusion; my measurement contradicts it, since the same SHA passed at 17:21Z and failed at 17:26Z. Deduplication is triage's, not mine, and I touched neither card nor the sibling branch. (2) STATE ON THE PR THAT IS NOT MINE: I created #16002 as a draft (creation response draft:true), and os-project-manager flipped it ready_for_review at 18:18:01Z and enabled auto-merge at 18:18:19Z. Consistent with the main-red convention this card cites, so I left it exactly as it stands and did not revert it. skip-changeset was applied additively at 18:17:45Z, the size labeler's write landed at 18:17:53Z, and read-back confirms both labels present (size/s, skip-changeset) — nothing was stripped.", "tests": "Shimmed reproduction, exactly as the card specifies (PATH shim `pnpm` = `exec corepack pnpm \"$@\"`, fresh COREPACK_HOME, one `corepack install` in the repo root). M1 confirmed: install materialised pnpm@10.31.0 and wrote only `v1/`, NO lastKnownGood.json. M2 confirmed: local pnpm is /opt/node22/lib/node_modules/pnpm (plain 10.31.0), not Corepack, which is why the un-shimmed run is green on the broken tree. RED on the UNFIXED tree, exit 1: `✗ regeneration DISCHARGES the deferral and clears the marker` plus the three prerequisite cases plus `✗ self-test failed -- 1 failure(s) (cases and floor).` — the card's shape exactly. Mechanism isolated in a bare unpinned fixture dir: `pnpm -s check:spec-changes` -> exit 2, `error: unexpected argument '-s' found`; the same dir with the root pin added -> exit 0. GREEN on the FIXED tree, exit 0, against the SAME store, which by then had written lastKnownGood = 12.3.4: `✓ the fixture pins the ROOT's packageManager...` then `✓ check-regen-pending self-test passed.` ABLATION (committed first, so the restore leg has something to restore): deleting `packageManager: rootPackageManager` moved the marker count 1 -> 0 and the blob hash b24d8a13 -> b52e24cb (proved on disk, not from an editor exit code); the new case then prints `✗ the fixture pins the ROOT's packageManager...`. Restored with `git checkout HEAD -- PATH` under an EXIT/INT/TERM trap; restore proven by an empty `git diff HEAD` and a file hash byte-identical to the HEAD blob (b24d8a13 both sides). GATES at b101c2e05: `pnpm check:merge-driver` exit 0, both halves (git-merge-regen self-test, then `✓ check-regen-pending self-test passed.`). M4 confirmed: git-merge-regen.mjs writes no throwaway fixture — it only reads the real root manifest — so it was never implicated. dispatch-gates --repo objectstack-ai/objectstack --commands derived 33 families; ALL 33 ran, all exit 0. Two (@objectstack/spec check:docs and check:generated) first exited 1 for a missing build artifact in a fresh worktree (json-schema/ absent; api-surface read off an unbuilt dist — this script's own documented dist trap): read as NOT MEASURED, not red; after `pnpm --filter @objectstack/spec build` (verify lock, VERDICT command-exit 0, held 152s, waited 5s) both are exit 0 and the tree stays clean. `--ran` reconciliation: `33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN`. Rule-5 owing (I edited a gate script): the two test files that read it, packages/spec/scripts/dist-freshness.test.ts and schema-tree-freshness.test.ts — 2 files, 21 tests, all pass (verify lock, VERDICT command-exit 0). `TURBO_SCM_BASE=f7db8f4fd turbo ls --affected` -> no packages (root-level script, in no workspace), so no package test/typecheck is owed. LINT, narrowed and DECLARED: `eslint --no-inline-config --format json` over the changed file -> 1 file linted, 0 errors, 0 warnings. The narrowing excludes nothing because eslint.config.mjs states of itself that this repo `runs one eslint.config.mjs, which never enables type-aware linting (no parserOptions.project, no typed @typescript-eslint rules) for ANY file` — with no cross-file type program this diff cannot move the verdict on a file it does not touch. Repo-wide `pnpm lint` is CI's run. All exit codes captured redirect-first; every verdict quoted above is the gate's own printed line, never a bare $?.", "mcp_calls": "0 — the whole run went through git plus repo-scoped REST (session probe green on the first read); no MCP GitHub call was made, including the duplicate scan, which used the REST list endpoint with local grep and a positive control.", "open_questions": [ { "question": "CI-level belt-and-braces the card deliberately left out of this PR: should the workflow jobs pin Corepack's resolution behaviour so no unpinned directory anywhere can ever pull `latest` again?", "options": [ "A — devx-lane follow-up card: set COREPACK_DEFAULT_TO_LATEST=0 (and/or COREPACK_ENABLE_STRICT) on the CI jobs, so an unpinned dir fails loudly instead of silently resolving latest. Note the measured limit: it does NOT repair a store that has already written lastKnownGood = 12.x, so it is a second layer, never a substitute for the pin.", "B — leave it: this PR removes the only unpinned directory CI actually runs pnpm in, so the class is empty today.", "C — a gate that refuses any fixture package.json written without a packageManager, so the next fixture cannot reintroduce it." ], "recommendation": "A as a separate devx card, not a rider here — a p0 fix-forward should change one thing. C is the contract-first version of the same idea and is worth pricing in that card: it makes the mistake structurally hard to rewrite rather than relying on an env var per job, which is the axis this repo's decision frame weights (harder for an AI to get wrong at write time beats tolerance at run time). B undersells it: nothing stops the next throwaway fixture from being written unpinned." }, { "question": "Three open cards describe this one defect (#15992 anchor, #15990 claimed by another session with a pushed branch, #15994 with a contradicted bisect). How should they be closed out?", "options": [ "A — land #16002; PM marks #15990 and #15994 as duplicates of the anchor, closing them and tells session_01ARYe3yQTQCUFm5qPYNgKaJ to stand down before it opens a competing PR.", "B — compare both branches first, in case the sibling's launcher-independence framing covers a case the pin does not." ], "recommendation": "A, with one check from B first: the sibling branch is pushed but has no PR, so a word now costs nothing and a second PR on the same file would collide. On the merits the pin is sufficient — the failure is measured to be a WRONG pnpm being resolved, not an absent one, and both readings are cured by naming the version. #15994's bisect to aa6ba0623 is disproved by my own timing measurement and should not drive a second fix." }, { "question": "Attribution-footer conflict I did not resolve silently: my agent rules specify the `---` rule line plus the italic `_Generated by [Claude Code](...session_ID)_` form for a PR body, while a harness instruction in this session states it replaces earlier attribution guidance and specifies the `🤖 Generated with [Claude Code](https://claude.com/claude-code)` form plus a bare session URL.", "options": [ "A — the harness instruction wins (what I did): it is the most recent operator-level directive and explicitly supersedes prior attribution guidance.", "B — the repo/agent convention wins for repo artifacts." ], "recommendation": "A, and recorded here rather than chosen quietly. No gate reads a PR-body footer (the only in-repo matches are workflow-authored COMMENT footers), so nothing mechanical is at stake either way. Note the platform then appended its own bare `---` + italic block below mine, so #16002 now carries both forms; the body read back 7197 bytes against 7107 sent, i.e. purely the appended block — nothing was eaten by the sanitizer." } ], "out_of_scope_findings": [ "filed as #16007: the SELF_TEST_BATTERIES governance comment in check-regen-pending.mjs transcribes `14 calls` for fixtureSelfTest while the body has 27 (28 after this PR) — and the sibling count in the same sentence (decisionTableSelfTest's `8-row table`) is still correct, so a reader cannot tell which transcribed number to trust in the one block about which numbers are load-bearing. Unassigned, labelled finding/tooling/domain:devx, matching the #15231 and #15291 precedent for this class. Not repaired in this PR: different defect class from the Corepack pin." ] }
Generated by Claude Code
Duplicate-card record (2026-09-05T18:25Z): #15990 (17:44Z,
domain:cliseat, claimed 18:08Z bysession_01ARYe3yQTQCUFm5qPYNgKaJ) is the first-filed anchor for this red check; this card was filed two minutes later without seeing it. #15994 (maintainer-filed 17:54Z, p1) reports the same symptom with a bisect the timing measurement contradicts. PR #16002 carriesFixes #15992andFixes #15994; #15990 is the other session's to close (notepostedthere). No further card.
Generated by Claude Code
Release:
session_01M59rPZZFzqhfMUPFqqZTkf(domain:spec seat, cross-lane takeover) · reason: landed — PR #16002 merged intomainasf50c394daat 2026-09-05T19:14:38Z · destination: closed by the PR (Fixes #15992); nothing further owed on this card.Landing note (2026-09-05T19:15Z). Probe on
origin/mainf50c394da:scripts/check-regen-pending.mjswritespackageManager: rootPackageManagerinto the self-test fixture (1 hit; control 0 atf7db8f4fd), and the self-test's first sequence case pins both halves.mainwas red onLint & Repo Gates › Merge-driver wiring gatefrom ~17:22Z (the pnpmlatest= 12.3.4 resolution in the unpinned fixture) to this merge; the fix's own merge-group run passed that gate before merging, and themainpush run onf50c394dais the confirmation (read at the next patrol). Follow-ups: the belt-and-braces (COREPACK_DEFAULT_TO_LATEST=0/ strict env on CI jobs, or a gate refusing an unpinned fixture manifest) is the devx lane's — recorded in the fix dev's report as open question 1, no card filed by this seat (the devx seat holds #15990); #16007 (a stale count in the gate's governance comment) was filed by the dev. Duplicate cards: #15994 closed by this PR; #15990 (first-filed anchor, another session's claim) is that session's to close — one line left there.
Generated by Claude Code
main is red on
Lint & Repo Gatessince 2026-09-05T17:05Z and the merge queue is blocked for every lane — anchor card per the main-red convention (one failing check, one card; later readers comment here, ⛔ no second card). Filed by thedomain:specexecution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T17:47Z).Symptom (readings 17:38–17:45Z)
pnpm check:merge-driver=node scripts/git-merge-regen.mjs --self-test && node scripts/check-regen-pending.mjs --self-test) fails incheck-regen-pending.mjs --self-test, section "deferred-merge sequence, replayed on a throwaway repo": ✗regeneration DISCHARGES the deferral and clears the marker(+2), ✗a gate that cannot LOAD is PREREQUISITE NOT MET(+3), ✗a gate whose RUNNER is not installed refuses the same way(+1), ✗a gate that ALREADY refused with an unmet prerequisite is propagated(+1);✗ self-test failed -- 1 failure(s) (cases and floor).pushmainaa6ba0623(run 33979882868, job 101343111648, step at 17:26Z),merge_grouppr-15235 (33979941402),merge_grouppr-15967 (33980463305), PRs feat(spec)!: atreefield'sreference, when present, must name the declaring object — refused at parse otherwise (#14892) #15979 (33980257436), InlineI18nLabelmaps are invisible toos i18n extractandcheck:i18n-coverage— should the extractor and the coverage gate see them? (objectstack#14412 ruling A follow-up) #14749 (33980432580),service-cluster-redis's contract test runs ioredis-mock@8 (peerioredis@^5) against a package that depends onioredis@^6, with the import seam suppressed by @ts-expect-error #15467 (33980643121). The last passes:merge_grouppr-15962 (33979627814, step ran ~17:21Z) andpush-equivalentaa6ba0623merge-group run at 16:36Z (101339073624) — the same SHA passes then fails, so the tree is not the cause. Runner git is 2.55.0 on both sides; node 22.23.2 on both.aa6ba0623(git 2.43.0, pnpm 10.31.0 on PATH, Corepack not consulted) the gate exits 0.Root cause (reproduced locally, 17:44–17:46Z)
check-regen-pending.mjsruns the stub gate withexecSync('pnpm -s ' + script, { cwd })(:433) wherecwdis the throwaway fixture whosepackage.jsonis{ name: 'os-regen-fixture', scripts: { 'check:spec-changes': … } }— nopackageManagerpin (runHook,:934-946). CI runs pnpm through Corepack (.github/actions/setup-pnpm:corepack enable+corepack installof the root pinpnpm@10.31.0). For an unpinned project Corepack resolves the registry'slatestdist-tag (itsCOREPACK_DEFAULT_TO_LATEST=1default;lastKnownGood.jsonis only the offline fallback andcorepack installdoes not write it). The npmlatesttag ofpnpmnow reads 12.3.4 (npm view pnpm dist-tagsat 17:45Z; publish time of 12.3.4: 2026-09-04T14:20:10.390Z | 12.0.0: 2026-08-26T15:12:06.912Z | 11.25.0: 2026-08-29T14:17:49.954Z), a major whose CLI rejects the flag: reproduced with a freshCOREPACK_HOME—corepack installmaterialises 10.31.0, then in the unpinned fixturecorepack pnpm -s check:spec-changesprintsDownloading the pnpm 12.3.4 binary for linux-x64...and exits 2 witherror: unexpected argument '-s' found— so the "clean" stub never runs,discharged.code !== 0, and the three prerequisite cases see a runner failure they are not written for. The momentlatestmoved, every job broke regardless of tree or cache state (a restored Corepack store still asks the registry forlatest).Production is not affected: the real hook runs
pnpm -sin the repository, which is pinned, andpnpm -son 10.31.0 is fine. Only the self-test fixture is unpinned.Fix (mechanical, one file, verified locally)
In
scripts/check-regen-pending.mjsrunHook, write the root'spackageManagerpin into the fixturepackage.json(read it from the repo root'spackage.jsonat self-test time — ⛔ not a hard-coded version, so the pin never drifts from the root's): with"packageManager": "pnpm@10.31.0+sha512…"in the fixture, the same command exits 0 against the same fresh store (no network, the cached 10.31.0 runs).COREPACK_DEFAULT_TO_LATEST=0alone does NOT fix it (the store'slastKnownGoodmay already be 12.x — measured). Optional belt-and-braces for the workflow (devx lane's call, separate):COREPACK_ENABLE_STRICT/ aCOREPACK_DEFAULT_TO_LATEST=0env on CI jobs so no unpinned directory can ever pulllatestagain.Landing point:
scripts/check-regen-pending.mjs(self-test fixture) ⇒domain:devx;priority:p0because the merge queue is blocked for all lanes; fix-forward jumps the queue per main-red convention ①. Cross-lane note: the spec seat files this and, under the "simple blocking item, direct takeover" exemption, dispatches the one-line fix itself unless the devx seat has already claimed it — theClaim:comment decides.Generated by Claude Code