## Changelog

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

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.5.0] - 2026-03-23

### Added
- **CLI `--template` flag** with 5 template types for Pythonic code generation:
  - `pythonic-class`: Class-based state machine using `StateMachine` base class
  - `pythonic-builder`: Builder pattern using `MachineBuilder` fluent API
  - `pythonic-functional`: Functional style using `build_machine()` factory
  - `class`: Classic class-based template (existing behavior)
  - `functional`: Classic functional template (existing behavior)
- **Strategy pattern architecture** for code generation with pluggable `CodeGenStrategy` implementations
- **Pythonic API** for defining state machines in pure Python without JSON dicts:
  - `StateMachine` base class with metaclass for class-based declarations
  - `MachineBuilder` fluent builder for programmatic/dynamic construction
  - `build_machine()` function for functional-style machine definition
  - `State` class for defining states with all features (hierarchy, parallel, final, after, invoke, always, onDone)
  - `Transition` and `TransitionGroup` for fluent transition definitions with `|` combinator
  - `@action`, `@guard`, `@service` decorators with auto snake_case-to-camelCase naming
  - `transition()` standalone function for functional API
  - Full backward compatibility — all existing JSON-based APIs work unchanged
- **Comprehensive validation** for Pythonic API:
  - Final state validation: blocks outgoing transitions, child states, and Transition objects from final states
  - Parallel child validation: raises `InvalidConfigError` if a child of a parallel state has `initial=True`
  - `MachineBuilder` duplicate state name detection
  - `MachineBuilder.build()` validates initial state is defined (multi-state machines)
  - `@state.enter`/`@state.exit` decorators raise `InvalidConfigError` when used outside a `StateMachine` class
  - `Transition.__or__` and `TransitionGroup.__or__` return `NotImplemented` for invalid operand types
- **`__repr__` methods** on `State`, `Transition`, `TransitionGroup`, and `MachineBuilder` for better debugging
- **143 Pythonic API tests** across 20 test classes covering all three API styles, error handling, edge cases, merge rules, async/sync interpreter compatibility, and snapshot/restore
- **Comprehensive README rewrite** (2,508 lines): Complete documentation overhaul covering all 24 public API symbols with accurate signatures, code examples, and full feature coverage including:
  - `get_snapshot()` / `from_snapshot()` API with persistence examples
  - `transition()` standalone function, `TransitionGroup`, `State.internal()`, `reenter` parameter
  - `MachineLogic` constructor, `LogicLoader` singleton with global module registration
  - `DoneEvent` / `AfterEvent` internal event types
  - `MachineNode.get_state_by_id()` / `.get_next_state()` inspection methods
  - `State.__init_subclass__` class inheritance pattern
  - `PluginBase` hooks with correct signatures (`on_transition(interpreter, from_states, to_states, transition)`)
  - `LoggingInspector` output format reference
  - `always` (eventless transitions) with full example
  - All 5 CLI templates deep dive with generated code examples
- **Stress test suite**: 50 real-world XState machine configs tested against all 5 templates (250 code generation runs) with `py_compile` + `importlib` validation

### Changed
- Generated code now includes rich docstrings, error handling, and type hints
- `--async-mode` defaults are template-aware (Pythonic templates default to sync)
- **Performance**: `_snake_to_camel` helper uses `@functools.lru_cache(maxsize=256)` for hot-path optimization
- **Idempotent builds**: `MachineBuilder.build()` uses `copy.deepcopy` on internal state so repeated calls produce independent machines
- **Defensive copying**: `_compile_state()` copies `entry`, `exit`, and `on` data from State objects to prevent mutation of shared State instances across builds
- **Falsy context handling**: All context checks use `is not None` instead of truthiness to preserve empty dicts `{}`
- **State.exit naming**: Internal storage uses `_exit_actions` with a public `exit_actions` property, keeping `exit()` as the decorator method — avoids shadowing Python's `exit` builtin
- **`_resolve_target()` signature**: Added optional `source_prefix` parameter for hierarchical context-aware target resolution
- **`collect_all_transitions()`**: Now passes `source_prefix` to `_resolve_target()` for accurate nested state resolution

