Documentation
¶
Index ¶
- func Debug(w io.Writer, opts ...Option) error
- func GetMachine[T AbstractStateMachine](m Machines, sm T) (T, bool)
- func Goto(ctx context.Context, state AbstractState)
- func Halt(ctx context.Context, target AbstractStateMachine)
- func NewHandlerContext(sm AbstractStateMachine) context.Context
- func OnEntry[SM AbstractStateMachine](spec *StateMachineSpec[SM], state AbstractState, fn EntryHandler[SM])
- func OnEvent[T AbstractEvent, SM AbstractStateMachine](spec *StateMachineSpec[SM], state AbstractState, fn EventHandler[T, SM])
- func OnExit[SM AbstractStateMachine](spec *StateMachineSpec[SM], state AbstractState, fn ExitHandler[SM])
- func OnHalt[SM AbstractStateMachine](spec *StateMachineSpec[SM], state AbstractState, fn HaltHandler[SM])
- func OnTransition[SM AbstractStateMachine](spec *StateMachineSpec[SM], state AbstractState, fn TransitionHandler[SM])
- func SendTo(ctx context.Context, target AbstractStateMachine, event AbstractEvent)
- func WriteDot(w io.Writer, opts ...Option) error
- type AbstractEvent
- type AbstractState
- type AbstractStateMachine
- type Condition
- func BoolCondition(name string, b bool) Condition
- func NewCondition[T AbstractStateMachine](name string, sm T, check func(T) bool) Condition
- func NewCondition2[T1, T2 AbstractStateMachine](name string, sm1 T1, sm2 T2, check func(T1, T2) bool) Condition
- func NewCondition3[T1, T2, T3 AbstractStateMachine](name string, sm1 T1, sm2 T2, sm3 T3, check func(T1, T2, T3) bool) Condition
- func NewMultiCondition(name string, checkFunc func(Machines) bool, sms ...AbstractStateMachine) Condition
- type ConditionName
- type EntryHandler
- type Event
- type EventHandler
- type EventSnapshot
- type ExitHandler
- type HaltHandler
- type Machines
- type Option
- type Result
- type Rule
- type State
- type StateMachine
- type StateMachineSnapshot
- type StateMachineSpec
- type Summary
- type TransitionHandler
- type UnTypedEvent
- type Violation
- type WorldSnapshot
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Debug ¶
Debug performs model checking and outputs detailed JSON results. Unlike Test(), this function provides comprehensive debugging information including all explored worlds and their states in JSON format.
Parameters:
- w: Writer to output the JSON results to
- opts: Configuration options including state machines and invariants
Returns an error if model creation, solving, or JSON encoding fails.
Example:
var buf bytes.Buffer err := goat.Debug(&buf, goat.WithStateMachines(sm), goat.WithRules(goat.Always(cond))) fmt.Println(buf.String()) // JSON output
func GetMachine ¶ added in v0.2.0
func GetMachine[T AbstractStateMachine](m Machines, sm T) (T, bool)
GetMachine provides type-safe access to a state machine from Machines.
Parameters:
- m: Machines accessor provided to the check function
- sm: A sample instance used to identify the target machine by ID
Returns the typed state machine and true on success. Returns the zero value and false when the machine does not exist or the type does not match.
Example:
machine, ok := goat.GetMachine(machines, client)
if !ok { return false }
state := machine.currentState().(*ClientState)
func Goto ¶
func Goto(ctx context.Context, state AbstractState)
Goto triggers a state transition for the current state machine. This function must be called from within event handlers registered with OnEvent, OnEntry, OnExit, OnTransition, or OnHalt functions. It automatically generates the necessary sequence of events (Exit, Transition, Entry).
Parameters:
- ctx: Context passed to the event handler
- state: The target state to transition to
Example:
goat.OnEvent(spec, IdleState{}, func(ctx context.Context, event Event, sm *MyStateMachine) {
goat.Goto(ctx, &ActiveState{Ready: true})
})
func Halt ¶
func Halt(ctx context.Context, target AbstractStateMachine)
Halt stops the execution of a specific state machine permanently. This function must be called from within event handlers registered with OnEvent, OnEntry, OnExit, OnTransition, or OnHalt functions. It triggers the haltEvent and any associated cleanup handlers.
Parameters:
- ctx: Context passed to the event handler
- target: The state machine to halt
Example:
goat.OnEvent(spec, ActiveState{}, func(ctx context.Context, event Event, sm *MyStateMachine) {
goat.Halt(ctx, sm) // Stop this state machine
})
func NewHandlerContext ¶ added in v0.5.0
func NewHandlerContext(sm AbstractStateMachine) context.Context
NewHandlerContext creates a context with a minimal environment for executing handlers. This is used when you need to execute handlers outside of the normal model checking flow.
Parameters:
- sm: The state machine instance to include in the context
Returns a context that can be used with SendTo, Goto, and other handler functions.
Example:
instance, _ := spec.NewInstance() ctx := goat.NewHandlerContext(instance) response := handler(ctx, input, instance)
func OnEntry ¶
func OnEntry[SM AbstractStateMachine]( spec *StateMachineSpec[SM], state AbstractState, fn EntryHandler[SM], )
OnEntry registers an entry handler that defines what actions the state machine should perform when entering a specific state. This allows you to specify initialization logic, setup operations, or state-specific preparations.
Parameters:
- spec: The state machine specification to register the handler with
- state: The state for which to register the entry handler
- fn: The function to call when entering the state
Example:
goat.OnEntry(spec, ActiveState{}, func(ctx context.Context, sm *MyStateMachine) {
// Perform initialization when entering active state
sm.StartTime = time.Now()
})
func OnEvent ¶
func OnEvent[T AbstractEvent, SM AbstractStateMachine]( spec *StateMachineSpec[SM], state AbstractState, fn EventHandler[T, SM], )
OnEvent registers an event handler that defines how a state machine responds to a specific event when in a particular state. This is the primary way to specify the behavior and reactions of your state machine to events.
Parameters:
- spec: The state machine specification to register the handler with
- state: The state in which this handler should be active
- fn: The function to call when the event occurs
Example:
goat.OnEvent(spec, IdleState{}, func(ctx context.Context, event Event, sm *MyStateMachine) {
// Handle start event
goat.Goto(ctx, &ActiveState{})
})
func OnExit ¶
func OnExit[SM AbstractStateMachine]( spec *StateMachineSpec[SM], state AbstractState, fn ExitHandler[SM], )
OnExit registers an exit handler that defines what cleanup or finalization actions the state machine should perform when leaving a specific state. This is essential for proper resource management and state transitions.
Parameters:
- spec: The state machine specification to register the handler with
- state: The state for which to register the exit handler
- fn: The function to call when exiting the state
Example:
goat.OnExit(spec, ActiveState{}, func(ctx context.Context, sm *MyStateMachine) {
// Perform cleanup when exiting active state
sm.cleanup()
})
func OnHalt ¶
func OnHalt[SM AbstractStateMachine]( spec *StateMachineSpec[SM], state AbstractState, fn HaltHandler[SM], )
OnHalt registers a halt handler that defines what final cleanup or shutdown actions the state machine should perform when stopping execution while in a specific state. This ensures proper termination and resource cleanup.
Parameters:
- spec: The state machine specification to register the handler with
- state: The state for which to register the halt handler
- fn: The function to call when the state machine halts
Example:
goat.OnHalt(spec, ActiveState{}, func(ctx context.Context, sm *MyStateMachine) {
// Perform final cleanup before halting
sm.saveState()
})
func OnTransition ¶
func OnTransition[SM AbstractStateMachine]( spec *StateMachineSpec[SM], state AbstractState, fn TransitionHandler[SM], )
OnTransition registers a transition handler that defines what actions should occur during state transitions from a specific state. This allows you to specify logic that runs between exiting one state and entering another.
Parameters:
- spec: The state machine specification to register the handler with
- state: The source state for which to register the transition handler
- fn: The function to call during transition from this state
Example:
goat.OnTransition(spec, IdleState{}, func(ctx context.Context, toState AbstractState, sm *MyStateMachine) {
// Log transition from idle to any other state
log.Printf("Transitioning from Idle to %T", toState)
})
func SendTo ¶
func SendTo(ctx context.Context, target AbstractStateMachine, event AbstractEvent)
SendTo sends an event to a specific state machine. This function must be called from within event handlers registered with OnEvent, OnEntry, OnExit, OnTransition, or OnHalt functions.
Parameters:
- ctx: Context passed to the event handler
- target: The state machine that should receive the event
- event: The event to send
Example:
goat.OnEntry(spec, IdleState{}, func(ctx context.Context, sm *MyStateMachine) {
goat.SendTo(ctx, otherSM, Event{Name: "NOTIFY"})
})
func WriteDot ¶
WriteDot performs model checking and outputs the state graph in DOT format. The output can be used with Graphviz to visualize the state space and identify paths to invariant violations.
Parameters:
- w: Writer to output the DOT graph to
- opts: Configuration options including state machines and invariants
Returns an error if model creation or solving fails.
Example:
var file *os.File
file, err := os.Create("model.dot")
if err != nil {
return err
}
defer file.Close()
err = goat.WriteDot(file, goat.WithStateMachines(sm), goat.WithRules(goat.Always(cond)))
Types ¶
type AbstractEvent ¶
type AbstractEvent interface {
// contains filtered or unexported methods
}
type AbstractState ¶
type AbstractState interface {
// contains filtered or unexported methods
}
AbstractState is the base interface for all states in the state machine. States represent discrete conditions or modes that a state machine can be in.
Implementations should embed the State struct to satisfy this interface.
Example:
type IdleState struct {
goat.State
Timeout int
}
type AbstractStateMachine ¶
type AbstractStateMachine interface {
SetInitialState(state AbstractState)
// contains filtered or unexported methods
}
AbstractStateMachine is the base interface for all state machines. State machines encapsulate behavior and state transitions in response to events.
Implementations must embed the StateMachine struct. Instances are typically created through NewStateMachineSpec and its methods for proper configuration.
Example:
type MyStateMachine struct {
goat.StateMachine
CustomData string
}
// Create via specification
spec := goat.NewStateMachineSpec(&MyStateMachine{})
spec.DefineStates(IdleState{}, ActiveState{}).
SetInitialState(IdleState{})
instance := spec.NewInstance()
type Condition ¶ added in v0.3.0
type Condition interface {
Name() ConditionName
Evaluate(w world) bool
}
Condition represents a named predicate evaluated against a world. Implementations must return true when the condition holds for the provided world, and false otherwise.
func BoolCondition ¶ added in v0.3.0
BoolCondition creates a condition from a constant boolean value. This is useful for creating conditions that always pass (true) or always fail (false), typically used for testing or as placeholder conditions.
Parameters:
- name: The name of this condition
- b: The boolean value that this condition will always return
Returns a Condition that can be used with Test() (for example via WithRules(Always(...))).
Example:
alwaysPass := goat.BoolCondition("pass", true)
alwaysFail := goat.BoolCondition("fail", false)
func NewCondition ¶ added in v0.3.0
func NewCondition[T AbstractStateMachine](name string, sm T, check func(T) bool) Condition
NewCondition creates a condition for a specific state machine instance. It allows checking properties of that particular state machine during model exploration and testing.
Parameters:
- name: The condition name
- sm: The state machine instance to create a condition for
- check: A predicate function that returns true if the condition holds
Returns a Condition that can be used with Test() (for example via WithRules(Always(...))).
Example:
serverCond := goat.NewCondition("conn-limit", serverSM, func(sm *ServerStateMachine) bool {
return sm.ConnectionCount <= sm.MaxConnections
})
func NewCondition2 ¶ added in v0.3.0
func NewCondition2[T1, T2 AbstractStateMachine](name string, sm1 T1, sm2 T2, check func(T1, T2) bool) Condition
NewCondition2 creates a condition that references two state machines.
Parameters:
- name: The condition name
- sm1, sm2: The state machines to reference
- check: A predicate function that returns true if the condition holds
Returns a Condition that can be used with Test() (for example via WithRules(Always(...))).
Example:
cond := goat.NewCondition2("pair", client, server, func(c *Client, s *Server) bool {
return true
})
func NewCondition3 ¶ added in v0.3.0
func NewCondition3[T1, T2, T3 AbstractStateMachine](name string, sm1 T1, sm2 T2, sm3 T3, check func(T1, T2, T3) bool) Condition
NewCondition3 creates a condition that references three state machines.
Parameters:
- name: The condition name
- sm1, sm2, sm3: The state machines to reference
- check: A predicate function that returns true if the condition holds
Returns a Condition that can be used with Test() (for example via WithRules(Always(...))).
Example:
cond := goat.NewCondition3("triple", client, server, db, func(c *Client, s *Server, d *Database) bool {
return true
})
func NewMultiCondition ¶ added in v0.3.0
func NewMultiCondition(name string, checkFunc func(Machines) bool, sms ...AbstractStateMachine) Condition
NewMultiCondition creates a condition that can reference multiple state machines. The provided check function receives a Machines accessor.
Parameters:
- name: The condition name
- checkFunc: Predicate that inspects one or more state machines
- sms: State machines referenced by the condition
Returns a Condition that can be used with Test() (for example via WithRules(Always(...))).
Example:
func NewConditionClientServer(client *Client, server *Server, check func(*Client, *Server) bool) goat.Condition {
return goat.NewMultiCondition("client-server", func(machines goat.Machines) bool {
c, ok1 := goat.GetMachine(machines, client)
if !ok1 { return false }
s, ok2 := goat.GetMachine(machines, server)
if !ok2 { return false }
return check(c, s)
}, client, server)
}
// Usage
cond := NewConditionClientServer(client, server, func(c *Client, s *Server) bool {
// business logic referencing both machines
return c.Server != nil && s != nil
})
type ConditionName ¶ added in v0.3.0
type ConditionName string
ConditionName represents the identifier for a condition.
func (ConditionName) String ¶ added in v0.4.0
func (c ConditionName) String() string
type EntryHandler ¶
type EntryHandler[SM AbstractStateMachine] func(ctx context.Context, sm SM)
EntryHandler is a function type for handling state entry events. It is called when a state machine enters a new state.
type Event ¶
type Event[Sender AbstractStateMachine, Recipient AbstractStateMachine] struct { // contains filtered or unexported fields }
Event is the base struct that should be embedded in all event implementations. It provides the required methods to satisfy the AbstractEvent interface and ensures events are properly copyable for the state machine system.
Example:
type MyCustomEvent struct {
goat.Event[*ProducerStateMachine, *ConsumerStateMachine]
Payload string
}
func (*Event[Sender, Recipient]) Recipient ¶ added in v0.3.0
func (e *Event[Sender, Recipient]) Recipient() Recipient
Recipient returns the recipient using the concrete type specified by the event's type parameters. If the actual recipient does not match the requested type, the zero value for Recipient is returned.
Parameters:
- e: The event whose recipient should be retrieved.
Example:
var event goat.Event[*ProducerStateMachine, *ConsumerStateMachine]
typedRecipient := event.Recipient()
if typedRecipient != nil {
// Use the strongly typed recipient
}
func (*Event[Sender, Recipient]) Sender ¶ added in v0.3.0
func (e *Event[Sender, Recipient]) Sender() Sender
Sender returns the sender using the concrete type specified by the event's type parameters. If the actual sender does not match the requested type, the zero value for Sender is returned.
Parameters:
- e: The event whose sender should be retrieved.
Example:
var event goat.Event[*ProducerStateMachine, *ConsumerStateMachine]
typedSender := event.Sender()
if typedSender != nil {
// Use the strongly typed sender
}
type EventHandler ¶
type EventHandler[T AbstractEvent, SM AbstractStateMachine] func(ctx context.Context, event T, sm SM)
EventHandler is a function type for handling generic events in a state machine. It receives the event, the state machine instance, and a context for interacting with other state machines via SendTo, Goto, or Halt functions.
type EventSnapshot ¶ added in v0.6.0
EventSnapshot is a snapshot of a queued event.
type ExitHandler ¶
type ExitHandler[SM AbstractStateMachine] func(ctx context.Context, sm SM)
ExitHandler is a function type for handling state exit events. It is called when a state machine exits its current state.
type HaltHandler ¶
type HaltHandler[SM AbstractStateMachine] func(ctx context.Context, sm SM)
HaltHandler is a function type for handling halt events. It is called when a state machine is about to stop permanently.
type Machines ¶ added in v0.2.0
type Machines interface {
Get(sm AbstractStateMachine) (AbstractStateMachine, bool)
}
Machines provides type-safe access to state machines during condition evaluation. It is used inside check functions to reference multiple state machines.
Implementations return false when the requested state machine does not exist in the current world.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option is a configuration option for model checking operations. Options are used with Test() and Debug() functions to configure state machines, conditions, invariants, and other testing parameters.
Use the provided helper functions like WithStateMachines(), WithRules() to create options.
Example:
result, err := goat.Test(
goat.WithStateMachines(sm1, sm2),
goat.WithRules(goat.Always(cond1)),
)
func WithRules ¶ added in v0.3.0
WithRules returns an Option that registers the provided rules during model checking.
Parameters:
- rs: Rules created with helpers such as Always or WheneverPEventuallyQ
Returns an Option that can be supplied to Test.
Example:
result, err := goat.Test( goat.WithStateMachines(node), goat.WithRules( goat.Always(consistency), goat.WheneverPEventuallyQ(requested, responded), ), )
func WithStateMachines ¶
func WithStateMachines(sms ...AbstractStateMachine) Option
WithStateMachines configures the test with the specified state machines. These state machines will be included in the model checking process.
Parameters:
- sms: The state machines to include in the test
Returns an Option that can be passed to Test() or Debug().
Example:
goat.WithStateMachines(serverSM, clientSM, proxysSM)
type Result ¶ added in v0.6.0
Result holds the outcome of a model checking run.
func Test ¶
Test performs model checking on state machines with the provided options. It creates a Kripke model, explores all reachable states, checks invariants and temporal properties, and returns the results.
Parameters:
- opts: Configuration options including state machines and rules
Returns:
- *Result: verification results (violations, path information, summary)
- error: if model creation or solving fails
Example:
result, err := goat.Test(
goat.WithStateMachines(serverSM, clientSM),
goat.WithRules(goat.Always(cond)),
)
if err != nil {
log.Fatal(err)
}
// result is automatically printed to stdout
func (*Result) HasViolation ¶ added in v0.6.0
HasViolation reports whether any violations were found.
type Rule ¶ added in v0.3.0
type Rule interface {
// contains filtered or unexported methods
}
Rule represents a property that can be enforced during model checking. Rules register additional checks that run while exploring the state space.
func Always ¶ added in v0.3.0
Always returns a rule that ensures c holds in every explored world.
Parameters:
- c: Condition that must remain true in all explored states
Returns a Rule that can be supplied to WithRules.
Example:
result, err := goat.Test( goat.WithStateMachines(node), goat.WithRules( goat.Always(healthy), ), )
func AlwaysEventually ¶ added in v0.3.0
AlwaysEventually returns a rule enforcing that c holds infinitely often.
Parameters:
- c: Condition that must recur indefinitely
Returns a Rule that can be registered with WithRules.
Example:
result, err := goat.Test( goat.WithStateMachines(node), goat.WithRules( goat.AlwaysEventually(heartbeat), ), )
func EventuallyAlways ¶ added in v0.3.0
EventuallyAlways returns a rule enforcing that c eventually holds forever.
Parameters:
- c: Condition that must eventually remain true
Returns a Rule that can be registered with WithRules.
Example:
result, err := goat.Test( goat.WithStateMachines(nodes...), goat.WithRules( goat.EventuallyAlways(stable), ), )
func WheneverPEventuallyQ ¶ added in v0.3.0
WheneverPEventuallyQ returns a rule enforcing that whenever p holds, q eventually holds.
Parameters:
- p: Condition that triggers the obligation
- q: Condition that must eventually become true
Returns a Rule that can be registered with WithRules.
Example:
result, err := goat.Test( goat.WithStateMachines(primary, replica), goat.WithRules( goat.WheneverPEventuallyQ(write, replicated), ), )
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is the base struct that should be embedded in all state implementations. It provides the required methods to satisfy the AbstractState interface and ensures states are properly copyable for the state machine system.
Example:
type MyState struct {
goat.State
CustomField int
}
type StateMachine ¶
type StateMachine struct {
EventHandlers map[AbstractState][]handlerInfo
HandlerBuilders map[AbstractState][]handlerBuilderInfo
State AbstractState
// contains filtered or unexported fields
}
StateMachine provides the core infrastructure for state machine behavior. It must be embedded in concrete state machine implementations to provide state management, event handling, and transition capabilities.
Do not instantiate directly; instead embed in your state machine types and use NewStateMachineSpec to create properly configured instances.
Example:
type MyStateMachine struct {
goat.StateMachine
Data string
}
func (*StateMachine) SetInitialState ¶
func (sm *StateMachine) SetInitialState(state AbstractState)
SetInitialState sets the starting state for this state machine instance. This can only be called once per instance, typically during initialization.
Parameters:
- state: The state this state machine should start in
Panics if the initial state has already been set.
Example:
sm.SetInitialState(&IdleState{})
type StateMachineSnapshot ¶ added in v0.6.0
StateMachineSnapshot is a snapshot of a single state machine.
type StateMachineSpec ¶
type StateMachineSpec[T AbstractStateMachine] struct { // contains filtered or unexported fields }
StateMachineSpec defines the specification for a state machine type. It serves as a template for creating multiple instances of the same state machine with consistent behavior and state definitions.
Use NewStateMachineSpec to create a specification, then configure it with DefineStates and SetInitialState before creating instances.
func NewStateMachineSpec ¶
func NewStateMachineSpec[T AbstractStateMachine](prototype T) *StateMachineSpec[T]
NewStateMachineSpec creates a new state machine specification with the given prototype. The prototype defines the structure and behavior that all instances created from this spec will share.
Parameters:
- prototype: An instance of the state machine type to use as template
Returns a specification that can be configured with states and handlers.
Example:
spec := goat.NewStateMachineSpec(&MyStateMachine{})
spec.DefineStates(StateA{}, StateB{}).
SetInitialState(StateA{})
func (*StateMachineSpec[T]) DefineStates ¶
func (spec *StateMachineSpec[T]) DefineStates(states ...AbstractState) *StateMachineSpec[T]
DefineStates sets the valid states for this state machine specification. It configures all provided states and sets up default handlers for each.
Parameters:
- states: All valid states that this state machine can be in
Returns the spec for method chaining.
Example:
spec.DefineStates(IdleState{}, ActiveState{}, ErrorState{})
func (*StateMachineSpec[T]) NewInstance ¶
func (spec *StateMachineSpec[T]) NewInstance() (T, error)
NewInstance creates a new state machine instance based on this specification. Each instance is independent and starts in the initial state defined by SetInitialState with all handlers configured.
Returns a fully configured state machine instance and any validation error.
Example:
instance1, err := spec.NewInstance()
if err != nil {
return err
}
instance2, err := spec.NewInstance() // Independent instance
func (*StateMachineSpec[T]) SetInitialState ¶
func (spec *StateMachineSpec[T]) SetInitialState(state AbstractState) *StateMachineSpec[T]
SetInitialState defines which state new instances will start in. The provided state must be one of the states defined in DefineStates.
Parameters:
- state: The state that new instances should start in
Returns the spec for method chaining.
Example:
spec.SetInitialState(IdleState{})
type Summary ¶ added in v0.6.0
type Summary struct {
// TotalWorlds is the number of distinct worlds (unique combinations of
// state machine states and queued events) explored during model checking.
TotalWorlds int
ExecutionTimeMs int64
}
Summary contains statistics about the model checking run.
type TransitionHandler ¶
type TransitionHandler[SM AbstractStateMachine] func(ctx context.Context, toState AbstractState, sm SM)
TransitionHandler is a function type for handling state transitions. It receives information about the target state and the state machine.
type UnTypedEvent ¶ added in v0.3.0
type UnTypedEvent = Event[AbstractStateMachine, AbstractStateMachine]
UnTypedEvent is a convenience alias for an Event that does not specify concrete sender or recipient types.
type Violation ¶ added in v0.6.0
type Violation struct {
Rule string
Path []WorldSnapshot
Loop []WorldSnapshot
}
Violation represents a single property violation found during model checking.
type WorldSnapshot ¶ added in v0.6.0
type WorldSnapshot struct {
StateMachines []StateMachineSnapshot
QueuedEvents []EventSnapshot
}
WorldSnapshot represents a world — the combination of every state machine's current state and all queued events at a single point in time. A violation path is a sequence of worlds that leads to the violation.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
example
|
|
|
client-server
command
|
|
|
simple-halt
command
|
|
|
simple-non-deterministic
command
|
|
|
simple-transition
command
|
|
|
temporal-rule
command
|
|
|
temporal-rule-violation
command
|
|
|
internal
|
|
|
example
command
|
|
|
example
command
|