Repository navigation
fix(create-objectstack,cli): the scaffolded pnpm-workspace.yaml is one comment line per block, and both scaffold paths write the same bytes - #22229
Conversation
…e comment line per block, and both scaffold paths write the same bytes The blank template carried 66 comment lines and the os init / os create render 57, each explaining measurements and version history the new project's reader does not decide. Both now emit the same 21-line file: the four configuration blocks unchanged, each under one comment line naming its reason. The facts the two files carried that the init.ts docblocks did not (esbuild's role, better-sqlite3 as driver-sql's optional dependency, the 2026-09-11 better-auth 1.7.3 re-read) move into those docblocks. scaffold-workspace-consistency.test.ts gains two limbs: the two producers render the same bytes, and each stays within one comment line per block, directly above its key, inside 80 columns. Its per-key version-boundary limb reads the new one-line shape. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWZbGvPFcRKvUqASZtunCU
📓 Docs Drift CheckThis PR changes 2 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 28 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 139a81292d6bb3a00b5a0d5ce6a39cda4decfac3 && git checkout 139a81292d6bb3a00b5a0d5ce6a39cda4decfac3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7b926f76007316ec13d2b17ec4b0a316b94e4d7e e95920e028bf731347515a3a613f3cacd5752175 && git checkout -B drift-repro 7b926f76007316ec13d2b17ec4b0a316b94e4d7e && git merge --no-ff e95920e028bf731347515a3a613f3cacd5752175
node scripts/docs-audit/affected-docs.mjs --json 7b926f76007316ec13d2b17ec4b0a316b94e4d7e
|
Fixes #22162
Clause-②: no
A new project's
pnpm-workspace.yamlis now a 21-line settings file. Both scaffold paths,npm create objectstackandobjectstack init/ a standaloneobjectstack create, write the same bytes. The four configuration blocks are unchanged, and each now has one comment line naming its reason. The measurements and version history the file used to carry now live in theinit.tsdocblocks, next to the values they explain.Readings (on
origin/main7d7943dd, then on this branch's head)create-objectstackblank templaterenderPnpmWorkspaceYaml()(os init, standaloneos create)cmpexit 0)H1, the two outputs before: not byte-identical (first difference at line 10, byte 501). The configuration was identical: with comments stripped and blank lines dropped, both sides hash to sha256 prefix
9992ee6451e59720. Both sides still hash to that prefix after the change.os initandos createcall the same renderer. The BEFORE render was taken through the realinit.tsimport; a source-extraction instrument rendered the same bytes (cmpexit 0), and that instrument is what rendered BASE afterwards.H2, the configuration stays as it is: held. Keys, values and order are unchanged. Every comment-stripped configuration assertion in
init.test.ts,template-consistency.test.tsandcreate.test.tspasses without an edit.One PM reading is partly false: the consistency tests did not assert configuration only.
scaffold-workspace-consistency.test.ts's second limb, "states the same pnpm version boundary for each key", reads the PROSE. It parsed a# allowBuilds ...definition list out of the header comment and required each producer to name a dotted pnpm version for each approval key. A one-line comment does not have that shape. I kept the assertion and adapted its reader to the one-line shape: it reads the comment line directly above each key, still requires a version from each producer, and still compares the two. That is why the two approval lines name10.0–10.25and10.26.H3, where the rationale went: each fact is now next to the value or test that owns it.
packages:key: pnpm 9.x and 10.0–10.4 refuse the file without it; not['.']renderPnpmWorkspaceYamldocblock andSCAFFOLD_PNPM_RANGEdocblock (already there);init.test.tsandtemplate-consistency.test.tscomments (already there)allowBuildsversusonlyBuiltDependencies; pnpm 11's hard errorrenderPnpmWorkspaceYamldocblock, per-version table (already there)driver-sql's optional dependency; esbuild compilesobjectstack.config.tsSCAFFOLD_BUILT_DEPENDENCIESdocblock (added; checked againstdriver-sql'soptionalDependenciesand the CLI'sbundle-requireloader)SCAFFOLD_BUILT_DEPENDENCIESdocblock (already there)SCAFFOLD_ALLOWED_PEER_VERSIONSdocblock (already there)SCAFFOLD_ALLOWED_PEER_VERSIONSdocblock (added)@better-auth/*utils skews, the symbols measured, and their retirement at the pnpm 10.31 floorSCAFFOLD_ALLOWED_PEER_VERSIONSdocblock (already there)@better-auth/scim>better-callentry and its datesSCAFFOLD_ALLOWED_PEER_VERSIONSdocblock and inline note (already there); its absence is pinned in both packagesSCAFFOLD_ALLOWED_PEER_VERSIONSdocblock (already there)The
renderPnpmWorkspaceYamldocblock now maps each block to the docblock that holds its reasons. The note intemplate-consistency.test.tsabove the workspace blocks points there as well.pkg-utils.tswas named as a candidate home. It only syncs the@objectstack/*ranges and owns none of these facts, so nothing moved there. No docs page was added (the seat's scope cut), and no link was needed.H4, both scaffolders render the same file: they do now, byte for byte, and a new limb holds it (below).
H5, size ranking in a scaffolded project: I scaffolded with
--skip-install --skip-skillsfrom the BASE build and from this branch's source. Before, the 22 files ranked: README.md 6,491, AGENTS.md 5,514,.github/copilot-instructions.md5,514 (a byte copy of AGENTS.md), pnpm-workspace.yaml 4,700, objectstack.config.ts 4,032. That is 4th by bytes, and 3rd as the card counted it, with the AGENTS.md copy folded in. After, pnpm-workspace.yaml is 722 bytes and ranks 10th of 22. The scaffolded file is byte-identical to the template in both runs.Two departures from the card's sketch, both forced by existing pins
^\s*#.*$). An inlinepackages: [] # ...failsdeclares it EMPTY(the reader sees[] # ...), and an inline comment onallowBuilds:breaks the^allowBuilds:\nblock readers.packages,onlyBuiltDependencies,allowBuilds,peerDependencyRules. The sketch swapped the middle two. Theadds no other top-level settingtests pin this order in both packages, and H2 keeps it.New pins (
packages/cli/test/scaffold-workspace-consistency.test.ts)renders the same bytes in both scaffold paths:renderPnpmWorkspaceYaml()equals the template file, byte for byte. This also ends the drift class seen in [finding] The scaffoldpnpm-workspace.yamlthatobjectstack initrenders still explains the RETIRED@better-auth/scim>better-callpeer rule as if it were live — and both consistency tests strip comments before asserting, so no gate reads it #17093, where prose that nothing compared shipped wrong in one of the two files. There is now one text to keep true.%s carries at most one short comment line per block, run for each producer. Every line containing#must be a full-line comment directly above a top-level key, at most 80 columns wide. Two comment lines in a row break the rule, and so does a comment inside or after a setting. Why a width and not a line cap: a line count alone lets one block spend what the others save, and a one-line rule with no width lets a single line hold a paragraph. The pair bounds the comment to a few hundred bytes. No value in this file can contain#(package names, versions,true), so any#is a comment.Ablation (one-time; no permanent test file)
Run from the committed fix (
e95920e0). Each leg wrote BASE's bytes over one file and checked that the write landed (on-disk blob hash equals the BASE blob, old anchorAn explicit EMPTY workspacecounted 1, new anchorOlder pnpm needs this keycounted 0). It then ran the suite and restored withgit checkout HEAD --under anEXIT INT TERMtrap. The restore was checked by hash (on-disk blob equals the HEAD blob), withgit diff HEADempty andgit statusclean. Both subjects resolve to source: the template is read withfsfromsrc/, and the renderer is imported from../src. Nodistsits in the path, so neither leg needed a rebuild. The direction was predicted before each run, and the observed result matched.npx create-objectstackcomment budget (66 breaches: 65 lines not directly above a key, plus old line 17 at 81 columns); per-key version boundary (the old template has a blank line above each approval key)objectstack initbudgetobjectstack initcomment budget (54 breaches); per-key version boundarynpx create-objectstackbudgetIn both legs, the one old comment line that already sat directly above
packages: []was correctly not flagged.Tests (head
e95920e0)pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2: 261 of 263 files passed and 3848 tests passed (29 skipped). The other 2 files (published-subpath-console.pin,published-subpath-hook-body.pin) refused with "packages/cli is not built", a prerequisite and not a verdict. I built the CLI and re-ran them: 2 files and 29 tests passed. Theintegrationtier is left to CI: the diff touches no integration file and no spawn entry point.pnpm --filter create-objectstack test: 16 files, 249 tests passed.pnpm --filter @objectstack/cli typecheck(tsc --noEmitpluscheck:test-typecheckovertsconfig.test.json, which coverstest/): exit 0, "3 file(s) / 28 error(s) / 6 pinned signature(s) held", unchanged.pnpm --filter create-objectstack typecheck: exit 0. Itsincludeissrc, so it covers the edited test.Gates
All at head
e95920e0. I derived the list withnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsfrom the delivered change set (5 paths against merge base7d7943dd). It is the same 68 commands as the dispatch list. I addedpnpm lintand recorded each exit code before any pipe.dispatch-gates --ranreports "68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN" and "a DERIVED zero — all 68 recorded an exit code and none of them is 3".pnpm lintis listed as outside the derivation.pnpm lint(eslint . --no-inline-config, the whole repo): exit 0, no findings printed.check:dual-build-cjs-loads,check:i18n,check:i18n-coverageandcheck:i18n-walk-parity. I built the workspace (turbo run build, exit 0) and re-ran them, all exit 0:dist-reading gates (check:published-files,check:dts-closure,check:lean-entry-closure,check:sourcemap-no-sources-content) were re-run on the fresh build, all exit 0.Acceptance notes
SCAFFOLD_BUILT_DEPENDENCIESdocblock, which both say that without the build better-sqlite3 ships no usable binding andservefails with "Could not locate the bindings file". I did not re-measure which one is right. Dropping it from the user's file removes the contradiction either way, and the docblock keeps its own measured statement.@better-auth/scim>better-callretirement and its dates, and the dated re-reads. [finding] The scaffoldpnpm-workspace.yamlthatobjectstack initrenders still explains the RETIRED@better-auth/scim>better-callpeer rule as if it were live — and both consistency tests strip comments before asserting, so no gate reads it #17093 (closed) and the docblocks keep them.scaffold-workspace-consistency.test.tsheader said the prose was "NOT compared ... on purpose". That design is superseded by the ruling that both paths render one file. The header now says so and gives the reason.origin/maingained 4 commits since7d7943dd(b8feb550,35396b5e,3b493184,7b926f76). None of them touchespackages/cliorpackages/create-objectstack, so no merge was taken here, and CI's merge ref covers the joint state.Files
packages/create-objectstack/src/templates/blank/pnpm-workspace.yaml: the 21-line file.packages/cli/src/commands/init.ts: the renderer emits the same 21 lines; its docblock maps blocks to reasons;SCAFFOLD_BUILT_DEPENDENCIESandSCAFFOLD_ALLOWED_PEER_VERSIONSgain the facts only the old files carried.packages/cli/test/scaffold-workspace-consistency.test.ts: the two new limbs, the one-line version reader, and the header.packages/create-objectstack/src/template-consistency.test.ts: a pointer note to where the reasons live (comment only)..changeset/22162-scaffold-workspace-minimal.md:create-objectstackpatch and@objectstack/clipatch (the rendered output ofos init/os createchanges).Generated by Claude Code