Releases: riddler/statifier
v1.9.0
[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
v1.8.0
[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
v1.7.0
[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 qualitytask 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.
v1.6.0
[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_states→active_leaf_states,active_ancestors→all_active_states - Single Source of Truth: All active state queries now handled by
Configurationmodule - Removed Wrapper Functions: Eliminated duplicate functions from
StateChartandInterpretermodules - 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
- Renamed Functions for Clarity:
-
Removed Backwards Compatibility Layers: Cleaned up legacy API functions for better maintainability
- Removed Legacy Delegates: Eliminated
Statifier.validate/1andStatifier.interpret/1delegate functions - Removed
Statifier.parse_only/1: Eliminated unused function that provided no additional value overSCXML.parse/2 - Forced Explicit Module Usage: Users must now call
Statifier.Interpreter.initialize/1andStatifier.Validator.validate/1directly - Updated Documentation: All examples and README updated to use explicit module references
- Removed Legacy Delegates: Eliminated
Code Quality Improvements
-
Implemented Proper Logging: Replaced TODO comments with actual logging infrastructure
- Validation Warning Logging:
Interpreter.initialize/1now properly logs validation warnings usingLogManager - Structured Logging: Warnings logged with warning count and detailed messages
- Consistent Infrastructure: Uses existing logging system throughout codebase
- Validation Warning Logging:
-
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 --strictwith 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.
v1.5.0
[1.5.0] 2025-08-29
Added
Modern API with Relaxed Parsing Mode
-
Statifier.parse/2Function: 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: falsereturns unvalidated documents for advanced use cases
- 3-Tuple Return Format: Returns
-
Enhanced
SCXML.parse/2with XML Normalization: Comprehensive relaxed parsing mode for simplified SCXML authoring- XML Declaration Handling: Optional XML declaration addition with
xml_declarationoption (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
- XML Declaration Handling: Optional XML declaration addition with
-
Validation Status Tracking: Added
validatedfield 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 Functions:
Statifier.validated?/1andStatifier.parse_only/2for API completeness
Basic Send Element Support
-
<send>Element Implementation: Comprehensive Phase 1 support for SCXML send elements with internal event communicationStatifier.Actions.SendAction: Complete data structure with event_expr, target_expr, type_expr, delay_expr, namelist supportStatifier.Actions.SendParam: Support for<param>child elements with name/expr attributesStatifier.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
- Send Element Parsing: Complete parsing of
-
ActionExecutor Integration: Enhanced action execution framework with send support
- Transition Action Execution: Added
execute_transition_actions/3for actions within transitions - Proper Action Order: SCXML-compliant action execution (exit → transition → entry)
- Pipeline Programming: Refactored parameter order for better |> operator usage
- Transition Action Execution: Added
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
- 8 Core Functions:
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/1for 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-tupleStatifier.parse/2API- 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.exwith modern architecture- New Functions:
parse/2,parse_only/2,validated?/1for comprehensive API coverage - Error Handling: Enhanced error handling with
handle_validation/2helper - Reduced Nesting: Improved code maintainability with better function organization
- Options Integration: Seamless integration with relaxed parsing options
- New Functions:
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/3function 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/1for 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
- No XML Declaration Required: Tests can omit
-
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), StateSt...
v1.4.0
[1.4.0] 2025-08-29
Added
Complete SCXML History State Support
-
History State Data Model: Full support for SCXML
<history>elements per W3C specificationStatifier.StateExtensions: Addedhistory_typefield (:shallow | :deep) andhistory_type_locationfor validation- Parser Support: Complete parsing of
<history>elements withtype="shallow|deep"attributes - Default Behavior: History type defaults to
:shallowwhen not specified - Element Builder: New
build_history_state/4function 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 (
:shallowor: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.targetsfield (list) replacestargetfield (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
- Parser Enhancement: Handles
-
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/3identifies all parallel ancestors in hierarchy - Region Identification:
are_in_parallel_regions/3correctly identifies states in different parallel regions - Cross-Boundary Exits:
exits_parallel_region/3detects 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.Transitionstruct field renamed fromtargettotargets- Type Change:
target: String.t() | nil→targets: [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
- Type Change:
Document Helper Functions
Statifier.DocumentEnhancements: New helper functions for history state runtime managementis_history_state?/2: Check if state has history type with O(1) lookupfind_history_states/2: Find all history states within a parent stateget_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/2identifies parents needing history recording - Ancestor Analysis:
get_ancestors_with_history/2finds 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 inhandle_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
- StateStack Fix: Added missing
-
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
FeatureDetectorto mark:history_statesas: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
- New Test Organization: Created
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
v1.3.0
[1.3.0] 2025-08-27
Added
Core Logging Infrastructure
-
Flexible Protocol-Based Logging System: Complete logging architecture for state chart operations
Statifier.Logging.AdapterProtocol: Extensible logging backend interface withlog/5andenabled?/2functionsStatifier.Logging.ElixirLoggerAdapter: Production logging adapter that integrates with Elixir's Logger systemStatifier.Logging.TestAdapter: In-memory log storage adapter for clean test environmentsStatifier.Logging.LogManager: Central coordination module with automatic metadata extraction- Log Level Hierarchy: Complete support for
:trace,:debug,:info,:warn,:errorlevels with filtering
-
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_entriesfor 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/1for test log inspection and management
- Configurable Limits: TestAdapter supports optional
-
StateChart Integration: Enhanced StateChart structure with logging capabilities
- Logging Fields: Added
log_adapter,log_level, andlogsfields to StateChart struct - Configuration Helpers:
configure_logging/3andset_log_level/2functions for easy setup - Seamless Integration: Logging works with existing StateChart lifecycle and event processing
- Logging Fields: Added
Logging Configuration System
-
Enhanced
Interpreter.initialize/2: Comprehensive logging configuration support during state chart initialization- Runtime Configuration Options: Accept
:log_adapterand:log_leveloptions via keyword list - Adapter Configuration Flexibility: Support for direct adapter structs or
{Module, opts}tuples - Backward Compatibility: Existing
initialize/1calls continue to work with sensible defaults - Comprehensive Documentation: Detailed examples and usage patterns in function documentation
- Runtime Configuration Options: Accept
-
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/3for 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.exsfor 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
endLogging 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 configConfiguration 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 newLogManager.*API- ActionExecutor: All debug logging now uses
LogManager.debugwith structured metadata (action_type, state_id, phase, etc.) - LogAction: Replaced
Logger.infowithLogManager.info, now returns updated StateChart from logging operations - RaiseAction: Migrated
Logger.infotoLogManager.infowith event metadata, properly threads StateChart through logging calls - AssignAction: Updated
Logger.errortoLogManager.errorwith comprehensive error context and assignment details - Datamodel: Replaced
Logger.debugcalls withLogManager.debugfor expression evaluation failures
- ActionExecutor: All debug logging now uses
-
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_ordernow 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, old...
v1.2.0
[1.2.0] 2025-08-27
Added
If/Else/ElseIf Conditional Action Support
-
<if>Action Support: Full implementation of SCXML<if>elements with conditional executionStatifier.Actions.IfActionStruct: 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.EvaluatorModule: ConsolidatedConditionEvaluatorandValueEvaluatorinto 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.DatamodelModule: Improved data model operations and separation of concernsput_in_path/3Function: 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
:datamodeland:data_elementsas:supportedin feature registry - Accurate Test Results: Prevents false test failures from unsupported feature detection
- Better Compliance Tracking: Improved visibility into SCXML feature implementation status
- Datamodel Support: Marked
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
- Public
-
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>v1.1.0
[1.1.0] 2025-08-26
Renames project from SC to Statifier.
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/2function 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
:undefinedfor missing properties instead of errors
- Enhanced Nested Property Access: Deep dot notation support (
-
Statifier.ValueEvaluatorModule: Comprehensive value evaluation system for SCXML expressions- Expression Compilation:
compile_expression/1for reusable expression compilation - Value Evaluation:
evaluate_value/2extracts actual values (not just boolean results) - Location Path Resolution:
resolve_location/1,2validates assignment paths using predicator v3.0 - Safe Assignment:
assign_value/3performs type-safe nested data model updates - Integrated Assignment:
evaluate_and_assign/3combines evaluation and assignment - SCXML Context Support: Full integration with state machine context (events, configuration, datamodel)
- Error Handling: Comprehensive error handling with detailed logging
- Expression Compilation:
-
<assign>Element Support: Full W3C SCXML assign element implementationStatifier.Actions.AssignActionStruct: 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
- Data Model Storage: Added
data_modelfield toStatifier.StateChartfor variable persistence - Current Event Context: Added
current_eventfield for expression evaluation context - Helper Methods:
update_data_model/2andset_current_event/2for 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/4creates AssignAction structs with location tracking - Handler Integration: Added assign element start/end handlers
- StateStack Integration:
handle_assign_end/1properly collects assign actions - Mixed Action Support: Parse assign actions alongside log/raise actions in onentry/onexit
- Location Tracking: Complete source location tracking for debugging
- Element Builder:
Feature Detection Updates
- Assign Elements Support: Updated
assign_elementsfeature 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.0to~> 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: truefor 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_elementsfeature now supported (awaiting Phase 2 for full datamodel tests)