This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
tooling(pin): commit the pin's packed manifests so a lockfile-only resolution needs no build (objectui#13008) - #13031
Merged
objectstack-fleet[bot] merged 4 commits intoOct 19, 2026
Conversation
…solution needs no build (objectui#13008) Every @objectstack/* override now names `.objectstack-pin/NAME`, a committed directory holding only that package's packed package.json at the pin. `objectstack-pin.mjs build` still builds into node_modules/.cache/objectstack (CI caches that path) and hard-links the rest of the build beside the manifests. A build at the pin refuses when a committed manifest is not the pin's; a stand-in writes its own and the next pin build restores them. The root preinstall refuses an install with no build beside the manifests. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…manifests with it (objectui#13008) The bump runs `objectstack-pin.mjs build --write-manifests` after writing .objectstack-sha (with OBJECTSTACK_ROOT unset, so the checkout it read does not stand in), restores the old pin byte for byte when that build fails, and commits .objectstack-sha with .objectstack-pin. Tests cover the manifest policy (pin refuses drift, stand-in residue is restored and nothing else), the install check, and the lockfile key spelling the rename moved in check-lockfile-integrity's samples. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…ectui#13008) Measured on a clean clone: a second build of the same pin packed @objectstack/client and @objectstack/lint with the same values in a different dependency-key order (pnpm pack rewrites workspace: ranges as they complete), and the byte comparison refused it. Manifests are now committed and compared in a canonical form that sorts the dependency maps and moves nothing else; an equal committed manifest is left byte for byte. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…sts (objectui#13008) Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contributor
Author
|
ACCEPT · objectui
Landing: ready → auto-merge (squash) → merge queue. Generated by Claude Code |
objectstack-fleet
Bot
deleted the
claude/issue-13008-pin-lockfile-resolvable
branch
October 19, 2026 08:49
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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 #13008
Option B, measured and built. Every
@objectstack/*override now namesfile:.objectstack-pin/NAME, a committed directory that holds one file per package: its packedpackage.jsonat the pin. A lockfile-only resolution, which is what Dependabot runs on a fresh clone, now needs no build.scripts/objectstack-pin.mjs buildstill builds intonode_modules/.cache/objectstack, the path CI caches by the pin and whose stamp turbo hashes. It then hard-links the rest of each packed package beside its committed manifest (git-ignored, with a copy where a link fails). No workflow changes, and no new gate.Done when, item by item
git clone --depth 1of this branch's headcd2035a(nonode_modules, pnpm 10.31.0), with the command Dependabot's job ran (run 39180936608, read from its log):pnpm update next@16.3.8 --lockfile-only --no-save -r --config.minimum-release-age=0→ exit 0.nextmoved to 16.3.8, zero@objectstacklines moved, and nonode_moduleswas created.pnpm run setup→ exit 0. That clone did its own cold build of the pin.pnpm install --frozen-lockfile→ exit 0, thengit diff --exit-code pnpm-lock.yaml→ exit 0, andgit statuswas clean.mainat4484a11→ exit 1,ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND ... node_modules/.cache/objectstack/client. That is the job's own failure, reproduced.OBJECTSTACK_ROOTstand-in (measured below), andscripts/bump-objectstack.shwriting the manifests with the pin. No guarantee breaks, so A was not built./onmainafter this lands to succeed, with its run id recorded. The stand-in for that run is item 1's clean-clone measurement above.@objectstack/*resolves from npm. The lockfile has 0@objectstack/NAME@VERSIONkeys and 14@objectstack/NAME@file:.objectstack-pin/keys. The control pattern (azod@VERSIONkey) hits 4, so the count was a real reading.checkOverrideSetis unchanged. The objectui#12957 tests stay green: the wholescripts/vitest set passes atcd2035a(189 files passed, 2 skipped).What changed
.objectstack-pin/NAME/package.json(7 files) holds the packed manifests at the pin..gitignoretracks only those files there.eslint.config.jsignores.objectstack-pin, because the spec packs its TypeScriptsrc/.scripts/objectstack-pin.mjsmaterialize()puts the build beside the committed manifests.canonicalManifest()is the committed form; why it exists is below.build --write-manifestswrites the manifests for the pin as it stands.checksubcommand runs as the rootpreinstall.statusalso reports a hollow.objectstack-pin.file:.objectstack-pin/.scripts/bump-objectstack.shobjectstack-pin.mjs build --write-manifests, withOBJECTSTACK_ROOTunset so the checkout it read does not stand in..objectstack-shatogether with.objectstack-pin.pnpm-lock.yaml: a pure path rename. Aftersed 's#node_modules/.cache/objectstack/#.objectstack-pin/#',main's lockfile diffs to nothing against this one (exit 0).scripts/__tests__/check-lockfile-integrity.test.tsbuilds its samples from the real lockfile by its literal snapshot keys, so it would go red.scripts/check-lockfile-integrity.mjsandscripts/check-installed-spec-pin-claims.mjs.scripts/__tests__/ci-cd-pipeline-doc.test.ts.content/docs/guide/ci-cd-pipeline.md.Mechanism hypotheses: readings
4484a11, re-measured: seven overrides at the cache form,setup= build then frozen install,CACHE_DIR, theOBJECTSTACK_ROOThook,pnpm@10.31.0, and.objectstack-sha=2c9bf9430a11.file:directory resolves from itspackage.jsonalone (item 1).file:directory's files at install time: the same inode, link count 2, innode_modules/.pnpm. So the build must be in place before the install, whichsetupalready does: build first, then install.pnpm updateandpnpm install --lockfile-only) does not run the rootpreinstall. A marker file stayed empty. Its control, a real install, wrote the marker and exited 1.distis not followed. pnpm linked only themainfile of a symlinked directory, so links have to be per file.setuprefused because a second build of the same pin packed@objectstack/clientand@objectstack/lintwith every value equal and the dependency keys in a different order. The likely cause ispnpm packrewritingworkspace:ranges as they complete.canonicalManifestform: dependency maps sorted, nothing else moved, because the order ofexportsconditions carries meaning. Three independent packs of the pin now agree: this worktree's and two clean clones'.--write-manifests(and sobump-objectstack.sh) writes them.buildsubcommand, theOBJECTSTACK_ROOThook, theobjectstack:buildscript and the virtual-store prefix@objectstack+spec@that spec-shape-gate's inject step looks for are all kept.maine11ae4b:OBJECTSTACK_ROOT=TREE node scripts/objectstack-pin.mjs build→ exit 0. The 7 manifests show as modified, and the stamp isexternalwithreplacedrecorded.pnpm install --frozen-lockfile→ exit 0, lockfile diff exit 0.node scripts/objectstack-pin.mjs build(back to the pin) → exit 0, andgit statusis clean again.pnpm install --frozen-lockfile→ exit 0, lockfile diff exit 0.OBJECTSTACK_ROOT=/home/user/objectstackbuild → exit 1,ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL. That checkout is neither installed nor built, which is the precondition the script documents. Nothing was written there (git status --ignoredis the same before and after).materialize()takes its source directory as an argument, so a shared build is one morefrom. One cost to note: across filesystems the hard link falls back to a copy (the spec is about 184 MB).Choices I settled (four-axis frame)
--write-manifests, called by the bump.preinstall=objectstack-pin.mjs check).pnpm installwithout the build dies withENOENT. With B and no check, it would exit 0 and link packages that hold only a manifest, which fail later as module-not-found. Agents run a barepnpm installin fresh worktrees routinely.pnpm run setup), and the refusal names that command.preinstallline to drop it..objectstack-pin/, not tracked files insidenode_modules/.cache/objectstack. In the latter, CI's cache restore would overwrite the committed manifests before the drift check could read them.Files, line budget, changeset, governance
pnpm-lock.yamland the generated manifests: +402 −76 = 478, against the card's budget of about 300.pnpm pack, then canonicalised). The lockfile is +113 −113, all path rename.node scripts/check-changeset-presence.mjssays none is owed, because no released package's source or contract changed. This matches objectui#13024.node scripts/check-governed-queue-guard.mjs --testover the 20 changed paths answers NOT GOVERNED.Acceptance notes (not filed; the seat decides)
AGENTS.md§9's dependency and lockfile section (the override value, and theENOENTtext after removingnode_modules), and the comments on the pin-cache steps in.github/workflows/ci.yml,lint.yml,lockfile-dedupe.ymlandchangeset-release.yml. The cache step itself is still right.scripts/build-console.shand.github/workflows/spec-shape-gate.ymlstill namefile:node_modules/.cache/objectstack/NAME. Their behaviour is unchanged (measured above).scripts/check-lockfile-dedupe.mjsstill requires the pin's build stamp before it reads. Under B a dedupe resolution no longer needs the build, so that precondition is now stricter than it has to be. It is not wrong.apps/console/vercel.json. ItsinstallCommandis a barepnpm install --frozen-lockfilewith no pin build. It has failed since objectui#12957 (ENOENT) and still refuses here (in thepreinstall). Inferred from reading the file only: no deploy log was read./.objectstack-pin/NAMEafter landing.scripts/run timed out once, indollar-dialect-alias-census.test.ts(15 s, an ablation case), on a shared box. It passed alone and in the final full run. It is not related to this change.Generated by Claude Code