Changelog

View Source

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[1.9.0] 2025-09-09

Added

Enhanced Data Model Support

  • Statifier.active_leaf_states/1: Added public API function to retrieve only leaf states from active configuration
    • Leaf State Focus: Returns only the leaf (atomic) states that are currently active, excluding ancestor states
    • MapSet Return: Returns active leaf states as a MapSet for efficient membership testing and set operations
    • Public API: Provides direct access to leaf state information for client applications
    • Documentation: Comprehensive function documentation with clear usage examples

Enhanced Event Processing Improvements

  • SCXML-Compliant Event Matching: Complete implementation of W3C SCXML event matching patterns

    • Universal Wildcard: "*" matches any event name per SCXML specification
    • Prefix Matching: "foo" matches "foo", "foo.bar", "foo.bar.baz" with dot-separated token logic
    • OR Pattern Support: "foo bar" matches events that match "foo" OR "bar" (space-separated alternatives)
    • Wildcard Suffix: "foo.*" matches "foo.bar", "foo.baz" but not "foo" (requires additional tokens)
    • Token-Based Logic: Proper dot-separated token parsing for hierarchical event names
  • Error Event Generation: Comprehensive error.execution event generation per SCXML specification

    • Assign Action Errors: Failed assignments now generate error.execution events with detailed context
    • Error Event Structure: Events include reason, type, location, and expression information
    • Internal Event Queue: Error events properly queued as internal events for processing
    • Graceful Error Handling: State machine continues execution after logging errors

Strict Nested Assignment Validation

  • Enhanced Datamodel Validation: Strict checking for nested map assignments to prevent auto-creation
    • Intermediate Structure Validation: Assignments to nested paths require all intermediate structures to exist
    • Type Safety: Prevents assignment to non-map intermediate values with clear error messages
    • SCXML Compliance: Aligns with proper SCXML datamodel semantics for assignment operations
    • Error Reporting: Detailed error messages indicating specific validation failures

Changed

Test Infrastructure Improvements

  • Updated Internal Tests: Modified 9 internal tests to expect strict nested assignment behavior
    • Correct SCXML Behavior: Tests now verify proper failure when attempting to assign to non-existent intermediate structures
    • Error Expectation: Tests properly expect {:error, reason} responses for invalid assignments
    • Maintained Coverage: All test updates preserve comprehensive test coverage

Event Processing Updates

  • Enhanced Event Module: Improved event matching capabilities with comprehensive pattern support
    • Robust Pattern Matching: Handles complex event patterns with proper token parsing
    • Performance Optimization: Efficient string splitting and token comparison algorithms
    • Comprehensive Testing: Full test coverage for all event matching scenarios

Fixed

Code Quality Improvements

  • Removed Unnecessary Validation: Eliminated whitespace validation from Evaluator resolve_location functions
    • Simplified Logic: Removed redundant whitespace checking that wasn't addressing root issues
    • Cleaner Implementation: Focus on core location resolution functionality without extra validation layers
    • Performance: Reduced unnecessary string processing in location resolution

Datamodel Assignment Fixes

  • Strict Assignment Implementation: Fixed auto-creation of intermediate map structures in nested assignments
    • Prevented Invalid Behavior: No longer auto-creates intermediate maps when assigning to nested paths
    • Proper Error Handling: Clear error messages when attempting to assign to non-existent intermediate structures
    • SCXML Compliance: Aligns with W3C SCXML specification for datamodel assignment semantics

Technical Improvements

Enhanced Test Coverage

  • Comprehensive Event Testing: Added extensive tests for SCXML event matching patterns
    • Universal Wildcard Tests: Verification that "*" matches all event types
    • Prefix Pattern Tests: Testing hierarchical event matching with dot notation
    • OR Logic Tests: Validation of space-separated alternative event patterns
    • Wildcard Suffix Tests: Complex wildcard pattern testing with proper token requirements
    • Coverage Achievement: Improved test coverage to 90.1% (up from 89.7%)

Developer Experience

  • Enhanced Error Messages: Improved error context and logging throughout assignment operations
  • Structured Logging: Comprehensive logging with metadata for debugging assignment failures
  • Debug Support: Enhanced debugging capabilities with elixir log adapter recommendations

Examples

Event Matching Patterns

<!-- Universal wildcard - matches any event -->
<transition event="*" target="catch_all"/>

<!-- Prefix matching - matches "user", "user.login", "user.logout" -->
<transition event="user" target="user_handler"/>

<!-- OR patterns - matches "start" OR "begin" OR "init" -->
<transition event="start begin init" target="startup"/>

<!-- Wildcard suffix - matches "system.error", "system.warning" but not "system" -->
<transition event="system.*" target="system_handler"/>

Error Event Handling

<state id="processing">
  <onentry>
    <!-- This will generate error.execution event if foo doesn't exist -->
    <assign location="foo.bar" expr="'value'"/>
  </onentry>
  
  <!-- Handle assignment errors -->
  <transition event="error.execution" target="error_state">
    <log expr="'Assignment failed: ' + _event.data.reason"/>
  </transition>
</state>

Strict Assignment Validation

# This will now fail with proper error instead of auto-creating structures
{:error, reason} = Datamodel.put_in_path(%{}, ["foo", "bar"], "value")
# reason: "Cannot assign to nested path: 'foo' does not exist"

# Proper usage requires intermediate structures to exist
datamodel = %{"foo" => %{}}
{:ok, updated} = Datamodel.put_in_path(datamodel, ["foo", "bar"], "value")
# updated: %{"foo" => %{"bar" => "value"}}

Migration Notes

  • Event Matching: Existing event patterns continue to work with enhanced capabilities
  • Assignment Behavior: Code relying on auto-creation of intermediate structures may need updates
  • Error Handling: New error.execution events provide better error visibility and handling
  • Test Coverage: Internal tests updated to reflect correct SCXML assignment behavior

Notes

  • Enhanced SCXML Compliance: Improved adherence to W3C SCXML specification for event processing and datamodel operations
  • Better Error Handling: Comprehensive error event generation and structured error reporting
  • Robust Event Processing: Full implementation of SCXML event matching patterns with proper token-based logic
  • Strict Datamodel Semantics: Proper validation of nested assignments prevents unexpected behavior
  • Test Coverage Improvement: Achieved 90.1% test coverage with comprehensive event matching tests

[1.8.0] 2025-09-02

Added

Documentation Site and Infrastructure

  • VitePress Documentation Site: Complete documentation site setup with Diataxis structure following the four documentation types (Tutorials, How-to Guides, Reference, Explanation)
  • GitHub Actions Integration: Automatic deployment to GitHub Pages with separate workflows for documentation building and linting
  • Specialized Documentation Agent: Added Diataxis-aware documentation agent for structured content creation and management

SCXML Feature Enhancements

  • Internal Transitions: Complete implementation of type="internal" transitions that execute actions without exiting/re-entering source state per W3C SCXML specification
  • Enhanced Send Elements: Improved <send> element support with better content data processing, parameter validation, and JSON serialization for complex values
  • Nested If Parsing: Fixed SAX parser to properly handle nested <if> blocks, enabling complex conditional logic structures

Performance and Developer Experience

  • Macro-Based Logging: Converted all LogManager logging functions to performance-optimized macros with lazy evaluation and zero overhead when logging is disabled
  • Environment-Aware Logging: Added automatic logging configuration based on environment (trace in dev, debug in test, info in prod)
  • Enhanced Debugging: Comprehensive trace logging throughout transition resolution and action execution with structured metadata

Fixed

  • Parallel Transition Conflicts: Enhanced TransitionResolver to handle conflicts between transitions from parallel regions using document order per SCXML specification
  • Expression Compilation: Moved expression compilation from creation-time to validation-time with fallback runtime compilation for backward compatibility
  • Pipeline-Friendly APIs: Updated all action execute functions to take state_chart as first argument for better Elixir pipeline composition

Changed

  • Feature Detection Updates: Moved send_content_elements and send_param_elements from partial to supported status
  • Code Quality: Resolved Credo static analysis issues by extracting helper functions and reducing cyclomatic complexity
  • Error Handling: Improved error context logging for failed conditions and expression evaluations

Infrastructure

  • Separated Workflows: Split documentation workflows into focused build/deployment and linting processes
  • ESM Module Support: Added proper ES module configuration for VitePress compatibility
  • Test Coverage: Improved test coverage across parser components, action executors, and logging infrastructure

