This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Local Validation Workflow: When verifying code changes, always follow this sequence (also automated via pre-push git hook):
mix format- Auto-fix formatting issues (trailing whitespace, final newlines, etc.)mix test --cover- Ensure functionality and maintain 95%+ test coveragemix credo --strict- Run static code analysis only after tests passmix dialyzer- Run Dialyzer static analysis for type checking
Git Hooks:
./scripts/setup-git-hooks.sh- Install pre-push hook for validation pipeline- Pre-push hook automatically runs the validation workflow to catch issues before CI
- Located at
.git/hooks/pre-push(executable) - Blocks push if any validation step fails
Regression Testing:
test/passing_tests.json- Registry of tests that should always pass- Tracks internal tests, SCION tests, and W3C tests separately
- Updated manually when new tests start passing consistently
- Used by CI pipeline to catch regressions early
Testing:
mix test- Run all internal tests (excludes SCION/W3C by default) - 1045 testsmix test --include scion --include scxml_w3- Run all tests including SCION and W3C testsmix test.regression- Run regression tests that should always pass - 63 tests (critical functionality)mix test.baseline- Check which tests are currently passing (for updating regression suite)mix test --cover- Run all tests with coverage reporting (maintain 90%+ coverage - currently 90.1%)mix coveralls- Alternative coverage commandmix coveralls.detail- Run tests with detailed coverage report showing uncovered linesmix test test/statifier/location_test.exs- Run location tracking testsmix test test/statifier/parser/scxml_test.exs- Run specific SCXML parser tests (uses pattern matching)mix test test/statifier/interpreter/compound_state_test.exs- Run compound state testsmix test test/statifier/interpreter/eventless_transitions_test.exs- Run eventless transition testsmix test test/statifier/logging/- Run comprehensive logging infrastructure tests (30 tests)mix test test/statifier/actions/- Run action execution tests with integrated StateChart logging
Documentation:
mix docs.validate- Validate code examples in documentation files (README.md, docs/*.md)mix docs.validate --file README.md- Validate specific file onlymix docs.validate --verbose- Show detailed validation outputmix docs.validate --path docs/- Validate specific directory
Development:
mix deps.get- Install dependenciesmix compile- Compile the projectmix docs- Generate documentationmix format- Format code according to Elixir standards (run first for code verification)mix format --check-formatted- Check if code is properly formattedmix credo --strict- Run static code analysis with strict mode (run after tests pass)mix dialyzer- Run Dialyzer for static type analysis (run last in verification workflow)
This is an Elixir implementation of SCXML (State Chart XML) state machines with a focus on W3C compliance.
The State Chart reference XML is here: https://www.w3.org/TR/scxml/
This project uses Elixir Structs for the data structures, and MapSets for sets.
Also use this initial Elixir implementation as reference: https://github.com/camshaft/ex_statechart
Statifier.Document- Root SCXML document structure with:- Attributes:
name,initial,datamodel,version,xmlns - Collections:
states,datamodel_elements - O(1) Lookup maps:
state_lookup(id → state),transitions_by_source(id → [transitions]) - Built via
Document.build_lookup_maps/1during validation phase
- Attributes:
Statifier.State- Individual state withid, optionalinitialstate, nestedstateslist, andtransitionslistStatifier.Transition- State transitions with optionalevent,targets(list), andcondattributesStatifier.Data- Datamodel elements with requiredidand optionalexprandsrcattributes
Statifier.Parser.SCXML- Main SCXML parser using Saxy SAX parser for accurate location tracking- Parses XML strings into
Statifier.Documentstructs with precise source location information - Event-driven SAX parsing for better memory efficiency and location tracking
- Handles namespace declarations and XML attributes correctly
- Supports nested states and hierarchical structures
- Converts empty XML attributes to
nilfor cleaner data representation - Returns
{:ok, document}or{:error, reason}tuples - Pure parsing only - does not build optimization structures
- Parses XML strings into
Statifier.Parser.SCXML.Handler- SAX event handler for SCXML parsing- Implements
Saxy.Handlerbehavior for processing XML events - Tracks element occurrences and position information during parsing
- Manages element stack for proper hierarchical document construction
- Implements
Statifier.Parser.SCXML.ElementBuilder- Builds SCXML elements from SAX eventsStatifier.Parser.SCXML.LocationTracker- Tracks precise source locations for elements and attributesStatifier.Parser.SCXML.StateStack- Manages parsing state stack for hierarchical document construction
Statifier.Validator- Main validation orchestrator- Modular architecture: Split into focused sub-validators for maintainability
- Validation: Structural correctness, semantic consistency, reference validation
- Optimization: Builds O(1) lookup maps via
finalize/2for valid documents only - Returns
{:ok, optimized_document, warnings}or{:error, errors, warnings} - Clean architecture: Only optimizes documents that pass validation
Statifier.Validator.StateValidator- State ID uniqueness and validationStatifier.Validator.TransitionValidator- Transition target validation (supports multiple targets)Statifier.Validator.InitialStateValidator- All initial state constraints (attributes, elements, conflicts)Statifier.Validator.HistoryStateValidator- Complete history state validation per W3C specificationStatifier.Validator.ReachabilityAnalyzer- State reachability graph analysisStatifier.Validator.Utils- Shared utilities across validators
Statifier.Interpreter- Core SCXML interpreter with W3C-compliant processing model- Microstep/Macrostep Execution: Implements SCXML event processing model where microsteps (single transition set execution) are processed until stable macrostep completion
- Exit Set Computation: Uses W3C SCXML exit set calculation algorithm for determining which states to exit during transitions
- LCCA Algorithm: Full Least Common Compound Ancestor computation for accurate transition conflict resolution and exit set calculation
- Eventless Transitions: Automatic transitions without event attributes (also called NULL transitions in SCXML spec)
- Optimal Transition Set: SCXML-compliant transition conflict resolution where child state transitions take priority over ancestors
- Compound state support: Automatically enters initial child states recursively
- Parallel state support: Proper concurrent execution with cross-boundary exit semantics and parallel region preservation
- Conditional transitions: Full
condattribute support with Predicator v3.0 expression evaluation and SCXMLIn()function - Assign action support: Complete
<assign>element execution with data model integration - Cycle Detection: Prevents infinite loops in eventless transitions with configurable iteration limits (100 iterations default)
- O(1 lookups: Uses
Document.find_state/2andDocument.get_transitions_from_state/2 - Separates
active_states()(leaf only) fromactive_ancestors()(includes parents) - Provides
{:ok, result}or{:error, reason}responses
Statifier.StateChart- Runtime container for SCXML state machines- Combines document, configuration, event queues, and data model
- Maintains internal and external event queues per SCXML specification
- Datamodel storage: Persistent variable storage with
datamodelfield - Current event context: Tracks current event for expression evaluation
- History tracking: Integrated
HistoryTrackerfor shallow and deep history state support
Statifier.HistoryTracker- Core history state tracking infrastructure- Shallow history: Records immediate children of parent states that contain active descendants
- Deep history: Records all atomic descendant states within parent states
- Efficient operations: Uses MapSet operations with O(1) document lookups
- W3C compliant: Full compliance with SCXML history state specification
Statifier.Configuration- Active state configuration management- Stores only leaf states for efficient memory usage
- Computes ancestor states dynamically via
active_ancestors/2using O(1) document lookups - Uses MapSets for fast state membership testing
- Optimized MapSet operations (direct construction vs incremental building)
Statifier.Event- Event representation with internal/external origins- Supports event data and origin tracking
- Used for state machine event processing
Statifier.Evaluator- Unified expression evaluation system for SCXML- Expression compilation:
compile_expression/1for reusable predicator compilation - Value evaluation:
evaluate_value/2extracts actual values (not just boolean results) - Condition evaluation:
evaluate_condition/2for boolean transition guards - Location path resolution:
resolve_location/1,2validates assignment paths using predicator v3.0'scontext_location - Safe assignment operations:
assign_value/3performs type-safe nested data model updates - Integrated assignment:
evaluate_and_assign/3combines evaluation and assignment - Parameter processing: Centralized
evaluate_params/3with strict/lenient error handling modes - SCXML context support: Full integration with state machine context (events, configuration, datamodel)
- Nested property access: Support for deep property access (
user.profile.settings.theme) - Mixed access patterns: Combined bracket/dot notation (
users['john'].active) - Error handling: Comprehensive error handling with detailed logging
- Predicator v3.0: Enhanced nested property access capabilities with SCXML
In()function support
- Expression compilation:
Statifier.Logging.Adapter- Protocol-based logging system for extensible backend integration- ElixirLoggerAdapter: Production logging adapter integrating with Elixir's Logger system
- TestAdapter: In-memory log storage adapter for clean test environments with circular buffer support
- LogManager: Central coordination module with automatic StateChart metadata extraction
- Structured Logging: All logging includes contextual metadata (action_type, state_id, phase, event context)
- StateChart Integration: Logging operations thread StateChart state through all calls
- Test Environment Configuration: Automatic TestAdapter setup in
test/test_helper.exsfor clean test output - Log Helpers: Comprehensive test helpers in
Statifier.Case(assert_log_entry,assert_log_order) - Chronological Storage: Logs stored in chronological order (oldest first) for intuitive debugging
Statifier.Actions.AssignAction- SCXML<assign>element implementation- Location-based assignment: Validates assignment paths using Statifier.Evaluator
- Expression evaluation: Uses Statifier.Evaluator 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
Statifier.Actions.InvokeAction- SCXML<invoke>element implementation for external service integration- Handler-based security: Only registered handlers can be invoked, preventing arbitrary code execution
- SCXML event generation: Generates
done.invoke.{id},error.execution, anderror.communicationevents per specification - Parameter processing: Uses centralized Evaluator for parameter evaluation with strict error handling
- Service integration: Safe way to integrate SCXML with external services, APIs, and business logic
- Exception safety: Comprehensive error handling with try/rescue blocks for handler execution
Statifier.Actions.Param- Unified parameter data structure for<send>and<invoke>elements- Expression parameters: Support for
exprattribute with dynamic evaluation - Location parameters: Support for
locationattribute for datamodel variable references - Parameter validation: Name validation with identifier rules per SCXML specification
- Expression parameters: Support for
Statifier.InvokeHandler- Behavior defining secure invoke handler interface- Handler contract: Standardized function signature for invoke handlers
- Return value specification: Supports success with/without data and communication/execution errors
- Security isolation: Handlers operate in controlled environment with limited access
Statifier.Actions.LogAction- SCXML<log>element implementation for debuggingStatifier.Actions.RaiseAction- SCXML<raise>element implementation for internal eventsStatifier.Actions.ActionExecutor- Centralized action execution system- Phase tracking: Executes actions during appropriate state entry/exit phases
- Mixed action support: Handles log, raise, assign, invoke, and other action types
- StateChart integration: Actions can modify state chart data model and event queues
The implementation follows a clean Parse → Validate → Optimize architecture:
# 1. Parse Phase: XML → Document structure
{:ok, document} = Statifier.Parser.SCXML.parse(xml_string)
# 2. Validate + Optimize Phase: Check semantics + build lookup maps
{:ok, optimized_document, warnings} = Statifier.Validator.validate(document)
# 3. Interpret Phase: Use optimized document for runtime
{:ok, state_chart} = Statifier.initialize(optimized_document)Benefits:
- Parsers focus purely on structure (supports future JSON/YAML parsers)
- Validation catches semantic errors before optimization
- Only valid documents get expensive optimization treatment
- Clear separation of concerns across phases
Statifier.FeatureDetector- Detects SCXML features used in documents- Enables proper test validation by failing tests that depend on unsupported features
- Prevents false positive test results from unsupported feature usage
- Supports both XML string and parsed document analysis
- Tracks feature support status (
:supported,:unsupported,:partial)
Statifier.Case- Test case template module for SCXML testing- Provides
test_scxml/4function for testing state machine behavior - Uses Statifier.Interpreter for document initialization and event processing
- Supports initial configuration verification and event sequence testing
- Used by both SCION and W3C test suites
- Provides
All parsed SCXML elements include precise source location information for validation error reporting:
- Element locations: Each parsed element (
Statifier.Document,Statifier.State,Statifier.Transition,Statifier.Data) includes asource_locationfield with line/column information - Attribute locations: Individual attributes have dedicated location fields (e.g.,
name_location,id_location,event_location) for precise error reporting - Multiline support: Accurately tracks locations for both single-line and multiline XML element definitions
- SAX-based tracking: Uses Saxy's event-driven parsing to maintain position information throughout the parsing process
predicator(~> 3.0) - Safe condition and value evaluator with enhanced nested property accesssaxy(~> 1.6) - Fast, memory-efficient SAX XML parser with position tracking support
credo(~> 1.7) - Static code analysis tool for code quality and consistencydialyxir(~> 1.4) - Dialyzer wrapper for static type analysis and error detection
This project includes comprehensive test coverage:
- 127+ test files from the SCION project
- Module naming:
SCIONTest.Category.TestNameTest(e.g.,SCIONTest.ActionSend.Send1Test) - Uses
Statifier.Casefor test infrastructure - Tests cover basic state machines, transitions, parallel states, history, etc.
- 59+ test files from W3C SCXML conformance tests
- Module naming:
Test.StateChart.W3.Category.TestName(e.g.,Test.StateChart.W3.Events.Test396) - Uses
Statifier.Casefor test infrastructure - Organized by SCXML specification sections (mandatory tests)
- Unit tests for
Statifier.Parser.SCXML - Uses pattern matching instead of multiple individual asserts for cleaner, more informative tests
- Tests parsing of simple documents, transitions, datamodels, nested states
- Validates error handling for invalid XML
- Ensures proper attribute handling (nil for empty values)
- Tests for precise source location tracking in SCXML documents
- Validates line number accuracy for elements and attributes
- Tests both single-line and multiline XML element definitions
- Ensures proper location tracking for nested elements and datamodel elements
test/statifier/evaluator_test.exs- Comprehensive tests for unified Statifier.Evaluator module- Value evaluation, condition evaluation, location resolution, assignment operations
- Parameter processing with strict/lenient error handling modes
- Nested property access and mixed notation support
- SCXML context integration and error handling
test/statifier/actions/assign_action_test.exs- Complete assign action functionality- Action creation, execution, and error handling
- Data model integration and context evaluation
- Mixed action execution and state chart modification
test/statifier/actions/invoke_action_test.exs- Complete invoke action functionality with 100% coverage- Secure handler-based invoke execution
- SCXML event generation (done.invoke, error.execution, error.communication)
- Parameter evaluation and passing to handlers
- Handler exception safety and comprehensive error scenarios
test/statifier/parser/assign_parsing_test.exs- SCXML assign element parsing- Assign element parsing in onentry/onexit contexts
- Mixed action parsing (log, raise, assign together)
- Complex expression and location parsing
test/statifier/parser/invoke_parsing_test.exs- SCXML invoke element parsing- Invoke element parsing with type, src, id attributes
- Parameter child element parsing with expr and location support
- Mixed action parsing in onentry/onexit contexts
- All generated files have no trailing whitespace
- Code is formatted using
mix format - Static code analysis with
mix credo --strict- all issues resolved - Type specs (
@spec) are provided for all public functions - Comprehensive documentation with
@moduledocand@doc - Consistent naming for unused variables (meaningful names with
_prefix) - Pattern matching preferred over multiple individual assertions in tests
- Git pre-push hook enforces validation workflow automatically
Test files use triple-quote multiline strings for XML content:
xml = """
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="a">
<state id="a"/>
</scxml>
"""XML content within triple quotes uses 4-space base indentation.
The invoke system provides safe integration between SCXML state machines and external services:
defmodule MyApp.UserService do
def handle_invoke("create_user", params, state_chart) do
case create_user(params["name"], params["email"]) do
{:ok, user} ->
{:ok, %{"user_id" => user.id}, state_chart}
{:error, reason} ->
{:error, :execution, "User creation failed: #{reason}"}
end
end
def handle_invoke("get_profile", params, state_chart) do
{:ok, state_chart} # Success with no return data
end
def handle_invoke(operation, _params, _state_chart) do
{:error, :execution, "Unknown operation: #{operation}"}
end
end# Register handlers during StateChart initialization
invoke_handlers = %{
"user_service" => &MyApp.UserService.handle_invoke/3,
"email_service" => &MyApp.EmailService.handle_invoke/3
}
{:ok, state_chart} = Statifier.initialize(document, [
invoke_handlers: invoke_handlers,
log_level: :debug
])<state id="creating_user">
<onentry>
<invoke type="user_service" src="create_user" id="user_creation">
<param name="name" expr="user_name"/>
<param name="email" location="user.email"/>
</invoke>
</onentry>
<transition event="done.invoke.user_creation" target="success"/>
<transition event="error.execution" target="failed"/>
<transition event="error.communication" target="retry"/>
</state>- No arbitrary code execution - Only registered handlers can be invoked
- Controlled environment - Handlers operate with limited access to state chart
- Exception safety - Handler exceptions are caught and converted to error events
- Parameter validation - All parameters are validated and evaluated safely
Current Status: Significant improvement with major SCXML features implemented
Working Features:
- ✅ Basic state transitions (basic1, basic2 tests pass)
- ✅ Compound states with automatic initial child entry
- ✅ Initial state elements (
<initial>with transitions) - W3C compliant - ✅ Parallel states with concurrent execution and proper exit semantics
- ✅ History states - Complete shallow and deep history support (5/8 SCION history tests now passing)
- ✅ Multiple transition targets - Space-separated target support enables complex transitions
- ✅ SCXML-compliant processing - Proper microstep/macrostep execution model with exit set computation and LCCA algorithms
- ✅ Eventless transitions - Automatic transitions without event attributes (also called NULL transitions in SCXML spec)
- ✅ Conditional transitions - Full
condattribute support with Predicator v3.0 expression evaluation and SCXMLIn()function - ✅ Assign elements - Complete
<assign>element support with location-based assignment and nested property access - ✅ If/Else/ElseIf blocks - Complete conditional execution support
- ✅ Value evaluation - Non-boolean expression evaluation using Predicator v3.0 for actual data values
- ✅ Data model support - StateChart data model integration with dynamic variable assignment
- ✅ Optimal Transition Set - SCXML-compliant transition conflict resolution where child state transitions take priority over ancestors
- ✅ Enhanced parallel exit logic - Critical W3C SCXML exit set computation fixes
- ✅ Hierarchical states with O(1) optimized lookups
- ✅ Event-driven state changes
- ✅ Initial state configuration (both
initial="id"attributes and<initial>elements) - ✅ Document validation and error reporting
- ✅ Parse → Validate → Optimize architecture
- ✅ Modular validator architecture with focused sub-validators
Major Test Improvements:
- History Tests: 5/8 SCION history tests now passing (history0, history1, history2, history3, history6)
- Complex Parallel: history4b and history5 tests now pass with multiple target and parallel exit fixes
- Document Parsing: All major SCXML structural elements now parsed correctly
Remaining Challenges:
- Missing SCXML features: Targetless transitions, internal transitions
- Missing executable content:
<script>,<send>elements - Advanced datamodel features: Enhanced expression evaluation, additional functions
✅ Completed:
- Core data structures (Document, State, Transition, Data) with location tracking
- SCXML parser using Saxy SAX parser for accurate position tracking
- Parse → Validate → Optimize architecture with clean separation of concerns
- Complete interpreter infrastructure (Interpreter, StateChart, Configuration, Event, Validator)
- Compound state support with automatic initial child entry recursion
- Parallel state support with concurrent execution and proper cross-boundary exit semantics
- SCXML-compliant processing model with proper microstep/macrostep execution, exit set computation, and LCCA algorithms
- Eventless transitions - Automatic transitions without event attributes (also called NULL transitions in SCXML spec)
- Conditional transitions - Full
condattribute support with Predicator v3.0 expression evaluation and SCXMLIn()function - Assign elements - Complete
<assign>element support with Statifier.ValueEvaluator and location-based assignment - If/Else/ElseIf blocks - Complete conditional execution blocks with nested expression evaluation
- Value evaluation system - Statifier.ValueEvaluator module for non-boolean expression evaluation and data model operations
- Enhanced expression evaluation - Predicator v3.0 integration with nested property access and mixed notation support
- History states - Complete shallow and deep history state support per W3C SCXML specification
- Multiple transition targets - Support for space-separated multiple targets in transitions
- Enhanced parallel state exit logic - Critical W3C SCXML exit set computation improvements
- Optimal Transition Set - SCXML-compliant transition conflict resolution where child state transitions take priority over ancestors
- Exit Set Computation - W3C SCXML exit set calculation algorithm for proper state exit semantics
- LCCA Algorithm - Full Least Common Compound Ancestor computation for accurate transition conflict resolution
- O(1 performance optimizations via state and transition lookup maps
- Comprehensive test suite integration (SCION + W3C) - 1030 internal tests, 118 regression tests, 90.9% coverage
- Test infrastructure with Statifier.Case module using interpreter
- Pattern matching in tests instead of multiple individual assertions
- XML parsing with namespace support and precise source location tracking
- Error handling for malformed XML
- Location tracking for elements and attributes (line numbers for validation errors)
- Support for both single-line and multiline XML element definitions
- State machine interpretation with event processing and optimized lookups
- Document validation with finalize callback building optimization structures
- Active state tracking with hierarchical ancestor computation using O(1) lookups
- Git pre-push hook for automated local validation workflow
- Enhanced test coverage - 92.3% overall coverage (exceeds 90% minimum), interpreter module at 83.0%
- Initial state elements (
<initial>with<transition>) with comprehensive validation - Modular validator architecture - refactored from 386-line monolith into focused modules
- Full Credo compliance - all code quality issues resolved
📋 Comprehensive Implementation Plan Available: See documentation/SCXML_IMPLEMENTATION_PLAN.md for detailed 3-phase roadmap to achieve 98%+ test coverage across 444 SCION and W3C tests.
✅ Complete SCXML History State Support (v1.4.0) - Full W3C compliance for history states:
- History State Data Model - Complete
<history>element support with shallow/deep types - History State Validation - Comprehensive validation per W3C specification via
HistoryStateValidator - History Tracking Infrastructure -
HistoryTrackerwith efficient MapSet operations - History State Resolution - W3C compliant transition resolution and restoration
- StateChart Integration - History recording before onexit actions per SCXML timing
✅ Multiple Transition Target Support (v1.4.0) - Enhanced transition capabilities:
- Space-Separated Target Parsing - Handles
target="state1 state2"syntax - Enhanced Data Model -
Transition.targetsfield (list) replacestarget(string) - Parallel State Exit Fixes - Critical W3C SCXML exit set computation improvements
- Comprehensive Validation - All validators updated for multiple target support
✅ Structural SCXML Features - Complete W3C compliance for basic state machine functionality:
- Core state machine elements (states, transitions, parallel, initial)
- SCXML-compliant processing model (microstep/macrostep, exit sets, LCCA)
- Conditional transitions with expression evaluation
- Eventless/automatic transitions (NULL transitions)
- Feature detection and test validation infrastructure
✅ Complete Executable Content (v1.0-v1.3) - Full action execution framework:
<onentry>/<onexit>actions - Execute actions during state entry/exit ✅ COMPLETE<raise event="name"/>elements - Generate internal events ✅ COMPLETE<log expr="message"/>elements - Debug logging support ✅ COMPLETE<assign>elements - Variable assignment with nested property access ✅ COMPLETE<if>/<elseif>/<else>blocks - Conditional execution blocks ✅ COMPLETE<invoke>elements - Secure external service integration with handler-based system ✅ COMPLETE
Current Test Coverage: 1030 internal tests, 118 regression tests
🚧 Phase 2: Enhanced Data Model (4-6 weeks) - Further datamodel enhancements Target: Unlock additional SCION/W3C tests
<datamodel>/<data>elements - Enhanced variable storage and initialization- JavaScript expression engine - Full ECMAScript expression support
- Enhanced condition evaluation - Advanced datamodel variable access
🚧 Phase 3: Advanced Features (2-3 weeks) - Final SCXML features Target: Achieve comprehensive SCXML support (98%+ coverage)
<send>elements - External event sending with delays<script>elements - Inline JavaScript execution- Internal/targetless transitions - Advanced transition behaviors
The phased approach systematically adds SCXML features:
- Parser Extensions: Add executable content parsing to existing SAX-based parser
- Interpreter Integration: Extend microstep/macrostep processing with action execution
- Data Model Layer: Add variable storage and JavaScript expression evaluation
- Feature Detection Updates: Maintain comprehensive feature tracking
- Test Coverage Validation: Ensure each phase improves test coverage without regressions
- Phase 1: 370+ tests passing, all basic executable content working
- Phase 2: 415+ tests passing, full datamodel and expression support
- Phase 3: 435+ tests passing, comprehensive SCXML implementation
- Final Goal: 98%+ test coverage, industry-leading SCXML compliance
The implementation plan transforms Statifier from a basic state machine library into a comprehensive, production-ready SCXML engine with industry-leading test coverage and W3C compliance.
Current State: Statifier currently provides a functional, synchronous API for state chart execution with immutable data structures.
Future Enhancement: Add GenServer-based long-lived state chart interpreters for:
Statifier.InterpreterServer: GenServer wrapper around functional interpreter- State Persistence: Maintain state chart configuration across multiple events
- Event Queuing: Asynchronous event processing with proper SCXML queue semantics
- Runtime Reconfiguration: Dynamic logging, data model, and configuration changes
- Process Supervision: OTP supervision trees for fault-tolerant state chart execution
- Workflow Engines: Long-running business process execution
- User Session Management: Stateful user interaction flows
- IoT Device State Management: Persistent device state tracking
- Game State Management: Complex game logic with persistent state
- Backward Compatibility: Existing functional API remains unchanged
- Optional GenServer Layer: Choice between functional and process-based execution
- Event Broadcasting: Phoenix PubSub integration for state change notifications
- Clustering Support: Distributed state chart execution across nodes
- Basic GenServer Wrapper: Simple process-based state chart execution
- Advanced Features: Supervision, clustering, persistence
- Integration Layer: Phoenix, LiveView, and ecosystem integration
Flexible Logging Architecture for both functional and GenServer-based execution:
Statifier.Logging.LogManager: Central logging coordination- Per-Adapter Log Levels: Different log levels for different adapters
- Runtime Reconfiguration: Dynamic logging configuration during execution
- Test-Friendly:
TestAdapterfor clean test output and log inspection
ElixirLoggerAdapter: Integration with Elixir's Logger (production)TestAdapter: In-memory log collection for testing- Future: Database adapters, file adapters, external service adapters
state_chart_id: Unique identifier for state chart instancescurrent_state: Active leaf state(s) for contextevent: Current event being processedaction_type: Type of action generating the log entry
This logging system will integrate seamlessly with both the current functional API and future GenServer-based persistent interpreters.
When debugging state chart execution, configure enhanced logging for detailed visibility:
# Enable detailed tracing for debugging
{:ok, state_chart} = Statifier.initialize(document, [
log_adapter: :elixir,
log_level: :trace
])
# Alternative: use internal adapter for testing/development
{:ok, state_chart} = Statifier.initialize(document, [
log_adapter: :internal,
log_level: :trace
]):elixir- Uses ElixirLoggerAdapter (integrates with Elixir's Logger system):internal- Uses TestAdapter for internal debugging:test- Uses TestAdapter (alias for test environments):silent- Uses TestAdapter with no log storage (disables logging)
:trace- Very detailed execution tracing (transitions, conditions, actions):debug- General debugging information (state changes, events):info- High-level execution flow:warn- Unusual conditions:error- Execution errors
All LogManager logging functions (trace/3, debug/3, info/3, warn/3, error/3) are implemented as macros that provide lazy evaluation for optimal performance:
# Expensive computations are only performed if logging level is enabled
state_chart = LogManager.debug(state_chart, "Complex operation", %{
expensive_data: build_debug_info(), # Only called if debug enabled
complex_calculation: heavy_computation() # Only called if debug enabled
})
# Zero overhead when logging is disabled - arguments are never evaluated
state_chart = LogManager.trace(state_chart, "Detailed info", %{
massive_object: serialize_entire_state() # Never called if trace disabled
})This provides significant performance benefits in hot code paths while maintaining the familiar LogManager.level/3 API.
Statifier automatically detects your environment and configures appropriate logging defaults:
- Development (
MIX_ENV=dev)::tracelevel with:elixiradapter for detailed debugging - Test (
MIX_ENV=test)::debuglevel with:testadapter for clean test output - Production (other):
:infolevel with:elixiradapter for essential information
Users can override these defaults via application configuration:
# config/config.exs
config :statifier,
default_log_adapter: :elixir,
default_log_level: :trace# In dev environment, no additional configuration needed
{:ok, document, _warnings} = Statifier.parse(xml)
{:ok, state_chart} = Statifier.initialize(document) # Auto-configured for dev
# Manual configuration for other environments
{:ok, state_chart} = Statifier.initialize(document, [
log_adapter: :elixir,
log_level: :trace
])
# Debug specific state chart behavior
xml = """
<scxml initial="s1">
<state id="s1">
<transition event="go" target="s2"/>
</state>
<state id="s2"/>
</scxml>
"""
# Send event - will show detailed trace logs with full metadata
event = %Event{name: "go"}
{:ok, new_state_chart} = Interpreter.send_event(state_chart, event)- Always refer to state machines as state charts
- Always run 'mix format' after writing an Elixir file.
- When creating git commit messages:
- be concise but informative, and highlight the functional changes
- no need to mention code quality improvements as they are expected (unless the functional change is about code quality improvements)
- commit titles should be less than 50 characters and be in the simple present tense (active voice) - examples: 'Adds ..., Fixes ...'
- commit descriptions should wrap at about 72 characters and also be in the simple present tense (active voice)
- When writing functions that take a state_chart, put the state_chart as the first argument to help with threading the state_chart through code execution using Elixir pipelines