ox build is fail-closed
A built artifact evaluates every rule it contains, or it does not exist. ox build runs three gates in order; any gate that fails aborts the build and writes no .oxbin. A wrong artifact is worse than no artifact.
-
Parse gate. Elaboration is error-tolerant — it recovers from malformed input by dropping the broken construct. Left unchecked, a parse error would silently produce an
.oxbinmissing whatever the parser choked on. Soox buildfirst collects every error-severity parse diagnostic; if any exist, it prints them and exits 1 before resolution runs (oxc-driver/src/lib.rs:759). -
Resolution and type gate. It then runs the full resolve/typecheck pass (
collect_check_diagnostics). Any error-severity diagnostic — an unresolved predicate, a type error — aborts the build with no artifact. -
Un-evaluable-rule oracle gate. The lowering pipeline admits some rule shapes the runtime’s rule compiler then refuses. Such a rule is silently dropped from evaluation, so an artifact containing one returns wrong (under-derived) query answers with no runtime error. To prevent that,
ox buildloads the elaborated artifact and re-runs the runtime’s owncompile_ruleas an oracle over every rule (Module::uncompilable_rules). If any rule will not evaluate, the build fails loudly and writes nothing.ox checkenforces the same oracle through the driver’s internalvalidate_runtime_evaluable_rulespath, so editor/CI validation cannot green-light a package thatox buildlater rejects. This intentionally makesox checkdo the extra work needed for artifact-parity validation: package elaboration, stdlib loading, comptime lifting, event encoding, andModule::load. Refused shapes:Shape Diagnostic Unsafe rule — a head / negated / comparison / compute variable not bound by a positive body atom (range-restriction) OE1303Nested aggregate ( count { count { … } > N })OE1311Collection/string aggregate kind ( collect/set_collect/string_join/percentile); the folding kindscount/sum/min/max/avg/count_distinctevaluateOE1312notwrapping an aggregate subqueryOE1313Empty aggregate body ( count { })OE1314Unsupported quantifier shape ( existsbinder,forall(path, T), under-specifiedforall)OE1315Rule bodies the semi-naive executor does not compile — a type-test atom or a meta-equality (
==onmeta(x)) — are recorded the same way and surface as the same load-time refusal (oxc-runtime/src/lib.rs:299).The oracle reports executor-capability failures. A hard
Module::loadfailure surfaces through normal artifact load/build diagnostics.The fix is always to rephrase the rule into a supported shape — typically by exposing the offending subterm through an intermediate
pub deriverule. The supported universalforall v: T where Body, Head(the lastwhereatom is the consequent, the rest the domain) does evaluate; it lowers to a count-equality.