- Static checks: shape, dtype, target support, launch limits (spec 3.2).
- Known answers: literals that do not fit,
x * 0,a / a, a divisor array containing a zero, a divide where every|a| >= |b|. Answered or rejected on the host; no launch. - Range bound: carry operand min/max through the reference rules. No
event possible (e.g.
K * max|A| * max|B| <= max, spec 3.4): launch and skip the post-op scan. Event certain for every input: reject before launch, naming the op and the reason. - Golden-vector probe: for the undecidable band, run the golden boundary
vectors plus a slice of the real data through the host reference. A hit is
a suspicion: warn by default, refuse or verify by exact replay under
sf.config(suspect=...). A sample never by itself justifies “every element”.
errstate, e.g.
sf.config(preflight="raise" | "ask" | "warn" | "off"), subtle by default.
Only step 4 costs anything, and it is host-side and small. Step 3 is also
what sf.explain (Stage 1.2) reports per op.