4b2c3d524c
`pi_natives` failed to load in Bun worker threads on macOS x64 when the
host built only the `modern` (AVX2) variant. The runtime detector's
`child_process.spawnSync("sysctl", ...)` returned null from the worker
even though the build-time detector (`scripts/host-detect.ts`) succeeded
in the parent shell, so `loadNative()` resolved `variant=baseline` and
searched a file list that excluded the `pi_natives.darwin-x64-modern.node`
the build had actually produced.
Two compounding root causes in `packages/natives/native/loader-state.js`:
- `runCommand` only used `child_process.spawnSync`, which is the path
observed to fail under Bun's worker shim on darwin. The build-time
detector uses `Bun.spawnSync` and works fine.
- The darwin branch looked up `sysctl` via PATH. Login shells supply
`/usr/sbin` so the build picks it up, but worker/embedded spawn
contexts can ship without it.
Fix:
- `runCommand` now prefers `Bun.spawnSync` (matches the build-time
detector) and falls back to `child_process.spawnSync` for non-Bun
embeds.
- The darwin branch tries `/usr/sbin/sysctl` before bare `sysctl`.
- New private env key `__PI_NATIVE_VARIANT_CACHE`: once any context
resolves the variant (the main thread does first), it is written
there. Bun workers and child subprocesses inherit `process.env` at
spawn, so they read the cache and skip detection — sidestepping the
worker-context spawn flakiness end-to-end.
- New exported pure helper `selectCpuVariant({ arch, override, env,
detectAvx2 })` codifies the override > cache > detect order and
returns the cache write hints so the helper itself stays
side-effect-free.
Regression test `packages/natives/test/issue-3238-repro.test.ts` pins
every branch of the resolution order, including the file-list shape
that surfaced the bug.
Fixes #3238