[1.7.0] 2025-09-01

Added

Enhanced SCXML Feature Detection and Test Infrastructure

  • Comprehensive Feature Detection: Added detection for 8 new SCXML features including wildcard_events, invoke_elements, script_elements, cancel_elements, finalize_elements, donedata_elements, send_content_elements, send_param_elements, and send_delay_expressions
  • Automated Test Updates: Created script to automatically update @required_features attributes across 182 test files (123 SCION + 59 W3C) based on actual XML content analysis
  • Wildcard Events Support: Full implementation of event="*" patterns with proper transition processing and comprehensive test coverage
  • Partial Feature Testing: Modified test framework to allow :partial features to run, providing better feedback instead of automatic exclusion

New SCXML Elements and Features

  • Foreach Element Support: Complete SCXML <foreach> implementation with W3C-compliant variable scoping, permanent variable declaration, and nested action support
  • Targetless Transitions: Implementation of SCXML targetless transitions that execute actions without state changes, following W3C specification requirements
  • Enhanced Send Elements: Improved <send> element parsing with proper content element text capture, fixing previously ignored text content in send actions

Development Infrastructure

  • Quality Mix Task: Added comprehensive mix quality task with automated formatting, testing, static analysis, and coverage checking
  • Coverage Improvements: Significantly improved test coverage across multiple modules including parser components, action executors, and logging infrastructure

Changed

Test Framework Improvements

  • Enhanced Feature Validation: Updated FeatureDetector.validate_features/1 to treat :partial features as runnable rather than excluded
  • Improved Test Accuracy: All test files now have precise feature requirements based on actual SCXML content rather than manual specification
  • Better Regression Coverage: Regression test coverage improved from 141/142 to 145/145 (100% pass rate)

SCXML Compliance Enhancements

  • History State Fixes: Fixed history state restoration to properly execute ancestor onentry actions per W3C specification
  • Logging Improvements: Implemented safe_to_string function to handle complex data types in log actions, preventing String.Chars protocol errors
  • Increased Iteration Limits: Raised eventless transition iteration limit from 100 to 1000 to handle complex automatic transition chains

Fixed

  • Content Element Parsing: Fixed SAX parser to capture text content within <content> elements for send actions
  • Variable Scoping: Proper SCXML variable scoping in foreach loops with restoration of existing variables after iteration
  • Feature Classification: Corrected wildcard_events status from :partial to :supported with full implementation

Benefits

  • Enhanced Test Coverage: Comprehensive detection prevents false positive/negative test results with accurate feature requirements
  • Better Development Feedback: Partial features now provide real feedback rather than being automatically excluded from testing
  • SCXML Compliance: Improved adherence to W3C SCXML specification with proper implementation of complex features like foreach and targetless transitions
  • Developer Experience: Automated quality checking and enhanced test infrastructure provide better development workflow

All 857+ tests continue to pass with enhanced regression coverage and improved SCXML feature support.

[1.6.0] 2025-08-30

Changed

API Consolidation and Cleanup

  • Consolidated Active States API: Unified active states functionality into single source of truth

    • Renamed Functions for Clarity: active_statesactive_leaf_states, active_ancestorsall_active_states
    • Single Source of Truth: All active state queries now handled by Configuration module
    • Removed Wrapper Functions: Eliminated duplicate functions from StateChart and Interpreter modules
    • Updated All Tests: All 857 tests updated to use consolidated API directly
    • Fixed History Tracking: History tracking now correctly uses all active states (including ancestors) for proper shallow history computation
  • Removed Backwards Compatibility Layers: Cleaned up legacy API functions for better maintainability

    • Removed Legacy Delegates: Eliminated Statifier.validate/1 and Statifier.interpret/1 delegate functions
    • Removed Statifier.parse_only/1: Eliminated unused function that provided no additional value over SCXML.parse/2
    • Forced Explicit Module Usage: Users must now call Statifier.Interpreter.initialize/1 and Statifier.Validator.validate/1 directly
    • Updated Documentation: All examples and README updated to use explicit module references

Code Quality Improvements

  • Implemented Proper Logging: Replaced TODO comments with actual logging infrastructure

    • Validation Warning Logging: Interpreter.initialize/1 now properly logs validation warnings using LogManager
    • Structured Logging: Warnings logged with warning count and detailed messages
    • Consistent Infrastructure: Uses existing logging system throughout codebase
  • Fixed All Credo Issues: Resolved all static code analysis warnings

    • Added Module Aliases: Proper module aliasing to eliminate nested module access warnings
    • Clean Code Standards: All 288 source files now pass mix credo --strict with no issues
    • Improved Readability: Better import organization and alias usage

Benefits

  • Clearer API: Eliminates confusion between multiple similar functions
  • Better Maintainability: Single source of truth for active state management
  • Explicit Architecture: Direct module usage removes API ambiguity
  • Enhanced Debugging: Proper structured logging for validation issues
  • Code Quality: Clean codebase with no static analysis issues

All 857 tests pass with 91.2% code coverage maintained throughout the refactoring.

[1.5.0] 2025-08-29

Added

Modern API with Relaxed Parsing Mode

  • Statifier.parse/2 Function: New streamlined API combining parsing and validation in one call

    • 3-Tuple Return Format: Returns {:ok, document, warnings} for comprehensive result handling
    • Automatic Validation: Validates documents by default, returns errors as {:error, {:validation_errors, errors, warnings}}
    • Options Support: Accepts keyword options for parsing customization
    • Relaxed Mode Support: Passes options to SCXML.parse for enhanced flexibility
    • Skip Validation Option: validate: false returns unvalidated documents for advanced use cases
  • Enhanced SCXML.parse/2 with XML Normalization: Comprehensive relaxed parsing mode for simplified SCXML authoring

    • XML Declaration Handling: Optional XML declaration addition with xml_declaration option (default: false to preserve line numbers)
    • Default Namespace Addition: Automatically adds W3C SCXML namespace when missing
    • Default Version Addition: Automatically adds version="1.0" when missing
    • Backwards Compatible: Preserves existing XML declarations and attributes when present
    • Test-Friendly: Eliminates XML boilerplate for cleaner test documents
  • Validation Status Tracking: Added validated field to Document struct for better API clarity

    • Document.validated: Boolean field indicating whether document has been validated
    • Interpreter Optimization: Skips redundant validation for pre-validated documents
    • Helper Function: Statifier.validated?/1 for checking document validation status

Basic Send Element Support

  • <send> Element Implementation: Comprehensive Phase 1 support for SCXML send elements with internal event communication

    • Statifier.Actions.SendAction: Complete data structure with event_expr, target_expr, type_expr, delay_expr, namelist support
    • Statifier.Actions.SendParam: Support for <param> child elements with name/expr attributes
    • Statifier.Actions.SendContent: Support for <content> child elements with expr attribute
    • Expression Evaluation: Dynamic event names, target resolution, and data payload construction
    • Internal Event Routing: Events sent to #_internal properly queued and processed in state machine
    • Transition Actions: Send elements within <transition> elements with proper execution order
  • Enhanced Parser Support: Extended SCXML parser for comprehensive send element parsing

    • Send Element Parsing: Complete parsing of <send> elements with all W3C attributes
    • Child Element Support: Parsing of nested <param> and <content> elements
    • Location Tracking: Precise source location tracking for all send-related elements
    • Handler Integration: SAX-based parsing with proper state stack management
  • ActionExecutor Integration: Enhanced action execution framework with send support

    • Transition Action Execution: Added execute_transition_actions/3 for actions within transitions
    • Proper Action Order: SCXML-compliant action execution (exit → transition → entry)
    • Pipeline Programming: Refactored parameter order for better |> operator usage

StateHierarchy Module Extraction

  • Statifier.StateHierarchy: 422-line dedicated module extracted from Interpreter for hierarchy operations
    • 8 Core Functions: descendant_of?/3, compute_lcca/3, get_ancestor_path/2, get_parallel_ancestors/2, etc.
    • Reduced Interpreter Size: 824 → 636 lines (23% reduction, 188 lines extracted)
    • Single Responsibility: All state hierarchy logic consolidated in focused module
    • Comprehensive Testing: 45 new tests covering complex hierarchies, edge cases, parallel regions

Hierarchy Caching Infrastructure

  • Statifier.HierarchyCache: O(1) performance optimization system for expensive hierarchy operations

    • Pre-computed Relationships: Ancestor paths, LCCA matrix, descendant sets, parallel regions
    • Performance Gains: 5-15x speedup for hierarchy operations (O(depth) → O(1))
    • Memory Efficient: ~1.5-2x memory overhead for significant performance benefits
    • Automatic Building: Cache built during validation phase for valid documents only
    • Statistics Tracking: Build time, memory usage, and cache size metrics
  • Enhanced Document Structure: Extended Document struct with hierarchy_cache field

    • Integration with Validation: Cache built in Validator.finalize/2 pipeline
    • Helper Functions: Document.get_all_states/1 for comprehensive state enumeration
    • Benchmark Testing: Performance and memory usage validation with dedicated benchmarks

TransitionResolver Module Extraction

  • Statifier.Interpreter.TransitionResolver: 161-line focused module extracted from Interpreter
    • Single Responsibility: Dedicated to SCXML transition conflict resolution and matching
    • 6 Core Functions: find_enabled_transitions/2, find_eventless_transitions/1, resolve_transition_conflicts/2, etc.
    • SCXML-Compliant: Implements W3C specification for optimal transition set computation
    • Comprehensive Testing: 300 lines of tests with 12 test cases covering all scenarios
    • Better Maintainability: Reduces Interpreter complexity from 655 to 581 lines (11% reduction)

Changed

API Modernization and Backwards Compatibility

  • ⚠️ BREAKING: Updated all test files to use new 3-tuple Statifier.parse/2 API

    • Comprehensive Migration: All 857 tests updated to new API format
    • Maintained Coverage: All tests continue passing with enhanced API
    • Improved Test Clarity: 3-tuple format provides better access to warnings in tests
  • Streamlined Main Module: Complete rewrite of /lib/statifier.ex with modern architecture

    • New Functions: parse/2 and validated?/1 for comprehensive API coverage
    • Error Handling: Enhanced error handling with handle_validation/2 helper
    • Reduced Nesting: Improved code maintainability with better function organization
    • Options Integration: Seamless integration with relaxed parsing options

Code Quality and Performance Improvements

  • Perfect Credo Compliance: Achieved 0 issues across 863 analyzed modules/functions

    • Function Nesting Depth: Fixed all nesting depth violations in StateHierarchy module
    • Helper Function Extraction: Added check_descendant_relationship/3, lookup_lcca_in_matrix/3, normalize_lcca_key/2
    • Clean Architecture: Better separation of concerns and improved readability
    • Benchmark Test Configuration: Added Credo disable for IO.puts in benchmark tests
  • Major Interpreter Refactoring: Comprehensive architectural improvements for better maintainability

    • Module Extraction Benefits: StateHierarchy, TransitionResolver, and HierarchyCache provide focused functionality
    • Performance Optimizations: O(1) hierarchy operations with pre-computed cache infrastructure
    • Pipeline Programming: Enhanced parameter ordering for better Elixir |> operator usage
    • Action Execution Improvements: Proper SCXML-compliant action execution order and integration
    • Future Extensibility: Clean architecture prepared for advanced SCXML features and optimizations

Enhanced Action Execution Architecture

  • ActionExecutor Parameter Refactoring: Improved parameter ordering for better Elixir programming patterns
    • StateChart First: All execute_*_actions functions now put state_chart as first parameter
    • Pipeline Friendly: Better |> operator support for functional programming style
    • Transition Actions: New execute_transition_actions/3 function for actions within transitions
    • Separation of Concerns: Moved transition action execution from Interpreter to ActionExecutor

Fixed

XML Normalization and Location Tracking

  • Version Attribute Detection: Fixed regex pattern in maybe_add_default_version/1 for proper version attribute recognition
  • Location Tracking Preservation: Ensured line number accuracy maintained with optional XML declaration
  • Function Signature Conflicts: Resolved parse/1 vs parse/2 function definition conflicts

Test Infrastructure Improvements

  • Location Tracking Tests: Updated location-specific tests to include XML declarations for accurate line numbers
  • TransitionResolver Integration: Fixed StateChart field name issues and event timing in extracted module tests
  • Comprehensive Test Coverage: All 857 tests passing with new architecture and API changes

Technical Improvements

Enhanced Developer Experience

  • Simplified SCXML Authoring: Relaxed parsing mode eliminates repetitive XML boilerplate

    • No XML Declaration Required: Tests can omit <?xml version="1.0" encoding="UTF-8"?>
    • No Namespace Required: Automatic W3C SCXML namespace addition
    • No Version Required: Automatic version="1.0" addition
    • Cleaner Test Documents: Focus on state machine logic rather than XML syntax
  • Better Error Messages: Enhanced validation error reporting with maintained source location accuracy

  • Improved API Consistency: Uniform return patterns and option handling across all parsing functions

  • Comprehensive Documentation: Updated all function documentation with examples and options

Performance and Quality Metrics

  • All Quality Gates Pass: Format ✓ Test (857/857) ✓ Credo (0 issues) ✓ Dialyzer ✓
  • Comprehensive Test Coverage: 857 total tests with significant new module coverage
    • New Test Modules: SendAction (236 lines), StateHierarchy (591 lines), TransitionResolver (313 lines)
    • Advanced Testing: Handler (483 lines), StateStack (453 lines), HierarchyCache (524 lines)
    • Performance Benchmarks: HierarchyCache benchmarks demonstrate 5-15x performance improvements
  • Memory Efficiency: O(1) hierarchy operations with intelligent caching system
  • Production Ready: All functionality thoroughly tested with comprehensive edge case coverage
  • Architecture Quality: Clean separation of concerns with focused, testable modules

Examples

New Streamlined API

# Modern API - Parse and validate in one step
{:ok, document, warnings} = Statifier.parse(xml)

# Parse without validation for advanced use cases  
{:ok, document, []} = Statifier.parse(xml, validate: false)

# Check validation status
validated = Statifier.validated?(document)  # true/false

# Skip validation explicitly
{:ok, document, []} = Statifier.parse(xml, validate: false)

Relaxed XML Parsing Mode

# Before v1.5.0 - Full XML boilerplate required
xml = """
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="start">
  <state id="start"/>
</scxml>
"""

# After v1.5.0 - Clean, minimal syntax
xml = """
<scxml initial="start">
  <state id="start"/>
</scxml>
"""

{:ok, document, warnings} = Statifier.parse(xml)
# XML declaration, namespace, and version automatically added

XML Declaration Control

# Preserve line numbers (default behavior)
{:ok, document, warnings} = Statifier.parse(minimal_xml)

# Add XML declaration explicitly
{:ok, document, warnings} = Statifier.parse(minimal_xml, xml_declaration: true)

Error Handling Examples

# Validation errors with enhanced format
case Statifier.parse(invalid_xml) do
  {:ok, document, warnings} -> 
    # Success with optional warnings
  {:error, {:validation_errors, errors, warnings}} -> 
    # Validation failed with detailed errors
  {:error, reason} -> 
    # Parsing failed
end

Send Element Usage

<scxml initial="waiting">
  <state id="waiting">
    <transition event="start" target="processing">
      <!-- Send internal event with data -->
      <send target="#_internal" event="process_data">
        <param name="userId" expr="'user123'"/>
        <param name name="priority" expr="5"/>
        <content expr="'Processing started'"/>
      </send>
    </transition>
  </state>
  
  <state id="processing">
    <transition event="process_data" target="complete">
      <!-- Event data available via _event.data -->
      <log expr="'Processing for user: ' + _event.data.userId"/>
    </transition>
  </state>
  
  <state id="complete"/>
</scxml>

Dynamic Send Elements

<state id="router">
  <transition event="route_message">
    <!-- Dynamic event and target evaluation -->
    <send targetexpr="_event.data.target" 
          eventexpr="_event.data.eventName"
          namelist="status priority">
      <param name="timestamp" expr="Date.now()"/>
    </send>
  </transition>
</state>

Performance Optimization Examples

# Before v1.5.0 - O(depth) hierarchy operations
time_uncached = benchmark_hierarchy_operations(uncached_document)

# After v1.5.0 - O(1) hierarchy operations with caching
{:ok, cached_document, _warnings} = Statifier.parse(xml)
time_cached = benchmark_hierarchy_operations(cached_document)

# Typical performance improvement: 5-15x speedup
speedup = time_uncached / time_cached  # => ~10.5x

Migration Guide

API Updates

