Skip to content

Implicit State Derivation v2 Proposal ​

Status: 🟑 DRAFT

Supersedes: IMPLICIT_STATES_PROPOSAL.md (REJECTED)


Executive Summary ​

This proposal demonstrates that implicit state derivation is fully achievable in EventFlow. The v1 proposal rejection was overly pessimistic - structural analysis of code can determine states with high confidence in virtually all cases.

Key Insight ​

The v1 rejection's "calculator ambiguity" example is NOT ambiguous:

flow
on :add (api)          // No guards = can run anytime
on :subtract (api)     // No guards = can run anytime

Without guards, these handlers ARE independent. The code tells us this - there's no ambiguity to resolve. No guards + No emit = Single state machine.

Three Derivation Strategies ​

  1. Event-Flow Derivation (95% confidence) - From emit ... to @actor + response handlers
  2. Guard-Derived States (85% confidence) - From ? $variable exists and similar guards
  3. Context-Derived States (80% confidence) - From mode variables with enumerated values

What's Actually Undecidable? ​

Very little. The only truly undecidable cases are:

  • Timeout events without explicit source or scheduling
  • Race conditions in parallel responses (runtime concern, not derivation)

Machine mode markers are OPTIONAL - they document intent but don't change derivation. The algorithm derives states from code structure, not developer annotations.


Addressing the v1 Rejection ​

The Original Rejection Reason ​

The relationship between event handlers (whether they form a sequential process or are independent operations) is semantic information that cannot be inferred from code structure alone.

Example: Given two handlers :checkout and :payment_received, the CLI cannot determine if these are part of a sequential checkout process, or two independent operations (like a calculator with separate :add, :subtract operations).

Why This Rejection is Overly Pessimistic ​

The rejection treats all event handlers as equally ambiguous. In reality, structural and contextual signals exist that disambiguate most cases:

SignalWhat It Tells UsConfidence
emit :X to @Y + on :response from @YSequential request/responseHigh
(api) marker on handlerExternal entry pointHigh
from @actor clauseEvent origin is explicitHigh
Guards checking $variable existsHandler depends on prior stateMedium
Context variable data flowHandler depends on prior handlerMedium
scenario: block groupingEvents are relatedMedium

The :checkout β†’ :payment_received example is not ambiguous when we look at the full context:

flow
on :checkout from @customer (api)
  emit :request_payment to @payment    // ← This TELLS us we're waiting for payment

on :payment_received from @payment     // ← This is the RESPONSE

The emit ... to @payment followed by on ... from @payment is an explicit request/response pattern. This is not semantic guessing - it's structural analysis.

What About the Calculator Example? ​

The v1 rejection used a calculator as an example of ambiguity:

flow
machine: @calculator

on :add (api)
  $result increases by $value

on :subtract (api)
  $result decreases by $value

This is NOT ambiguous. Here's why:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                         β”‚
β”‚  FUNDAMENTAL RULE: No Guards = No Sequence = Independent Operations     β”‚
β”‚                                                                         β”‚
β”‚  If handler B required handler A to run first, there would be a guard:  β”‚
β”‚                                                                         β”‚
β”‚    on :subtract (api)                                                   β”‚
β”‚      ? $add_was_called      ← This guard would ENFORCE sequence         β”‚
β”‚      $result decreases by $value                                        β”‚
β”‚                                                                         β”‚
β”‚  Without such a guard, BOTH handlers can run at ANY time.               β”‚
β”‚  This means they ARE independent - not "might be" independent.          β”‚
β”‚                                                                         β”‚
β”‚  RESULT: Single state (#ready) with self-loops                          β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The derivation is deterministic:

Code StructureDerivation Result
Multiple (api) handlers, no guardsSingle #ready state, all handlers loop back
Multiple (api) handlers, with guardsGuards define the implicit states
Handlers with emit/from patternsWait states from communication patterns

EventFlow derives states from CODE, not developer intent. If a developer wants sequential behavior but doesn't write guards, that's either:

  1. A bug (guards should be added)
  2. Or they actually don't need sequencing

The Core Derivation Principle ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                         β”‚
β”‚                    THE STATE DERIVATION AXIOM                           β”‚
β”‚                                                                         β”‚
β”‚  A STATE exists when and only when:                                     β”‚
β”‚                                                                         β”‚
β”‚    1. A WAIT POINT exists (machine is waiting for an event)             β”‚
β”‚       - After emit to another actor                                     β”‚
β”‚       - After queued/async operation                                    β”‚
β”‚       - At machine start (initial state)                                β”‚
β”‚                                                                         β”‚
β”‚    2. A GUARD PARTITION exists (behavior differs based on condition)    β”‚
β”‚       - ? $variable exists                                              β”‚
β”‚       - ? $mode is "value"                                              β”‚
β”‚       - ? machine is in #state                                          β”‚
β”‚                                                                         β”‚
β”‚    3. An EXPLICIT DECLARATION exists                                    β”‚
β”‚       - moves to #state                                                 β”‚
β”‚       - machine mode marker                                             β”‚
β”‚                                                                         β”‚
β”‚  If NONE of these exist β†’ Single state with self-loops                  β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Insight: State Types by Derivation Source ​

States in EventFlow can be categorized by how they are derived:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         STATE DERIVATION TAXONOMY                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  1. EVENT-FLOW DERIVED STATES                                       β”‚   β”‚
β”‚  β”‚     Source: emit/response patterns, cross-machine communication     β”‚   β”‚
β”‚  β”‚     Confidence: HIGH                                                β”‚   β”‚
β”‚  β”‚     Example: emit :pay to @payment β†’ waiting β†’ on :paid from @pay   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  2. GUARD-DERIVED STATES                                            β”‚   β”‚
β”‚  β”‚     Source: Conditional logic that partitions behavior              β”‚   β”‚
β”‚  β”‚     Confidence: MEDIUM                                              β”‚   β”‚
β”‚  β”‚     Example: ? $pending_op exists β†’ "has pending operation" state   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  3. CONTEXT-DERIVED STATES                                          β”‚   β”‚
β”‚  β”‚     Source: Variable existence/value creating behavior modes        β”‚   β”‚
β”‚  β”‚     Confidence: MEDIUM                                              β”‚   β”‚
β”‚  β”‚     Example: $mode = "degrees" vs "radians" β†’ different calc modes  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  4. DECLARED STATES (Explicit)                                      β”‚   β”‚
β”‚  β”‚     Source: Developer uses `moves to #state` or mode markers        β”‚   β”‚
β”‚  β”‚     Confidence: EXPLICIT                                            β”‚   β”‚
β”‚  β”‚     Example: order moves to #shipped                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  5. DEFAULT STATE (Stateless Operations)                            β”‚   β”‚
β”‚  β”‚     Source: No state transitions, all handlers return to #ready     β”‚   β”‚
β”‚  β”‚     Confidence: HIGH (when declared with mode marker)               β”‚   β”‚
β”‚  β”‚     Example: machine: @calculator (stateless)                       β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Algorithm 1: Event-Flow Derivation ​

Overview ​

Event-flow derivation identifies states from explicit communication patterns between machines or actors. This is the highest-confidence derivation method.

Algorithm ​

ALGORITHM: EventFlowStateDerivation

INPUT:
  - flow_file: Parsed EventFlow AST

OUTPUT:
  - states: List of derived states with transitions

PROCEDURE:

1. IDENTIFY ENTRY POINTS
   ─────────────────────
   For each handler H in flow_file:
     If H has (api) marker:
       Add H.event to entry_points
       Mark as "can be triggered from #initial"

2. BUILD EMIT/RESPONSE GRAPH
   ──────────────────────────
   For each handler H in flow_file:
     For each emit E in H.actions:
       Create edge: H.event β†’ E.target_event
       If E has "to @actor" clause:
         expected_responses = FindHandlers(from: @actor)
         For each R in expected_responses:
           Create edge: E β†’ R (response relationship)
           Mark transition: "after E, waiting for R"

3. IDENTIFY WAIT POINTS
   ─────────────────────
   For each emit E with expected_responses:
     Create state: #after_{E.event} or #awaiting_{response.event}
     Type: waiting
     Waiting_for: expected_responses

4. IDENTIFY TERMINAL POINTS
   ─────────────────────────
   For each handler H:
     If H has no outgoing edges (no emit, no further handlers expected):
       Create state: #after_{H.event}
       Type: terminal
       Analyze for outcome (success/failure/neutral)

5. CONNECT TRANSITIONS
   ────────────────────
   For each state S:
     incoming = events that lead to S
     outgoing = events that exit S
     Create transition map

RETURN states with full transition graph

Visual Representation ​

                    EMIT/RESPONSE PATTERN DETECTION

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚                                                                 β”‚
  β”‚   on :checkout from @customer (api)                             β”‚
  β”‚     validate cart                                               β”‚
  β”‚     emit :request_payment to @payment  ──────────┐              β”‚
  β”‚                   β”‚                              β”‚              β”‚
  β”‚                   β”‚                              β”‚              β”‚
  β”‚                   β–Ό                              β”‚              β”‚
  β”‚         ╔═════════════════════╗                  β”‚              β”‚
  β”‚         β•‘    WAIT POINT       β•‘                  β”‚              β”‚
  β”‚         β•‘  #awaiting_payment  β•‘                  β”‚              β”‚
  β”‚         β•‘                     β•‘                  β”‚              β”‚
  β”‚         β•‘  waiting_for:       β•‘                  β”‚              β”‚
  β”‚         β•‘   - :payment_success║◄──────────────────              β”‚
  β”‚         β•‘   - :payment_failed ║◄──────────────────              β”‚
  β”‚         β•šβ•β•β•β•β•β•β•β•β•β•β•€β•β•β•β•β•β•β•β•β•β•β•                  β”‚              β”‚
  β”‚                    β”‚                             β”‚              β”‚
  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚              β”‚
  β”‚    β–Ό                                β–Ό            β”‚              β”‚
  β”‚  on :payment_success          on :payment_failed β”‚              β”‚
  β”‚  from @payment                from @payment      β”‚              β”‚
  β”‚    β”‚                               β”‚             β”‚              β”‚
  β”‚    β–Ό                               β–Ό             β”‚              β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚              β”‚
  β”‚  β”‚ TERMINAL β”‚                β”‚ TERMINAL β”‚        β”‚              β”‚
  β”‚  β”‚#confirmedβ”‚                β”‚ #failed  β”‚        β”‚              β”‚
  β”‚  β”‚ success  β”‚                β”‚ failure  β”‚        β”‚              β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚              β”‚
  β”‚                                                                 β”‚
  β”‚  DERIVED BECAUSE: emit to @payment creates expectation          β”‚
  β”‚                   for response from @payment                    β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pattern Catalog ​

PatternDetectionWait State Created
emit :X to @YDirect emit to actor#awaiting_{X}_response
emit async :X + handler existsAsync with callback#processing_{X}
(queued api)Background processing#queued_{event}
reply 202 async forDeferred response#processing_{request}
emit :X + on :X_success / on :X_failedSuccess/failure pattern#awaiting_{X}_result

Algorithm 2: Guard-Derived States ​

Overview ​

Guard-derived states emerge when conditional logic partitions the machine's behavior based on runtime conditions. Guards that check for the existence or value of context variables effectively define implicit states.

Core Insight ​

flow
on :number (api)
  ? $pending_operation exists     // ← This guard IMPLIES a state
    perform calculation
  otherwise
    $operand becomes $value       // ← Different behavior = different state

The guard ? $pending_operation exists tells us:

  • There's a state where $pending_operation does NOT exist
  • There's a state where $pending_operation DOES exist
  • These states have different behaviors for the same event

Algorithm ​

ALGORITHM: GuardDerivedStateDetection

INPUT:
  - flow_file: Parsed EventFlow AST

OUTPUT:
  - implicit_states: States derived from guard conditions
  - state_constraints: What context conditions define each state

PROCEDURE:

1. EXTRACT GUARD CONDITIONS
   ─────────────────────────
   guard_conditions = {}

   For each handler H in flow_file:
     For each guard G in H.guards:
       condition = ParseCondition(G)
       guard_conditions[H.event].add(condition)

2. IDENTIFY STATE-DEFINING GUARDS
   ───────────────────────────────
   State-defining guards are those that:
   a) Check for variable EXISTENCE: "$X exists", "$X is empty"
   b) Check for specific VALUES: "$mode is 'degrees'"
   c) Check for STATE-LIKE values: "$status is 'pending'"

   For each condition C in guard_conditions:
     If C matches existence pattern:
       Create state pair:
         - #has_{variable}
         - #no_{variable} (or #awaiting_{variable})
     If C matches value pattern:
       Create state: #{variable}_{value}
     If C matches state-like pattern:
       Create state: #{value}

