Found while fixing the os create example scaffold's manifest (PR #14821). Out of that card's scope — a different defect class from the manifest one — so filed rather than fixed, and unassigned.
Measured, on origin/main8f9ef6f7c8
packages/cli/test/init-template-comments-self-contained.test.ts renders its population from exactly one source:
import{TEMPLATES,sanitizeNamespace,writeTemplateSrcFiles}from'../src/commands/init.js';
...
for(consttemplateKeyofObject.keys(TEMPLATES)){ ... }packages/cli/src/commands/create.ts exports a second, independent template map (templates), whose example entry renders an objectstack.config.ts as an in-source string literal and writes it straight into the user's project — the same emitter shape, the same "text a scaffolded project actually receives" population that pin's own header defines. Nothing reads it.
The three assertions that pin holds for init therefore hold for init only:
- no monorepo-only reference (ADR identifiers, issue numbers) in text that ships to a reader who has just their own project;
- the rationale each comment carries is still stated (the half that stops the cheap fix of deleting the comment);
- every canonical-origin docs URL in the rendered output resolves against the docs content tree.
Why this is worth a pin rather than a note
It is the same defect class the pin already closes, one scaffolder over — and the create template now ships more comment text than it used to. PR #14821 adds a protocol-range comment to that template, copied verbatim from init's (so it is self-contained today, and its https://objectstack.ai/docs/upgrading link is one the existing pin already checks). Nothing keeps that true: an edit to create.ts's literal that cites an ADR, or links a docs page that later moves, ships to every os create example user with every gate green.
The same gap applies to the plugin template's src/index.ts and README.md literals, which also ship as project text.
Shape of the fix
Widen the pin's renderAll() to a two-source population, the way packages/cli/test/scaffold-manifest-schema.test.ts (added in #14821) derives its sweep from both TEMPLATES and create.ts's templates. create has no configContent / srcFiles split — every file it writes lives in one files map keyed by its destination path, rendered by calling the entry — so the emitter half is a few lines; the three assertions are reused unchanged.
Generated by Claude Code
Found while fixing the
os createexample scaffold's manifest (PR #14821). Out of that card's scope — a different defect class from the manifest one — so filed rather than fixed, and unassigned.Measured, on
origin/main8f9ef6f7c8packages/cli/test/init-template-comments-self-contained.test.tsrenders its population from exactly one source:packages/cli/src/commands/create.tsexports a second, independent template map (templates), whoseexampleentry renders anobjectstack.config.tsas an in-source string literal and writes it straight into the user's project — the same emitter shape, the same "text a scaffolded project actually receives" population that pin's own header defines. Nothing reads it.The three assertions that pin holds for
inittherefore hold forinitonly:Why this is worth a pin rather than a note
It is the same defect class the pin already closes, one scaffolder over — and the
createtemplate now ships more comment text than it used to. PR #14821 adds a protocol-range comment to that template, copied verbatim frominit's (so it is self-contained today, and itshttps://objectstack.ai/docs/upgradinglink is one the existing pin already checks). Nothing keeps that true: an edit tocreate.ts's literal that cites an ADR, or links a docs page that later moves, ships to everyos create exampleuser with every gate green.The same gap applies to the
plugintemplate'ssrc/index.tsandREADME.mdliterals, which also ship as project text.Shape of the fix
Widen the pin's
renderAll()to a two-source population, the waypackages/cli/test/scaffold-manifest-schema.test.ts(added in #14821) derives its sweep from bothTEMPLATESandcreate.ts'stemplates.createhas noconfigContent/srcFilessplit — every file it writes lives in onefilesmap keyed by its destination path, rendered by calling the entry — so the emitter half is a few lines; the three assertions are reused unchanged.Generated by Claude Code