# Before v1.5.0
{:ok, document} = SCXML.parse(xml)
{:ok, validated_doc, warnings} = Validator.validate(document)

# After v1.5.0 - Streamlined approach
{:ok, document, warnings} = Statifier.parse(xml)

Test Simplification

# Before v1.5.0 - Verbose XML
xml = """
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="idle">
  <state id="idle">
    <transition event="start" target="running"/>
  </state>
  <state id="running"/>
</scxml>
"""

# After v1.5.0 - Focus on logic
xml = """
<scxml initial="idle">
  <state id="idle">
    <transition event="start" target="running"/>
  </state>
  <state id="running"/>
</scxml>
"""

Notes

  • Major Release: Comprehensive modernization spanning API, architecture, performance, and new SCXML features
  • API Modernization: Complete modernization of parsing and validation API for better developer experience
  • Architectural Revolution: Major refactoring with StateHierarchy, TransitionResolver, HierarchyCache, and SendAction modules
  • Performance Breakthrough: O(1) hierarchy operations provide 5-15x performance improvements for complex state machines
  • SCXML Feature Expansion: Basic send element support enables internal event communication and transition actions
  • Quality Excellence: Perfect Credo compliance, comprehensive test coverage (857 tests), and thorough documentation
  • Developer Productivity: Significant reduction in XML boilerplate and improved error handling
  • Production Ready: Battle-tested architecture with comprehensive edge case coverage and benchmark validation
  • Foundation for Future: Clean, extensible architecture prepares for advanced SCXML features (delays, external targets, etc.)

[1.4.0] 2025-08-29

Added

Complete SCXML History State Support

  • History State Data Model: Full support for SCXML <history> elements per W3C specification

    • Statifier.State Extensions: Added history_type field (:shallow | :deep) and history_type_location for validation

    • Parser Support: Complete parsing of <history> elements with type="shallow|deep" attributes
    • Default Behavior: History type defaults to :shallow when not specified
    • Element Builder: New build_history_state/4 function for creating history state structures
    • Location Tracking: Full source location tracking for history elements and attributes
  • History State Validation: Comprehensive validation per W3C SCXML specification requirements

    • Statifier.Validator.HistoryStateValidator: Dedicated validator module for all history constraints
    • Structural Validation: History states cannot be at root level (must have compound/parallel parent)
    • Content Validation: History states cannot have child states (pseudo-states only)
    • Uniqueness Validation: Only one history state per type (shallow/deep) per parent state
    • Type Validation: History type must be valid (:shallow or :deep)
    • Target Validation: Default transition targets must exist in document
    • Reachability Analysis: Warns if history states are unreachable (no transitions target them)
  • History Tracking Infrastructure: Complete W3C SCXML compliant history recording and restoration

    • Statifier.HistoryTracker: Core history state tracking with efficient MapSet operations
    • Shallow History: Records and restores immediate children of parent state that contain active descendants
    • Deep History: Records and restores all atomic descendant states within parent state
    • StateChart Integration: History tracking integrated into StateChart lifecycle
    • Record History API: record_history/2, get_shallow_history/2, get_deep_history/2, has_history?/2
  • History State Resolution: Full W3C SCXML compliant history state transition resolution

    • Pseudo-State Handling: History states resolve to stored configuration or default targets (never active themselves)
    • Shallow Resolution: Restores immediate children from recorded shallow history
    • Deep Resolution: Restores all atomic descendants from recorded deep history
    • Default Transitions: Uses history state's default transitions when parent has no recorded history
    • Complex Hierarchy Support: Maintains proper state hierarchy during restoration

Multiple Transition Target Support

  • Space-Separated Target Parsing: SCXML transitions now support multiple targets per W3C specification

    • Parser Enhancement: Handles target="state1 state2 state3" syntax with proper whitespace splitting
    • Data Model: Statifier.Transition.targets field (list) replaces target field (string)
    • Validator Updates: All transition validators updated for list-based target validation
    • Empty Target Support: Empty target lists properly handled for targetless transitions
    • Feature Detection: Updated feature detection to recognize multiple target capability
  • Enhanced Parallel State Exit Logic: Critical fix for W3C SCXML parallel state exit semantics

    • Exit Set Computation: Proper W3C SCXML exit set calculation for complex parallel hierarchies
    • Parallel Ancestor Detection: get_parallel_ancestors/3 identifies all parallel ancestors in hierarchy
    • Region Identification: are_in_parallel_regions/3 correctly identifies states in different parallel regions
    • Cross-Boundary Exits: exits_parallel_region/3 detects transitions that exit parallel regions
    • Comprehensive Exit Logic: All parallel regions properly exited when transitioning to external states

Changed

API Improvements (Breaking Changes)

  • ⚠️ BREAKING: Statifier.Transition struct field renamed from target to targets
    • Type Change: target: String.t() | niltargets: [String.t()]

    • Migration: Update pattern matches from %Transition{target: target} to %Transition{targets: targets}
    • Benefit: Self-documenting code that clearly indicates list-based target support
    • Validation: All existing tests and validators updated for new API

Document Helper Functions

  • Statifier.Document Enhancements: New helper functions for history state runtime management
    • is_history_state?/2: Check if state has history type with O(1) lookup
    • find_history_states/2: Find all history states within a parent state
    • get_history_default_targets/2: Get default transition targets for history state
    • Optimized Performance: All functions use existing O(1) state_lookup maps

History Integration in Interpreter

  • Interpreter History Support: Complete integration of history states into state machine lifecycle
    • History Recording: Automatic history recording before onexit actions during state transitions
    • W3C Timing Compliance: History recorded "before taking any transition that exits the parent"
    • Parent Detection: find_parents_with_history/2 identifies parents needing history recording
    • Ancestor Analysis: get_ancestors_with_history/2 finds all ancestors with history children
    • StateChart Parameters: Enhanced interpreter functions to work with StateChart for history access

Fixed

SCION Test Coverage Improvements

  • History Test Parsing: Fixed critical parser bug where transitions inside <history> elements weren't being processed

    • StateStack Fix: Added missing {"history", parent_state} case in handle_transition_end/1
    • History Default Transitions: History states can now have proper default transitions
    • SCION History Tests: 5/8 SCION history tests now passing (62.5% success rate, up from 12.5%)
    • Test Results: history0, history1, history2, history3, history6 now pass
  • Parallel State Exit Logic: Resolved critical parallel state exit semantics issues

    • Cross-Region Transitions: Fixed transitions from parallel regions to external states
    • Exit Set Calculation: Proper W3C SCXML exit set computation for complex hierarchies
    • SCION Test Fixes: Multiple SCION history tests (history4b, history5) now pass completely
    • Regression Protection: All 118 regression tests continue to pass

Feature Detection Updates

  • History State Support: Updated FeatureDetector to mark :history_states as :supported
  • Multiple Target Support: Enhanced feature detection for multiple transition targets
  • Test Infrastructure: 12 history state tests (8 SCION + 4 W3C) now properly validated

Technical Improvements

Test Infrastructure

  • Comprehensive Test Coverage: 707 total tests with enhanced history state coverage
    • New Test Organization: Created test/statifier/history/ folder for organized history testing
    • History Test Suite: 15+ dedicated history tests covering all scenarios (recording, restoration, validation)
    • Integration Tests: End-to-end testing of history states with complex state hierarchies
    • Regression Tests: All 118 regression tests continue passing with new functionality

Code Quality

  • Credo Compliance: All static analysis issues resolved across the codebase
  • Pattern Matching: Enhanced pattern matching for cleaner, more readable code
  • Type Safety: Full typespec coverage for all new history state functionality
  • Documentation: Comprehensive documentation for all new modules and functions
  • Performance: Maintained O(1) lookups with efficient MapSet operations for history tracking

W3C SCXML Compliance

  • History State Specification: Full compliance with W3C SCXML 1.0 history state requirements
  • Parallel State Semantics: Proper W3C exit set computation and parallel region handling
  • Multiple Target Support: Compliant with W3C SCXML multiple target syntax
  • Pseudo-State Handling: Correct implementation of history as non-active pseudo-states
  • Default Transition Logic: Proper handling of history default transitions per specification

Examples

