Skip to content

build: replace pnpm with Bun for package management #1469

Description

@FelixTJDietrich

Outcome

Use Bun as the repository package manager for 1.0 while retaining Node 24 as the runtime for Vite, Vitest, Storybook, Playwright and Node-based scripts. Bun is already the runtime for the agent trees; this migration removes pnpm after the formatter dependency topology is final.

Existing evidence

A Bun 1.4.0 dry run previously produced:

Scenario Bun pnpm 11.22.0
Cold install 3.72s 20.43s
Warm install without node_modules 0.31s 2.71s
Installed tree 1.7 GB 2.5 GB

The full typecheck, Vite build, 932 webapp unit tests, 1,496 Storybook browser tests and Biome 2.5.9 completed in that audit.

Version policy

Pin the latest officially verifiable stable Bun release at implementation time. Keep the exact version in one source of truth and verify Docker/action configuration against it. Do not pin a version that cannot be independently confirmed from Bun's official releases.

Do not use automatic pnpm-workspace.yaml migration. Translate workspaces, overrides and policy manually into reviewed package.json/bunfig.toml, then generate bun.lock from that state.

Controls that must survive

  • isolated linker;
  • frozen text lockfile;
  • minimum release age consistent with repository/Renovate policy;
  • deny-by-default lifecycle scripts with an explicit trusted set;
  • explicit peer-dependency behavior;
  • supported Linux/macOS and x64/arm64 optional/native packages;
  • immutable setup-action pin and exact Bun version;
  • verified Docker installation rather than a floating installer;
  • an explicit replacement for, or documented acceptance of, pnpm's exotic-dependency/lockfile policy controls.

Node remains the runtime; Bun is the package manager and existing agent runtime.

Determinism qualification

From the committed bun.lock:

  • run 25 clean bun install --frozen-lockfile installs on Linux x64;
  • run 25 on Linux arm64;
  • inspect nested resolved versions for every override/alias collision, not only root hoists;
  • assert the lockfile remains byte-identical and no frozen install mutates it.

Done when

  • build(java): migrate Java formatting to Spotless and palantir-java-format #1464 and build(webapp): replace Biome formatting with oxfmt #1475 have landed, so the final lockfile is generated once from the intended 1.0 dependency topology.
  • Workspace, override, peer, lifecycle, release-age and platform behavior is deliberately represented.
  • Determinism qualification passes on x64 and arm64.
  • Root check, webapp unit, Storybook, E2E, docs, production build, generation, release/changeset and Docker paths pass.
  • Bun version consistency is checked across package metadata, CI and Docker.
  • No active command or contributor documentation invokes pnpm.
  • Lost supply-chain controls are replaced or explicitly accepted with rationale.
  • A rollback path is documented.

Sequencing

Execute last in the pre-1.0 tooling wave, after #1464 and #1475. Large call-site churn is acceptable before 1.0; dependency-resolution and supply-chain regressions are not.

References:

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciGitHub Actions, workflows, build pipeline changesdependenciesPackage updates, version bumps, lock file changesmaintenanceChores, cleanup, non-functional improvementssize:MThis PR changes 30-99 lines, ignoring generated files.status:blockedBlocked by external dependency or other issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions