Each invariant's temporal-logic form derives its checker — proven, not sampled.

Formal invariant verification (temporal form → model checking)

Intent — Give every model invariant a temporal form: a temporal-logic operator saying whether it is safety ([]P, always holds) or liveness (P ~> Q, eventually leads to), and make that form the routing input: it derives which exhaustive checker verifies the invariant. An invariant is then proven by the method its shape demands, a state-space model-check rather than a sampled test, and it cannot be silently mis-verified (our instance: temporal-logic operators on the cross-service state model, checked by a model checker plus a bounded-BFS "simworld").

SummaryEach invariant's temporal-logic form derives its checker — proven, not sampled.
TargetBridge · System models
Formvalidation
EnforcementHard (deterministic) — an exhaustive model-check (state-space BFS / a temporal model checker) proves the invariant or emits a counterexample trace; a lint asserts the temporal form matches the routed checker

Motivation — the failure it kills

Some invariants are about a single reachable state: "a job is never both leased and free." Others are about interleavings over time: "a preempted job eventually re-runs." Stated in prose, or pinned by one example test, either kind can be believed true while a rare interleaving violates it: a property test samples the input space and sails past the one adversarial schedule; a distributed race has failure traces no hand-picked example hits. Worse, when the same invariant is restated in three places (prose, a runtime assertion, a formal spec) with nothing tying them, they drift; and a mis-declared liveness invariant gets routed to a safety runtime that structurally cannot see its violation, with zero signal.

Why it's not just "property-based testing"

A property test generates inputs and checks a predicate; it samples a space it cannot exhaust, so it raises confidence without proving. A model-check exhaustively explores the (bounded) state space: it either proves the invariant across every interleaving or returns a concrete counterexample trace. And the temporal form does something a property test conflates: it names safety vs liveness explicitly ([]P vs P ~> Q), and that operator derives which checker runs. The form is consumed, not decorative. A lint rejects an invariant whose temporal shape doesn't match its routed checker, so "a liveness property checked by a safety runtime" becomes impossible rather than silent. A sampled test that misses the one adversarial schedule reports green and moves on; the exhaustive check routed from the temporal form has no un-visited schedule to hide the bug in.

Mechanism

Each invariant records a temporal-logic form in a standard operator syntax: []P (always: safety), []<>P (infinitely often), P ~> Q (leads-to: liveness). The form is a required field: an invariant cannot be constructed without declaring its temporal shape (a defaulted boolean is exactly what rots). From that operator the model derives the verification tier and the checker. A safety property routes to an exhaustive state-space search (BFS over reachable states, or a model checker); a liveness property routes to a temporal model checker. A lint asserts the routed checker matches the operator (a leads-to body must carry the leads-to token; a safety body must not). Reuse one mature formal engine rather than building a parallel one, since an established model checker already subsumes the temporal logic.

Prerequisites

Consequences & costs

Known uses

Related mechanisms