Entry point for Spex runtime APIs and high-level integration.

Spex tracks observed runtime behaviour as implementation models and compares those models to declarative specifications (LTSs). It is designed for:

  • online runtime observation (init_instance*, transition*),
  • detection/reporting of behavioural deviations,
  • export and offline checking of derived implementation models.

Quick Start

  1. Define one or more specifications with Spex.Specification.
  2. Start Spex (or an instance manager) under a supervisor.
  3. Initialize instances with init_instance/4.
  4. Feed observed transitions with transition/3.

Minimal usage example:

:ok = Spex.init_instance(MySpec, :order_123)
:ok = Spex.transition(:order_123, :pay, :paid)
:ok = Spex.transition(:order_123, :ship, :shipped)

How To Start Spex

There are two primary integration styles.

1) Spex As Its Own OTP Application

This is the usual setup when the dependency is started normally (runtime: true, default). Your app depends on Spex and Spex boots its own supervision tree.

2) Explicit Supervision (runtime: false)

If Spex is configured with runtime: false, add either Spex or a concrete instance manager directly to your supervision tree:

children = [
  Spex
]

or:

children = [
  {Spex.InstanceManager.SimpleInstanceManager,
   impl_models_dir: "./spex_impl_models",
   dets_dir: "./spex_dets"}
]

or:

children = [
  {Spex.InstanceManager.DistributedInstanceManager,
   distribution_factor: 8,
   impl_models_dir: "./spex_impl_models",
   dets_dir: "./spex_dets"}
]

Online Production Usage

In production, call init_instance/4 when a domain entity begins its tracked lifecycle, then call transition/3 for each observed state change.

Behavioural checks and error handling are driven by the underlying specification (error_handler/2, timeout settings, pruning rules).

ImplModel Derivation During Tests

Spex can derive implementation models from test execution and persist them as .spex files. The main purpose of this derivation flow is to run offline bisimilarity checks with the mix spex task.

Typical flow:

Example:

# test/test_helper.exs
Spex.Testing.prepare_for_test_suite(impl_models_dir: "./test_meta/impl_models/live")

# CI or local verification
# Uses configured :impl_models_dir when no path is given
mix spex

Configuration Entry Point

This module delegates to a compile-time default instance manager selected via config :spex, :instance_manager.

Accepted forms are:

  • MyManagerModule
  • {MyManagerModule, manager_opts}

Documentation Map

Summary

Types

Action label on transitions.

State label used in specifications and runtime observations.

A labelled transition tuple {from_state, action, to_state}.

Types

action()

@type action() :: atom()

Action label on transitions.

Conventional reserved actions used internally by Spex are:

  • :__internal__ for unobservable/internal steps,
  • :__initialisation__ for synthetic instance initialization transitions.

state()

@type state() :: atom()

State label used in specifications and runtime observations.

transition()

@type transition() :: {from_state :: state(), action :: action(), to_state :: state()}

A labelled transition tuple {from_state, action, to_state}.

Functions

child_spec(opts)

@spec child_spec(keyword()) :: Supervisor.child_spec()

export_impl_models()

See Spex.InstanceManager.SimpleInstanceManager.export_impl_models/0.

init_instance(spec, instance_identifier, meta \\ nil, initial_state \\ nil)

See Spex.InstanceManager.SimpleInstanceManager.init_instance/4.

init_instance!(spec, instance_identifier, meta \\ nil, initial_state \\ nil)

See Spex.InstanceManager.SimpleInstanceManager.init_instance!/4.

init_instance_async(spec, instance_identifier, meta \\ nil, initial_state \\ nil)

See Spex.InstanceManager.SimpleInstanceManager.init_instance_async/4.

transition(instance_identifier, action, state)

See Spex.InstanceManager.SimpleInstanceManager.transition/3.

transition!(instance_identifier, action, state)

See Spex.InstanceManager.SimpleInstanceManager.transition!/3.

transition_async(instance_identifier, action, state)

See Spex.InstanceManager.SimpleInstanceManager.transition_async/3.