chore(bindings): migrate pnpm→bun package management; Bun 1.4.0; deps latest stable - #27
Merged
Merged
Conversation
…cy contract; Bun 1.4.0 The binding package/tests were already Bun-native while pnpm managed the dependencies. This makes the package manager match the runtime: packageManager is bun@1.4.0, bun.lock replaces pnpm-lock.yaml, and both binding CI lanes install and run through Bun. bindings_package_manager_contract_test.sh is inverted rather than deleted — the old policy required pnpm and forbade bun.lock, the new one requires bun.lock and forbids pnpm-lock.yaml/package-lock.json/yarn.lock plus any pnpm invocation in a workflow. A second lockfile resolves a different dependency graph than the one CI installs, and it does so silently, which is the failure this guards against. The ci.yml bindings job now installs no Node: the root CI/CD STANDARD's Node 26 baseline exempts binding gates that execute under Bun. Node 26 + npm 11.18.0 stay in publish-bindings.yml for the npm pack tarball guard, and the OIDC publish job is untouched. Biome is deliberately held at the 2.5.8 canon (via @ceralive/biome-config 2026.8.0) instead of floating to the newly published 2.5.9, so biome.json's $schema stays truthful; the caret range is unchanged.
Todo 8 was dispatched before the root canon bump landed, so it deliberately held Biome at 2.5.8. That hold is now skew. Bumps @biomejs/biome to ^2.5.9 and the biome.json $schema URL to match. @ceralive/biome-config stays at ^2026.8.0: 2026.8.1 is not published yet (it is an unreleased source bump in the root worktree), and the caret range already admits it, so this consumer picks it up automatically on the first install after the root publish.
…b; replace node -p with bun -e (F1/F2/F4 review fix)
bindings_release_ref_contract_test.sh and bindings_package_manager_contract_test.sh
both evaluate JavaScript, but ran in ci.yml's Rust `test` job, which declares no JS
runtime at all — only setup-rust-toolchain and setup-uv. They worked purely on the
Node the ubuntu-latest image happens to preinstall. Masking `node` from PATH
reproduces exit 127 on both.
They now run in the `bindings` job, right after setup-bun, with working-directory: .
because they are repo-root scripts under a job whose default is bindings/typescript.
Their own `node -p` calls become `bun -e` + console.log, which produces byte-identical
output (verified with od -c for both the version and packageManager reads). No
setup-node was added anywhere: the Rust gate stays Rust/uv-only.
ci/verify-bindings-release-ref.sh is untouched. It is the sanctioned Node island —
publish-bindings.yml's Node-26 OIDC publish job runs it, and that is where its `node`
call is correct. But the release-ref contract test IS that island's test, so it
reaches the island's node from a Bun-only job. Rather than change the island, the
wrapper provisions a Bun-backed `node` shim and prepends it to PATH.
That prepend is UNCONDITIONAL, deliberately. A GitHub runner ships an ambient Node, so
an `if ! command -v node` guard would never fire where it matters: the island's node -p
would resolve to an unpinned ambient runtime and the test would report OK while proving
nothing about the Bun-only job it now lives in. Prepending always means every run
exercises the Bun path, and the script then asserts the result rather than assuming it —
`command -v node` must be the shim AND process.versions.bun must be set, a behavioral
check no real Node can pass, so a shim that exec'd node would also be caught. The
resolved runtime is echoed on the success line (node-runtime=bun@<version>) so every CI
log carries the proof. The export is scoped to the process; the production publish job
resolves its own real Node 26 and is untouched.
Note the wrapper's positive case runs before every expect_rejection, so a broken runtime
aborts under set -e instead of making the rejection assertions pass for the wrong reason;
do not reorder those lines.
release_workflow_contract_test.py drops the two now-stale job("test") assertions and
gains test_binding_contracts_run_under_bun_never_on_an_ambient_node, which requires
both scripts absent from the Rust gate, present in `bindings` after setup-bun, carrying
working-directory: ".", and no setup-node in either job. It fails on the pre-fix ci.yml.
workflow_contract.py's Step model gains working-directory so that override — without
which the repo-root paths do not resolve — is assertable rather than invisible.
Docs: AGENTS.md's Biome prose said 2.5.8 while package.json, bun.lock, and biome.json's
$schema are all 2.5.9 since the previous commit; its files.includes list was also
missing !dist. Both corrected, along with the job-location prose for the contract
scripts in AGENTS.md and README.md.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Migrates bindings package management from pnpm to Bun (
bun@1.4.0), rewrites the package-manager policy contract to enforce Bun-only, moves the two contract-verification scripts into the Bun-onlybindingsCI job, and replaces an undocumented ambient-Node dependency with an explicit, falsifiable Bun-shim proof. Also sweeps dependencies to the latest stable versions, including Biome 2.5.9 and@ceralive/biome-config2026.8.1.Why
Completes the workspace-wide Bun 1.4.0 migration and reverses the deliberate pnpm exception for this package per the plan decision. This is the sibling PR to merged root policy PR #81.
How to verify
Risks
Low — Rust workspace and workflows are untouched, golden fixtures remain byte-identical, and the dependency update uses published stable packages with no pre-releases.