docs(adr): record Bun 1.4.3 verification results and decisions

Stable Bun 1.4.3 runs installs, the development server, standalone type
checks, the native test runner and a Bun.serve static server. Native
lint/fmt are canary-only, and Angular's server build needs Node loader
hooks Bun does not apply, so the spec now keeps ESLint/Prettier until a
stable release, builds Angular client-only behind a Bun static server,
converts line coverage from lcov, and replaces the heap cap with a
container memory limit.

Refs #289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nessarandClaude Opus 5.5 committed 2026-10-17 12:49:17 +02:00
1 parent c949480e49
commit 558c70aa24
2 files changed
+80 -2

No files matched your search

+72 -2
View File
@@ -1,7 +1,8 @@
# Bun Runtime and Native Tooling — Development Spec
Status: local draft synthesized from the agreed individual decisions. Integration
feasibility remains unverified; ADR 0009 remains proposed.
Status: the agreed decisions are amended by the verification results in #289,
recorded below. ADR 0009 remains proposed until the migration passes its final
gate.
## Problem Statement
@@ -104,6 +105,75 @@ The following acceptance criteria define completion:
native-tool documentation. Select the exact version only after verifying the
required capabilities together.
## Verification Results and Decisions (#289)
Probes ran on 2026-10-17 against the stable Bun `1.4.3` release (`1.4.3+c6da4a4d3`)
from a clean checkout. "Node unavailable" means a `PATH` holding only a `bun`
executable plus `/usr/bin:/bin`, with `command -v node` failing.
**Verified:**
- **Install.** `bun install --frozen-lockfile` succeeds and leaves `bun.lock`
unchanged.
- **Runtime.** Package binaries with a `#!/usr/bin/env node` shebang (`ng`,
`eslint`, `prettier`, `tsc`) run on Bun only with `--bun`. Without it they use
Node when Node is on `PATH`, so every such command must pass `--bun`
explicitly. Spawned build children are native executables (esbuild,
dart-sass); Angular's workers are threads of the Bun process.
- **Development server.** `bun --bun x ng serve` serves the application and
direct navigation to `/benchmark` with Node unavailable.
- **Type checking.** `bun check -p tsconfig.app.json` and
`-p tsconfig.spec.json` match `tsc` 6 on the clean tree and catch injected
application and test type errors. Only the Angular build catches template
errors, as expected.
- **Tests.** `bun test` runs the whole functional suite with a preload that
compiles components through Angular's JIT transform with inlined templates,
sets up jsdom, TestBed and zoneless change detection, plus a small shim for
the Vitest APIs Bun lacks (`stubGlobal`, `unstubAllGlobals`, `waitFor`,
`advanceTimersByTimeAsync`, `expect.poll`, `toHaveBeenCalledExactlyOnceWith`,
`setSystemTime` ordering and Date-only fake timers). Real-worker specs work
with Node unavailable. `--isolate` or `--parallel` is required for per-file
isolation. No spec uses snapshots.
- **Server.** `Bun.serve` passes route, asset, cache-header, missing-file and
path-traversal checks.
- **CI scripts.** The policy regression script passes under Bun. The image
regression script needs its fake `docker` shebang changed from `node` to
`bun`.
**Decisions taken after the probes:**
- **Linter and formatter.** Native `bun lint` and `bun fmt` exist only in canary
builds (`1.4.4-canary.1`), not in stable `1.4.3`. Pin stable `1.4.3`
everywhere and keep ESLint and Prettier, executed by Bun, until a stable
release ships them. Then replace them in one change. Until then, user story 5
stays open.
- **Client-only Angular build and a Bun static server.** Angular's production
build fails under Bun whenever a server or SSR entry is configured: route
extraction loads the server bundle through Node `module.register` loader
hooks, which Bun accepts but never applies. Every route is client-rendered
today, so the Angular build drops its server and SSR entries and a small
`Bun.serve` server delivers static assets with the same cache behavior and
falls back to `index.html`. This replaces the agreed Angular web request
handler integration and gives up `@angular/ssr`. Adding server rendering later
requires revisiting this decision.
- **Coverage.** `bun test` reports text and lcov with line data only. HTML and
Cobertura reports are generated from the lcov with the istanbul report
libraries. Branch and function coverage are no longer reported; this
reduction is accepted.
- **Benchmark memory guard.** JavaScriptCore has no `--max-old-space-size`
equivalent. The CI benchmark job enforces the limit with a container memory
limit instead of a heap-only cap.
**Platform constraints, not project commands:**
- **Gitea actions.** `actions/checkout@v4` (`node20`) and
`actions/upload-artifact@v3` (`node16`) are JavaScript actions, so the job
container must still provide `node` for the runner. Project commands must not
use it.
- **Allowed hosts.** Found while probing: the current Express server answers 400
unless `NG_ALLOWED_HOSTS` is set, and the compose files only set `PORT`. The
static Bun server removes this dependency.
## Testing Decisions
- Test observable behavior and failure outcomes, rather than configuration text