Skip to content

Run the repository's author tooling on Bun 1.4.4 - #88

Merged
DocksDocks merged 4 commits into
mainfrom
87-evaluate-and-adopt-the-bun-runtime-for-the-repository-mjs-tooling
Oct 23, 2026
Merged

DocksDocks merged 4 commits into
mainfrom
87-evaluate-and-adopt-the-bun-runtime-for-the-repository-mjs-tooling

Conversation

@DocksDocks

@DocksDocks DocksDocks commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Yolo run: #87 Evaluate and adopt the Bun runtime for the repository .mjs tooling

Pull request: #88. Checks: all 5 pass. Reviewed head: b202b3b7.

What changed

  • The gate runs author scripts as bun <script> through new bun()/bunOk() runners (scripts/ci.mjs). The package scripts, the CI gate lines, the release preflight, and 25 author shebangs follow (package.json, .github/workflows/ci.yml, scripts/lib/plugin-release.mjs, scripts/, tests/).
  • The shipped payload stays on Node, also inside the gate: scripts/tests/plan-cli.mjs (it drives the shipped plan.mjs) and the skill-guard.mjs scorer keep node()/nodeOk(). The fake gh that plan-cli.mjs calls moves to Bun (scripts/tests/fixtures/gh-stub/gh).
  • Unit tests run with bun test --parallel=4 --timeout=180000, and the test-contract registry checks that runner (package.json, scripts/tests/test-contracts.mjs). test:coverage stays on Node.
  • packageManager pins bun@1.4.4, so setup-bun installs the measured version (package.json).
  • Three tests no longer depend on Node-only behavior: the guard prints the spawn error code (scripts/skills/guard.mjs), the vacuity fixture loads through --import instead of NODE_OPTIONS (scripts/tests/unit/agent-score-vacuity.test.mjs), and the stub PATH is restored in test.after (scripts/tests/unit/tag-ci-run-identity.test.mjs).
  • The instructions state the runtime split and use bun for author commands (AGENTS.md, scripts/AGENTS.md, .github/AGENTS.md, README.md, both plugin skills/AGENTS.md nodes, and three this-kit lines in write-skill/SKILL.md).

Decisions and corrections

  • Request correction: the shipped plan.mjs, docks hook, and skill-guard.mjs stay on Node. Consumers run them with node, and no agent host documents Bun on PATH (Claude Code setup and hooks docs, Codex install docs). Running plan.mjs on Bun would save 4.5 s more per plugin gate, but CI would then stop proving it on the consumer runtime.
  • Runtimes are chosen by command name. bun --bun and bunfig run.bun were rejected: they make every node in the process tree mean Bun, so the gate could not test the shipped files on Node.
  • resolve-shards keeps node scripts/ci-target.mjs shards: that job installs no Bun.

Reviews

Plan review passed in round 1. Code review passed in round 1.
Open findings: none. The self-review found 2 LOW findings; commit b202b3b7 fixes both.