### Fixed
- **Nested state target resolution**: Fixed 14 `pythonic-class` template failures where child states with the same name under different parents (e.g., `login.idle` vs `signup.idle`) resolved to the wrong target. Added `source_prefix` parameter to `_resolve_target()` for context-aware sibling resolution that walks up the parent chain to find the closest matching state.
- **State/event name collision in code generation**: Fixed `'Transition' object has no attribute 'to'` error when event names (e.g., `preview_failed`) collide with state variable names. Code generator now detects collisions and appends `_event` suffix to transition variable names.
- **Empty actions list emission**: Changed `actions_val is not None` to truthy check to avoid emitting `actions=[]` in generated `pythonic-class` code.
- **Conditional `service` decorator import**: The `service` decorator is now only imported in generated code when the machine actually defines services, preventing unused import warnings.
- **Function complexity compliance**: Extracted `_format_action_list_kwarg()` helper in `pythonic_functional.py` to reduce `_generate_build_function` complexity from 36 to ≤35, fixing flake8 C901 violation.

### Deprecated
- `--style` flag (use `--template` instead; `--style` will be removed in v0.6.0)

## [0.4.3] - 2025-02-03

### Added

- **Python 3.14 Support**: Added full support for Python 3.14 with comprehensive testing across all supported Python versions (3.9-3.14).
  - Verified compatibility with 2,754 tests across Python 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14.
  - Updated project classifiers to include Python 3.14.
