The guarantee ladder

A property does not merely pass or fail. It sits on a rung, and the rung is recorded in the definition's metadata. Oath's central discipline is never dressing up a claim as more certain than it is.

The rungs

asserted

The property exists in the signature but has not been checked. It is a claim, nothing more.

tested

The property held for 200 generated inputs. Generation is deterministic — seeded from the definition's own hash — so a tested verdict is reproducible byte-for-byte. Testing can only ever find counterexamples, never rule them out.

proven

The property was translated to SMT-LIB and Z3 held it for all inputs. Datatypes become SMT algebraic datatypes, recursive functions become quantified defining equations, matches become tester/selector chains, records become single-constructor datatypes, and function values are array-encoded — so higher-order properties quantify over all functions and capability properties over all worlds. Recursion is handled by induction — structural and lexicographic for shrinking datatypes, and recursion induction for functions that recurse on an integer counter (proving measure laws like length (replicate n x) == n).

falsified

A counterexample was found. This is a first-class, recorded outcome — a wrong definition is a fact in the store, not a hidden bug. oath build refuses to compile an executable from a falsified oath.

Why the rungs differ, in one exhibit. abs-small passes all 200 test cases and is then refuted by Z3 at an input the generator never draws.

examples/undertested.oath — abs-smalltested · refuted at x = -401
(defn abs-small [] [(x Int)] Int
  (if (< x 0) (- 0 x) x)
  (prop bounded-wrongly [(x Int)]
    (< (abs-small x) 401)))

The standing caveat

Z3 reasons over unbounded integers, and the evaluator now matches it: Int is arbitrary precision, so a proof carries no modulo overflow asterisk. Integer division and modulo still stay outside the proof fragment on purpose — the kernel truncates toward zero while SMT-LIB integer division is Euclidean, so a "proof" over Int division would certify the wrong theorem. Rational and float division are different: Rat is exact ℚ over the Real sort (so (a/b)*b == a is genuinely proven), and Float is IEEE-754 over the Float64 sort — both theories are complete, so both reach proven. The nuance for floats is that fewer laws are true: x*1.0 == x proves, but 0.1f + 0.2f == 0.3f is falsified — not for any weakness of the prover, but because it is false. That is the prover being right, and it is categorically different from the recursion fragment, where a true property bails to tested because the solver can't reason about it.

Four dimensions, not one

Alongside property proofs, every definition carries three more verdicts:

Verdicts are structure × seed facts. Mutation scores and waivers derive from the definition's hash; they are never carried across an identity change. A fixture is only evidence once you know it was regenerated under the current identity.