3. BUILD STATE CONSTRAINT MAP
   ───────────────────────────
   For each handler H:
     active_states = []
     For each guard G in H.guards:
       state = MapGuardToState(G)
       active_states.add(state)

     handler_state_map[H] = active_states

4. DETECT STATE TRANSITIONS
   ─────────────────────────
   For each handler H:
     pre_state = handler_state_map[H]  // State required to enter

     For each action A in H.actions:
       If A modifies variable V:
         If V is state-defining:
           post_state = DeterminePostState(V, A)
           Create transition: pre_state β†’ post_state

5. VALIDATE STATE GRAPH
   ─────────────────────
   Check for:
   - Unreachable states
   - Missing transitions
   - Conflicting conditions

RETURN implicit_states, transitions

Guard Pattern Catalog ​

Guard PatternImplied StatesTransition Trigger
? $X exists#has_X, #no_X$X becomes value
? $X is empty#X_empty, #X_filled$X adds item
? $X is "value"#X_value for each value$X becomes "other"
? $X is greater than N#X_low, #X_high$X increases/decreases
otherwise after guardsDefault/fallback state-

Example: Calculator with Pending Operation ​

flow
machine: @calculator

on :number (api)
  ? $pending_operation exists
    perform $pending_operation with $operand and $value
    $result becomes $calculation_result
    $pending_operation becomes empty
    $operand becomes empty
  otherwise
    $operand becomes $value

on :operation (api)
  ? $operand exists
    $pending_operation becomes $operation_type

on :equals (api)
  ? $pending_operation exists
    perform $pending_operation with $operand and $value
    $result becomes $calculation_result
    $pending_operation becomes empty

Guard Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  GUARD CONDITION EXTRACTION                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Handler: on :number                                                    β”‚
β”‚    Guard 1: $pending_operation exists β†’ State: #has_pending_op          β”‚
β”‚    Guard 2: otherwise                 β†’ State: #no_pending_op           β”‚
β”‚                                                                         β”‚
β”‚  Handler: on :operation                                                 β”‚
β”‚    Guard 1: $operand exists           β†’ State: #has_operand             β”‚
β”‚                                                                         β”‚
β”‚  Handler: on :equals                                                    β”‚
β”‚    Guard 1: $pending_operation exists β†’ State: #has_pending_op          β”‚
β”‚                                                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  DERIVED IMPLICIT STATES                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  #ready                                                                 β”‚
β”‚    constraints: $operand is empty AND $pending_operation is empty       β”‚
β”‚    description: Calculator ready for first number                       β”‚
β”‚                                                                         β”‚
β”‚  #has_operand                                                           β”‚
β”‚    constraints: $operand exists AND $pending_operation is empty         β”‚
β”‚    description: First number entered, waiting for operation             β”‚
β”‚                                                                         β”‚
β”‚  #has_pending_op                                                        β”‚
β”‚    constraints: $pending_operation exists                               β”‚
β”‚    description: Operation selected, waiting for second number           β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Derived State Machine:

                    GUARD-DERIVED STATE MACHINE

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  #ready    β”‚  $operand = empty
    β”‚            β”‚  $pending_op = empty
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β”‚ :number (otherwise branch)
          β”‚ $operand becomes $value
          β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ #has_operand   β”‚  $operand exists
    β”‚                β”‚  $pending_op = empty
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β”‚ :operation
          β”‚ $pending_operation becomes $op_type
          β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚#has_pending_op β”‚  $pending_op exists
    β”‚                β”‚
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β”‚ :number (guard branch)
          β”‚ or :equals
          β”‚ $pending_op becomes empty
          β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  #ready    β”‚  (back to start)
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Algorithm 3: Context-Derived States ​

Overview ​

Context-derived states are similar to guard-derived states but focus on mode variables - context variables that fundamentally change machine behavior without explicit guard checks in every handler.

Distinction from Guard-Derived ​

AspectGuard-DerivedContext-Derived
DetectionExplicit ? conditionVariable assignment patterns
ScopePer-handlerMachine-wide behavior mode
Example? $cart is empty$mode becomes "degrees"

Algorithm ​

ALGORITHM: ContextDerivedStateDetection

INPUT:
  - flow_file: Parsed EventFlow AST

OUTPUT:
  - mode_states: States representing operational modes
  - mode_variables: Variables that define modes

PROCEDURE:

1. IDENTIFY MODE VARIABLES
   ────────────────────────
   Criteria for mode variables:
   a) Set to enumerated values: "degrees", "radians", "scientific"
   b) Checked in multiple handlers
   c) Changes machine behavior globally

   mode_candidates = {}

   For each handler H:
     For each action A:
       If A is "$var becomes 'string_value'":
         mode_candidates[var].add(string_value)

   For var in mode_candidates:
     If mode_candidates[var].size >= 2:
       Mark var as mode_variable

2. BUILD MODE STATE MAP
   ─────────────────────
   For each mode_variable M:
     For each value V in M.possible_values:
       Create state: #{M}_{V}
       Example: $angle_mode = "degrees" β†’ #angle_mode_degrees

3. DETECT MODE TRANSITIONS
   ────────────────────────
   For each handler H:
     For each action A that sets mode_variable M:
       pre_mode = current mode or "any"
       post_mode = A.new_value
       Create transition: #{M}_{pre} β†’ #{M}_{post}

4. ANALYZE MODE IMPACT
   ────────────────────
   For each handler H:
     For each guard G or action A:
       If G/A references mode_variable M:
         Mark H as mode-dependent
         Document behavior difference per mode

RETURN mode_states, mode_transitions

Example: Scientific Calculator Modes ​

flow
machine: @calculator

scenario: mode switching

  on :set_degrees (api)
    $angle_mode becomes "degrees"

  on :set_radians (api)
    $angle_mode becomes "radians"

  on :set_gradians (api)
    $angle_mode becomes "gradians"

scenario: trigonometric operations

  on :sin (api)
    ? $angle_mode is "degrees"
      $result becomes sin($value * PI / 180)
    ? $angle_mode is "radians"
      $result becomes sin($value)
    ? $angle_mode is "gradians"
      $result becomes sin($value * PI / 200)

Context Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MODE VARIABLE DETECTION                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Variable: $angle_mode                                                  β”‚
β”‚  Possible values: "degrees", "radians", "gradians"                      β”‚
β”‚  Set by: :set_degrees, :set_radians, :set_gradians                      β”‚
β”‚  Used by: :sin, :cos, :tan (affects calculation)                        β”‚
β”‚                                                                         β”‚
β”‚  Classification: MODE VARIABLE βœ“                                        β”‚
β”‚                                                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  DERIVED MODE STATES                                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  #degrees_mode                                                          β”‚
β”‚    constraint: $angle_mode is "degrees"                                 β”‚
β”‚    entry: :set_degrees                                                  β”‚
β”‚    behavior: Trig functions convert degrees to radians                  β”‚
β”‚                                                                         β”‚
β”‚  #radians_mode                                                          β”‚
β”‚    constraint: $angle_mode is "radians"                                 β”‚
β”‚    entry: :set_radians                                                  β”‚
β”‚    behavior: Trig functions use value directly                          β”‚
β”‚                                                                         β”‚
β”‚  #gradians_mode                                                         β”‚
β”‚    constraint: $angle_mode is "gradians"                                β”‚
β”‚    entry: :set_gradians                                                 β”‚
β”‚    behavior: Trig functions convert gradians to radians                 β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Derived State Machine:

              CONTEXT-DERIVED MODE STATES

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                                                  β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
    β”‚   β”‚ #degrees_mode  │◄──── :set_degrees           β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
    β”‚           β”‚                                      β”‚
    β”‚           β”‚ :set_radians                         β”‚
    β”‚           β–Ό                                      β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
    β”‚   β”‚ #radians_mode  │◄──── :set_radians           β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
    β”‚           β”‚                                      β”‚
    β”‚           β”‚ :set_gradians                        β”‚
    β”‚           β–Ό                                      β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
    β”‚   β”‚ #gradians_mode │◄──── :set_gradians          β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
    β”‚                                                  β”‚
    β”‚   Note: All modes can transition to any other    β”‚
    β”‚         mode via the set_* events                β”‚
    β”‚                                                  β”‚
    β”‚   Trig operations (:sin, :cos, :tan) work in     β”‚
    β”‚   ALL modes but with different behavior          β”‚
    β”‚                                                  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Combined Derivation Pipeline ​

Overview ​

The three algorithms are combined into a unified pipeline that produces a complete state model:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     COMBINED STATE DERIVATION PIPELINE                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                            β”‚
β”‚  β”‚  .flow file β”‚                                                            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                                                            β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 1: Parse & Extract                                           β”‚   β”‚
β”‚  β”‚  ─────────────────────────                                          β”‚   β”‚
β”‚  β”‚  β€’ Parse flow file into AST                                         β”‚   β”‚
β”‚  β”‚  β€’ Extract handlers, guards, actions, emits                         β”‚   β”‚
β”‚  β”‚  β€’ Build symbol table (events, actors, variables)                   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 2: Event-Flow Analysis (HIGH CONFIDENCE)                     β”‚   β”‚
β”‚  β”‚  ──────────────────────────────────────────────                     β”‚   β”‚
β”‚  β”‚  β€’ Identify emit/response patterns                                  β”‚   β”‚
β”‚  β”‚  β€’ Build cross-machine communication graph                          β”‚   β”‚
β”‚  β”‚  β€’ Create wait states for each emit with expected response          β”‚   β”‚
β”‚  β”‚  β€’ Mark terminal states (no outgoing transitions)                   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 3: Guard Analysis (MEDIUM CONFIDENCE)                        β”‚   β”‚
β”‚  β”‚  ───────────────────────────────────────────                        β”‚   β”‚
β”‚  β”‚  β€’ Extract all guard conditions                                     β”‚   β”‚
β”‚  β”‚  β€’ Identify state-defining guards (existence, value checks)         β”‚   β”‚
β”‚  β”‚  β€’ Create implicit states from guard partitions                     β”‚   β”‚
β”‚  β”‚  β€’ Map handlers to their required states                            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 4: Context/Mode Analysis (MEDIUM CONFIDENCE)                 β”‚   β”‚
β”‚  β”‚  ──────────────────────────────────────────────                     β”‚   β”‚
β”‚  β”‚  β€’ Identify mode variables (enumerated string values)               β”‚   β”‚
β”‚  β”‚  β€’ Create mode states for each possible value                       β”‚   β”‚
β”‚  β”‚  β€’ Map mode transitions from setter handlers                        β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 5: State Merging & Conflict Resolution                       β”‚   β”‚
β”‚  β”‚  ────────────────────────────────────────────                       β”‚   β”‚
β”‚  β”‚  β€’ Merge states from all three sources                              β”‚   β”‚
β”‚  β”‚  β€’ Resolve naming conflicts                                         β”‚   β”‚
β”‚  β”‚  β€’ Handle orthogonal state dimensions (mode Γ— workflow state)       β”‚   β”‚
β”‚  β”‚  β€’ Validate completeness                                            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  PHASE 6: Confidence Scoring & Ambiguity Detection                  β”‚   β”‚
β”‚  β”‚  ─────────────────────────────────────────────                      β”‚   β”‚
β”‚  β”‚  β€’ Score each derived state by confidence                           β”‚   β”‚
β”‚  β”‚  β€’ Identify ambiguous cases                                         β”‚   β”‚
β”‚  β”‚  β€’ Flag states that need human confirmation                         β”‚   β”‚
β”‚  β”‚  β€’ Check for machine mode markers                                   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚         β”‚                                                                   β”‚
β”‚         β–Ό                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                            β”‚
β”‚  β”‚.states.flow β”‚ + confidence report                                        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                            β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Confidence Scoring ​

Each derived state receives a confidence score:

ConfidenceScoreSourceRequires Confirmation?
High90-100Event-flow patternsNo
Medium60-89Guard/context patternsOptional
Low30-59Heuristic inferenceYes
Undecidable0-29No clear patternYes (or mode marker)

Conflict Resolution ​

When multiple derivation sources suggest different states:

CONFLICT RESOLUTION RULES:

1. EXPLICIT > IMPLICIT
   If developer wrote "moves to #state", use that state name.

2. EVENT-FLOW > GUARD > CONTEXT
   Higher confidence sources take precedence.

3. ORTHOGONAL DIMENSIONS
   When states are independent (e.g., mode + workflow), create composite:
   #degrees_mode + #awaiting_payment β†’ #degrees_awaiting_payment
   Or keep as separate state dimensions.

4. MERGE EQUIVALENT STATES
   If two derived states have identical constraints and transitions,
   merge them and use the more descriptive name.

Comprehensive Machine Configuration Analysis ​

This section analyzes ALL possible machine configurations and their state derivation rules.


Configuration 1: Single Machine, Single Actor, No Scenarios (Minimal) ​

The simplest possible flow file:

flow
validate order details

Implicit Structure:

flow
machine: @default           // Implicit default machine

scenario: default           // Implicit default scenario

  on :trigger (api)         // Implicit trigger event
    validate order details

State Derivation:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MINIMAL FLOW DERIVATION                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Input: "validate order details"                                        β”‚
β”‚                                                                         β”‚
β”‚  Implicit elements:                                                     β”‚
β”‚    β€’ Machine: @default                                                  β”‚
β”‚    β€’ Scenario: default                                                  β”‚
β”‚    β€’ Event: :trigger (api)                                              β”‚
β”‚                                                                         β”‚
β”‚  Derivation:                                                            β”‚
β”‚    1. Single handler β†’ single entry point                               β”‚
β”‚    2. No emit β†’ no wait states                                          β”‚
β”‚    3. No guards β†’ no partitions                                         β”‚
β”‚    4. Handler completes β†’ terminal state                                β”‚
β”‚                                                                         β”‚
β”‚  Result:                                                                β”‚
β”‚    #idle (initial) β†’ :trigger β†’ #completed (terminal, success)          β”‚
β”‚                                                                         β”‚
β”‚  Confidence: 100% (trivial case)                                        β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States:

flow
#idle
  type: initial
  waiting_for: :trigger

#completed
  type: terminal
  outcome: success
  after: :trigger

Configuration 2: Single Machine, Single Actor, Single Scenario, Multiple Events ​

flow
machine: @order

scenario: checkout

  on :add_item (api)
    $items adds $item

  on :remove_item (api)
    $items removes $item

  on :checkout (api)
    process order

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SINGLE SCENARIO, MULTIPLE API HANDLERS                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Question: Are these sequential or independent?                         β”‚
β”‚                                                                         β”‚
β”‚  Analysis:                                                              β”‚
β”‚    β€’ :add_item (api) - no guards                                        β”‚
β”‚    β€’ :remove_item (api) - no guards                                     β”‚
β”‚    β€’ :checkout (api) - no guards                                        β”‚
β”‚    β€’ No emit/response patterns                                          β”‚
β”‚    β€’ All modify $items but no guard checks                              β”‚
β”‚                                                                         β”‚
β”‚  Decision: NO GUARDS = INDEPENDENT                                      β”‚
β”‚                                                                         β”‚
β”‚  All three handlers can be called at any time, in any order.            β”‚
β”‚  They share context ($items) but don't REQUIRE prior state.             β”‚
β”‚                                                                         β”‚
β”‚  Result: Single #ready state with self-loops                            β”‚
β”‚                                                                         β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
β”‚       β”‚                                               β”‚                 β”‚
β”‚       β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚                 β”‚
β”‚       β”‚   :add_item  β”‚ #ready  β”‚  :remove_item        β”‚                 β”‚
β”‚       └─────────────►│         β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β”‚
β”‚                      β”‚         β”‚                                        β”‚
β”‚       :checkout      β”‚         β”‚                                        β”‚
β”‚       ──────────────►│         β”‚                                        β”‚
β”‚                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚                                                                         β”‚
β”‚  Note: :checkout COULD be terminal, but without guards there's no       β”‚
β”‚        structural indication it's the "final" operation.                β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What if :checkout should be final? Add guards:

flow
on :checkout (api)
  ? $items is not empty       // ← Guard creates implicit state
  process order

Now derivation changes:

  • :add_item and :remove_item can run anytime
  • :checkout requires $items is not empty β†’ implies #has_items state

Configuration 3: Single Machine, Single Actor, Multiple Scenarios ​

flow
machine: @calculator

scenario: basic operations

  on :add (api)
    $result increases by $value

  on :subtract (api)
    $result decreases by $value

scenario: memory operations

  on :memory_store (api)
    $memory becomes $result

  on :memory_recall (api)
    $result becomes $memory

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MULTIPLE SCENARIOS - SAME MACHINE                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Scenarios are DOCUMENTATION GROUPINGS, not state boundaries.           β”‚
β”‚                                                                         β”‚
β”‚  From derivation perspective:                                           β”‚
β”‚    β€’ All 4 handlers are (api) entry points                              β”‚
β”‚    β€’ No guards enforce ordering                                         β”‚
β”‚    β€’ No emit/response patterns                                          β”‚
β”‚                                                                         β”‚
β”‚  Scenarios help humans understand related functionality:                β”‚
β”‚    β€’ "basic operations" = add, subtract                                 β”‚
β”‚    β€’ "memory operations" = memory_store, memory_recall                  β”‚
β”‚                                                                         β”‚
β”‚  But they DON'T create separate state spaces.                           β”‚
β”‚                                                                         β”‚
β”‚  Result: Single #ready state                                            β”‚
β”‚                                                                         β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚      β”‚                      #ready                           β”‚          β”‚
β”‚      β”‚                                                       β”‚          β”‚
β”‚      β”‚   Handles:                                            β”‚          β”‚
β”‚      β”‚     scenario: basic operations                        β”‚          β”‚
β”‚      β”‚       β€’ :add, :subtract                               β”‚          β”‚
β”‚      β”‚     scenario: memory operations                       β”‚          β”‚
β”‚      β”‚       β€’ :memory_store, :memory_recall                 β”‚          β”‚
β”‚      β”‚                                                       β”‚          β”‚
β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