History State Usage

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="main">
  <state id="main" initial="sub1">
    <!-- Shallow history - restores immediate children -->
    <history id="main_hist" type="shallow">
      <transition target="sub1"/>  <!-- Default when no history -->
    </history>
    
    <state id="sub1">
      <transition event="go" target="sub2"/>
    </state>
    
    <state id="sub2">
      <transition event="go" target="sub3"/>
    </state>
    
    <state id="sub3">
      <transition event="exit" target="other"/>
      <transition event="back" target="main_hist"/>  <!-- Restore history -->
    </state>
  </state>
  
  <state id="other">
    <transition event="return" target="main_hist"/>  <!-- Restore to last sub-state -->
  </state>
</scxml>

Deep History Example

<parallel id="game">
  <!-- Deep history - restores all atomic descendants -->
  <history id="game_hist" type="deep">
    <transition target="level1"/>  <!-- Default: start at level 1 -->
  </history>
  
  <state id="progress" initial="level1">
    <state id="level1">
      <state id="checkpoint1"/>
      <state id="checkpoint2"/>
    </state>
    <state id="level2">
      <state id="checkpoint3"/>
      <state id="checkpoint4"/>
    </state>
  </state>
  
  <state id="inventory" initial="empty">
    <state id="empty"/>
    <state id="sword"/>
    <state id="shield"/>
  </state>
</parallel>

Multiple Target Transitions

<state id="source">
  <!-- Multiple targets - enter multiple states simultaneously -->
  <transition event="activate" target="target1 target2 target3"/>
</state>

<parallel id="system">
  <state id="target1"/>
  <state id="target2"/>  
  <state id="target3"/>
</parallel>

Programmatic History Usage

# Check if state is a history state
Document.is_history_state?(document, "main_hist")  # true

# Find all history states in a parent
history_states = Document.find_history_states(document, "main")

# Get default targets for history state
defaults = Document.get_history_default_targets(document, "main_hist")

# Record and retrieve history
state_chart = StateChart.record_history(state_chart, "main")
shallow_history = StateChart.get_shallow_history(state_chart, "main")
deep_history = StateChart.get_deep_history(state_chart, "main")

Migration Guide

Transition Target API

# Before v1.4.0
%Transition{target: "state1"}
%Transition{target: nil}  # targetless

# After v1.4.0  
%Transition{targets: ["state1"]}
%Transition{targets: []}  # targetless

# Pattern matching migration
case transition do
  %Transition{target: nil} -> # targetless
  %Transition{target: target} -> # has target
end

# becomes
case transition do
  %Transition{targets: []} -> # targetless
  %Transition{targets: targets} -> # has targets
end

Notes

  • History State Foundation: Complete foundation for SCXML history states established
  • W3C Compliance: Full compliance with W3C SCXML 1.0 history state specification
  • Multiple Target Support: Enhanced SCXML transition capability per specification
  • Parallel State Fixes: Critical parallel state exit logic issues resolved
  • Test Coverage: Comprehensive test coverage maintained (91.8% overall)
  • Production Ready: All functionality thoroughly tested and validated
  • SCION Progress: Significant improvement in SCION history test compliance

[1.3.0] 2025-08-27

Added

Core Logging Infrastructure

  • Flexible Protocol-Based Logging System: Complete logging architecture for state chart operations

  • Automatic Metadata Extraction: StateChart context automatically added to all log messages

    • Current State Tracking: Active states automatically included in log metadata
    • Event Context: Current event name automatically included when available
    • Custom Metadata Support: Additional metadata can be provided per log message
    • Metadata Precedence: Custom metadata takes precedence over automatic extraction
  • Advanced Memory Management: Circular buffer support for bounded log storage

    • Configurable Limits: TestAdapter supports optional max_entries for memory-bounded logging
    • Circular Buffer Behavior: Automatically removes oldest entries when limit exceeded
    • Unlimited Storage: Optional unlimited log storage for comprehensive test coverage
    • Helper Functions: get_logs/1,2, clear_logs/1 for test log inspection and management
  • StateChart Integration: Enhanced StateChart structure with logging capabilities

    • Logging Fields: Added log_adapter, log_level, and logs fields to StateChart struct
    • Configuration Helpers: configure_logging/3 and set_log_level/2 functions for easy setup
    • Seamless Integration: Logging works with existing StateChart lifecycle and event processing

Logging Configuration System

  • Enhanced Interpreter.initialize/2: Comprehensive logging configuration support during state chart initialization

    • Runtime Configuration Options: Accept :log_adapter and :log_level options via keyword list
    • Adapter Configuration Flexibility: Support for direct adapter structs or {Module, opts} tuples
    • Backward Compatibility: Existing initialize/1 calls continue to work with sensible defaults
    • Comprehensive Documentation: Detailed examples and usage patterns in function documentation
  • Centralized Configuration Logic: All configuration logic consolidated in LogManager.configure_from_options/2

    • Configuration Precedence: Runtime options > Application config > Environment defaults
    • Application Configuration Support: Integration with Application.get_env/3 for system-wide settings
    • Robust Error Handling: Graceful fallback to ElixirLoggerAdapter on invalid configurations
    • Validation and Safety: Comprehensive configuration validation with detailed error messages
  • Production-Ready Defaults: Sensible defaults that work across all environments

    • ElixirLoggerAdapter Default: Always the base default for robust logging in all environments
    • Test Environment Configuration: TestAdapter configured via test_helper.exs for clean test output
    • Flexible Fallback Strategy: Invalid configurations always fall back to most robust adapter
    • Environment Independence: No dependency on Mix.env() or custom environment detection
  • Comprehensive Configuration Testing: 12 dedicated tests covering all configuration scenarios

    • Runtime Configuration Tests: Verification of all option types and combinations
    • Application Configuration Tests: Testing precedence and override behavior
    • Error Handling Tests: Validation of graceful fallback for invalid configurations
    • Integration Tests: End-to-end testing of configuration system with state chart initialization

Examples

Core Logging Infrastructure

# Configure logging with TestAdapter for testing
adapter = %Statifier.Logging.TestAdapter{max_entries: 100}
state_chart = StateChart.configure_logging(state_chart, adapter, :debug)

# Configure logging with ElixirLoggerAdapter for production
adapter = %Statifier.Logging.ElixirLoggerAdapter{}
state_chart = StateChart.configure_logging(state_chart, adapter, :info)

# Log messages with automatic metadata extraction
state_chart = LogManager.info(state_chart, "Processing started", %{action_type: "initialization"})
state_chart = LogManager.error(state_chart, "Validation failed", %{field: "email"})

# Inspect captured logs in tests
logs = TestAdapter.get_logs(state_chart)
error_logs = TestAdapter.get_logs(state_chart, :error)
state_chart = TestAdapter.clear_logs(state_chart)

Production Logging Integration

# Initialize state chart with production logging
{:ok, state_chart} = Interpreter.initialize(document)
adapter = %Statifier.Logging.ElixirLoggerAdapter{}
state_chart = StateChart.configure_logging(state_chart, adapter, :info)

# All state chart operations now include automatic logging
{:ok, state_chart} = Interpreter.send_event(state_chart, event)
# Logs: [info] Processing event "start" current_state=["idle"] event="start"

Test Environment Usage

defmodule MyStateMachineTest do
  use ExUnit.Case

  test "validates error logging during processing" do
    adapter = %Statifier.Logging.TestAdapter{max_entries: 50}
    state_chart = StateChart.configure_logging(state_chart, adapter, :debug)
    
    # ... perform operations that should log ...
    
    # Verify specific log messages were captured
    logs = TestAdapter.get_logs(state_chart)
    assert [%{level: :error, message: "Validation failed"}] = logs
    
    # Check metadata extraction
    assert logs |> hd() |> Map.get(:metadata) |> Map.get(:current_state) == ["processing"]
  end
end

Logging Configuration System

# Use default configuration (ElixirLoggerAdapter, :info level)
{:ok, state_chart} = Interpreter.initialize(document)

# Configure with runtime options
{:ok, state_chart} = Interpreter.initialize(document, [
  log_adapter: {TestAdapter, [max_entries: 50]},
  log_level: :debug
])

# Configure with direct adapter struct
adapter = %TestAdapter{max_entries: 100}
{:ok, state_chart} = Interpreter.initialize(document, 
  log_adapter: adapter,
  log_level: :trace
)

# Configure via application environment (in config files or test_helper.exs)
Application.put_env(:statifier, :default_log_adapter, {TestAdapter, [max_entries: 200]})
Application.put_env(:statifier, :default_log_level, :warn)
{:ok, state_chart} = Interpreter.initialize(document)  # Uses application config

Configuration Precedence Examples

# Application configuration
Application.put_env(:statifier, :default_log_adapter, {TestAdapter, [max_entries: 300]})
Application.put_env(:statifier, :default_log_level, :error)

# Runtime options override application config
{:ok, state_chart} = Interpreter.initialize(document, [
  log_adapter: {ElixirLoggerAdapter, []},  # Overrides TestAdapter
  log_level: :info                         # Overrides :error
])

# Invalid configurations fall back gracefully
{:ok, state_chart} = Interpreter.initialize(document, [
  log_adapter: {NonExistentModule, []}     # Falls back to ElixirLoggerAdapter
])

Changed

Logger to LogManager Migration

  • Centralized Logging Architecture: Migrated all existing Logger.* calls throughout the codebase to use the new LogManager.* API

    • ActionExecutor: All debug logging now uses LogManager.debug with structured metadata (action_type, state_id, phase, etc.)
    • LogAction: Replaced Logger.info with LogManager.info, now returns updated StateChart from logging operations
    • RaiseAction: Migrated Logger.info to LogManager.info with event metadata, properly threads StateChart through logging calls
    • AssignAction: Updated Logger.error to LogManager.error with comprehensive error context and assignment details
    • Datamodel: Replaced Logger.debug calls with LogManager.debug for expression evaluation failures
  • Structured Logging Enhancement: All LogManager calls now include appropriate context-specific metadata

    • Action Context: Debug logs include action_type, state_id, and execution phase information
    • Error Context: Error logs include detailed failure information, locations, and expressions
    • Event Context: Event-related logs include event names and metadata
    • Expression Context: Expression evaluation logs include compiled expressions and error details
  • StateChart Threading: Actions now properly return updated StateChart instances from logging operations

    • Consistent Return Values: All action modules maintain StateChart consistency through logging calls
    • State Preservation: Logging operations preserve and return the complete StateChart state
    • Queue Management: Internal and external event queues remain intact through logging operations

Log Storage Optimization

  • Chronological Log Ordering: TestAdapter now stores logs in intuitive chronological order (oldest first, newest last)

    • Natural Reading Order: Logs now appear in the order they were created for easier debugging
    • Standard Behavior: Aligns with typical logging system expectations and developer intuitions
    • Improved Test Assertions: assert_log_order now uses ascending index order for cleaner test logic
  • Memory Management: Updated circular buffer behavior to maintain chronological ordering

    • FIFO Behavior: When max_entries limit is reached, oldest entries are removed first
    • Append Operations: New log entries are appended to maintain chronological sequence
    • Backward Compatibility: API remains unchanged while improving internal behavior

Test Infrastructure Enhancements

  • StateChart Log Integration: All action tests now use StateChart logs instead of capture_log for verification

    • Helper Functions: Added test_state_chart() helper for properly configured StateChart instances
    • Log Assertions: Created assert_log_entry() and assert_log_order() helpers for clean log verification
    • Configuration Helpers: Added create_configured_state_chart() helpers to reduce test duplication
  • Test Coverage Maintenance: Maintained 91.2% test coverage with comprehensive log assertion coverage

    • Regression Protection: All 108 regression tests continue passing with new logging infrastructure
    • Action Coverage: Complete test coverage for all action logging behaviors
    • Error Handling: Comprehensive test coverage for logging error scenarios

[1.2.0] 2025-08-27

Added

If/Else/ElseIf Conditional Action Support

  • <if> Action Support: Full implementation of SCXML <if> elements with conditional execution

    • Statifier.Actions.IfAction Struct: Represents if/elseif/else conditional blocks
    • Nested Action Execution: Supports multiple actions within each conditional block
    • Expression Evaluation: Uses Statifier.Evaluator for condition evaluation
    • ActionExecutor Integration: Seamlessly integrates with existing action execution framework
    • Complex Conditionals: Support for if/elseif/else chains with proper precedence
  • Parser Extensions for Conditional Actions: Extended SCXML parser to handle conditional elements

    • If/ElseIf/Else Parsing: Complete parsing support for conditional action blocks
    • StateStack Integration: Proper conditional block handling in parsing state stack
    • Mixed Action Support: Parse conditional actions alongside log/raise/assign actions
    • Location Tracking: Complete source location tracking for debugging conditional blocks

Test Coverage Improvements

  • 90.8% Overall Coverage: Comprehensive test coverage improvements through targeted edge case testing

    • StateStack Coverage: Improved from 72.7% to 95.8% (+23.1% - biggest impact module)
    • ActionExecutor Edge Cases: Added comprehensive error handling and edge case tests
    • Interpreter Coverage: Added simple edge case tests avoiding duplication with existing functionality
    • Handler Coverage: Added unknown element handling and parsing edge case tests
    • 4 New Test Files: Comprehensive coverage tests for critical modules
  • Enhanced LogAction: Improved string evaluation and error handling

    • Evaluator Integration: Uses Statifier.Evaluator for consistent expression handling
    • String Validation: Proper Unicode string validation and safe logging
    • Fallback Parsing: Graceful fallback for quoted string parsing
    • Error Recovery: Continues execution even with invalid expressions

Architecture Improvements

  • Unified Statifier.Evaluator Module: Consolidated ConditionEvaluator and ValueEvaluator into single module

    • Single Entry Point: One module for all expression evaluation (conditions and values)
    • Improved Maintainability: Eliminated code duplication between evaluator modules
    • Future Extensibility: Better prepared for pluggable datamodel architectures (ECMAScript, XPath)
    • Consistent API: Unified function signatures and error handling patterns
  • Enhanced Statifier.Datamodel Module: Improved data model operations and separation of concerns

    • put_in_path/3 Function: Moved from Evaluator to Datamodel for better architecture
    • Improved Error Handling: Returns {:ok, result} | {:error, reason} instead of raising exceptions

    • Type Safety: Proper Datamodel.t() typing throughout the codebase
    • Data Model Operations: Centralized location for all data model manipulation logic
  • Feature Detection Updates: Enhanced SCXML feature tracking for better test validation

    • Datamodel Support: Marked :datamodel and :data_elements as :supported in feature registry
    • Accurate Test Results: Prevents false test failures from unsupported feature detection
    • Better Compliance Tracking: Improved visibility into SCXML feature implementation status

Changed

Action Execution Architecture

  • ActionExecutor Delegation Pattern: Improved action execution through proper delegation

    • Public execute_single_action/2: Made function public for IfAction integration
    • Action Delegation: ActionExecutor now properly delegates to action.execute/2 methods
    • Centralized Execution: All actions now execute through consistent ActionExecutor interface
    • Better Separation of Concerns: Each action type handles its own execution logic
  • Code Quality Improvements: Enhanced code maintainability and compliance

    • Zero Credo Issues: All static analysis issues resolved across the codebase
    • Unused Variable Cleanup: Fixed unused variable warnings in Handler and ElementBuilder
    • Alias Ordering: Proper alphabetical alias ordering in all test files
    • Clean Validation Pipeline: All steps pass - format ✓ test ✓ credo ✓ dialyzer ✓

Test Coverage Improvements

  • 13 New Passing Tests: Unlocked additional test coverage through datamodel improvements

    • 9 SCION Tests: Including assign actions, current small step assignments, data initialization
    • 4 W3C Tests: Including executable content evaluation, foreach loops, conditional execution
    • Test Categories: assign/, assign_current_small_step/, data/, foreach/, if_else/
    • Overall Progress: Improved from 48/184 to 61/184 total tests passing (33% compliance)
  • Updated Test Baseline: Added new passing tests to regression test suite

    • SCION Tests: 44 → 53 passing tests
    • W3C Tests: 5 → 9 passing tests
    • Maintained Quality: All 98 regression tests continue to pass

Examples

If/Else/ElseIf Conditional Actions

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="start">
  <state id="start">
    <onentry>
      <assign location="score" expr="85"/>
      <if cond="score >= 90">
        <assign location="grade" expr="'A'"/>
        <log label="grade" expr="'Excellent work!'"/>
      <elseif cond="score >= 80"/>
        <assign location="grade" expr="'B'"/>
        <log label="grade" expr="'Good job!'"/>
      <elseif cond="score >= 70"/>
        <assign location="grade" expr="'C'"/>
        <log label="grade" expr="'Satisfactory'"/>
      <else/>
        <assign location="grade" expr="'F'"/>
        <log label="grade" expr="'Needs improvement'"/>
      </if>
    </onentry>
  </state>
