Typed expression evaluator rollout

Ordinary expressions now use the typed evaluator by default. No environment variable is needed:

python your_program.py

During qualification, the previous evaluator remains available as a temporary escape hatch. Select it before constructing expressions:

BLOSC2_EXPRESSION_EVALUATOR=legacy python your_program.py

Explicit BLOSC2_EXPRESSION_EVALUATOR=typed is also accepted. This selector is temporary, not permanent API configuration. Explicit compatibility DSL kernels and Python UDFs keep their existing execution contracts. The development default has switched ahead of fresh full platform CI; that qualification remains required before deleting the ordinary-expression legacy path.

The typed route reuses Menudet graph plans and admitted compression prefilters. Other layouts/signatures use bounded chunk evaluation through typed graph schedules or NumPy. It never retries an ordinary expression with the legacy uniform-dtype prefilter, and runtime failures are not replayed through NumPy. Typed scalar captures are not converted into untyped literals.

Rebuilt bindings additionally admit N-D layouts whose physical chunks and blocks are consecutive C-order runs, with padding only at the end. They reuse the typed native prefilter rather than decompressing whole chunks for Python evaluation. Older installed extensions still work but keep the narrower row-slab admission.

This addresses condition/reduction typing and integer-input floating operations without requiring a second numerical type system. It does not yet qualify arbitrary noncontiguous N-D native grids, WASM native prefilters, or indexed-query performance. WASM dispatch has representative host-side tests and actual Pyodide wheel tests. Qualification also requires the full Pyodide suite with typed globally selected; passing targeted typed tests alone is not that evidence.

On NumPy older than 2, automatic ordinary numerical-expression execution uses the installed NumPy with bounded Blosc2 chunk/reduction scheduling. Non-numeric (string/bytes) expressions keep their existing miniexpr-backed route because NumPy 1 has no string ufuncs. Resident preparation, cached native preparation, native-first dispatch, and typed prefilters decline native execution. This is an intentional compatibility policy, not a temporary promise to implement NumPy 1.x value-dependent scalar promotion in the native compiler. It can reduce acceleration but does not require whole-array decompression. Explicit expr.native_kernel() and expr.compute(_require_native=True) remain available with Menudet’s NumPy-2-style numerical contract, even on NumPy 1.x. Explicit Menudet functions/kernels retain that same contract and acceleration. Native-only optimization rewrites do not apply to ordinary NumPy 1.x fallback evaluation; options are validated, but arithmetic follows the installed NumPy.

Non-flat N-D layouts can still be slower than legacy fused execution. The chunk fallback amortizes native schedule preparation, avoids duplicate persisted edge reads and unnecessary assignment setup, and uses NumPy for small floating arithmetic chunks under the default policy. It does not yet reproduce the fused block pipeline for arbitrary N-D geometry. Profile evidence and remaining gaps are recorded in the migration plan; performance parity is not claimed for those layouts.

Use bench/ndarray/evaluator_migration.py for an interleaved timing probe and bench/ndarray/evaluator_fallbacks.py for route-aware fallback measurements. Cross-platform correctness, output/scratch-memory contracts, WASM, and the recorded performance tradeoffs are still being qualified under the new default. Some tests intentionally inspect the legacy prefilter or its allocation format; they are not interchangeable with typed-route storage-contract tests.

The implementation inventory, retirement stages, and acceptance criteria are in plans/migrate-typed-expression-evaluator.md in the repository. Historical implementation evidence remains in plans/retire-uniform-expression-evaluator.md.