Skip to content

[Decision] What should the scaffolded pnpm-workspace.yaml declare under packages:? Measured: no engines floor can reach pnpm 10.0–10.4, which parse the file before reading engines #10933

Description

@os-elon

Filed unassigned from the domain:cli lane execution seat (session session_019bmVFqoQPq63zhKrxdYG1r), on the path triage prescribed for exactly this outcome:

Only if a floor is rejected does the packages: decision matter, and that would come back as a decision card, not a unilateral pick. — #10497 triage, 5365563810

This is a decision about what the scaffolder writes into every new project, so it is the maintainer's. No seat has picked a shape and none will.

Why the cheap route did not close it — measured, not assumed

#10497 took the sanctioned route: pin an engines.pnpm floor so the failing pnpm band becomes unreachable. PR #10932 does that (>=10.15, both scaffold paths). It works for most of the band and provably cannot reach a sliver:

pnpmbehaviour after PR #10932
10.0.0 – 10.4.0still prints the raw ERROR packages field missing or empty — these versions parse pnpm-workspace.yaml before they read engines, so the floor is never consulted
10.5.0 – 10.14.0now refuse with ERR_PNPM_UNSUPPORTED_ENGINE, naming the expected range
10.15.0+installs unchanged

⭐ The 10.0–10.4 boundary was bisected across every minor from 10.1.0 to 10.13.0 — not inferred from the two endpoints the original card measured. And the conclusion is structural rather than a tuning problem: no floor value reaches that sliver, because those versions never arrive at the engines check on this code path. Raising the floor higher changes nothing about it.

So the only thing that can close it is the packages: key itself — which is this card.

The decision

The scaffolded pnpm-workspace.yaml deliberately omits packages: today. renderPnpmWorkspaceYaml() in packages/cli/src/commands/init.ts says so in its own comment ("Kept minimal (no packages: key) so it acts purely as a settings file"), and packages/create-objectstack/src/templates/blank/pnpm-workspace.yaml omits it too.

The options are not a typo fix — they are different statements about what a scaffolded project is:

  • packages: [] — an explicit empty workspace. Satisfies early pnpm 10, says "this is a workspace root with no member packages".
  • packages: ['.'] — the project itself is the single member. Also satisfies early pnpm 10, but declares the root a workspace member, which changes how pnpm treats it.
  • Leave it omitted — accept that pnpm 10.0–10.4 cannot install a scaffolded project, on the grounds that the band shipped Jan–Feb 2025, is narrow, and (after fix(cli): declare a pnpm floor in the scaffolded package.json #10932) is the only remaining case that fails without a diagnostic.

⛔ I am not recommending one. What I can supply is the constraint the measurement adds: the third option is now materially better than it was before #10932, because 10.5–10.14 stopped failing confusingly. The residue is smaller and louder than the original card described.

A rejected alternative, measured — worth reading before choosing

The #10497 dev also measured packageManager (the corepack stamp) as an alternative to engines.pnpm, and rejected it on evidence:

  • it auto-switches, so 10.5–10.14 would succeed rather than refuse — strictly stronger on that range;
  • but it still buys nothing on 10.0–10.4;
  • it would declare the project pnpm-only, while objectstack init deliberately hands off to npm / yarn / bun (which ignore engines.pnpm entirely);
  • and it pins an exact version that goes stale on every pnpm release.

⭐ A test now pins that choice, so the reasoning cannot be silently reversed by a later edit. If the maintainer disagrees with the trade, that test is the thing to change — deliberately.

Sequencing note (routing input, not a decision)

Three open cards land in the same rendered pnpm-workspace.yaml and are hard-serial against each other in this seat:

⚠️#10499 is the one that makes the other two recur: as long as two paths render the rule separately, any decision taken here has to be applied twice and can drift again. Whoever grades these may want that ordering considered.

Scope

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions