Practical guide

Choose between a data proof, a contract check and a code lemma

Z3 and Kind2 are not interchangeable “prove this program” buttons. Start by identifying whether the claim concerns data constraints, a temporal contract or a source function.

The tool name does not define the claim

Z3 solves logical constraints and can support program-proof obligations produced by a translator. Kind2 analyzes transition-system models and contracts. A model can be satisfiable, realizable or property-preserving under different questions. The official Z3 guide and Kind2 contract documentation describe these distinct roles.

Illustrative example: a maximum function

// Illustrative source claim; no solver result is asserted.
// reqproof:lemma max_bounds func(a, b int) bool {
//   return Max(a, b) >= a && Max(a, b) >= b
// }
func Max(a, b int) int {
    if a > b { return a }
    return b
}

The bound is meaningful but incomplete as a specification of maximum: a function returning a larger unrelated value could satisfy it. Add the requirement that the result equals one of the inputs. The example uses comparisons, so it does not depend on an unreviewed arithmetic-overflow assumption.

Use the corresponding Proof path

Commands answer different questions
Path Subject
proof verify-properties specs/system limits Supported authored variable properties and data constraints
proof realize specs/system controller Realizability of the modeled component contract
proof verify-lemma ./internal/mathx Supported source lemmas translated to solver obligations

The paths and components are examples. realize takes a configured spec and component, not a source package glob. A result for a contract is not a proof that the package implements it.

Inspect assumptions and translation limits

For a source lemma, review preconditions, assumed callees, trusted summaries and supported language features. A solver decides the translated formula. A successful result cannot repair an inaccurate translation boundary or an unjustified summary. Read unknown, timeout and translation errors as distinct outcomes rather than success. Separate-file binding hashes track freshness, not semantic equivalence.

Preserve the evidence that makes the result useful

Record the claim, source revision, solver configuration and actual verdict. Add tests for callers and environment outside the local lemma. Review whether the property would reject a plausible bug, then rerun the affected evidence when source or intent changes. Report the measured outcome of the actual run, with its assumptions and unresolved obligations.

Follow the evidence

Write the claim first, then select the analysis path that can actually address it.

Scope one formal claim. Bring the property and source boundary so we can identify the analysis path that addresses it and the evidence that path cannot supply.

Review source correspondence · Separate formal questions