Skip to content

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

@claude

main is red on Lint & Repo Gates since 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 the domain:spec execution seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T17:47Z).

Symptom (readings 17:38–17:45Z)

Root cause (reproduced locally, 17:44–17:46Z)

check-regen-pending.mjs runs the stub gate with execSync('pnpm -s ' + script, { cwd }) (:433) where cwd is the throwaway fixture whose package.json is { name: 'os-regen-fixture', scripts: { 'check:spec-changes': … } } — no packageManager pin (runHook, :934-946). CI runs pnpm through Corepack (.github/actions/setup-pnpm: corepack enable + corepack install of the root pin pnpm@10.31.0). For an unpinned project Corepack resolves the registry's latest dist-tag (its COREPACK_DEFAULT_TO_LATEST=1 default; lastKnownGood.json is only the offline fallback and corepack install does not write it). The npm latest tag of pnpm now reads 12.3.4 (npm view pnpm dist-tags at 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 fresh COREPACK_HOME — corepack install materialises 10.31.0, then in the unpinned fixture corepack pnpm -s check:spec-changes prints Downloading the pnpm 12.3.4 binary for linux-x64... and exits 2 with error: 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 moment latest moved, every job broke regardless of tree or cache state (a restored Corepack store still asks the registry for latest).

Production is not affected: the real hook runs pnpm -s in the repository, which is pinned, and pnpm -s on 10.31.0 is fine. Only the self-test fixture is unpinned.

Fix (mechanical, one file, verified locally)

In scripts/check-regen-pending.mjs runHook, write the root's packageManager pin into the fixture package.json (read it from the repo root's package.json at 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=0 alone does NOT fix it (the store's lastKnownGood may already be 12.x — measured). Optional belt-and-braces for the workflow (devx lane's call, separate): COREPACK_ENABLE_STRICT / a COREPACK_DEFAULT_TO_LATEST=0 env on CI jobs so no unpinned directory can ever pull latest again.

Landing point: scripts/check-regen-pending.mjs (self-test fixture) ⇒ domain:devx; priority:p0 because 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 — the Claim: comment decides.


Generated by Claude Code

Activity

  1. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    Claim: PM loop round R2 — domain:spec seat, session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T17:48Z. One dev, branch claude/issue-15992-regen-selftest-fixture-pin, mode:subagent, tier claude-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:devx card 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 in scripts/check-regen-pending.mjs (the self-test fixture's package.json gains the root's packageManager pin, 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, its Claim: 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 touches scripts/check-regen-pending.mjs.


    Generated by Claude Code

  2. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    Review — ACCEPT (domain:spec seat under the simple-blocking-item takeover, session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T18:18Z; PR #16002 at head b101c2e05, Clause-② no). One file, scripts/check-regen-pending.mjs (+45/−1): runHook writes the ROOT manifest's packageManager into the throwaway fixture's package.json (read from REPO_ROOT/package.json at 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 -s in this repository, :433) is untouched; no workflow, action or governed surface moved; no changeset (root scripts/). 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, so Merge-driver wiring gate goes green there. Follow-up left to the devx lane as the report's open question: a COREPACK_DEFAULT_TO_LATEST=0 / strict env on CI so no unpinned directory can pull latest again.


    Generated by Claude Code

  3. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    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

  4. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    Duplicate-card record (2026-09-05T18:25Z): #15990 (17:44Z, domain:cli seat, claimed 18:08Z by session_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 carries Fixes #15992 and Fixes #15994; #15990 is the other session's to close (note posted there). No further card.


    Generated by Claude Code

  5. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    Release: session_01M59rPZZFzqhfMUPFqqZTkf (domain:spec seat, cross-lane takeover) · reason: landed — PR #16002 merged into main as f50c394da at 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/main f50c394da: scripts/check-regen-pending.mjs writes packageManager: rootPackageManager into the self-test fixture (1 hit; control 0 at f7db8f4fd), and the self-test's first sequence case pins both halves. main was red on Lint & Repo Gates › Merge-driver wiring gate from ~17:22Z (the pnpm latest = 12.3.4 resolution in the unpinned fixture) to this merge; the fix's own merge-group run passed that gate before merging, and the main push run on f50c394da is 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:devxpriority:p0Critical: blocker, must ship before MVP

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions