ts-pantry/native's public provisionNativeRuntime() invokes bare pantry install ziglang.org@... --no-save --ignore-scripts without checking that executable against the supported SDK toolchain. Buddy setup validation is a separate caller and cannot enforce this for standalone SDK consumers.
Related: https://github.com/stacksjs/stacks/issues/3107. The Stacks correction must validate the executable each Stacks caller actually runs; it must not claim that an unrelated PANTRY_BIN validation covers the SDK's bare PATH command.
A bounded public subprocess reproduction against normally installed SDK 0.11.159 uses a real clean local authored Git fixture, the public nativeRuntimeCacheKey() and provisionNativeRuntime() exports, and no injected NativeCommand. A bare executable reporting Pantry 0.11.156 reaches install ziglang.org@0.17.0 --no-save --ignore-scripts while PANTRY_BIN names a different 0.11.159 executable. The install attempt is guarded with exit93, before compiler acquisition or native build. No runtime/backend source substitution, network acquisition, native build, profile changes or actual installation is claimed. Evidence: /tmp/stacks-3107-public-n745efwm/native-api/result.json, source/probe identities in /tmp/stacks-3107-reproduction-proposal.json SHA256 ee33dbceb20b44afebd6a75b71f4f4e6281244e348f292038cc39287f33ac8d4.
Acceptance:
- Define and enforce the SDK's supported CLI declaration through its owning public native contract, using existing Pantry version/semver facilities rather than a downstream wrapper or private import.
- Validate the same executable, cwd and effective environment that the actual native install executes. A good unrelated
PANTRY_BINmust not permit an incompatible bare PATH command. - Refuse known broken, malformed and incompatible executables before install or cache mutation, with actionable diagnostics and no silent global upgrade.
- Preserve paths that require no installation, including a qualified cached native runtime and valid explicit
CRAFT_BIN. Do not require an unused Pantry just to accept those paths. - Maintain public subprocess regressions proving refusal before a guarded install marker and compatible execution reaching that marker. Keep missing-command behavior explicit. No mocked successful install, SDK-private imports, generated runtime rewrites or widened native acceptance claims.
This is an owning-source gap, not proof that a specific native game scenario or provider is supported. It remains separate from the root pre-Bun shell acquisition issue.
Approved implementation policy (2026-11-02):
- The supported native CLI range is derived from the owning SDK package version in the paired SDK/CLI release metadata. The Node/Bun native contract validates versions and uses the owning Node-compatible version utility; it does not add a Bun-global requirement or a parallel hardcoded range.
- Preserve bare
pantryselection.PANTRY_BINis not an advertised selector for this native API.options.env, when supplied, remains the complete child environment, and final validation uses the exact installation cwd and environment. - Valid
CRAFT_BIN, no-runtime and qualified cached-runtime paths do not require unused Pantry. Existing source and binary provenance checks remain. - Existing checkouts that need installation are checked before clone/dependency/profile writes. Cold checkouts first pre-screen Pantry in the existing project root before acquisition, then validate again in the actual checkout cwd before profile invalidation or install. The first probe is explicitly a pre-screen, not identical-cwd evidence.
- An existing cache/profile is never discarded by a toolchain refusal. After a successful cold pre-screen, newly acquired immutable source may remain if a later cwd-dependent check refuses; that is unqualified source only, not a successful native cache. This policy does not promise that no source acquisition can ever precede a later refusal.
- Version probing uses an optional bounded owning NativeCommand timeout contract. Unrelated commands retain their existing defaults. The default executor must terminate and await its owned child, settle pipes/timers, and avoid race-and-abandon handling; this does not claim arbitrary process-group ownership.