</scxml>

Nested Conditional Logic

<state id="processing">
  <onentry>
    <if cond="user.authenticated">
      <if cond="user.role == 'admin'">
        <assign location="permissions" expr="'full'"/>
        <raise event="admin_access"/>
      <else/>
        <assign location="permissions" expr="'limited'"/>
        <raise event="user_access"/>
      </if>
    <else/>
      <assign location="permissions" expr="'none'"/>
      <raise event="auth_required"/>
    </if>
  </onentry>
</state>

Mixed Actions with Conditionals

<state id="validation">
  <onentry>
    <log label="status" expr="'Starting validation'"/>
    <assign location="errors" expr="[]"/>
    <if cond="data.email == null">
      <assign location="errors[0]" expr="'Email required'"/>
    </if>
    <if cond="data.age < 18">
      <assign location="errors[1]" expr="'Must be 18 or older'"/>
    </if>
    <if cond="errors.length > 0">
      <raise event="validation_failed"/>
    <else/>
      <raise event="validation_passed"/>
    </if>
  </onentry>
</state>

[1.1.0] 2025-08-26

Added

Phase 1 Enhanced Expression Evaluation

  • Predicator v3.0 Integration: Upgraded from v2.0 to v3.0 with enhanced capabilities

    • Enhanced Nested Property Access: Deep dot notation support (user.profile.settings.theme)
    • Mixed Access Patterns: Combined bracket/dot notation (users['john'].active)
    • Context Location Resolution: New context_location/2 function for assignment path validation
    • Value Evaluation: Non-boolean expression evaluation for actual data values
    • Type-Safe Operations: Improved type coercion and error handling
    • Graceful Fallback: Returns :undefined for missing properties instead of errors
  • Statifier.ValueEvaluator Module: Comprehensive value evaluation system for SCXML expressions

    • Expression Compilation: compile_expression/1 for reusable expression compilation
    • Value Evaluation: evaluate_value/2 extracts actual values (not just boolean results)
    • Location Path Resolution: resolve_location/1,2 validates assignment paths using predicator v3.0
    • Safe Assignment: assign_value/3 performs type-safe nested data model updates
    • Integrated Assignment: evaluate_and_assign/3 combines evaluation and assignment
    • SCXML Context Support: Full integration with state machine context (events, configuration, datamodel)
    • Error Handling: Comprehensive error handling with detailed logging
  • <assign> Element Support: Full W3C SCXML assign element implementation

    • Statifier.Actions.AssignAction Struct: Represents assign actions with location and expr attributes
    • Location-Based Assignment: Validates assignment paths before execution
    • Expression Evaluation: Uses Statifier.ValueEvaluator for complex expression processing
    • Nested Property Assignment: Supports deep assignment (user.profile.name = "John")
    • Mixed Notation Support: Handles both dot and bracket notation in assignments
    • Context Integration: Access to current event data and state configuration
    • Error Recovery: Graceful error handling with logging, continues execution on failures
    • Action Integration: Seamlessly integrates with existing action execution framework

StateChart Data Model Enhancement

  • Datamodel Storage: Added datamodel field to Statifier.StateChart for variable persistence
  • Current Event Context: Added current_event field for expression evaluation context
  • Helper Methods: update_datamodel/2 and set_current_event/2 for state management
  • SCXML Context Building: Enhanced context building for comprehensive expression evaluation

Parser Extensions

  • Assign Element Parsing: Extended SCXML parser to handle <assign> elements
    • Element Builder: build_assign_action/4 creates AssignAction structs with location tracking
    • Handler Integration: Added assign element start/end handlers
    • StateStack Integration: handle_assign_end/1 properly collects assign actions
    • Mixed Action Support: Parse assign actions alongside log/raise actions in onentry/onexit
    • Location Tracking: Complete source location tracking for debugging

Feature Detection Updates

  • Assign Elements Support: Updated assign_elements feature status to :supported
  • Feature Registry: Enhanced feature detection for new capabilities
  • Test Infrastructure: Tests now recognize assign element capability

Changed

Dependency Updates

  • predicator: Upgraded from ~> 2.0 to ~> 3.0 (major version upgrade)
    • Breaking Change: Enhanced property access semantics
    • Migration: Context keys with dots now require nested structure (e.g., %{"user" => %{"email" => "..."}} instead of %{"user.email" => "..."})
    • Benefit: More powerful and flexible data access patterns

Technical Improvements

  • Test Coverage: Maintained 92.9% overall code coverage with comprehensive new tests
    • New Test Modules: Statifier.ValueEvaluatorTest, Statifier.Actions.AssignActionTest, Statifier.Parser.AssignParsingTest
    • 556 Total Tests: All tests pass including new assign functionality
    • Log Capture: Added @moduletag capture_log: true for clean test output
  • Performance: O(1) lookups maintained with new data model operations
  • Error Handling: Enhanced error handling and logging throughout assign operations
  • Code Quality: Maintained Credo compliance with proper alias ordering

Examples

Basic Assign Usage

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="start">
  <state id="start">
    <onentry>
      <assign location="userName" expr="'John Doe'"/>
      <assign location="counter" expr="42"/>
      <assign location="user.profile.name" expr="'Jane Smith'"/>
    </onentry>
    <transition target="working"/>
  </state>
  <state id="working">
    <onentry>
      <assign location="counter" expr="counter + 1"/>
      <assign location="status" expr="'processing'"/>
    </onentry>
  </state>
</scxml>

Mixed Notation Assignment

<onentry>
  <assign location="users['admin'].active" expr="true"/>
  <assign location="settings.theme" expr="'dark'"/>
  <assign location="counters[0]" expr="counters[0] + 1"/>
</onentry>

Event Data Assignment

<state id="processing">
  <onentry>
    <assign location="lastEvent" expr="_event.name"/>
    <assign location="eventData" expr="_event.data.value"/>
  </onentry>
</state>

Programmatic Usage

# Value evaluation
{:ok, compiled} = Statifier.ValueEvaluator.compile_expression("user.profile.name")
{:ok, "John Doe"} = Statifier.ValueEvaluator.evaluate_value(compiled, context)

# Location validation
{:ok, ["user", "settings", "theme"]} = Statifier.ValueEvaluator.resolve_location("user.settings.theme")

# Combined evaluation and assignment
{:ok, updated_model} = Statifier.ValueEvaluator.evaluate_and_assign("result", "count * 2", context)

Notes

  • Phase 1 Complete: Enhanced Expression Evaluation phase is fully implemented
  • Foundation for Phase 2: Data model and expression evaluation infrastructure ready
  • Backward Compatible: All existing functionality preserved
  • Production Ready: Comprehensive test coverage and error handling
  • SCION Progress: assign_elements feature now supported (awaiting Phase 2 for full datamodel tests)

[1.0.0] - 2025-08-23

Added

Phase 1 Executable Content Support

  • <log> Action Support: Full implementation of SCXML <log> elements with expression evaluation
    • Statifier.LogAction Struct: Represents log actions with label and expr attributes
    • Expression Evaluation: Basic literal expression support (full evaluation in Phase 2)
    • Logger Integration: Uses Elixir Logger for output with contextual information
    • Location Tracking: Complete source location tracking for debugging
  • <raise> Action Support: Complete implementation of SCXML <raise> elements for internal event generation
    • Statifier.RaiseAction Struct: Represents raise actions with event attribute
    • Event Generation: Logs raised events (full event queue integration in future phases)
    • Anonymous Events: Handles raise elements without event attributes
  • <onentry> and <onexit> Action Support: Executable content containers for state transitions
    • Action Collection: Parses and stores multiple actions within onentry/onexit blocks
    • Mixed Actions: Support for combining log, raise, and future action types
    • State Integration: Actions stored in Statifier.State struct with onentry_actions/onexit_actions fields
  • Action Execution Infrastructure: Comprehensive system for executing SCXML actions
    • Statifier.ActionExecutor Module: Centralized action execution with phase tracking
    • Interpreter Integration: Actions executed during state entry/exit in interpreter lifecycle
    • Type Safety: Pattern matching for different action types with extensibility

Test Infrastructure Improvements

  • Required Features System: Automated test tagging system for feature-based test exclusion
    • @tag required_features: annotations on all W3C and SCION tests
    • Feature Detection Integration: Tests automatically excluded if required features unsupported
    • 262 Tests Tagged: Comprehensive coverage of W3C and SCION test requirements
    • Maintainable System: Script-based tag updates for easy maintenance

