Repository navigation
Evaluate and adopt the Bun runtime for the repository .mjs tooling #87
Description
Goal
Decide from measurements whether the repository's own .mjs tooling and the plan-lifecycle plugin's .mjs files should run on the Bun 1.4.4 runtime instead of Node 24. Make the faster runtime that passes the same gates the one that local commands and CI use.
Scope: author-side scripts under scripts/ and tests/, the package scripts in package.json, the CI workflows, the instructions that name the validator runtime, and the plan-lifecycle helper plan.mjs and its self-test. Compare both runtimes on process startup, each validator, the unit suite, and the gates, and record the numbers.
Yolo: the user delegated every decision except the merge to the agent.
Mode: plan-and-implement
Research
How the scripts run today
- Every script runs as
node <file>.package.jsonscriptsci,guard:skills,score:skills,test:observability, andtest:contractscallnode.test:unitisnode --test --test-concurrency=4 scripts/tests/unit/*.test.mjs.test:coverageisnode --test --experimental-test-coverageoverscripts/tests/plan-cli.mjs. scripts/ci.mjs-node()andnodeOk()- spawn a literalnodefor every sub-check.scripts/skills/guard.mjs-run()- andscripts/lib/plugin-release.mjs-runSelectedCi()- also spawn a literalnode. Tests spawnprocess.execPath.- Tests intercept gate children by command name through PATH shims:
scripts/tests/ci-plugin-targeting.mjs-writeCiProbeShim(),writeReleaseShim()- and thewriteShim()helpers inscripts/tests/unit/agent-score-vacuity.test.mjsandscripts/tests/unit/skill-score-vacuity.test.mjs. scripts/tests/test-contracts.mjs-gateInvocationArguments()- finds gate suites by matchingnode(...)/nodeOk(...)calls inscripts/ci.mjs, andunitDescriptors()reads thetest:unitcommand.scripts/lib/ci-targeting.mjs-extractCiGateInvocations()- matchesnode scripts/ci.mjsin workflow run lines..github/workflows/ci.ymlsets up Node 24 and Bun, runsnode scripts/ci.mjs,node scripts/ci-target.mjs,node scripts/tests/ci-plugin-targeting.mjs,node node_modules/@anthropic-ai/claude-code/install.cjs, andnpm audit signatures.resolve-shardsinstalls no Bun.package.jsonpinspackageManager: bun@1.4.0. The workflows give setup-bun nobun-version, so CI installs 1.4.0. Plan Release plan-lifecycle 0.5.0 and move the repo to Bun 1.4 #12 moved the package manager to Bun and kept the Node runtime out of scope.- Shipped to consumers:
plan.mjs(plan-contract.md: "Runnode <installed-helper> <command>"),plugins/docks/hooks/context-tree-nudge.mjs(hooks.json:node "${CLAUDE_PLUGIN_ROOT}/hooks/context-tree-nudge.mjs"), andskill-guard.mjs(write-skill/SKILL.md:node <write-skill-dir>/scripts/skill-guard.mjs). The gate exercisesplan.mjsonly throughscripts/tests/plan-cli.mjs, which spawns it withprocess.execPath, and it callsplan.mjsthrough the fakeghinscripts/tests/fixtures/gh-stub/gh(a#!/usr/bin/env nodescript).
Measurements
Linux x64, 20 cores, Node v24.22.1, Bun 1.4.4. Each value is the median of interleaved runs, with the start runtime rotated each round. Command: python3 "$(git rev-parse --git-path docks-review)/yolo-87/bench/bench.py" startup scripts unit gates. "Whole tree" puts a node symlink to bun first on PATH, which is what bun --bun run does.
| Command (30 runs startup, 10 runs scripts) | Node ms | Bun ms | Ratio |
|---|---|---|---|
empty script -e 0 |
21 | 5 | 4.4x |
plan.mjs usage error (no gh call) |
33 | 15 | 2.2x |
context-tree-nudge.mjs hook |
22 | 12 | 1.8x |
scripts/config/read-floor.mjs agents |
22 | 6 | 3.6x |
scripts/agents/guard.mjs |
23 | 7 | 3.3x |
scripts/agents/score.mjs --per-file |
23 | 8 | 3.1x |
scripts/tree/guard.mjs |
37 | 13 | 2.7x |
scripts/skills/durable-anchors.mjs |
47 | 20 | 2.4x |
scripts/plans/no-bespoke-gates.mjs |
42 | 14 | 2.9x |
skill-guard.mjs score --per-file |
29 | 13 | 2.3x |
scripts/skills/guard.mjs (spawns three children) |
133 | 57 whole tree, 112 parent only | 2.3x |
| Unit suite (3 runs) | Median | Result |
|---|---|---|
node --test --test-concurrency=4 |
6.62 s | 72 pass |
bun test (one shared process) |
10.37 s | 69 pass, 3 fail (RC2) |
bun test --parallel=4 |
6.44 s | 69 pass, 3 fail (RC2) |
ci.mjs --plugin <name> (3 runs) |
Node | Bun parent, node children |
Bun whole tree |
|---|---|---|---|
| plan-lifecycle | 19.46 s | 19.76 s | 9.71 s |
| docks | 20.41 s | 19.93 s | 9.39 s |
The gate's --timings-json shows where the time goes. scripts/tests/plan-cli.mjs takes 18.7 s of the 19.4 s Node plan-lifecycle gate and 9.2 s of the 9.7 s whole-tree Bun gate. All other plan-lifecycle commands sum to 0.49 s on Node and 0.21 s on Bun; docks: 0.69 s and 0.35 s. claude plugin validate takes 0.24 s on both.
plan-cli.mjs (3 runs): plan.mjs runtime |
fake gh runtime |
Median |
|---|---|---|
| Node | Node | 19.50 s |
| Node | Bun | 13.55 s |
| Bun | Node | 15.37 s |
| Bun | Bun | 9.06 s |
Compatibility
Every entry point that scripts/ci.mjs runs for the docks, plan-lifecycle, and repo lanes was run three ways (Node, Bun parent, whole tree on Bun), and the hook was run with five inputs. All outputs are byte-identical except the five root causes below and measured-time values. The docks and plan-lifecycle gates exit 0 on all three. Logs: $(git rev-parse --git-path docks-review)/yolo-87/compat/.
- RC1:
scripts/tests/author-tooling.mjs-testSkillsGuardSpawnFailure()- expects Node's spawn error textspawnSync node ENOENT. Bun printsExecutable not found in $PATH: "node".error.codeisENOENTon both. - RC2:
scripts/tests/unit/agent-score-vacuity.test.mjs-runCi()- loads its fixture throughNODE_OPTIONS=--import=<hook>. Bun ignores--importinNODE_OPTIONS, so three tests fail. The command-line flag works on both: Bun 1.4.4bun --helplists "--import=<val>Alias of --preload, for Node.js compatibility". - RC3:
test:unitneeds Node'snode --testrunner mode, which Bun does not have. Withnodealiased to Bun, it exits 1 and runs no test, so the failure is loud. - RC4:
scripts/tests/unit/tag-ci-run-identity.test.mjssetsprocess.env.PATHat module scope and cleans up only on processexit.bun testruns several files in one process, so the stub PATH leaks into later files. Results are unchanged today. - RC5: Bun coverage does not count lines that run in child processes:
plan.mjsline coverage is 22.34% underbun test --coverageand 99.01% under Node.
Decisions
- Run the repository's author tooling on Bun:
scripts/**,tests/**,plugins/plan-lifecycle/test/selftest.mjs, and the fakeghfixture. Each process starts 2-4x faster, and the outputs are identical. Rejected: keep Node (it gives up the measured gate and startup gains). - Keep shipped consumer payload on Node, in consumer instructions and in the gate:
plan.mjsthroughscripts/tests/plan-cli.mjs, theskill-guard.mjsscorer, and the hook. Consumers invoke these withnode(repo facts above). The Claude Code native installer needs no Node and documents no Bun for hooks; hook commands run throughsh -c. Codex is a Rust binary with no runtime requirement. Rejected: runplan.mjson Bun in the gate. It would save 4.5 s more per plugin gate (13.55 s to 9.06 s), but CI would then stop provingplan.mjson the runtime that consumers use. Rejected: require Bun from consumers. - Run the fake
gh(scripts/tests/fixtures/gh-stub/gh) on Bun through its shebang. It is author-side test infrastructure, and it removes 6 s from everyplan-cli.mjsrun whileplan.mjsstays on Node. - Select each runtime explicitly by command name.
scripts/ci.mjsruns author scripts asbun <script>and shipped payload asnode <script>, through runners named for their runtime:bun()/bunOk()andnode()/nodeOk(). Rejected:bun --bun runorbunfig.toml[run] bun = true. Either makes everynodein the process tree mean Bun, so the gate could not run shipped payload on Node, andtest:coveragewould move to Bun without notice.bun <file>does not alias at all (local probe). Rejected:process.execPathfor gate children, because the PATH shims that the tests use to intercept children work by command name. - Run unit tests with
bun test --parallel=4 --timeout=180000 ./scripts/tests/unit/*.test.mjs. The speed is equal (6.44 s and 6.62 s), and the tooling's unit tests then run on the runtime that runs the tooling.--parallelgives worker processes and a fresh global per file. Bun's default per-test timeout is 5000 ms and Node's is unlimited, so the command sets 180000 ms, the longest child timeout that the unit tests use. Anode:testAPI that Bun lacks throws, so the suite fails loudly (probe). Rejected: plainbun test(one shared process, 10.37 s). Rejected: keepnode --test(the unit tests would exercise the tooling on a runtime it no longer uses). - Keep
test:coverageon Node. Bun coverage cannot see child processes (RC5), andplan.mjsis consumer payload (decision 2). - Pin Bun 1.4.4:
packageManagerchanges frombun@1.4.0tobun@1.4.4. setup-bun readspackageManagerwhen the workflow gives nobun-version. Bun 1.4.3 fixednode:child_processregressions from 1.4.0: truncated pipe data, aspawnSyncthat never returned, and lost output. The gate depends on these paths. - CI: the gate jobs keep setup-node, because shipped-payload contracts,
npm audit signatures, and the claude-codeinstall.cjsneed Node. They runbun scripts/ci.mjs,bun scripts/ci-target.mjs release-tag, andbun scripts/tests/ci-plugin-targeting.mjs.resolve-shardskeepsnode scripts/ci-target.mjs shards:.github/AGENTS.mdstates that this job "needs only a checkout and Node", every shard waits on it, and adding setup-bun there would cost more than the 15 ms of startup it saves [INFERENCE: setup cost not measured].scripts/lib/ci-targeting.mjs-extractCiGateInvocations()- must then matchbun scripts/ci.mjs. - Shebangs: author entry points and the fake
ghuse#!/usr/bin/env bun.scripts/tests/plan-cli.mjskeeps#!/usr/bin/env node, because it provesplan.mjson Node. Shipped files keep#!/usr/bin/env node. - Fix RC1, RC2, and RC4 first, so that each suite passes on both runtimes before the switch. RC1: the guard prints
error.codewith the runtime's message. RC2: pass the hook as a--import=<hook>argument. RC4: restorePATHand remove the stub root intest.after. - Docs: update the author instructions that name the runtime or tell a reader to run author scripts. In shipped
write-skill/SKILL.md, change only the three commands that run this kit's own gate, then backfill itscontent_hash. Leavedocs/point-in-time records unchanged, asdocs/AGENTS.mdrequires.
Expected result: about 14 s for each plugin gate instead of 19.5 s (about -28%): the plan-cli.mjs split gives 13.55 s, and the other commands save 0.3 s. Repo-lane suites also start faster.
Request corrections
Asked: make "our .mjs scripts actually use bun runtime ... for both plan-lifecycle and scripts from the repo itself". Did: the repository's author tooling, the plan-lifecycle self-test, and the fake gh move to Bun. The shipped plan-lifecycle helper plan.mjs, the docks hook, and the shipped skill-guard.mjs scorer stay on Node, and the gate keeps proving them on Node. Reason: consumers invoke these files with node, and no agent host documents Bun on PATH (decision 2).
Engineering standards
- Step 1
runtime_neutral_tests:fix-workflow(the Bun repro commands are the feedback loop; each fix has a revert trigger: the suite that it repairs),code-clarity,commit-discipline. - Step 2
author_tooling_on_bun:code-clarity(runner names state their runtime; one comment states why shipped payload runs on Node; every rerun hint names the command that the gate ran),commit-discipline. - Step 3
runtime_docs:code-clarity(docs keep the rationale for the runtime split),commit-discipline. - Before code review round 1:
code-reviewself-review withcode-clarity.
Sources
- https://bun.com/docs/runtime/bunfig#run-bun - "When
true, Bun prepends$PATHwith anodesymlink that points to thebunbinary"; it works recursively. - https://bun.com/docs/runtime - "
--bunForce a script or package to use Bun's runtime instead of Node.js (via symlinking node)." - https://bun.com/docs/runtime/nodejs-compat#node-test -
node:testis partial; missing "code coverage" and "Node's--testCLI runner mode". - https://bun.com/docs/test - "By default the test runner runs all tests in a single process"; per-test timeout "The default value is
5000". - https://bun.com/docs/test/parallel -
--parallel[=N]"Runs files acrossNworker processes ... Implies--isolate". - https://bun.com/docs/test/code-coverage - "Coverage only tracks files that are loaded."
- https://nodejs.org/docs/latest-v24.x/api/cli.html#--test-isolationmode - "The default isolation mode is
'process'";--test-timeoutdefaultInfinity;NODE_V8_COVERAGE"will automatically propagate to subprocesses". - https://github.com/oven-sh/setup-bun/blob/v2.2.0/README.md - without input, setup-bun checks
package.jsonpackageManagerfirst. - https://bun.com/blog/bun-v1.4.3 -
node:child_processfixes: truncated data on failed pipe reads, aspawnSyncthat could spin and never return, dropped output on a full pipe. - https://code.claude.com/docs/en/setup - the native binary "doesn't use your Node.js at runtime".
- https://code.claude.com/docs/en/hooks - shell-form hook commands run through
sh -c; "Thenodeplus script-path pattern works on every platform". - https://github.com/openai/codex/blob/main/docs/install.md - "Codex is written in Rust"; system requirements name no runtime.
Steps
| # | Id | Task | Files | Depends | Effect | Status | Done when |
|---|---|---|---|---|---|---|---|
| 1 | runtime_neutral_tests | Make the author suites pass on Node and Bun: scripts/skills/guard.mjs prints the spawn error.code with the runtime's message and author-tooling.mjs matches the code (RC1); agent-score-vacuity.test.mjs passes its fixture hook as a --import=<hook> argument instead of NODE_OPTIONS (RC2); tag-ci-run-identity.test.mjs restores PATH and removes its stub root in test.after (RC4) |
scripts/skills/guard.mjs, scripts/tests/author-tooling.mjs, scripts/tests/unit/agent-score-vacuity.test.mjs, scripts/tests/unit/tag-ci-run-identity.test.mjs | - | local | done | node scripts/tests/author-tooling.mjs and bun scripts/tests/author-tooling.mjs exit 0; node --test --test-concurrency=4 scripts/tests/unit/*.test.mjs and bun test --parallel=4 --timeout=180000 ./scripts/tests/unit/*.test.mjs each report 72 pass, 0 fail |
| 2 | author_tooling_on_bun | Run author tooling on Bun 1.4.4 and keep shipped payload on Node: pin packageManager to bun@1.4.4; point ci, guard:skills, test:observability, and test:contracts at bun, and test:unit at bun test --parallel=4 --timeout=180000 ./scripts/tests/unit/*.test.mjs (score:skills and test:coverage stay on node); in scripts/ci.mjs add bun()/bunOk() for author scripts, keep node()/nodeOk() only for scripts/tests/plan-cli.mjs and the skill-guard.mjs scorer, and make every rerun hint name the command the gate ran; spawn bun in scripts/skills/guard.mjs and scripts/lib/plugin-release.mjs; spawn process.execPath in tests/idempotency.mjs; print bun scripts/ci.mjs in the gate-memo cost advice; set #!/usr/bin/env bun on author entry points and the fake gh (not scripts/tests/plan-cli.mjs or shipped files); run bun for scripts/ci.mjs, scripts/ci-target.mjs release-tag, and scripts/tests/ci-plugin-targeting.mjs in .github/workflows/ci.yml (resolve-shards keeps Node); match bun scripts/ci.mjs in scripts/lib/ci-targeting.mjs; move every test shim, assertion, and registry pattern that names the runner |
package.json, scripts/ci.mjs, scripts/skills/guard.mjs, scripts/lib/plugin-release.mjs, scripts/lib/gate-memo.mjs, scripts/lib/ci-targeting.mjs, tests/idempotency.mjs, scripts/tests/fixtures/gh-stub/gh, .github/workflows/ci.yml, scripts/tests/ci-plugin-targeting.mjs, scripts/tests/test-contracts.mjs, scripts/tests/author-tooling.mjs, scripts/tests/unit/agent-score-vacuity.test.mjs, scripts/tests/unit/skill-score-vacuity.test.mjs, scripts/tests/unit/gate-memo.test.mjs, scripts/capture-tdd-red.mjs, scripts/ci-target.mjs, scripts/release.mjs, scripts/agents/guard.mjs, scripts/agents/score.mjs, scripts/config/read-floor.mjs, scripts/lib/validate-skills.mjs, scripts/plans/no-bespoke-gates.mjs, scripts/skills/codex-facts.mjs, scripts/skills/content-hash.mjs, scripts/skills/durable-anchors.mjs, scripts/skills/no-author-scripts.mjs, scripts/skills/refs-guard.mjs, scripts/skills/transform-guard.mjs, scripts/tree/guard.mjs, scripts/tests/ci-observability.mjs, tests/skill-trigger-collision.mjs, plugins/plan-lifecycle/test/selftest.mjs | 1 | local | done | bun scripts/ci.mjs exits 0; its --timings-json lists node as argv[0] only for scripts/tests/plan-cli.mjs and the skill-guard.mjs scorer; bun scripts/tests/ci-plugin-targeting.mjs exits 0 |
| 3 | runtime_docs | State the runtime split and move every author command to bun in root AGENTS.md (Commands, the runtime sentence, validator commands), scripts/AGENTS.md, .github/AGENTS.md, README.md, plugins/docks/README.md, plugins/docks/skills/AGENTS.md, plugins/plan-lifecycle/skills/AGENTS.md, and the three this-kit gate commands in write-skill/SKILL.md, then run bun scripts/skills/content-hash.mjs --backfill plugins/docks/skills; commands that run shipped skill-guard.mjs or plan.mjs keep node |
AGENTS.md, scripts/AGENTS.md, .github/AGENTS.md, README.md, plugins/docks/README.md, plugins/docks/skills/AGENTS.md, plugins/plan-lifecycle/skills/AGENTS.md, plugins/docks/skills/productivity/write-skill/SKILL.md | 2 | local | done | each line that git grep -n -E '\bnode (scripts|tests)/' -- ':!docs/' prints runs scripts/tests/plan-cli.mjs or resolve-shards' scripts/ci-target.mjs on Node, is a consumer-side command in a shipped skill body, or is a test assertion of one of these, as listed in Verification Results; bun scripts/ci.mjs exits 0 |
Acceptance
| ID | Command | Expected |
|---|---|---|
| a1 | bun install --frozen-lockfile && git diff --exit-code bun.lock |
both exit 0 under Bun 1.4.4 |
| a2 | bun scripts/ci.mjs |
exits 0 for the repo-wide checks and both plugins (root AGENTS.md: the full gate for repo-wide and multi-plugin changes) |
| a3 | bun scripts/tests/ci-plugin-targeting.mjs |
exits 0 (the non-unit targeting contract that the targeting-contracts job runs, .github/AGENTS.md) |
| a4 | bun run test:unit |
bun test reports 72 pass, 0 fail, across 7 files |
| a5 | bun run test:coverage |
runs under Node and reports at least 99% line coverage for plan.mjs |
| a6 | bun scripts/ci.mjs --plugin plan-lifecycle --timings-json <file>, then print each command's argv[0] |
node only for scripts/tests/plan-cli.mjs and the skill-guard.mjs scorer, claude for plugin validate, and bun for every other command |
| a7 | Three interleaved runs each of node scripts/ci.mjs --plugin plan-lifecycle --timings-json <file> in a temporary worktree of origin/main and bun scripts/ci.mjs --plugin plan-lifecycle --timings-json <file> on the branch |
the branch median total_ms is at least 20% below the origin/main median |
| a8 | pull request checks | every check passes |
Do not touch
- Shipped consumer surfaces:
plan.mjscode and itsnode <installed-helper>contract line,plugins/docks/hooks/hooks.json,context-tree-nudge.mjs,skill-guard.mjscode, and every shipped skill body except the three this-kit gate commands inwrite-skill/SKILL.md(decision 2). docs/point-in-time records, includingdocs/authoring-audits.md(docs/AGENTS.md).- The
install.cjsandnpm audit signaturesCI steps, and.github/workflows/dependency-integrity.yml. test:coverageandscore:skills, which stay on Node (decisions 2 and 6).- Plugin versions, manifests, and marketplace catalogs. This plan makes no release.
- The
scripts/lib/gate-memo.mjskey fields.toolFingerprintalready records both runtimes. bunfig.toml: no[run] bunsetting (decision 4).
Open questions
Verification Results
Local runs: Linux x64, Node v24.22.1, Bun 1.4.4. Limitation: this workstation has a stray package.json with "type": "commonjs" at the root of its system temporary directory (not repository content). Node then loads the extensionless ESM PATH shims that tests write into os.tmpdir() as CommonJS, and 7 unit tests fail under Node for that reason alone. Every local run below therefore sets TMPDIR to a directory in the review scratch. Bun runs are unaffected, and hosted runners have no such file [INFERENCE].
Step 1 runtime_neutral_tests (commit 5e302e70)
node scripts/tests/author-tooling.mjsandbun scripts/tests/author-tooling.mjs: both exit 0.node --test --test-concurrency=4 scripts/tests/unit/*.test.mjs: 72 pass, 0 fail.bun test --parallel=4 --timeout=180000 ./scripts/tests/unit/*.test.mjs: 72 pass, 0 fail.
Step 2 author_tooling_on_bun (commit b65f78bb)
bun scripts/ci.mjs: exit 0, statuspassed. Its--timings-jsonlists 25buncommands, 2claude plugin validatecommands, and 3nodecommands:scripts/tests/plan-cli.mjsand theskill-guard.mjsscorer for each plugin.bun scripts/tests/ci-plugin-targeting.mjs: exit 0.bun scripts/tests/ci-plugin-targeting.mjs --unit: exit 0.bun scripts/tests/test-contracts.mjs:PASS test_contracts contracts=15 discovered=15 selected=15.bun run check:js: exit 0 with 7 warnings and 3 infos, the same counts as onorigin/main.
Step 3 runtime_docs (commit b52ce681)
bun scripts/skills/content-hash.mjs --backfill plugins/docks/skills:wrote productivity/write-skill.git grep -n -E '\bnode (scripts\|tests)/' -- ':!docs/'prints 5 lines, each an allowed exception: theresolve-shardsreason in.github/AGENTS.md; the tworesolve-shardsrun lines in.github/workflows/ci.yml; the consumer-sidescripts/validate.mjscommand in the shippedplugins/docks/skills/productivity/context-tree/SKILL.md; and theplan-cli.mjsrerun hint inscripts/ci.mjs.bun scripts/ci.mjs: exit 0.
Self-review fixes (commit b202b3b7)
bun test ./scripts/tests/unit/gate-memo.test.mjs ./scripts/tests/unit/ci-background-task.test.mjs: 31 pass, 0 fail. The old half-scope guard regex does not matchnode scripts/ci.mjs --plugin docks; the new one does.
Acceptance (final tree b202b3b7)
- a1
bun install --frozen-lockfile && git diff --exit-code bun.lock: exit 0 ("Checked 8 installs across 20 packages (no changes)"). - a2
bun scripts/ci.mjs: exit 0, statuspassed,total_ms23153. - a3
bun scripts/tests/ci-plugin-targeting.mjs: exit 0. - a4
bun run test:unit: 72 pass, 0 fail, across 7 files. - a5
bun run test:coverage: runsnode --test --experimental-test-coverage;plan.mjs99.01% lines, 76.01% branches, 98.56% functions, the same as before the change. - a6
bun scripts/ci.mjs --plugin plan-lifecycle --timings-json <file>:noderuns onlyscripts/tests/plan-cli.mjsand theskill-guard.mjsscorer,clauderuns plugin validate, andbunruns the other 11 commands;total_ms13940. - a7
python3 "$(git rev-parse --git-path docks-review)/yolo-87/bench/compare.py" <origin-main-worktree> 3 <gate-args>: three interleaved runs each, medians of the gate's owntotal_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 (-q) |
30.72 s | 23.84 s | -22.4% |
- a8 pull request checks on Run the repository's author tooling on Bun 1.4.4 #88 at the reviewed head
b202b3b7: all 5 pass (resolve validation shards, validation shard (repo), validation shard (core), CI plugin-targeting contracts, validate). The uploaded timing artifacts show the hosted gate at 18.1 s for the core lane and 10.0 s for the repo lane, against 20.6 s and 13.1 s on yolo: archive only on Merge now when the answer starts a new run #86 (one run each).
Activity
DocksDocks commentedon Oct 23, 2026
Plan review round 1
Plan-review: pass
None.
DocksDocks commentedon Oct 23, 2026
Self-review
Scope: full candidate diff since the merge base with
main(3 commits, 42 files), reviewed withcode-reviewandcode-clarity. Two-axis mode: the spec source is this issue.Standards
LOW · Maintainability ·
scripts/lib/ci-background-task.mjs:17(stale by this branch)Evidence:
// duration (`node --test scripts/tests/unit/ci-background-task.test.mjs`).Why it is a problem: the verify hint names Node's test runner, but
test:unitnow runs the unit files withbun test, so a reader runs the suite on a runtime the gate no longer uses for it.Suggested fix:
bun test ./scripts/tests/unit/ci-background-task.test.mjs.LOW · Maintainability (test strength) ·
scripts/tests/unit/gate-memo.test.mjs:406(introduced)Evidence:
assert.doesNotMatch(many, /bun scripts\/ci\.mjs --plugin/, 'no copy-pasteable half-scope');Why it is a problem: the guard now rejects only the Bun spelling of a half-scope command. Advice that printed
node scripts/ci.mjs --plugin ...would pass it.Suggested fix: match the command without its runtime:
/scripts\/ci\.mjs --plugin/.Spec
No findings. Research records the measurements for startup, each validator, the unit suite, and the gates; author tooling runs on Bun; the shipped
plan.mjs, hook, andskill-guard.mjsstay on Node as the recorded request correction states;packageManagerpinsbun@1.4.4.Summary
DocksDocks commentedon Oct 23, 2026
Code review round 1
Code-review: pass
Standards
None.
Spec
None.
test: make the author suites pass on Node and Bun
build: run the author tooling on Bun 1.4.4
docs: state the Bun and Node runtime split
fix: close the two self-review findings on #87