When DO scenarios affect state? When they contain sequential events with guards:

flow
scenario: checkout process

  on :start_checkout (api)
    $checkout_started becomes true

  on :confirm_payment (api)
    ? $checkout_started       // ← Guard creates sequence WITHIN scenario
    process payment

Configuration 4: Single Machine, Multiple Actors ​

flow
machine: @order

on :place_order from @customer (api)
  emit :validate to @validator

on :validated from @validator
  emit :charge to @payment

on :payment_success from @payment
  emit :confirmation to @customer

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SINGLE MACHINE, MULTIPLE ACTORS                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Actors involved:                                                       β”‚
β”‚    β€’ @customer - initiates order (external)                             β”‚
β”‚    β€’ @validator - validates order (service)                             β”‚
β”‚    β€’ @payment - processes payment (service)                             β”‚
β”‚                                                                         β”‚
β”‚  Event flow:                                                            β”‚
β”‚    @customer ──:place_order──► @order                                   β”‚
β”‚    @order ────:validate─────► @validator                                β”‚
β”‚    @validator ─:validated───► @order                                    β”‚
β”‚    @order ────:charge───────► @payment                                  β”‚
β”‚    @payment ──:payment_success─► @order                                 β”‚
β”‚    @order ────:confirmation──► @customer                                β”‚
β”‚                                                                         β”‚
β”‚  Emit/Response patterns detected:                                       β”‚
β”‚    1. emit :validate to @validator β†’ on :validated from @validator βœ“    β”‚
β”‚    2. emit :charge to @payment β†’ on :payment_success from @payment βœ“    β”‚
β”‚                                                                         β”‚
β”‚  Each emit creates a WAIT STATE (high confidence):                      β”‚
β”‚                                                                         β”‚
β”‚    #idle                                                                β”‚
β”‚      ↓ :place_order                                                     β”‚
β”‚    #awaiting_validation  ← emit :validate to @validator                 β”‚
β”‚      ↓ :validated                                                       β”‚
β”‚    #awaiting_payment     ← emit :charge to @payment                     β”‚
β”‚      ↓ :payment_success                                                 β”‚
β”‚    #completed            ← terminal                                     β”‚
β”‚                                                                         β”‚
β”‚  Confidence: 95% (clear emit/response patterns)                         β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration 5: Multiple Machines (System) ​

flow
// ─── order.flow ───
machine: @order

on :checkout from @customer (api)
  emit :request_payment to @payment

on :payment_success from @payment
  emit :reserve_stock to @warehouse

on :stock_reserved from @warehouse
  emit :confirmation to @customer
flow
// ─── payment.flow ───
machine: @payment

on :request_payment from @order
  process payment
  ? payment successful
    emit :payment_success to @order
  otherwise
    emit :payment_failed to @order
flow
// ─── warehouse.flow ───
machine: @warehouse

on :reserve_stock from @order
  check inventory
  ? items available
    emit :stock_reserved to @order
  otherwise
    emit :stock_unavailable to @order

System-Level Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MULTI-MACHINE SYSTEM DERIVATION                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  STEP 1: Build Cross-Machine Communication Graph                        β”‚
β”‚  ──────────────────────────────────────────────                         β”‚
β”‚                                                                         β”‚
β”‚    @customer                                                            β”‚
β”‚        β”‚                                                                β”‚
β”‚        β”‚ :checkout                                                      β”‚
β”‚        β–Ό                                                                β”‚
β”‚    @order ◄──────────────────────────────────────────┐                  β”‚
β”‚        β”‚                                             β”‚                  β”‚
β”‚        β”‚ :request_payment    :payment_success        β”‚                  β”‚
β”‚        β–Ό                     :payment_failed         β”‚                  β”‚
β”‚    @payment ──────────────────────────────────────────                  β”‚
β”‚                                                      β”‚                  β”‚
β”‚    @order ◄───────────────────────────────────────────                  β”‚
β”‚        β”‚                                             β”‚                  β”‚
β”‚        β”‚ :reserve_stock      :stock_reserved         β”‚                  β”‚
β”‚        β–Ό                     :stock_unavailable      β”‚                  β”‚
β”‚    @warehouse β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚                                                                         β”‚
β”‚  STEP 2: Derive States Per Machine                                      β”‚
β”‚  ─────────────────────────────────                                      β”‚
β”‚                                                                         β”‚
β”‚  @order states (orchestrator):                                          β”‚
β”‚    #idle β†’ #awaiting_payment β†’ #awaiting_stock β†’ #completed             β”‚
β”‚                             β†˜ #payment_failed   β†˜ #stock_unavailable    β”‚
β”‚                                                                         β”‚
β”‚  @payment states (service):                                             β”‚
β”‚    #idle β†’ #processing β†’ #completed                                     β”‚
β”‚    (simpler - single request/response cycle)                            β”‚
β”‚                                                                         β”‚
β”‚  @warehouse states (service):                                           β”‚
β”‚    #idle β†’ #checking β†’ #completed                                       β”‚
β”‚    (simpler - single request/response cycle)                            β”‚
β”‚                                                                         β”‚
β”‚  STEP 3: Cross-Reference Validation                                     β”‚
β”‚  ───────────────────────────────────                                    β”‚
β”‚                                                                         β”‚
β”‚  For each emit in @order:                                               β”‚
β”‚    β€’ emit :request_payment to @payment                                  β”‚
β”‚      βœ“ @payment has: on :request_payment from @order                    β”‚
β”‚    β€’ emit :reserve_stock to @warehouse                                  β”‚
β”‚      βœ“ @warehouse has: on :reserve_stock from @order                    β”‚
β”‚                                                                         β”‚
β”‚  For each response to @order:                                           β”‚
β”‚    β€’ :payment_success from @payment                                     β”‚
β”‚      βœ“ @payment emits: emit :payment_success to @order                  β”‚
β”‚    β€’ :stock_reserved from @warehouse                                    β”‚
β”‚      βœ“ @warehouse emits: emit :stock_reserved to @order                 β”‚
β”‚                                                                         β”‚
β”‚  All cross-machine references validated βœ“                               β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration 6: Single Scenario with Multiple Waiting Events ​

flow
machine: @loan

scenario: loan application

  on :submit from @customer (api)
    emit async :check_credit to @credit_bureau
    emit async :verify_identity to @identity_service
    emit async :check_fraud to @fraud_service

  on :credit_result from @credit_bureau
    $credit_score becomes $result.score
    check if all complete

  on :identity_result from @identity_service
    $identity_verified becomes $result.verified
    check if all complete

  on :fraud_result from @fraud_service
    $fraud_clear becomes $result.clear
    check if all complete

  on :all_checks_complete
    ? $credit_score > 700 and $identity_verified and $fraud_clear
      emit :approved to @customer
    otherwise
      emit :declined to @customer

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  PARALLEL ASYNC - MULTIPLE WAIT EVENTS                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Pattern: Fan-out / Fan-in (Scatter-Gather)                             β”‚
β”‚                                                                         β”‚
β”‚  After :submit, THREE parallel requests are made:                       β”‚
β”‚    β€’ emit async :check_credit                                           β”‚
β”‚    β€’ emit async :verify_identity                                        β”‚
β”‚    β€’ emit async :check_fraud                                            β”‚
β”‚                                                                         β”‚
β”‚  The machine enters a COLLECTING state where it waits for               β”‚
β”‚  ALL THREE responses (in any order).                                    β”‚
β”‚                                                                         β”‚
β”‚  State derivation:                                                      β”‚
β”‚                                                                         β”‚
β”‚    #idle                                                                β”‚
β”‚      ↓ :submit                                                          β”‚
β”‚    #collecting_results     ← waiting for 3 responses                    β”‚
β”‚      ↓ (when all received)                                              β”‚
β”‚    :all_checks_complete                                                 β”‚
β”‚      ↓                                                                  β”‚
β”‚    #approved OR #declined  ← terminal states                            β”‚
β”‚                                                                         β”‚
β”‚  Key insight: Even though 3 events can arrive,                          β”‚
β”‚  there's ONE waiting state (#collecting_results)                        β”‚
β”‚  with internal tracking of which responses arrived.                     β”‚
β”‚                                                                         β”‚
β”‚  The "check if all complete" action is the fan-in logic.                β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States:

flow
#idle
  type: initial
  waiting_for: :submit from @customer

#collecting_results
  type: waiting
  after: :submit
  waiting_for_all:
    - :credit_result from @credit_bureau
    - :identity_result from @identity_service
    - :fraud_result from @fraud_service
  collection_complete_event: :all_checks_complete

#approved
  type: terminal
  outcome: success
  after: :all_checks_complete
  when: all checks passed

#declined
  type: terminal
  outcome: failure
  after: :all_checks_complete
  when: any check failed

Why Same Scenario?

These 5 event handlers belong in the same scenario because:

  1. Single Business Flow: All events are part of the "loan application" process
  2. Causal Dependency: :credit_result, :identity_result, :fraud_result cannot occur without :submit first
  3. Shared Outcome: All responses contribute to a single decision (approve/decline)
  4. Temporal Coupling: The process starts together and ends together

If these were independent operations (e.g., standalone credit check API), they would be:

  • Separate machines (@credit_bureau, @identity_service, @fraud_service)
  • Each with their own scenarios
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SCENARIO GROUPING RULE                                                 β”‚
β”‚                                                                         β”‚
β”‚  Events belong in the SAME scenario when:                               β”‚
β”‚    βœ“ They form a single business flow (start β†’ ... β†’ end)               β”‚
β”‚    βœ“ Later events DEPEND on earlier events                              β”‚
β”‚    βœ“ They share context and contribute to a common outcome              β”‚
β”‚                                                                         β”‚
β”‚  Events belong in SEPARATE scenarios when:                              β”‚
β”‚    βœ“ They are independent operations (can be called anytime)            β”‚
β”‚    βœ“ No causal dependency between them                                  β”‚
β”‚    βœ“ Different business capabilities                                    β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration 7: Internal Events (Same Machine Communication) ​