- **Enhanced Test Coverage for `logic_providers`**: Added comprehensive tests for `logic_providers` camelCase to snake_case auto-discovery feature (Issue #17).
  - Tests verify that camelCase action names in JSON (e.g., `storeJobParams`) are correctly mapped to snake_case Python methods (e.g., `store_job_params`).
  - Added end-to-end async execution tests to ensure actions are properly invoked through the interpreter.
- **Documentation Improvements**: Cleaned up README.md by removing outdated version-specific references ("New in 0.4.1", "Headline for 0.4.1", "Upgrade Notes: 0.4.0 → 0.4.1") to make documentation more maintainable and version-agnostic.

### Changed

- **Build System Migration**: Migrated from Poetry to `uv` for faster, more reliable package management.
  - Switched build backend from `poetry-core` to `hatchling`.
  - Updated `pyproject.toml` to use PEP 621 metadata format.
  - Replaced Poetry dependency groups with `uv` dependency groups (`dev`, `lint`, `test`).
  - Updated all documentation with new `uv` commands:
    - `uv pip install -e . --group dev --group lint --group test`
    - `uv run pytest`
    - `uv run pre-commit run --all-files`
- **Python Version Support**: Updated minimum Python requirement from 3.8 to 3.9.
  - Python 3.8 reached end-of-life and is no longer supported.
  - All dependencies updated to require Python 3.9+.
- **CI/CD Updates**: Updated pre-commit configuration to use Python 3.14 and Black 26.1.0.

### Fixed

- **Deprecation Warning**: Replaced deprecated `asyncio.iscoroutinefunction()` with `inspect.iscoroutinefunction()` to resolve deprecation warnings and ensure compatibility with Python 3.16+.
- **Python 3.9 Compatibility**: Fixed union syntax usage in test files (`| None` → `Optional[...]`) to ensure compatibility with Python 3.9, which does not support PEP 604 union syntax.

## [0.4.2] - 2025-08-13

### Added

- **`reenter` Flag for Self-Transitions**: Introduced a `reenter` boolean flag for transitions to align with XState v5's handling of self-transitions.
  - When `reenter: true`, a self-transition becomes "external," causing the state to be exited and re-entered, triggering all entry and exit actions.
  - By default, or when `reenter: false`, a self-transition is "internal," meaning only the transition's actions are executed, and the state is not exited or re-entered. This is the new default behavior.
  - This feature is fully supported in both the asynchronous (`Interpreter`) and synchronous (`SyncInterpreter`) engines.

### Changed

- **Refactored Transition Logic**: The core event processing logic in both `BaseInterpreter` and `SyncInterpreter` was refactored to cleanly distinguish between internal and external transitions, improving clarity and maintainability.
- **Updated Self-Transition Tests**: Existing tests for self-transitions were updated to use `reenter: true` to preserve their original intent of testing external transitions. New tests were added to specifically validate the `reenter: false` internal transition behavior.

## [0.4.1] - 2025-07-27

### Added

- **Enhanced Sync Actor Spawning**: The `SyncInterpreter` now supports **non-blocking actor spawning** (via `spawn_` actions) by running child `SyncInterpreter` instances in dedicated background threads. This significantly expands the `SyncInterpreter`'s capabilities to manage concurrent, independent state machine processes without blocking the main thread, offering more flexibility for synchronous applications.
- **Multiple `after` Timers per State in SyncInterpreter**: Introduced the ability for a single state in the `SyncInterpreter` to declare and manage **multiple independent `after` (delayed) transitions**. This provides finer-grained control over time-based logic, enabling more complex timing behaviors within synchronous state machines.
- **Hierarchical Machine Generation in CLI**: The `xsm` CLI's `generate-template` command now intelligently handles **hierarchical state machine definitions** (parent-child relationships across multiple JSON files). This streamlines boilerplate generation for complex systems composed of a main machine orchestrating several child actors. The CLI can also **heuristically identify parent-child relationships** among input JSON files and offers interactive confirmation for the user.
- **CLI Subcommand Aliases**: Added support for shorter, alternative names (aliases) for CLI subcommands. This significantly enhances command-line usability and convenience. For example:
    - `generate-template` can now be invoked as `gt`.
    - `--json-parent` can be used as `-jp`.
    - `--json-child` can be used as `-jc`.
    - `--file-count` can be used as `-fc`.
    - `--async-mode` can be used as `-am`.
    - `--loader` can be used as `-l`.
    - `--style` can be used as `-s`.
    - `--output` can be used as `-o`.
    - `--force` can be used as `-f`.

### Changed

- **CLI Command Renamed**: The primary command-line interface tool has been renamed from `xstate-statemachine` to `xsm` for brevity and ease of use. All examples and documentation related to the CLI usage now reflect this new command.
- **Improved `SyncInterpreter` Shutdown**: The `stop()` method of the `SyncInterpreter` now ensures a more orderly shutdown by explicitly iterating and stopping all child actors *before* canceling any active `after` timers. This enhances reliability and resource management for complex synchronous systems.
- **Robust `after` Timer Management in `SyncInterpreter`**: The internal mechanism for managing `after` timers in the `SyncInterpreter` was refined to accurately track and cancel multiple timers associated with a single state. Each timer is now assigned a unique identifier, ensuring precise lifecycle management and preventing lingering background threads.
- **Streamlined Logic Loader for `spawn_` actions**: The `LogicLoader` no longer applies special parsing rules to `spawn_*` actions when extracting logic names. This simplifies the configuration and binding process by treating these as regular actions, with the runtime interpreter now handling the specific spawning behavior.
- **Refined Runner Code Logic Binding**: The generated runner code for both single and multiple machine setups now features more robust and accurate logic for binding the Python implementation (actions, guards, services) to the state machine. This ensures seamless integration and execution, especially with class-based logic and auto-discovery.
- **Enhanced Configuration File Path Resolution in Runner**: The boilerplate runner code generated by the CLI now incorporates smarter logic for locating the source JSON configuration file. It first attempts to find the file relative to the generated script, and then, as a fallback, relative to the script's parent directory, improving adaptability to various project structures.
- **CLI Argument Validation and User Experience**:
    - The CLI's argument parsing is now stricter, explicitly disabling partial matching of command-line options (`allow_abbrev=False`) to ensure clearer and more predictable behavior.
    - Added specific validation checks to prevent invalid command-line argument combinations, such as supplying the `--json-parent` flag multiple times.
    - Improved consistency and clarity in CLI prompts, especially during interactive hierarchy guessing.
    - The code generation logic now automatically adjusts generated Python function names if they conflict with Python's reserved keywords (e.g., `def` becomes `def_`), preventing syntax errors in the generated boilerplate.

### Fixed

- **CLI Subcommand Alias Execution**: Resolved a critical issue where CLI subcommand aliases (like `gt` for `generate-template`) were not correctly executing the associated workflow and instead displayed the help message. This was fixed by modifying the main CLI entry point to correctly dispatch to the appropriate subcommand logic when an alias is used.
- **Regression Fix: `SyncInterpreter` Target Resolution**: Corrected a regression in the `SyncInterpreter` where the internal `TransitionDefinition` object's `target_str` was not consistently updated with the fully resolved path after a successful state target resolution. This fix ensures that all subsequent internal logic consistently uses the correct, fully qualified state ID.
- **Generated Code Keyword Conflicts**: Addressed a bug that could lead to syntax errors in generated Python code when state machine action, guard, or service names coincided with Python's reserved keywords. The generator now automatically renames such conflicting elements by appending an underscore.
- **Minor Logging Consistency**: Ensured that the generated Python logic files consistently use the correct and intended logging messages when actions are executed, maintaining clarity in debug outputs.

## [0.4.0] - 2025-07-16

### Added

- **CLI Tool**: Introduced a new command-line interface (CLI) tool for interacting with state machines, including commands for creating, validating, and running machines from JSON configurations. This enhances usability for developers and enables easier integration into scripts and CI/CD pipelines.
- **'after' Transition Support in SyncInterpreter**: Added support for timed 'after' transitions in the synchronous interpreter (`SyncInterpreter`). This allows for delayed transitions without requiring an asynchronous event loop, using blocking sleep mechanisms for simplicity in synchronous environments. Note: This feature is limited to deterministic, non-concurrent use cases and may block the main thread.

### Changed

- Updated the `SyncInterpreter` to handle delayed events synchronously, ensuring compatibility with basic timing requirements while maintaining the blocking execution model.
- Minor internal refactoring in the `SyncInterpreter` to accommodate the new 'after' logic, including updates to task scheduling and event processing loops.
- Removed special treatment for 'spawn_' actions in the logic loader (`LogicLoader`), now treating them as regular actions. This may require users to adjust bindings for actor spawning in configurations.

### Fixed

- Resolved potential re-entrancy issues in the synchronous event queue by adding safeguards during processing cycles.
- Improved error messages for unsupported asynchronous features in `SyncInterpreter` to provide clearer guidance on limitations.

---

## [0.3.1] - 2025‑07‑11
### Added
- **Extended Plugin Hooks**
  Introduced new lifecycle hooks in `PluginBase` for granular introspection:
  - `on_guard_evaluated`: Notifies when a guard condition is checked and its result.
  - `on_service_start`: Notifies when an invoked service begins execution.
  - `on_service_done`: Notifies when an invoked service completes successfully, including its result.
  - `on_service_error`: Notifies when an invoked service encounters an error, including the exception.

### Changed
- **Improved Event Handling Robustness**
  Refactored `send` methods in `Interpreter` and `SyncInterpreter` for more resilient event object preparation, resolving `TypeError` issues with pre-formed `Event` instances and improving compatibility with mock objects in testing.

---

## [0.3.0] - 2025‑07‑11
### Added
- **Dual Execution Engines**
  New **`SyncInterpreter`** (blocking) complements the existing async `Interpreter`, both inheriting from a shared `BaseInterpreter`.
- **State Snapshotting**
  `get_snapshot()` / `restore_from_snapshot()` enable one‑call persistence and time‑travel debugging.
- **Plugin Framework**
  Formal `PluginBase` with life‑cycle hooks (`on_event`, `on_state_enter`, …) for custom loggers, telemetry, persistence, etc.
- **Actor Spawning Contract**
  `spawn_*` helpers plus `ActorSpawningError` for type‑safe child‑machine creation.
- **Utility APIs**
  Helpers suchs as `get_state_by_id()`, `get_next_state()`, and public camel⇄snake converters.
- **Enhanced Logging**
  Emoji‑tagged, interpreter‑ID‑stamped logs with an automatic `NullHandler`.

### Changed
- **Interpreter Hierarchy Refactor** — core transition logic moved to `BaseInterpreter`; async & sync variants now thin wrappers.
- **Factory** `create_machine()` gains `mode="async" | "sync"` (default *async*).
- **TaskManager** rewrite with smarter cancellation graph.
- **Logger** pre‑configured; manual `NullHandler` boilerplate no longer needed.
- **LogicLoader** faster discovery and clearer error messages.

### Removed
- Internal, non‑public helpers (e.g. `_legacy_cancel_all`) pruned; _no public API removed_.

---

## [0.2.3] - 2025‑07‑08
### Changed
- **Packaging‑only bump** — version strings updated to `0.2.3`; library code identical to `0.2.2`.

---

## [0.2.2] - 2025‑07‑08
### Changed
- **Packaging‑only bump** — version strings updated to `0.2.2`; library code identical to `0.2.1`.

---

## [0.2.1] - 2025‑07‑08
### Added
- **Automatic Logic Discovery**
  Introduced `LogicLoader`, a singleton that auto‑registers action/guard/service functions from user modules.
- **Plug‑and‑Play Modules**
  `create_machine()` now accepts `logic_modules`, letting you wire logic without boilerplate.
- **Public Exports**
  `LogicLoader` and `ActionDefinition` exported at package root.

### Changed
- **Factory API Upgrade**
  Extended signature of `create_machine()`; richer type hints and early validation.
- **Structured Logging**
  Emoji‑tagged logs with machine context.
- **Internal Naming Helpers**
  Robust camel⇄snake converters exposed publicly.

---

## [0.1.0] - 2025‑07‑07 — _Initial release_