Verification

  • Gate time, origin/main on Node against this branch on Bun (3 interleaved runs, medians of the gate's own total_ms):
Gate origin/main on Node Branch on Bun Change
--plugin plan-lifecycle 19.35 s 13.68 s -29.3%
--plugin docks 19.21 s 13.84 s -27.9%
--lane repo 10.98 s 9.45 s -13.9%
full gate 30.72 s 23.84 s -22.4%
  • Process startup: an empty script takes 5 ms on Bun and 21 ms on Node; single validators run 2.3x to 3.6x faster.
  • Hosted CI, one run each (the gate's own total_ms in the uploaded timing artifacts): the core lane took 18.1 s on this pull request against 20.6 s on yolo: archive only on Merge now when the answer starts a new run #86 and 22.9 s on plan-lifecycle: tear down what a plan created #84; the repo lane took 10.0 s against 13.1 s on both.
  • bun scripts/ci.mjs: exit 0. bun scripts/tests/ci-plugin-targeting.mjs: exit 0. bun run test:unit: 72 pass, 0 fail.
  • bun run test:coverage (Node): plan.mjs 99.01% lines, unchanged.
  • bun install --frozen-lockfile: no changes; bun.lock unchanged.

Limits and failures

  • Local Node test runs needed TMPDIR outside the system temporary directory. A stray package.json with "type": "commonjs" there makes Node load the tests' extensionless ESM shims as CommonJS, and 7 unit tests fail for that reason alone. It is not repository content; hosted runners are not expected to have it.
  • The unit suite is not faster (6.44 s on Bun, 6.62 s on Node), so the repo lane gains least.
  • Hosted job durations stay about the same (core 40 s against 39 s on yolo: archive only on Merge now when the answer starts a new run #86), because checkout, setup, and install steps dominate them. The hosted comparison uses one run per pull request.
  • The local numbers come from one workstation with background load (load average about 2 on 20 cores).

Kept resources

  • After Merge now: the review scratch docks-review/yolo-87 in the main checkout's git directory (benchmark harness and logs). No worktree, process, or remote resource remains.
  • After Leave pull request open: also the local and remote branch 87-evaluate-and-adopt-the-bun-runtime-for-the-repository-mjs-tooling.

After merge

  • none

Closes #87

Three author-side tests depended on Node-only behavior, which blocks
moving the tooling to Bun (#87):

- skills/guard.mjs printed only the runtime's spawn error message, and
  author-tooling.mjs matched Node's text. The guard now leads with the
  errno code, which both runtimes report the same way.
- agent-score-vacuity loaded its fixture through NODE_OPTIONS=--import,
  which Bun ignores. The hook now goes on the gate's command line,
  where both runtimes accept --import.
- tag-ci-run-identity changed PATH for the whole process and cleaned up
  only at exit. A runner that shares one process across files would
  leak the stub gh into later files, so the file restores PATH in
  test.after.

Refs #87
Author scripts start 2-4x faster on Bun (an empty script takes 5 ms
instead of 21 ms), and every validator, guard, scorer, and author suite
gives the same output on both runtimes (#87). The gate now runs them as
`bun <script>`, and CI, the package scripts, the release preflight, and
the author shebangs follow.

The shipped payload stays on Node, also inside the gate: consumers run
plan.mjs and skill-guard.mjs with `node`, so plan-cli.mjs (which drives
plan.mjs) and the skill scorer keep node()/nodeOk(). Only the fake gh
that plan-cli.mjs calls moves to Bun. That cuts plan-cli.mjs from
19.5 s to 13.6 s while plan.mjs is still proven on Node.

Runtimes are chosen by command name, not by `bun --bun` or bunfig
`run.bun`: an alias makes every `node` in the process tree mean Bun, so
the gate could no longer prove the shipped payload on Node. Unit tests
move to `bun test --parallel=4` (same speed as `node --test`, and they
now exercise the tooling on its own runtime); coverage stays on Node
because Bun coverage cannot see child processes.

packageManager moves to bun@1.4.4 so setup-bun installs the measured
version; Bun 1.4.3 fixed child_process regressions that the gate uses.

Refs #87
The instructions still called Node the validator runtime and told
readers to run author scripts with `node`. They now say that Bun runs
the repository's tooling and is the package manager, and that Node runs
the shipped plugin files that the gate tests, because consumers run
them with `node`. Every command that runs an author script says `bun`;
commands for plan-cli.mjs, skill-guard.mjs, install.cjs, and the
resolve-shards job keep `node`.

In the shipped write-skill skill only the three commands that run this
kit's own gate change, and its content_hash is backfilled. The docs/
point-in-time records stay as they are.

Refs #87
- gate-memo.test.mjs: the half-scope guard matched only
  `bun scripts/ci.mjs --plugin`, so advice that printed the Node
  spelling would have passed. Match the command without its runtime.
- ci-background-task.mjs: the verify hint named `node --test`; the unit
  files now run under `bun test`.

Refs #87
@DocksDocks DocksDocks linked an issue Oct 23, 2026 that may be closed by this pull request
@DocksDocks
DocksDocks merged commit 37852a8 into main Oct 23, 2026
5 checks passed
DocksDocks added a commit that referenced this pull request Oct 23, 2026
Every contract in scripts/config/test-contracts.json still listed
node-24 after #88 moved 16 of them to Bun, because the registry check
only verified that toolchains is a sorted string array (#96).

test-contracts.mjs now derives the runner of each suite from how the
gate runs it (node()/nodeOk() or bun()/bunOk() in scripts/ci.mjs,
`bun test` for the unit files, and the descriptor call sites for
plugin suites) and requires the matching token: node-<major> from the
workflow's node-version and bun-<major> from packageManager. The
registry now lists bun-1 for the Bun suites and bun-1 plus node-24 for
repo-plan-cli, whose fake gh runs on Bun.

Red baseline: before the registry change the check failed for exactly
the 16 Bun suites and passed for repo-plan-cli.

Refs #96
@DocksDocks
DocksDocks deleted the 87-evaluate-and-adopt-the-bun-runtime-for-the-repository-mjs-tooling branch October 23, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate and adopt the Bun runtime for the repository .mjs tooling

1 participant