Metadata-Version: 2.4
Name: determa-state
Version: 0.1.0
Summary: Determa State — Python reference implementation of the Determa statechart engine
Project-URL: Homepage, https://github.com/fruwehq/determa-state-python
Project-URL: Repository, https://github.com/fruwehq/determa-state-python
Project-URL: Specification, https://github.com/fruwehq/determa-state-spec
Project-URL: Issues, https://github.com/fruwehq/determa-state-python/issues
Author: Christian-Manuel Butzke
License: MIT License
        
        Copyright (c) 2026 Christian-Manuel Butzke
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: determa,fsm,hsm,scxml,state-machine,statechart,uml
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: cel-python>=0.1
Requires-Dist: jsonschema>=4
Requires-Dist: pyyaml>=6
Requires-Dist: rfc8785>=0.1.4
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: types-jsonschema; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Description-Content-Type: text/markdown

# determa-state

Python implementation of [Determa State](https://github.com/fruwehq/determa-state-spec),
a language-agnostic statechart engine with a shared normative conformance suite.

This release implements Determa State `format: 1` at the synchronized specification
commit `c1635d74e6a216301a8986d37be8ce7e7111dfd7`. Correctness is determined by the
110-case core suite and persistence profiles at conformance commit
`600523ca08c3b8a6ee790439a32dc4ce47f71b95`.

The package metadata is `0.1.0` for the next synchronized release of the specification,
conformance suite, Python engine, and Rust engine.

## Install

The published `0.0.7` distribution predates portable persistence and definition
migration. Until the synchronized `0.1.0` Determa State release is published, install
this release candidate from a checkout:

```sh
git clone https://github.com/fruwehq/determa-state-python.git
cd determa-state-python
python -m pip install -e .
```

The distribution is `determa-state`; the import is `determa.state`. It also installs
`determa-state` and `determa-state-python` commands.

## Define A Bundle

Format 1 uses one self-contained bundle containing one or more machines:

```yaml
format: 1
namespace: example.counter
events:
  increment:
    direction: input
    payload:
      amount: { type: int, required: true }
  reset:
    direction: input
machines:
  - machine_id: counter
    version: 1
    root:
      type: composite
      variables:
        count: { type: int, init: 0 }
      initial: { transition_to: running }
      states:
        running:
          on_events:
            increment:
              action:
                - assign: { count: "count + event.payload.amount" }
            reset:
              action:
                - assign: { count: "0" }
```

The same bundle is available at [`examples/format-1.yaml`](examples/format-1.yaml).
Documents are parsed using the portable YAML 1.2 scalar rules, then checked against the
bundled normative JSON Schema and semantic validation rules. Abandoned draft grammar
names are not accepted.

## Use The Library

`create` and `dispatch` are pure foreground operations. They do not retain hidden
machine state or call queues, timers, databases, or remote services.

```python
from pathlib import Path

import determa.state as ds

bundle = ds.load_bundle(Path("examples/format-1.yaml").read_text())
created = ds.create(
    bundle,
    machine_id="counter",
    root_instance_id="counter-42",
    creation_id="create-counter-42",
    bindings={},
)
state = created["state"]

target = {
    "root": {
        "root_instance_id": state["root_instance_id"],
        "root_runtime_id": state["root_runtime_id"],
    }
}
result = ds.dispatch(
    bundle,
    state,
    {
        "input": {
            "event": "increment",
            "event_id": "counter-42:increment:1",
            "target": target,
            "payload": {"amount": 2},
        }
    },
)

assert result["status"] == "running"
assert result["disposition"] == "handled"
state = result["state"]
root = state["runtimes"][state["root_runtime_id"]]
assert root["scopes"]["root"]["count"] == 2
```

Both calls return all result fields: `status`, `disposition`, `state`, `emissions`,
`fault`, and `rejection` (`create` has a null disposition). The caller owns delivery:
the core processes at most one supplied envelope and does not place it in an internal
queue. Successful processing returns a new JSON-compatible logical aggregate while
leaving the supplied prior state unchanged. Rejections and unhandled deliveries return
the exact supplied state object.

`load_bundle` also accepts a native Python mapping through the same structural and
semantic validation path. Native values must satisfy the same portable Unicode and
numeric domain as source documents.

## Persist And Migrate

`serialize_aggregate` produces the canonical §16 aggregate artifact. Restoration
resolves its exact validated definition by fingerprint and fails closed when the
definition is absent or untrusted:

```python
resolver = ds.MemoryArtifactResolver(definitions={bundle.fingerprint: bundle})
encoded = ds.serialize_aggregate(bundle, state)
restored = ds.restore_aggregate(encoded, resolver)
```

`restore_aggregate_package` verifies a self-contained transport package and seeds a
mutable resolver without replacing existing content. `migrate_aggregate` applies an
exact trusted descriptor route as a pure operation. `migrate_and_dispatch` returns one
commit-ready migration, audit, dispatch, aggregate, and outbox-intent boundary. Failed
migrations return a deterministic `MigrationFailure` and do not mutate the supplied
artifact or resolver.

Definition and descriptor resolvers are protocols, so applications can back them with
an immutable registry or a transaction-local cache. Database schemas, broker
acknowledgement, retries, and quarantine remain host responsibilities; the conformance
persistence profile verifies the required transaction ordering.

## Implemented Core

- strict format-1 loading, default materialization, bundle fingerprinting, and exact
  source-level scalar handling;
- portable CEL guards and action expressions;
- hierarchical dispatch, local and unmarked transitions, choices, shallow/deep
  history, entry/exit behavior, final states, and stop interruption;
- lexical typed variables, input/external bindings, `env` refresh, and typed payloads;
- explicit sends, isolated lifecycle-bound components, and deterministic routing;
- owned spawn, nominal instance references, binding, cancellation, completion,
  failure propagation, and cleanup cascades;
- atomic RTC rollback, deterministic identities/counters, pure inspection, and
  incompatible or malformed prior-state rejection;
- canonical aggregate serialization/restoration, portable typed values, package
  attachments, exact definition resolution, trusted lazy migration, deterministic
  audits, resource limits, and atomic migrate-and-dispatch results.

Format 1 deliberately does not define native queues, timers, deferral, dead letters,
database schemas, package imports, standardized enabled-event inspection, or a
standardized execution CLI.

The implementation-local CLI only validates a bundle:

```sh
determa-state validate examples/format-1.yaml
```

It prints the normalized bundle fingerprint on success.

## Develop

```sh
python -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'

ruff check .
mypy src/determa
pytest -q
pytest conformance -q
```

Unit tests are hermetic and offline. The conformance harness uses the immutable commits
listed above, cached under `.cache/`; local checkouts can be supplied with
`DETERMA_CONFORMANCE_DIR` and `DETERMA_SPEC_DIR`.

## License

MIT. See [LICENSE](LICENSE).