flow
machine: @order

on :checkout from @customer (api)
  validate cart
  emit :process_payment         // ← No "to @actor" = internal

on :process_payment             // ← Internal handler (no from clause)
  charge card
  emit :send_confirmation

on :send_confirmation           // ← Internal handler
  send email
  order moves to #completed

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  INTERNAL EVENTS - SAME MACHINE                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Internal emit (no "to @actor") triggers handler in SAME machine.       β”‚
β”‚                                                                         β”‚
β”‚  Execution model options:                                               β”‚
β”‚    A) SYNC: Handler runs immediately inline                             β”‚
β”‚    B) ASYNC: Event queued, handler runs later                           β”‚
β”‚                                                                         β”‚
β”‚  For state derivation:                                                  β”‚
β”‚    β€’ If SYNC: No wait state (all runs in one transaction)               β”‚
β”‚    β€’ If ASYNC: Wait state between each internal emit                    β”‚
β”‚                                                                         β”‚
β”‚  Default assumption: SYNC (no wait states for internal events)          β”‚
β”‚                                                                         β”‚
β”‚  State derivation (sync model):                                         β”‚
β”‚                                                                         β”‚
β”‚    #idle                                                                β”‚
β”‚      ↓ :checkout                                                        β”‚
β”‚      β”‚   validate cart                                                  β”‚
β”‚      β”‚   emit :process_payment (sync - continues inline)                β”‚
β”‚      β”‚     charge card                                                  β”‚
β”‚      β”‚     emit :send_confirmation (sync - continues inline)            β”‚
β”‚      β”‚       send email                                                 β”‚
β”‚      β”‚       order moves to #completed                                  β”‚
β”‚      ↓                                                                  β”‚
β”‚    #completed                                                           β”‚
β”‚                                                                         β”‚
β”‚  Result: Only 2 states (#idle, #completed) because internal             β”‚
β”‚  events execute synchronously within the same request.                  β”‚
β”‚                                                                         β”‚
β”‚  To create wait states, use:                                            β”‚
β”‚    emit async :process_payment                                          β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration 8: Hybrid - Guards AND Emit/Response ​

flow
machine: @order

on :checkout from @customer (api)
  ? cart is not empty
    ? $customer.is_premium
      apply premium discount
    emit :request_payment to @payment
  otherwise
    emit :empty_cart_error to @customer

on :payment_success from @payment
  ? $total > 1000
    emit :request_approval to @manager
  otherwise
    emit :confirmation to @customer

on :payment_failed from @payment
  emit :checkout_failed to @customer

on :approved from @manager
  emit :confirmation to @customer

on :rejected from @manager
  emit :request_refund to @payment
  emit :order_rejected to @customer

Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  HYBRID: GUARDS + EMIT/RESPONSE                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Multiple derivation sources combine:                                   β”‚
β”‚                                                                         β”‚
β”‚  From GUARDS:                                                           β”‚
β”‚    β€’ ? cart is not empty β†’ #has_cart vs #empty_cart                     β”‚
β”‚    β€’ ? $customer.is_premium β†’ affects actions but not state             β”‚
β”‚    β€’ ? $total > 1000 β†’ #needs_approval vs #auto_approved                β”‚
β”‚                                                                         β”‚
β”‚  From EMIT/RESPONSE:                                                    β”‚
β”‚    β€’ emit to @payment β†’ #awaiting_payment                               β”‚
β”‚    β€’ emit to @manager β†’ #awaiting_approval                              β”‚
β”‚                                                                         β”‚
β”‚  Combined state machine:                                                β”‚
β”‚                                                                         β”‚
β”‚                        :checkout                                        β”‚
β”‚                            β”‚                                            β”‚
β”‚               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”‚
β”‚               β–Ό                         β–Ό                               β”‚
β”‚    [cart not empty]              [cart empty]                           β”‚
β”‚               β”‚                         β”‚                               β”‚
β”‚               β–Ό                         β–Ό                               β”‚
β”‚    emit :request_payment         emit :empty_cart_error                 β”‚
β”‚               β”‚                         β”‚                               β”‚
β”‚               β–Ό                         β–Ό                               β”‚
β”‚    #awaiting_payment              #checkout_failed                      β”‚
β”‚               β”‚                     (terminal)                          β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                β”‚
β”‚    β–Ό                   β–Ό                                                β”‚
β”‚ :payment_success   :payment_failed                                      β”‚
β”‚    β”‚                   β”‚                                                β”‚
β”‚    β”‚                   β–Ό                                                β”‚
β”‚    β”‚            #payment_failed (terminal)                              β”‚
β”‚    β”‚                                                                    β”‚
β”‚    β”œβ”€β”€ [$total > 1000] ──────────────────┐                              β”‚
β”‚    β”‚                                     β”‚                              β”‚
β”‚    β–Ό                                     β–Ό                              β”‚
β”‚ emit :confirmation              emit :request_approval                  β”‚
β”‚    β”‚                                     β”‚                              β”‚
β”‚    β–Ό                                     β–Ό                              β”‚
β”‚ #completed (terminal)            #awaiting_approval                     β”‚
β”‚                                          β”‚                              β”‚
β”‚                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚                               β–Ό                     β–Ό                   β”‚
β”‚                          :approved             :rejected                β”‚
β”‚                               β”‚                     β”‚                   β”‚
β”‚                               β–Ό                     β–Ό                   β”‚
β”‚                        #completed (t)         #rejected (t)             β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What is Actually Undecidable? ​

After comprehensive analysis, very few cases are truly undecidable:

Truly Undecidable Case 1: Timeout Events Without Clear Ownership ​

flow
on :submit (api)
  emit :validate to @validator

on :validated from @validator
  proceed

on :timeout         // ← Whose timeout? When does it fire?
  cancel

Why undecidable:

  • :timeout has no from clause - could be from system, scheduler, or another service
  • No clear trigger point - does it start at :submit? How long?
  • No explicit connection to the validation flow

Solution: Require explicit source or scheduled event syntax

flow
on :submit (api)
  emit :validate to @validator
  schedule :validation_timeout after 30 seconds   // ← Explicit

on :validation_timeout
  cancel

Truly Undecidable Case 2: Race Conditions in Parallel Responses ​

flow
on :start (api)
  emit async :task_a to @service_a
  emit async :task_b to @service_b

on :task_a_result from @service_a
  process a result

on :task_b_result from @service_b
  process b result

// What if both arrive at EXACTLY the same time?
// Which handler runs first? Does order matter?

Why undecidable:

  • The relative order of :task_a_result and :task_b_result is non-deterministic
  • If actions affect shared state differently based on order, behavior is unpredictable

Solution: This is a runtime concern, not state derivation

  • State derivation gives: #idle β†’ #collecting β†’ #completed
  • Runtime must handle concurrent event processing

NOT Undecidable: Independent Operations ​

flow
machine: @calculator

on :add (api)
  $result increases by $value

on :subtract (api)
  $result decreases by $value

This IS decidable:

  • No guards = no sequence required
  • No emit = no waiting
  • Result: Single #ready state, all handlers loop back
  • Confidence: 100%

Machine Mode Markers (Optional) ​

Mode markers are optional documentation hints. The derivation algorithm can determine machine behavior from code structure in most cases. Mode markers are useful for:

  1. Explicit documentation - Make intent clear to readers
  2. Derivation optimization - Skip analysis when you know the answer
  3. Edge cases - Override derivation for special cases

Important: Mode Markers Do NOT Change Behavior ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                         β”‚
β”‚  Mode markers affect STATE DERIVATION only, not runtime behavior.       β”‚
β”‚                                                                         β”‚
β”‚  These two are EQUIVALENT at runtime:                                   β”‚
β”‚                                                                         β”‚
β”‚    machine: @calculator               machine: @calculator (stateless)  β”‚
β”‚                                                                         β”‚
β”‚    on :add (api)                      on :add (api)                     β”‚
β”‚      $result += $value                  $result += $value               β”‚
β”‚                                                                         β”‚
β”‚  The (stateless) marker just tells the derivation algorithm:            β”‚
β”‚  "Don't bother analyzing - I know this is a single-state machine."      β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Syntax ​

flow
machine: @name (mode)

Available Modes ​

ModeMeaningWhen to Use
(stateless)Explicit single-state machineDocumentation, skip analysis
(sequential)Force sequential interpretationWhen naming suggests sequence but guards are intentionally omitted
(no marker)Full derivation algorithmDefault - let the algorithm figure it out

When You DON'T Need Mode Markers ​

flow
// This calculator is automatically detected as single-state:
// - No guards
// - No emit/response patterns
// - All (api) handlers
// NO MODE MARKER NEEDED

machine: @calculator

on :add (api)
  $result increases by $value

on :subtract (api)
  $result decreases by $value

Derivation result (automatic): Single #ready state, confidence 100%

When Mode Markers ARE Useful ​

1. Documentation Clarity ​

flow
// The (stateless) marker documents intent:
// "This machine intentionally has no state transitions"

machine: @calculator (stateless)

on :add (api)
  $result increases by $value

2. Sequential Without Guards (Edge Case) ​

flow
// You WANT sequential behavior but intentionally skip guards
// (perhaps for a simplified prototype)

machine: @wizard (sequential)

on :step_one (api)
  do first thing

on :step_two (api)
  do second thing      // No guard, but (sequential) forces order

on :step_three (api)
  do third thing

Warning: This creates a state machine that the CODE doesn't enforce. The derived states exist for documentation/diagrams, but runtime doesn't prevent calling :step_three before :step_one.

Better approach: Add guards if you want enforcement:

flow
machine: @wizard

on :step_one (api)
  $step_one_done becomes true

on :step_two (api)
  ? $step_one_done
  do second thing

on :step_three (api)
  ? $step_two_done
  do third thing

Comprehensive Examples ​

Example 1: Basic Calculator (Stateless) ​

flow
machine: @calculator (stateless)

on :add (api)
  $result increases by $value

on :subtract (api)
  $result decreases by $value

Derivation Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  DERIVATION ANALYSIS: Basic Calculator                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Mode: STATELESS (explicit marker)                                      β”‚
β”‚                                                                         β”‚
β”‚  Phase 1: Event-Flow Analysis                                           β”‚
β”‚    β€’ No emit statements found                                           β”‚
β”‚    β€’ No cross-machine communication                                     β”‚
β”‚    β€’ Result: No event-flow derived states                               β”‚
β”‚                                                                         β”‚
β”‚  Phase 2: Guard Analysis                                                β”‚
β”‚    β€’ No guards found                                                    β”‚
β”‚    β€’ Result: No guard-derived states                                    β”‚
β”‚                                                                         β”‚
β”‚  Phase 3: Context Analysis                                              β”‚
β”‚    β€’ $result modified but no mode patterns                              β”‚
β”‚    β€’ Result: No context-derived states                                  β”‚
β”‚                                                                         β”‚
β”‚  Phase 4: Mode Marker Check                                             β”‚
β”‚    β€’ Mode: stateless                                                    β”‚
β”‚    β€’ Result: Single state derivation                                    β”‚
β”‚                                                                         β”‚
β”‚  FINAL RESULT:                                                          β”‚
β”‚    #ready (stateless) - handles all operations                          β”‚
β”‚    Confidence: 100% (explicit mode)                                     β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States File:

flow
// calculator.states.flow

machine: @calculator

#ready
  type: stateless
  description: Calculator ready for any arithmetic operation
  handles: :add, :subtract

Example 2: Calculator with Memory ​

flow
machine: @calculator

scenario: basic operations

  on :add (api)
    $result increases by $value

  on :clear (api)
    $result becomes 0
    $memory becomes 0

scenario: memory operations

  on :memory_store (api)
    $memory becomes $result

  on :memory_recall (api)
    ? $memory exists
      $result becomes $memory
    otherwise
      emit :error to @user
        with "No value in memory"

  on :memory_clear (api)
    $memory becomes 0

Derivation Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  DERIVATION ANALYSIS: Calculator with Memory                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Mode: DEFAULT (no marker)                                              β”‚
β”‚                                                                         β”‚
β”‚  Phase 1: Event-Flow Analysis                                           β”‚
β”‚    β€’ emit :error to @user found in :memory_recall                       β”‚
β”‚    β€’ No response handler for :error (fire-and-forget)                   β”‚
β”‚    β€’ Result: No wait states from event-flow                             β”‚
β”‚                                                                         β”‚
β”‚  Phase 2: Guard Analysis                                                β”‚
β”‚    β€’ Guard found: `? $memory exists` in :memory_recall                  β”‚
β”‚    β€’ State-defining: YES (existence check)                              β”‚
β”‚    β€’ Derived states:                                                    β”‚
β”‚        - #has_memory ($memory exists)                                   β”‚
β”‚        - #no_memory ($memory not set or 0)                              β”‚
β”‚                                                                         β”‚
β”‚  Phase 3: Context Analysis                                              β”‚
β”‚    β€’ $memory set by :memory_store                                       β”‚
β”‚    β€’ $memory cleared by :memory_clear and :clear                        β”‚
β”‚    β€’ Pattern: binary state (has/no memory)                              β”‚
β”‚                                                                         β”‚
β”‚  Phase 4: Merge Analysis                                                β”‚
β”‚    β€’ Guard-derived and context-derived agree                            β”‚
β”‚    β€’ No conflicts                                                       β”‚
β”‚                                                                         β”‚
β”‚  FINAL RESULT:                                                          β”‚
β”‚    #no_memory (initial) - memory empty                                  β”‚
β”‚    #has_memory - memory contains value                                  β”‚
β”‚    Confidence: 75% (guard-derived)                                      β”‚
β”‚                                                                         β”‚
β”‚  NOTE: Since no handler REQUIRES a specific state to run                β”‚
β”‚        (except :memory_recall with guard), these states are             β”‚
β”‚        INFORMATIONAL rather than ENFORCED.                              β”‚
β”‚                                                                         β”‚
β”‚  RECOMMENDATION: Mark as (stateless) if states are not important        β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States File:

flow
// calculator.states.flow

machine: @calculator

#no_memory
  type: initial
  description: Memory is empty
  constraint: $memory is empty or $memory equals 0
  transitions_to: #has_memory via :memory_store

#has_memory
  type: waiting
  description: Memory contains a stored value
  constraint: $memory exists and $memory is not 0
  transitions_to: #no_memory via :memory_clear, :clear

Example 3: Calculator with Pending Operation ​

flow
machine: @calculator

on :number (api)
  ? $pending_operation exists
    perform $pending_operation with $operand and $value
    $result becomes $calculation_result
    $pending_operation becomes empty
    $operand becomes $result
  otherwise
    $operand becomes $value
    $result becomes $value

on :operation (api)
  ? $operand exists
    $pending_operation becomes $operation_type
  otherwise
    emit :error to @user
      with "Enter a number first"

on :equals (api)
  ? $pending_operation exists
    ? $operand exists
      perform $pending_operation with $operand and $value
      $result becomes $calculation_result
      $pending_operation becomes empty
      $operand becomes empty

on :clear (api)
  $result becomes 0
  $operand becomes empty
  $pending_operation becomes empty

on :all_clear (api)
  $result becomes 0
  $operand becomes empty
  $pending_operation becomes empty
  $memory becomes 0

Derivation Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  DERIVATION ANALYSIS: Calculator with Pending Operation                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Phase 2: Guard Analysis                                                β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  HANDLER: on :number                                            β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  Guard Path 1: $pending_operation exists                        β”‚   β”‚
β”‚  β”‚    β†’ Implies state: #has_pending_op                             β”‚   β”‚
β”‚  β”‚    β†’ Actions: perform calculation, update $operand              β”‚   β”‚
β”‚  β”‚    β†’ Post-state: $pending_operation becomes empty               β”‚   β”‚
β”‚  β”‚                  $operand becomes $result                       β”‚   β”‚
β”‚  β”‚                  β†’ Returns to: #has_operand                     β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  Guard Path 2: otherwise ($pending_operation empty)             β”‚   β”‚
β”‚  β”‚    β†’ Implies state: #no_pending_op                              β”‚   β”‚
β”‚  β”‚    β†’ Actions: $operand becomes $value                           β”‚   β”‚
β”‚  β”‚    β†’ Post-state: #has_operand                                   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  HANDLER: on :operation                                         β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  Guard Path 1: $operand exists                                  β”‚   β”‚
β”‚  β”‚    β†’ Pre-state: #has_operand                                    β”‚   β”‚
β”‚  β”‚    β†’ Actions: $pending_operation becomes $operation_type        β”‚   β”‚
β”‚  β”‚    β†’ Post-state: #has_pending_op                                β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  Guard Path 2: otherwise ($operand empty)                       β”‚   β”‚
β”‚  β”‚    β†’ Pre-state: #ready                                          β”‚   β”‚
β”‚  β”‚    β†’ Actions: emit error                                        β”‚   β”‚
β”‚  β”‚    β†’ Post-state: #ready (unchanged)                             β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  HANDLER: on :equals                                            β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  Guard: $pending_operation exists AND $operand exists           β”‚   β”‚
β”‚  β”‚    β†’ Pre-state: #has_pending_op (with operand)                  β”‚   β”‚
β”‚  β”‚    β†’ Actions: perform calculation, clear all                    β”‚   β”‚
β”‚  β”‚    β†’ Post-state: #ready                                         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  HANDLER: on :clear / :all_clear                                β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  No guards - runs from any state                                β”‚   β”‚
β”‚  β”‚    β†’ Pre-state: ANY                                             β”‚   β”‚
β”‚  β”‚    β†’ Actions: reset everything                                  β”‚   β”‚
β”‚  β”‚    β†’ Post-state: #ready                                         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  DERIVED STATE MACHINE                                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚                         :clear / :all_clear                             β”‚
β”‚               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚
β”‚               β”‚                                      β”‚                  β”‚
β”‚               β”‚                                      β”‚                  β”‚
β”‚               β–Ό                                      β”‚                  β”‚
β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                β”‚                  β”‚
β”‚        β”‚  #ready    β”‚ $operand = empty               β”‚                  β”‚
β”‚        β”‚            β”‚ $pending_op = empty            β”‚                  β”‚
β”‚        β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                                β”‚                  β”‚
β”‚              β”‚                                       β”‚                  β”‚
β”‚              β”‚ :number (otherwise branch)            β”‚                  β”‚
β”‚              β”‚ $operand becomes $value               β”‚                  β”‚
β”‚              β–Ό                                       β”‚                  β”‚
β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚                  β”‚
β”‚        β”‚ #has_operand   β”‚ $operand exists            β”‚                  β”‚
β”‚        β”‚                β”‚ $pending_op = empty        β”‚                  β”‚
β”‚        β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                            β”‚                  β”‚
β”‚              β”‚                                       β”‚                  β”‚
β”‚              β”‚ :operation                            β”‚                  β”‚
β”‚              β”‚ $pending_op becomes $op_type          β”‚                  β”‚
β”‚              β–Ό                                       β”‚                  β”‚
β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚                  β”‚
β”‚        β”‚#has_pending_op β”‚ $pending_op exists         β”‚                  β”‚
β”‚        β”‚                β”‚                            β”‚                  β”‚
β”‚        β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                            β”‚                  β”‚
β”‚            β”‚       β”‚                                 β”‚                  β”‚
β”‚   :number  β”‚       β”‚ :equals                         β”‚                  β”‚
β”‚   (guard)  β”‚       β”‚ (perform & clear)               β”‚                  β”‚
β”‚            β”‚       β”‚                                 β”‚                  β”‚
β”‚            β–Ό       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                    β”‚
β”‚     β”‚#has_operand  β”‚  (chain calculation, keep operand)                 β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                    β”‚
β”‚                                                                         β”‚
β”‚  Confidence: 85% (clear guard patterns)                                 β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States File:

flow
// calculator.states.flow

machine: @calculator

#ready
  type: initial
  description: Calculator cleared, ready for first number
  constraint: $operand is empty AND $pending_operation is empty
  waiting_for: :number, :clear, :all_clear

#has_operand
  type: waiting
  description: First number entered, waiting for operation
  constraint: $operand exists AND $pending_operation is empty
  after: :number (when no pending operation)
  waiting_for: :operation, :number, :clear, :all_clear

#has_pending_op
  type: waiting
  description: Operation selected, waiting for second number
  constraint: $pending_operation exists
  after: :operation
  waiting_for: :number, :equals, :clear, :all_clear

Example 4: Order Processing (Event-Flow Derived) ​

flow
machine: @order

on :checkout from @customer (api)
  validate cart
  emit :request_payment to @payment
    with $order_id, $total

on :payment_success from @payment
  emit :reserve_stock to @warehouse
    with $order_id, $items

on :payment_failed from @payment
  emit :checkout_failed to @customer

on :stock_reserved from @warehouse
  emit :confirmation to @customer
  emit :schedule_delivery to @shipping

on :stock_unavailable from @warehouse
  emit :request_refund to @payment
  emit :out_of_stock to @customer

on :refund_complete from @payment
  // Order fully cancelled

on :delivery_scheduled from @shipping
  // Order complete

Derivation Analysis:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  DERIVATION ANALYSIS: Order Processing                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  Phase 1: Event-Flow Analysis (HIGH CONFIDENCE)                         β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  EMIT/RESPONSE PATTERN 1:                                       β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  :checkout                                                      β”‚   β”‚
β”‚  β”‚      β”‚                                                          β”‚   β”‚
β”‚  β”‚      └── emit :request_payment to @payment                      β”‚   β”‚
β”‚  β”‚              β”‚                                                  β”‚   β”‚
β”‚  β”‚              β”œβ”€β”€ on :payment_success from @payment βœ“            β”‚   β”‚
β”‚  β”‚              └── on :payment_failed from @payment βœ“             β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  CREATES: #awaiting_payment                                     β”‚   β”‚
β”‚  β”‚  Confidence: 95%                                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  EMIT/RESPONSE PATTERN 2:                                       β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  :payment_success                                               β”‚   β”‚
β”‚  β”‚      β”‚                                                          β”‚   β”‚
β”‚  β”‚      └── emit :reserve_stock to @warehouse                      β”‚   β”‚
β”‚  β”‚              β”‚                                                  β”‚   β”‚
β”‚  β”‚              β”œβ”€β”€ on :stock_reserved from @warehouse βœ“           β”‚   β”‚
β”‚  β”‚              └── on :stock_unavailable from @warehouse βœ“        β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  CREATES: #awaiting_stock                                       β”‚   β”‚
β”‚  β”‚  Confidence: 95%                                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  EMIT/RESPONSE PATTERN 3:                                       β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  :stock_unavailable                                             β”‚   β”‚
β”‚  β”‚      β”‚                                                          β”‚   β”‚
β”‚  β”‚      └── emit :request_refund to @payment                       β”‚   β”‚
β”‚  β”‚              β”‚                                                  β”‚   β”‚
β”‚  β”‚              └── on :refund_complete from @payment βœ“            β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  CREATES: #awaiting_refund                                      β”‚   β”‚
β”‚  β”‚  Confidence: 95%                                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  EMIT/RESPONSE PATTERN 4:                                       β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  :stock_reserved                                                β”‚   β”‚
β”‚  β”‚      β”‚                                                          β”‚   β”‚
β”‚  β”‚      └── emit :schedule_delivery to @shipping                   β”‚   β”‚
β”‚  β”‚              β”‚                                                  β”‚   β”‚
β”‚  β”‚              └── on :delivery_scheduled from @shipping βœ“        β”‚   β”‚
β”‚  β”‚                                                                 β”‚   β”‚
β”‚  β”‚  CREATES: #awaiting_delivery                                    β”‚   β”‚
β”‚  β”‚  Confidence: 95%                                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚  TERMINAL STATES:                                                       β”‚
β”‚    β€’ :payment_failed β†’ #checkout_failed (failure)                       β”‚
β”‚    β€’ :refund_complete β†’ #refunded (failure)                             β”‚
β”‚    β€’ :delivery_scheduled β†’ #completed (success)                         β”‚
β”‚                                                                         β”‚
β”‚  Overall Confidence: 95% (all event-flow derived)                       β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated State Diagram:

                              ORDER STATE MACHINE

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   #idle    β”‚
    β”‚ (initial)  β”‚
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
          β”‚ :checkout
          β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚#awaiting_payment │◄── emit :request_payment to @payment
    β”‚    (waiting)     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                                 β”‚
    β–Ό                                 β–Ό
:payment_success               :payment_failed
    β”‚                                 β”‚
    β–Ό                                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ #awaiting_stock  β”‚          β”‚#checkout_failedβ”‚
β”‚    (waiting)     β”‚          β”‚(terminal:fail) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                 β”‚
β–Ό                                 β–Ό
:stock_reserved            :stock_unavailable
    β”‚                             β”‚
    β–Ό                             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚#awaiting_delivery  β”‚    β”‚ #awaiting_refund β”‚
β”‚    (waiting)       β”‚    β”‚    (waiting)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                         β”‚
         β–Ό                         β–Ό
  :delivery_scheduled       :refund_complete
         β”‚                         β”‚
         β–Ό                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  #completed    β”‚        β”‚   #refunded    β”‚
β”‚(terminal:pass) β”‚        β”‚(terminal:fail) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generated States File:

flow
// order.states.flow

machine: @order

#idle
  type: initial
  description: No order started
  waiting_for: :checkout from @customer

#awaiting_payment
  type: waiting
  description: Order submitted, waiting for payment result
  after: :checkout
  emits: :request_payment to @payment
  waiting_for: :payment_success, :payment_failed from @payment

#checkout_failed
  type: terminal
  outcome: failure
  description: Payment failed, order cancelled
  after: :payment_failed from @payment

#awaiting_stock
  type: waiting
  description: Payment received, checking inventory
  after: :payment_success from @payment
  emits: :reserve_stock to @warehouse
  waiting_for: :stock_reserved, :stock_unavailable from @warehouse

#awaiting_refund
  type: waiting
  description: Stock unavailable, processing refund
  after: :stock_unavailable from @warehouse
  emits: :request_refund to @payment
  waiting_for: :refund_complete from @payment

#refunded
  type: terminal
  outcome: failure
  description: Order cancelled, customer refunded
  after: :refund_complete from @payment

#awaiting_delivery
  type: waiting
  description: Stock reserved, scheduling delivery
  after: :stock_reserved from @warehouse
  emits: :schedule_delivery to @shipping
  waiting_for: :delivery_scheduled from @shipping

#completed
  type: terminal
  outcome: success
  description: Order delivered successfully
  after: :delivery_scheduled from @shipping

CLI Commands ​

derive-states Command ​

bash
# Interactive mode (default)
eventflow derive-states order.flow

# Non-interactive mode (CI/CD)
eventflow derive-states order.flow --no-interactive

# Update existing states file
eventflow derive-states order.flow --update

# Show derivation analysis without generating
eventflow derive-states order.flow --analyze

# Set minimum confidence threshold
eventflow derive-states order.flow --min-confidence 70

# Force regeneration, overwrite existing
eventflow derive-states order.flow --force

analyze-states Command ​

bash
# Show detailed derivation analysis
eventflow analyze-states order.flow

# Output format options
eventflow analyze-states order.flow --format json
eventflow analyze-states order.flow --format markdown

# Show only specific derivation type
eventflow analyze-states order.flow --type event-flow
eventflow analyze-states order.flow --type guard-derived
eventflow analyze-states order.flow --type context-derived

Example CLI Output ​

bash
$ eventflow derive-states calculator.flow --analyze

╔══════════════════════════════════════════════════════════════════════════════╗
β•‘  STATE DERIVATION ANALYSIS: calculator.flow                                  β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Machine: @calculator
Mode: DEFAULT (no marker)

───────────────────────────────────────────────────────────────────────────────
PHASE 1: Event-Flow Analysis
───────────────────────────────────────────────────────────────────────────────

  Emit statements found: 1
    β€’ emit :error to @user (line 15) - fire-and-forget, no wait state

  Cross-machine patterns: 0
  Wait states derived: 0

───────────────────────────────────────────────────────────────────────────────
PHASE 2: Guard Analysis
───────────────────────────────────────────────────────────────────────────────

  Guards found: 4

  β”Œβ”€ Handler: on :number ─────────────────────────────────────────────────────┐
  β”‚  Guard: ? $pending_operation exists                                       β”‚
  β”‚  Type: EXISTENCE CHECK                                                    β”‚
  β”‚  Creates states: #has_pending_op, #no_pending_op                          β”‚
  β”‚  Confidence: 85%                                                          β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  β”Œβ”€ Handler: on :operation ──────────────────────────────────────────────────┐
  β”‚  Guard: ? $operand exists                                                 β”‚
  β”‚  Type: EXISTENCE CHECK                                                    β”‚
  β”‚  Creates states: #has_operand, #no_operand                                β”‚
  β”‚  Confidence: 85%                                                          β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  Guard-derived states: 3
    β€’ #ready ($operand empty, $pending_op empty)
    β€’ #has_operand ($operand exists, $pending_op empty)
    β€’ #has_pending_op ($pending_op exists)

───────────────────────────────────────────────────────────────────────────────
PHASE 3: Context Analysis
───────────────────────────────────────────────────────────────────────────────

  Mode variables: 0
  Context-derived states: 0

───────────────────────────────────────────────────────────────────────────────
SUMMARY
───────────────────────────────────────────────────────────────────────────────

  Total states: 3
  Derivation source:
    β€’ Event-flow: 0
    β€’ Guard-derived: 3
    β€’ Context-derived: 0

  Overall confidence: 85%

  β”Œβ”€ RECOMMENDATION ──────────────────────────────────────────────────────────┐
  β”‚                                                                           β”‚
  β”‚  The derived states look complete. Run without --analyze to generate      β”‚
  β”‚  calculator.states.flow                                                   β”‚
  β”‚                                                                           β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

? Generate states file? (Y/n):

Decision Matrix: Quick Reference ​

When Does Each Derivation Source Apply? ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        STATE DERIVATION DECISION MATRIX                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                     β”‚
β”‚  CODE PATTERN                          β”‚ DERIVATION          β”‚ CONFIDENCE β”‚ RESULT β”‚
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚  emit :X to @Y + on :Z from @Y         β”‚ Event-Flow          β”‚ HIGH (95%) β”‚ Wait   β”‚
β”‚  emit async :X + response handlers     β”‚ Event-Flow          β”‚ HIGH (95%) β”‚ Wait   β”‚
β”‚  (queued api)                          β”‚ Event-Flow          β”‚ HIGH (95%) β”‚ Wait   β”‚
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚  ? $var exists                         β”‚ Guard-Derived       β”‚ MED (85%)  β”‚ Branch β”‚
β”‚  ? $var is "value"                     β”‚ Guard-Derived       β”‚ MED (85%)  β”‚ Branch β”‚
β”‚  ? condition + otherwise               β”‚ Guard-Derived       β”‚ MED (85%)  β”‚ Branch β”‚
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚  $mode becomes "X" (enum values)       β”‚ Context-Derived     β”‚ MED (80%)  β”‚ Mode   β”‚
β”‚  Multiple mode handlers                β”‚ Context-Derived     β”‚ MED (80%)  β”‚ Mode   β”‚
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚  Multiple (api), no guards, no emit    β”‚ Auto: Single State  β”‚ HIGH(100%) β”‚ Ready  β”‚
│  Single action only                    │ Auto: Init→Terminal │ HIGH(100%) │ Simple │
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚  :timeout without from/scheduled       β”‚ UNDECIDABLE         β”‚ LOW (20%)  β”‚ Ask    β”‚
β”‚  ──────────────────────────────────────┼─────────────────────┼────────────┼────────│
β”‚                                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration Quick Reference ​

ConfigurationExampleStatesConfidence
Single actionvalidate order2 (idle β†’ done)100%
Multiple (api), no guardsCalculator1 (#ready)100%
Multiple (api), with guardsWizard with guardsN (guard-derived)85%
Single machine, emit to actorOrder β†’ PaymentN (wait states)95%
Multi-machine systemOrder/Payment/WarehouseN per machine95%
Parallel async (fan-out)Loan checks1 collecting + terminals90%
Internal events (sync)Chained handlersCollapsed90%
Mode variablesScientific calculatorN modes80%

The Golden Rule ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                         β”‚
β”‚                         THE GOLDEN RULE                                 β”‚
β”‚                                                                         β”‚
β”‚    "If you can call handler B without calling handler A first,          β”‚
β”‚     then A and B are independent and share the same state."             β”‚
β”‚                                                                         β”‚
β”‚    The CODE decides this, not the developer's intention.                β”‚
β”‚                                                                         β”‚
β”‚    Want sequential? Add guards.                                         β”‚
β”‚    Want waiting? Add emit/response.                                     β”‚
β”‚    Want modes? Add mode variable checks.                                β”‚
β”‚                                                                         β”‚
β”‚    No guards + No emit = Independent = Single state.                    β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Migration Path ​

Phase 1: Introduce v2 Derivation ​

  1. Implement combined derivation pipeline
  2. Add --analyze flag for transparency
  3. Support machine mode markers
  4. Maintain backward compatibility with moves to

Phase 2: Encourage Adoption ​

  1. Add warnings for ambiguous cases
  2. Suggest mode markers where appropriate
  3. Provide automated refactoring tools
  4. Update documentation with new examples

Phase 3: Gradual Transition ​

  1. Allow mixed explicit/implicit states
  2. Validate derived states against explicit ones
  3. Provide migration reports

Phase 4: Full Integration ​

  1. Make derivation the default
  2. moves to becomes optional override
  3. Generated .states.flow becomes source of truth for diagrams

Scenario Design Guidelines ​

Understanding when events belong in the same scenario vs. separate scenarios is crucial for proper machine design.

The Scenario Definition ​

A scenario groups events that form a single business flow. It's not just documentation - it represents a cohesive process with:

  • A clear starting point (entry event)
  • A defined progression (intermediate events)
  • Terminal outcomes (success/failure states)

When to Use SAME Scenario ​

Events belong in the same scenario when:

CriterionExampleReasoning
Causal dependency:checkout β†’ :payment_receivedPayment can't happen without checkout
Single business flowLoan: submit β†’ checks β†’ decisionOne process from start to finish
Shared contextAll events use $order_id, $totalData flows through the process
Common outcomeAll paths lead to #approved or #declinedSingle decision point
Temporal couplingFan-out/fan-in parallel eventsStart and end together
flow
// CORRECT: Single flow, same scenario
scenario: complete purchase

  on :checkout from @customer (api)
    emit :request_payment to @payment

  on :payment_success from @payment
    emit :reserve_stock to @warehouse

  on :stock_reserved from @warehouse
    emit :confirmation to @customer

When to Use SEPARATE Scenarios ​

Events belong in separate scenarios when:

CriterionExampleReasoning
Independent operationsCalculator: add, subtractCan call in any order
No causal dependencyCRUD operationsEach stands alone
Different capabilities"cart management" vs "checkout"Distinct business functions
Reusable operations"add to cart" used by multiple flowsShared utility
flow
// CORRECT: Independent operations, separate scenarios
machine: @calculator

scenario: addition
  on :add (api)
    $result increases by $value

scenario: subtraction
  on :subtract (api)
    $result decreases by $value

scenario: memory operations
  on :memory_store (api)
    $memory becomes $result

  on :memory_recall (api)
    $result becomes $memory

The Scenario Decision Tree ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         SCENARIO DESIGN DECISION TREE                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                  β”‚
β”‚  Q1: Can event B happen WITHOUT event A happening first?                         β”‚
β”‚      β”‚                                                                           β”‚
β”‚      β”œβ”€β”€ YES β†’ Different scenarios (independent operations)                      β”‚
β”‚      β”‚                                                                           β”‚
β”‚      └── NO β†’ Continue to Q2                                                     β”‚
β”‚              β”‚                                                                   β”‚
β”‚              Q2: Do events A and B share context and outcome?                    β”‚
β”‚                  β”‚                                                               β”‚
β”‚                  β”œβ”€β”€ YES β†’ Same scenario (single flow)                           β”‚
β”‚                  β”‚                                                               β”‚
β”‚                  └── NO β†’ Different scenarios (separate concerns)                β”‚
β”‚                                                                                  β”‚
β”‚  EXAMPLES:                                                                       β”‚
β”‚                                                                                  β”‚
β”‚  :checkout β†’ :payment_received                                                   β”‚
β”‚    Q1: Can payment happen without checkout? NO                                   β”‚
β”‚    Q2: Share context ($order_id, $total) and outcome (#paid)? YES                β”‚
β”‚    β†’ SAME SCENARIO βœ“                                                             β”‚
β”‚                                                                                  β”‚
β”‚  :add β†’ :subtract (calculator)                                                   β”‚
β”‚    Q1: Can subtract happen without add? YES                                      β”‚
β”‚    β†’ DIFFERENT SCENARIOS βœ“                                                       β”‚
β”‚                                                                                  β”‚
β”‚  :add_to_cart β†’ :checkout                                                        β”‚
β”‚    Q1: Can checkout happen without add_to_cart? NO (cart must have items)        β”‚
β”‚    Q2: Different capabilities (cart mgmt vs purchase)? YES                       β”‚
β”‚    β†’ DIFFERENT SCENARIOS (but checkout depends on cart state) βœ“                  β”‚
β”‚                                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Scenario vs. Machine Boundary ​

Sometimes the question isn't "same or different scenario" but "same or different machine":

SituationSolution
Independent service with its own lifecycleSeparate machine
Reusable capability called by multiple flowsSeparate machine
Tightly coupled steps in one processSame machine, same scenario
Related but independent operationsSame machine, different scenarios
flow
// Payment is a SEPARATE MACHINE (independent service)
machine: @payment

scenario: process payment
  on :request_payment from @order
    process with gateway
    ? successful
      emit :payment_success to @order
    otherwise
      emit :payment_failed to @order

Impact on State Derivation ​

Scenario boundaries do not affect state derivation directly, but they provide important context:

  1. Same scenario, sequential events β†’ Derived states between events
  2. Same scenario, parallel events β†’ Single collecting state (fan-out/fan-in)
  3. Different scenarios, no guards β†’ Single shared #ready state
  4. Different scenarios, with guards β†’ Guard-derived states

The derivation algorithm looks at code structure (guards, emit/response patterns), not scenario boundaries. Scenarios help humans understand the design intent.


Open Questions for Discussion ​

  1. Orthogonal State Dimensions: When mode states and workflow states coexist, should they be:

    • Merged into composite states (#degrees_awaiting_payment)
    • Kept as separate dimensions (parallel state machines)
    • Left to developer choice
  2. Internal Event Execution Model: Should internal events (no to @actor) be:

    • Sync by default (current assumption)
    • Async by default (queue-based)
    • Configurable via syntax (emit sync :event vs emit async :event)
  3. Guard Complexity Limit: How deep should guard-derived state analysis go?

    • Limit nesting depth (e.g., max 3 levels)
    • Limit total states per handler (e.g., max 8)
    • Warn but allow unlimited
  4. Scenario Semantics: Should scenarios affect state derivation? RESOLVED

    • Answer: Scenarios do NOT affect state derivation (code structure does)
    • Scenarios group events that form a single business flow
    • See Scenario Design Guidelines for detailed guidance


Changelog ​

VersionDateChanges
v2.22025-12-18Added "Scenario Design Guidelines" section, clarified when events belong in same vs. separate scenarios, resolved Open Question 4, added "Why Same Scenario?" explanation to Configuration 6
v2.12025-12-16Comprehensive machine configuration analysis, corrected "ambiguity" analysis (calculator IS decidable), added decision matrix, updated mode markers as optional
v2.02025-12-16Initial v2 proposal with three-algorithm approach

Released under the MIT License.