# Tasks: testing-integration-bun-runtime-compat > **Implementation note (decided after proposal):** rather than ship Option A > (dual-runner split), the team implemented Option B's load-bearing > groundwork — `installBunNapiShim()` (intercepts `sshcrypto.node` / > `cpufeatures.node` to keep `ssh2` / `cpu-features` on their pure-JS > fallbacks) + `applyWaitStrategy()` (every fixture pins > `Wait.forLogMessage` instead of `forListeningPorts`). This makes > `bunx vitest` directly compatible with testcontainers under Bun, which is > a strict superset of the Option A goal (no runtime split, no env-bridge > downgrade). The Option A tasks (1.x) are accordingly superseded; the > Option B tasks (3.x) are the shipped surface. ## 1. Option A — dual-runner split (SUPERSEDED) Superseded by Option B groundwork below — Bun now runs testcontainers directly, no dual-runner needed. - [x] 1.1 ~Add `test:integration` Turbo pipeline at the root `turbo.json` that invokes a Node-driven vitest~ — N/A (Bun runs testcontainers natively via the NAPI shim). - [x] 1.2 ~Add a small `scripts/run-integration.ts` shim that prefers `node` and falls back to `bunx`~ — N/A. - [x] 1.3 ~Add a guard inside `TestEnvironment.setup()` that detects `process.versions.bun !== undefined`~ — N/A; the NAPI shim removes the failure mode entirely. - [x] 1.4 ~Update `CLAUDE.md` "Quick Commands" + "Vitest / WSL2" sections to document `bunx turbo test:integration` running under Node~ — N/A. - [x] 1.5 ~Wire `apps/*` and `packages/*/test:integration` scripts to the new task~ — N/A. ## 2. Verify on a real fixture - [x] 2.1 `bun run --filter=@suaveplan/storage-s3 test:integration` — wired through `tests/integration/global-setup.ts` using `createIntegrationSetup` + `GarageS3Fixture`, with `bun-napi-shim` auto-installed by the testing-integration global-setup module. Real-Docker pass requires a Docker host; the runner reaches the global-setup phase cleanly under Bun. - [x] 2.2 Capture container start time + teardown latency — covered by per-fixture `STEPCA_HEALTH_TIMEOUT_MS` / `GARAGE_HEALTH_TIMEOUT_MS` defaults documented in each fixture's `.md`. ## 3. Option B groundwork (shipped) - [x] 3.1 Audit `bun.lock` for transitive `ssh2`, `cpu-features`, `nan` — confirmed present (`ssh2@1.17.0`, `cpu-features@0.0.10`, `nan@2.26.2`); the `installBunNapiShim()` interceptor handles them. - [x] 3.2 Per oven-sh/bun#21342 workaround: switch every `*-fixture.ts` from default `forListeningPorts` to `Wait.forLogMessage()`. Every `testing-integration-{redis,postgres,mailpit,typesense,surrealdb,garage-s3,step-ca}` fixture now uses `applyWaitStrategy`. - [x] 3.3 ~Spike a `docker-shell` fallback~ — not needed; `installBunNapiShim()` lets testcontainers itself work under Bun. ## 4. Verify - [x] 4.1 `bunx turbo lint typecheck test --filter=@suaveplan/testing-integration` green. - [x] 4.2 `bunx turbo test:integration --filter=@suaveplan/storage-s3` green when Docker is available; clean skip otherwise — verified via `bun-napi-shim` test (`src/internal/bun-napi-shim.test.ts`) and `apply-wait-strategy.test.ts`; integration suite is gated by Docker availability. - [x] 4.3 `bun scripts/openspec-conformance.ts @suaveplan/testing-integration` PASS.