Eventless/Automatic Transitions

  • Eventless Transitions: Full W3C SCXML support for transitions without event attributes that fire automatically
  • Automatic Transition Processing: Microstep loop processes chains of eventless transitions until stable configuration
  • Cycle Detection: Prevents infinite loops with configurable iteration limits (100 iterations default)
  • Parallel Region Preservation: Proper SCXML semantics for transitions within and across parallel regions
  • Conflict Resolution: Child state transitions take priority over ancestor transitions per W3C specification

Enhanced Parallel State Support

  • Parallel State Transitions: Fixed regression where transitions within parallel regions affected unrelated parallel regions
  • Cross-Parallel Boundaries: Proper exit semantics when transitions cross parallel region boundaries
  • SCXML Exit State Calculation: Implements correct W3C exit set computation for complex state hierarchies
  • Sibling State Management: Automatic exit of parallel siblings when transitions leave their shared parent

Fixed

  • Regression Test: Fixed parallel state test failure (test/scion_tests/more_parallel/test1_test.exs)
  • SCION Test Suite: All 4 cond_js tests now pass (previously 3/4)
  • Parallel Interrupt Tests: Fixed 6 parallel interrupt test failures in regression suite
  • Code Quality: Resolved all mix credo --strict issues (predicate naming, unused variables, aliases)
  • Pattern Matching Refactoring: Converted Handler module case statements to idiomatic Elixir pattern matching
    • handle_event(:end_element, ...) Function: Refactored to separate function clauses with pattern matching
    • dispatch_element_start(...) Function: Converted from case statement to pattern matching function clauses
    • StateStack Module: Applied same pattern matching refactoring to action handling functions

Changed (Breaking)

ActionExecutor API Modernization

  • REMOVED: Statifier.Actions.ActionExecutor.execute_onentry_actions/2 function clause that accepted %Document{} as second parameter
  • REMOVED: Statifier.Actions.ActionExecutor.execute_onexit_actions/2 function clause that accepted %Document{} as second parameter
  • BREAKING: These functions now only accept %StateChart{} as the second parameter for proper event queue integration
  • Migration: Replace ActionExecutor.execute_*_actions(states, document) with ActionExecutor.execute_*_actions(states, state_chart)
  • Benefit: Action execution now properly integrates with the StateChart event queue system, enabling raised events to be processed correctly

Technical Improvements

  • SCXML Terminology Alignment: Updated codebase to use proper SCXML specification terminology
    • Microstep/Macrostep Processing: Execute microsteps (single transition sets) until stable macrostep completion
    • Exit Set Computation: Implements W3C SCXML exit set calculation algorithm for proper state exit semantics
    • LCCA Computation: Full Least Common Compound Ancestor algorithm for accurate transition conflict resolution
    • NULL Transitions: Added SCXML specification references while maintaining "eventless transitions" terminology
  • Feature Detection: Enhanced feature registry with newly supported capabilities
    • Added eventless_transitions: :supported to feature registry
    • Added log_elements: :supported for log action support
    • Added raise_elements: :supported for raise action support
    • Maintained onentry_actions: :supported and onexit_actions: :supported** status
  • Performance: Optimized ancestor/descendant lookup using existing parent attributes
  • Test Coverage: Comprehensive testing across all new functionality
    • Total Tests: 461 tests (up from 444), including extensive executable content testing
    • New Test Files: 13 comprehensive test files for log/raise actions and execution
    • Coverage Improvement: Interpreter module coverage increased from 70.4% to 83.0%
    • Project Coverage: Overall coverage improved from 89.0% to 92.3% (exceeds 90% minimum requirement)
  • Regression Testing: All core functionality tests pass with no regressions

[0.1.0] - 2025-08-20

Added

Core SCXML Implementation

  • W3C SCXML Parser: Full XML parser supporting SCXML 1.0 specification
  • State Machine Interpreter: Synchronous, functional API for state chart execution
  • State Configuration Management: Efficient tracking of active states with O(1) lookups
  • Event Processing: Support for internal and external events with proper queueing
  • Document Validation: Comprehensive validation with detailed error reporting

SCXML Elements Support

  • <scxml>: Root element with version, initial state, and namespace support
  • <state>: Compound and atomic states with nested hierarchy
  • <initial>: Initial state pseudo-states for deterministic startup
  • <transition>: Event-driven transitions with conditions and targets
  • <data>: Data model elements for state machine variables

Conditional Expressions

  • cond Attribute: Full support for conditional expressions on transitions
  • Predicator Integration: Secure expression evaluation using predicator library v2.0.0
  • SCXML In() Function: W3C-compliant state checking predicate
  • Logical Operations: Support for AND, OR, NOT, and comparison operators
  • Event Data Access: Conditions can access current event name and payload
  • Error Handling: Invalid expressions gracefully handled per W3C specification
  • Modern Functions API: Uses Predicator v2.0's improved custom functions approach

Performance Optimizations

  • Parse-time Compilation: Conditional expressions compiled once during parsing
  • O(1) State Lookups: Fast state and transition resolution using hash maps
  • Document Order Processing: Deterministic transition selection
  • Memory Efficient: Minimal memory footprint with optimized data structures

Developer Experience

  • Comprehensive Testing: 426+ test cases covering all functionality
  • Integration Tests: End-to-end testing with real SCXML documents
  • Type Safety: Full Elixir typespec coverage for all public APIs
  • Documentation: Detailed module and function documentation
  • Error Messages: Clear, actionable error reporting with location information

Validation & Quality

  • State ID Validation: Ensures unique and valid state identifiers
  • Transition Validation: Validates target states exist and are reachable
  • Initial State Validation: Enforces SCXML initial state constraints
  • Reachability Analysis: Identifies unreachable states in state charts
  • Static Analysis: Credo-compliant code with strict quality checks

Test Coverage

  • W3C Compliance: Support for W3C SCXML test cases (excluded by default)
  • SCION Compatibility: Integration with SCION test suite for validation
  • Unit Tests: Comprehensive unit testing of all modules
  • Integration Tests: Real-world SCXML document processing
  • Regression Tests: Critical functionality protection

Dependencies

  • saxy ~> 1.6: Fast XML parser for SCXML document processing
  • predicator ~> 2.0: Secure conditional expression evaluation (upgraded to v2.0 with improved custom functions API)
  • credo ~> 1.7: Static code analysis (dev/test)
  • dialyxir ~> 1.4: Static type checking (dev/test)
  • excoveralls ~> 0.18: Test coverage analysis (test)

Technical Specifications

  • Elixir: Requires Elixir ~> 1.17
  • OTP: Compatible with OTP 26+
  • Architecture: Functional, immutable state machine implementation
  • Concurrency: Thread-safe, stateless evaluation
  • Memory: Efficient MapSet-based state tracking

Examples

Basic State Machine

<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="idle">
  <state id="idle">
    <transition event="start" target="working"/>
  </state>
  <state id="working">
    <transition event="finish" target="done"/>
  </state>
  <state id="done"/>
</scxml>

Conditional Transitions

<state id="validation">
  <transition event="submit" cond="score > 80" target="approved"/>
  <transition event="submit" cond="score >= 60" target="review"/>
  <transition event="submit" target="rejected"/>
</state>

SCXML In() Function

<state id="processing">
  <transition event="check" cond="In('processing') AND progress > 50" target="almost_done"/>
  <transition event="check" target="continue_working"/>
</state>

Usage

# Parse SCXML document
{:ok, document} = Statifier.Parser.SCXML.parse(scxml_string)

# Initialize state machine
{:ok, state_chart} = Statifier.Interpreter.initialize(document)

# Send events
event = %Statifier.Event{name: "start", data: %{}}
{:ok, new_state_chart} = Statifier.Interpreter.send_event(state_chart, event)

# Check active states
active_states = new_state_chart.configuration.active_states

Notes

  • This is the initial release of the Statifier SCXML library
  • Full W3C SCXML 1.0 specification compliance for supported features
  • Production-ready with comprehensive test coverage
  • Built for high-performance state machine processing in Elixir applications
  • Uses Predicator v2.0 with modern custom functions API (no global function registry)

About

Statifier is a W3C SCXML (State Chart XML) implementation for Elixir, providing a robust, performant state machine engine for complex application workflows.

For more information, visit: https://github.com/riddler/sc