diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6afb1f8..eb42913 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,34 +21,6 @@ jobs: - name: Check out tutorial uses: actions/checkout@v7 - - name: Check out specification - uses: actions/checkout@v7 - with: - repository: fruwehq/determa-state-spec - ref: c1635d74e6a216301a8986d37be8ce7e7111dfd7 - path: .sources/determa-state-spec - - - name: Check out conformance - uses: actions/checkout@v7 - with: - repository: fruwehq/determa-state-conformance - ref: 600523ca08c3b8a6ee790439a32dc4ce47f71b95 - path: .sources/determa-state-conformance - - - name: Check out Python engine - uses: actions/checkout@v7 - with: - repository: fruwehq/determa-state-python - ref: 7b17d788b48049648e7e463aa3d35ba13dc1aa6e - path: .sources/determa-state-python - - - name: Check out Rust engine - uses: actions/checkout@v7 - with: - repository: fruwehq/determa-state-rust - ref: d17480c8b281dcd17953f59afcf6b5d23ff44efd - path: .sources/determa-state-rust - - name: Set up Python uses: actions/setup-python@v7 with: @@ -63,6 +35,9 @@ jobs: - name: Install pinned dependencies run: python -m pip install --requirement requirements.txt + - name: Fetch pinned Determa State sources + run: make sources + - name: Validate released version is current env: GITHUB_TOKEN: ${{ github.token }} diff --git a/AGENTS.md b/AGENTS.md index 7ccc8b7..1bae2e7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,12 +17,13 @@ and applicable `determa-state-conformance` core cases decide portable behavior. ## Current target -- Determa State synchronized version: `0.1.0` +- Determa State synchronized version: `0.2.0` - machine grammar: numeric `format: 1` - exact source revisions: `sources.lock.yaml` -The coverage matrix must contain every normative specification section and every -actual core conformance case at the pinned revisions. +The coverage matrix must contain every normative specification section, every actual +core conformance case, and every released execution-checkpoint profile case directory +at the pinned revisions. ## Working rules @@ -50,8 +51,8 @@ actual core conformance case at the pinned revisions. name an existing chapter. Planned entries must name an open implementation issue. - Normative text belongs in `determa-state-spec`, not here. Link to it and explain it in beginner language. -- Persistence/migration content is released in State 0.1.0 and tracked for tutorial - implementation by issue #7. +- Persistence, migration, and execution-checkpoint hosting are released in State 0.2.0 + and taught in the corresponding guides. - Package-import content remains unsupported until a portable import contract exists. ## Gates @@ -68,7 +69,7 @@ strict site-build validation. CI is the same contract. ## Repository map - `docs/`: authored tutorial chapters. -- `coverage.yaml`: spec-section and core-case disposition. +- `coverage.yaml`: spec-section, core-case, and released profile-case disposition. - `sources.lock.yaml`: immutable upstream source identities. - `STATE_VERSION`: synchronized State version displayed and checked. - `scripts/`: extraction and validation tools. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2aa52e1..4c7b504 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,8 +31,8 @@ same extracted machine and assert the same observable trace. ## Update coverage -Every pinned normative section and core conformance case has exactly one entry in -`coverage.yaml`. +Every pinned normative section, core conformance case, and released +execution-checkpoint profile case directory has exactly one entry in `coverage.yaml`. - `covered`: an existing chapter demonstrably explains or executes the item. - `planned`: the item is assigned to an existing chapter path and open child issue. diff --git a/README.md b/README.md index 8cab25e..7d16990 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The manual, beginner-friendly tutorial, and documentation website for [Determa State](https://github.com/fruwehq/determa-state-spec). -The tutorials currently target synchronized Determa State **0.1.0** and the numeric +The tutorials currently target synchronized Determa State **0.2.0** and the numeric `format: 1` grammar. Start with [Your first machine](docs/getting-started/first-machine.md). @@ -18,8 +18,8 @@ Every chapter is ordinary Markdown: are never maintained as duplicate authored copies. This repository explains and demonstrates Determa State. The -[specification](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md) and -[conformance suite](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0) +[specification](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md) and +[conformance suite](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0) remain normative. Independent, fully working real-world applications live in @@ -37,8 +37,9 @@ make sources make check ``` -`make check` verifies the pinned source versions, coverage totality, YAML 1.2 parsing, -JSON Schema validity, Python and Rust traces, and the strict MkDocs build. +`make check` verifies the pinned source versions, specification/core/profile coverage +totality, YAML 1.2 parsing, JSON Schema validity, Python and Rust traces, and the strict +MkDocs build. Use `make serve` to preview the site locally. @@ -46,13 +47,13 @@ Use `make serve` to preview the site locally. The released format-1 user-facing surface is taught and executed across the progressive guides. The machine-readable [`coverage.yaml`](coverage.yaml) inventories every -normative section and core conformance case as covered or deliberately -non-user-facing. +normative section, core conformance case, and released execution-checkpoint profile +case as covered or deliberately non-user-facing. -Persistence and definition migration include a beginner SQLite walkthrough and an -advanced 105-vector Python/Rust reference lab. Aggregate packages are supported as -content-addressed transport; portable package imports in machine definitions remain -unsupported. +Persistence and definition migration include a durable execution-checkpoint tutorial, +a lower-level SQLite transaction walkthrough, and an advanced 108-vector Python/Rust +reference lab. Aggregate packages are supported as content-addressed transport; +portable package imports in machine definitions remain unsupported. See [CONTRIBUTING.md](CONTRIBUTING.md) before changing examples or coverage. diff --git a/STATE_VERSION b/STATE_VERSION index 6e8bf73..0ea3a94 100644 --- a/STATE_VERSION +++ b/STATE_VERSION @@ -1 +1 @@ -0.1.0 +0.2.0 diff --git a/coverage.yaml b/coverage.yaml index 4549422..73d7abb 100644 --- a/coverage.yaml +++ b/coverage.yaml @@ -1,4 +1,4 @@ -state_version: "0.1.0" +state_version: "0.2.0" specification: - id: "0" @@ -151,6 +151,21 @@ specification: - { id: "16.12", status: covered, chapter: docs/guides/persistence-migration-reference.md } - { id: "16.13", status: covered, chapter: docs/guides/persistence-migration-reference.md } - { id: "16.14", status: covered, chapter: docs/guides/persistence-migration-reference.md } + - { id: "17", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.1", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.2", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.3", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.4", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.5", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.6", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.7", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.8", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.9", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.10", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.11", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.12", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.13", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { id: "17.14", status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } conformance: - { case: 01-guarded-leaf, status: covered, chapter: docs/getting-started/first-machine.md } @@ -263,3 +278,9 @@ conformance: - { case: 113-migration-failure-completeness, status: covered, chapter: docs/guides/persistence-migration-reference.md } - { case: 114-occurrence-local-transform-binding, status: covered, chapter: docs/guides/persistence-migration-reference.md } - { case: 115-target-identity-decimal-projections, status: covered, chapter: docs/guides/persistence-migration-reference.md } + - { case: 116-legacy-format-policy, status: covered, chapter: docs/guides/core-statecharts.md } + +execution_checkpoint_profile: + - { case: checkpoint-01-delivery-lifecycle, status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { case: checkpoint-02-outbox-lifecycle, status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } + - { case: checkpoint-03-retention-and-root-lifecycle, status: covered, chapter: docs/guides/execution-checkpoint-hosting.md } diff --git a/docs/getting-started/first-machine.md b/docs/getting-started/first-machine.md index 4e5bc5d..292252c 100644 --- a/docs/getting-started/first-machine.md +++ b/docs/getting-started/first-machine.md @@ -51,7 +51,7 @@ type errors before the machine runs. Install the released engine: ```sh -python -m pip install determa-state==0.1.0 +python -m pip install determa-state==0.2.0 ``` The complete program is below. `create` returns the initial state. `dispatch` returns @@ -146,12 +146,12 @@ Create a small Cargo project with the released crate. ```toml [package] name = "determa-first-counter" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" ``` The Rust program uses the same machine file and asserts the same count and @@ -228,7 +228,7 @@ The [coverage status](../reference/coverage.md) maps the complete released forma surface. Normative references: -[bundle grammar §4](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#4-bundle-grammar), -[CEL §5](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#5-static-validation-and-cel), +[bundle grammar §4](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#4-bundle-grammar), +[CEL §5](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#5-static-validation-and-cel), and -[dispatch §6](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#6-event-and-transition-semantics). +[dispatch §6](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#6-event-and-transition-semantics). diff --git a/docs/guides/cel-and-actions.md b/docs/guides/cel-and-actions.md index 0efb5e2..5450e92 100644 --- a/docs/guides/cel-and-actions.md +++ b/docs/guides/cel-and-actions.md @@ -4,7 +4,7 @@ Determa State uses [CEL](https://cel.dev/) for guards and computed action values The machine file remains data: the engine parses and type-checks every expression when the bundle loads, then evaluates only the expressions selected by an event. -This chapter uses the closed portable CEL profile from Determa State 0.1.0. It does not +This chapter uses the closed portable CEL profile from Determa State 0.2.0. It does not use host functions or implementation-specific CEL extensions. ## Start with ordered guards @@ -607,7 +607,7 @@ and a root fault is terminal. Install the pinned engine: ```sh -python -m pip install determa-state==0.1.0 +python -m pip install determa-state==0.2.0 ``` @@ -887,12 +887,12 @@ print(f"guards=standard,bulk,empty; total=4.5; audit={audit_summary}; faults=11" ```toml [package] name = "determa-cel-actions" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" ``` @@ -1302,24 +1302,24 @@ language traces. The code above is the tested source, not pseudocode. ## Coverage This chapter covers the format-1 structured-action and CEL rules linked below. The -matching Determa State v0.1.0 conformance cases are: - -- [12 guarded list](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/12-guarded-list) -- [17 action fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/17-action-fault) -- [61 expression map order](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/61-expression-map-order) -- [64 dynamic target expression order](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/64-dynamic-target-expression-order) -- [65 portable CEL profile](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/65-portable-cel-profile) -- [66 CEL profile rejections](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/66-cel-profile-rejections) -- [68 CEL AND non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/68-cel-and-nonabsorbed-error) -- [69 CEL OR non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/69-cel-or-nonabsorbed-error) -- [70 dynamic target list order](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/70-dynamic-target-list-order) -- [71 reversed CEL AND non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/71-cel-reversed-and-nonabsorbed-error) -- [72 reversed CEL OR non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/72-cel-reversed-or-nonabsorbed-error) -- [79 missing refresh field](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/79-missing-refresh-field) +matching Determa State v0.2.0 conformance cases are: + +- [12 guarded list](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/12-guarded-list) +- [17 action fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/17-action-fault) +- [61 expression map order](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/61-expression-map-order) +- [64 dynamic target expression order](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/64-dynamic-target-expression-order) +- [65 portable CEL profile](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/65-portable-cel-profile) +- [66 CEL profile rejections](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/66-cel-profile-rejections) +- [68 CEL AND non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/68-cel-and-nonabsorbed-error) +- [69 CEL OR non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/69-cel-or-nonabsorbed-error) +- [70 dynamic target list order](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/70-dynamic-target-list-order) +- [71 reversed CEL AND non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/71-cel-reversed-and-nonabsorbed-error) +- [72 reversed CEL OR non-absorbed error](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/72-cel-reversed-or-nonabsorbed-error) +- [79 missing refresh field](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/79-missing-refresh-field) Normative references: -[structured actions §4.8](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#48-structured-actions), -[static validation and CEL §5](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#5-static-validation-and-cel), -[portable CEL profile](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#portable-cel-profile), +[structured actions §4.8](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#48-structured-actions), +[static validation and CEL §5](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#5-static-validation-and-cel), +[portable CEL profile](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#portable-cel-profile), and -[faults §10](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#10-faults-and-envelope-disposition). +[faults §10](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#10-faults-and-envelope-disposition). diff --git a/docs/guides/components-and-spawning.md b/docs/guides/components-and-spawning.md index 9f4edee..ce59dfb 100644 --- a/docs/guides/components-and-spawning.md +++ b/docs/guides/components-and-spawning.md @@ -717,12 +717,12 @@ emission order, stale-target rejection, and final output. ```toml [package] name = "determa-components-spawning" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" ``` @@ -1190,37 +1190,37 @@ portable lifecycle model: ## Coverage This chapter covers specification -[§7](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#7-components-spawning-and-lifecycle), -[§7.1](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#71-lifecycle-bound-components), -[§7.2](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#72-owned-spawned-instances), +[§7](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#7-components-spawning-and-lifecycle), +[§7.1](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#71-lifecycle-bound-components), +[§7.2](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#72-owned-spawned-instances), and -[§7.3](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#73-runtime-and-aggregate-root-completion). - -The matching v0.1.0 conformance cases are: - -- [09 parallel components](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/09-parallel-components) -- [13 spawn completion](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/13-spawn-completion) -- [14 explicit targets](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/14-explicit-targets) -- [29 owned spawn](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/29-owned-spawn) -- [30 owned spawn cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/30-owned-spawn-cancel) -- [38 destroyed reference binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/38-destroyed-reference-binding) -- [47 scoped owned-child lifetime](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/47-scoped-owned-child-lifetime) -- [48 null cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/48-null-cancel) -- [49 exit-action cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/49-exit-action-cancel) -- [51 component initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/51-component-initialization-fault) -- [52 spawned initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/52-spawned-initialization-fault) -- [54 stale component target](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/54-stale-component-target) -- [55 root owner target](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/55-root-owner-target) -- [73 synchronous initialization cycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/73-synchronous-initialization-cycle) -- [74 sibling cleanup order](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/74-sibling-cleanup-order) -- [78 component external refresh](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/78-component-external-refresh) -- [80 unbound owned child](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/80-unbound-owned-child) -- [81 holder reference reuse](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/81-holder-reference-reuse) -- [82 instance-reference target identity](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/82-instance-reference-target-identity) -- [83 contained dynamic instance send](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/83-contained-dynamic-instance-send) -- [86 initial component completion order](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/86-initial-component-completion-order) -- [87 internal env target mode](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/87-internal-env-target-mode) -- [91 component host-input rejection](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/91-component-host-input-rejection) +[§7.3](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#73-runtime-and-aggregate-root-completion). + +The matching v0.2.0 conformance cases are: + +- [09 parallel components](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/09-parallel-components) +- [13 spawn completion](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/13-spawn-completion) +- [14 explicit targets](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/14-explicit-targets) +- [29 owned spawn](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/29-owned-spawn) +- [30 owned spawn cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/30-owned-spawn-cancel) +- [38 destroyed reference binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/38-destroyed-reference-binding) +- [47 scoped owned-child lifetime](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/47-scoped-owned-child-lifetime) +- [48 null cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/48-null-cancel) +- [49 exit-action cancel](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/49-exit-action-cancel) +- [51 component initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/51-component-initialization-fault) +- [52 spawned initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/52-spawned-initialization-fault) +- [54 stale component target](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/54-stale-component-target) +- [55 root owner target](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/55-root-owner-target) +- [73 synchronous initialization cycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/73-synchronous-initialization-cycle) +- [74 sibling cleanup order](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/74-sibling-cleanup-order) +- [78 component external refresh](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/78-component-external-refresh) +- [80 unbound owned child](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/80-unbound-owned-child) +- [81 holder reference reuse](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/81-holder-reference-reuse) +- [82 instance-reference target identity](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/82-instance-reference-target-identity) +- [83 contained dynamic instance send](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/83-contained-dynamic-instance-send) +- [86 initial component completion order](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/86-initial-component-completion-order) +- [87 internal env target mode](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/87-internal-env-target-mode) +- [91 component host-input rejection](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/91-component-host-input-rejection) Portable package imports and direct host-to-component input are deliberately not introduced here. diff --git a/docs/guides/core-statecharts.md b/docs/guides/core-statecharts.md index f29a192..6736cfa 100644 --- a/docs/guides/core-statecharts.md +++ b/docs/guides/core-statecharts.md @@ -5,7 +5,7 @@ nested phases, data with clear lifetimes, predictable entry and exit behavior, a way to resume interrupted work. This chapter builds those ideas in layers. Every complete file is extracted from this -Markdown and run against Determa State 0.1.0 in both Python and Rust. +Markdown and run against Determa State 0.2.0 in both Python and Rust. ## 1. Read a statechart from the outside in @@ -466,7 +466,7 @@ use the YAML 1.2 core model narrowed to an acyclic JSON-compatible tree. Every current document must carry the numeric value `format: 1`. Omission, a quoted `"1"`, or any other value is `unsupported_format`; loaders never guess the nearest grammar. This format identifier is separate from the released package/specification -version 0.1.0 and from each author's machine `version`. +version 0.2.0 and from each author's machine `version`. Identifiers match `^[A-Za-z_][A-Za-z0-9_]*$`; namespaces are dot-separated identifiers. Every string in source, creation bindings, event envelopes, and logical @@ -844,12 +844,12 @@ The Rust program uses the same four extracted YAML files and checks the same out ```toml [package] name = "determa-core-statecharts" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" ``` @@ -1249,55 +1249,56 @@ Before relying on a machine: ## 14. Conformance coverage The executable arbiter for these explanations is the pinned Determa State conformance -suite. This chapter covers these exact v0.1.0 cases: +suite. This chapter covers these exact v0.2.0 cases: - Hierarchy, initialization, scope, payloads, transitions, and external values: - [02-hierarchy-bubbling](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/02-hierarchy-bubbling), - [03-initial-action](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/03-initial-action), - [05-variable-scope](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/05-variable-scope), - [06-payload-typing](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/06-payload-typing), - [07-internal-external](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/07-internal-external), - [08-local-vs-external](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/08-local-vs-external), and - [15-external-env-refresh](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/15-external-env-refresh). + [02-hierarchy-bubbling](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/02-hierarchy-bubbling), + [03-initial-action](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/03-initial-action), + [05-variable-scope](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/05-variable-scope), + [06-payload-typing](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/06-payload-typing), + [07-internal-external](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/07-internal-external), + [08-local-vs-external](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/08-local-vs-external), and + [15-external-env-refresh](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/15-external-env-refresh). - Choices and reachability: - [23-choice](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/23-choice), - [24-choice-chain](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/24-choice-chain), - [25-choice-invalid](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/25-choice-invalid), - [26-unreachable](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/26-unreachable), - [27-dead-branch](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/27-dead-branch), - [28-reachable-ok](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/28-reachable-ok), and - [53-compound-choice-lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/53-compound-choice-lifecycle). + [23-choice](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/23-choice), + [24-choice-chain](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/24-choice-chain), + [25-choice-invalid](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/25-choice-invalid), + [26-unreachable](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/26-unreachable), + [27-dead-branch](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/27-dead-branch), + [28-reachable-ok](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/28-reachable-ok), and + [53-compound-choice-lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/53-compound-choice-lifecycle). - History, lifecycle, and transition boundaries: - [10-history-deep](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/10-history-deep), - [11-history-shallow](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/11-history-shallow), - [32-history-resume-restart](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/32-history-resume-restart), - [33-history-capture-timing](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/33-history-capture-timing), - [34-history-first-entry](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/34-history-first-entry), - [35-shallow-deep-history](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/35-shallow-deep-history), - [36-history-variable-reinitialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/36-history-variable-reinitialization), - [37-destroyed-variable-write](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/37-destroyed-variable-write), - [39-ancestor-internal-transition](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/39-ancestor-internal-transition), - [40-noncanonical-transitions](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/40-noncanonical-transitions), - [42-initial-history-rejection](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/42-initial-history-rejection), - [43-self-history-lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/43-self-history-lifecycle), - [44-local-history](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/44-local-history), and - [45-proper-ancestor-target](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/45-proper-ancestor-target). + [10-history-deep](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/10-history-deep), + [11-history-shallow](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/11-history-shallow), + [32-history-resume-restart](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/32-history-resume-restart), + [33-history-capture-timing](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/33-history-capture-timing), + [34-history-first-entry](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/34-history-first-entry), + [35-shallow-deep-history](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/35-shallow-deep-history), + [36-history-variable-reinitialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/36-history-variable-reinitialization), + [37-destroyed-variable-write](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/37-destroyed-variable-write), + [39-ancestor-internal-transition](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/39-ancestor-internal-transition), + [40-noncanonical-transitions](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/40-noncanonical-transitions), + [42-initial-history-rejection](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/42-initial-history-rejection), + [43-self-history-lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/43-self-history-lifecycle), + [44-local-history](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/44-local-history), and + [45-proper-ancestor-target](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/45-proper-ancestor-target). - Variable creation, defaults, parsing, and stop interruption: - [56-variable-initialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/56-variable-initialization), - [57-creation-binding-defaults](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/57-creation-binding-defaults), - [58-missing-creation-binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/58-missing-creation-binding), - [59-payload-default-materialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/59-payload-default-materialization), - [60-payload-default-validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/60-payload-default-validation), - [62-parsed-value-model](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/62-parsed-value-model), - [63-entry-stop-interruption](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/63-entry-stop-interruption), and - [84-choice-stop-chain](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/84-choice-stop-chain). + [56-variable-initialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/56-variable-initialization), + [57-creation-binding-defaults](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/57-creation-binding-defaults), + [58-missing-creation-binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/58-missing-creation-binding), + [59-payload-default-materialization](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/59-payload-default-materialization), + [60-payload-default-validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/60-payload-default-validation), + [62-parsed-value-model](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/62-parsed-value-model), + [63-entry-stop-interruption](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/63-entry-stop-interruption), + [84-choice-stop-chain](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/84-choice-stop-chain), and + [116-legacy-format-policy](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/116-legacy-format-policy). Normative references: -[parsing and format identity §2](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#2-conformance-parsing-and-format-identity), -[states §4.6](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#46-state-nodes), -[transitions §4.7](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#47-transitions), -[hierarchical dispatch §6.3](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#63-hierarchical-dispatch), -[execution order §6.4](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#64-transition-execution-order), -[choice and history §6.5](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#65-choice-and-history), +[parsing and format identity §2](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#2-conformance-parsing-and-format-identity), +[states §4.6](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#46-state-nodes), +[transitions §4.7](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#47-transitions), +[hierarchical dispatch §6.3](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#63-hierarchical-dispatch), +[execution order §6.4](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#64-transition-execution-order), +[choice and history §6.5](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#65-choice-and-history), and -[stop interruption §6.6](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#66-stop-interruption). +[stop interruption §6.6](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#66-stop-interruption). diff --git a/docs/guides/effects-faults-hosting.md b/docs/guides/effects-faults-hosting.md index 34bb64d..230fe1d 100644 --- a/docs/guides/effects-faults-hosting.md +++ b/docs/guides/effects-faults-hosting.md @@ -342,12 +342,12 @@ The Rust program consumes the same bundle and asserts the same portable observat ```toml [package] name = "determa-effects-faults-hosting" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" ``` @@ -634,8 +634,10 @@ state, no disposition, and no new emissions. The in-memory aggregate can be inspected for identities, status, active configuration, variables, ownership, history, counters, and fault records. This is an abstract -logical-state API. Determa State 0.1.0 also defines portable aggregate serialization, -restoration, and definition migration. Build the database-backed host in the +logical-state API. Determa State 0.2.0 also defines portable aggregate serialization, +restoration, definition migration, and optional durable execution checkpoints. Start +with the [durable checkpoint host](execution-checkpoint-hosting.md), build the +lower-level database-backed host in the [persistence and migration tutorial](persistence-and-migration.md), then run packages, complete transforms, terminal maintenance, and security limits in the [persistence reference lab](persistence-migration-reference.md). @@ -660,8 +662,8 @@ and a delivered intent is not remote success. Format 1 deliberately has no native clocks, timers, sleeps, queues, retries, acknowledgements, deferrals, dead-letter store, implicit parallel broadcast, shared runtime variables, direct host-to-component delivery, cross-runtime transitions, -remote or detached spawn, package imports, definition hot-swap, portable snapshot -wire, standardized store/CLI protocol, root-fault recovery, root re-entry, distributed +remote or detached spawn, package imports, implicit definition hot-swap, +standardized cross-language store/CLI protocol, root-fault recovery, root re-entry, distributed exactly-once transaction, hard real-time guarantee, or standardized plugin configuration. @@ -676,34 +678,34 @@ aggregate inspection instead of executable observers. The exact released specification sections explained here are: -- [§9 deterministic identities and emissions](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#9-deterministic-identities-and-emissions); -- [§10 faults and envelope disposition](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#10-faults-and-envelope-disposition); -- [§10.1 engine faults](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#101-engine-faults); -- [§10.2 contained runtime faults](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#102-contained-runtime-faults); -- [§10.3 domain failures](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#103-domain-failures); -- [§11 plugins and hosting](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#11-plugins-and-hosting); -- [§11.1 queue plugins](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#111-queue-plugins); -- [§11.2 timer extensions](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#112-timer-extensions); -- [§11.3 external effects](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#113-external-effects); -- [§11.4 hosting profiles](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#114-hosting-profiles); -- [§12 inspection and visualization](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#12-inspection-and-visualization); -- [§13 deliberately unsupported in format 1](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#13-deliberately-unsupported-in-format-1). +- [§9 deterministic identities and emissions](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#9-deterministic-identities-and-emissions); +- [§10 faults and envelope disposition](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#10-faults-and-envelope-disposition); +- [§10.1 engine faults](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#101-engine-faults); +- [§10.2 contained runtime faults](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#102-contained-runtime-faults); +- [§10.3 domain failures](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#103-domain-failures); +- [§11 plugins and hosting](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#11-plugins-and-hosting); +- [§11.1 queue plugins](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#111-queue-plugins); +- [§11.2 timer extensions](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#112-timer-extensions); +- [§11.3 external effects](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#113-external-effects); +- [§11.4 hosting profiles](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#114-hosting-profiles); +- [§12 inspection and visualization](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#12-inspection-and-visualization); +- [§13 deliberately unsupported in format 1](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#13-deliberately-unsupported-in-format-1). Released conformance examples: -- [16 timer extension](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/16-timer-extension) -- [18 domain failure](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/18-domain-failure) -- [19 public event contract](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/19-public-event-contract) -- [20 invalid public correlation](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/20-invalid-public-correlation) -- [46 root boundary validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/46-root-boundary-validation) -- [50 root fault terminal aggregate](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/50-root-fault-terminal-aggregate) -- [67 bundle/state binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/67-bundle-state-binding) -- [75 root initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/75-root-initialization-fault) -- [76 invalid creation Unicode](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/76-invalid-create-unicode) -- [77 invalid dispatch Unicode](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/77-invalid-dispatch-unicode) -- [85 initialization emission rollback](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/85-initialization-emission-rollback) -- [88 reserved payload validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/88-reserved-payload-validation) -- [89 non-finite creation binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/89-nonfinite-creation-binding) -- [90 host numeric normalization](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/90-host-numeric-normalization) -- [92 faulted-root/component precedence](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/92-faulted-root-component-precedence) -- [93 optional correlation](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/93-optional-correlation) +- [16 timer extension](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/16-timer-extension) +- [18 domain failure](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/18-domain-failure) +- [19 public event contract](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/19-public-event-contract) +- [20 invalid public correlation](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/20-invalid-public-correlation) +- [46 root boundary validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/46-root-boundary-validation) +- [50 root fault terminal aggregate](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/50-root-fault-terminal-aggregate) +- [67 bundle/state binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/67-bundle-state-binding) +- [75 root initialization fault](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/75-root-initialization-fault) +- [76 invalid creation Unicode](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/76-invalid-create-unicode) +- [77 invalid dispatch Unicode](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/77-invalid-dispatch-unicode) +- [85 initialization emission rollback](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/85-initialization-emission-rollback) +- [88 reserved payload validation](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/88-reserved-payload-validation) +- [89 non-finite creation binding](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/89-nonfinite-creation-binding) +- [90 host numeric normalization](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/90-host-numeric-normalization) +- [92 faulted-root/component precedence](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/92-faulted-root-component-precedence) +- [93 optional correlation](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/93-optional-correlation) diff --git a/docs/guides/execution-checkpoint-hosting.md b/docs/guides/execution-checkpoint-hosting.md new file mode 100644 index 0000000..26f521c --- /dev/null +++ b/docs/guides/execution-checkpoint-hosting.md @@ -0,0 +1,331 @@ +# Durable execution checkpoints + +The pure Determa State engine handles one delivery and returns the next aggregate. In +many applications that is exactly the right boundary: the application already owns its +database transaction and queue. Determa State 0.2.0 also provides an optional +`ExecutionHost` for applications that want a portable, durable inbox, state, receipts, +and outbox around that same pure core. + +An execution checkpoint belongs to one root ownership aggregate. It contains the +current serialized aggregate (or a terminal tombstone), accepted deliveries, operation +receipts, outbox records, retention evidence, and migration audit. A delivery that the +host reports as accepted is therefore not memory-only. + +The checkpoint does not contain database credentials, locks, leases, broker +acknowledgement tokens, running network requests, timers, or plugin configuration. +Those remain host resources. An external effect intent can be serialized before an +adapter attempts it; the adapter's active HTTP call cannot. Stop accepting work, let +active adapter calls finish or record them as ambiguous according to host policy, and +the checkpoint remains portable and restartable. + +## 1. Create the project + +```sh +mkdir determa-checkpoint-tutorial +cd determa-checkpoint-tutorial +python -m venv .venv +. .venv/bin/activate +python -m pip install determa-state==0.2.0 +``` + +This tutorial uses SQLite so that stopping the Python process does not erase accepted +work. The same host accepts an `ExecutionStore` object directly, so an application can +instead inject memory, file, PostgreSQL, or its own adapter. + +## 2. Define a workflow + + +```yaml +format: 1 +namespace: tutorial.checkpoint +events: + increment: + direction: input + payload: + request_id: { type: string, required: true } + amount: { type: int, required: true } + count_changed: + direction: output + payload: + count: { type: int, required: true } +machines: + - machine_id: counter + version: 1 + root: + variables: + count: { type: int, init: 0 } + on_events: + increment: + action: + - assign: { count: "count + event.payload.amount" } + - send: + event: count_changed + to: { external: true } + correlation_id: event.payload.request_id + payload: { count: count } +``` + +Save this as `counter.yaml`. The action produces an external **intent**. Committing the +intent to the checkpoint outbox does not claim that another system received it. + +Only current format-1 bundles are accepted. A current document must contain numeric +`format: 1`, a namespace, and a `machines` list. Determa does not infer the grammar from +an old document's shape or silently upgrade it. + +## 3. Register and select storage + +The registry starts empty. Bundled adapters are registered through the same public +operation used by third-party adapters; no scheme receives special treatment in the +host: + +```python +registry = ds.ExecutionStoreRegistry() +ds.register_bundled_execution_stores(registry, include_postgresql=False) +store = registry.resolve( + "sqlite:///absolute/path/state.db" + "?replay_retention=permanent&outbox_retention=strict" +) +store.setup_schema() +``` + +URI resolution selects a factory by its lowercase scheme. The factory owns the rest of +the URI and its configuration. Applications that do not need discovery can instantiate +or implement `ExecutionStore` directly. + +Storage setup is always explicit. Memory is ephemeral; file storage is restart +persistent; SQLite advertises durable single-writer behavior after validating its +schema and settings; PostgreSQL can provide concurrent compare-and-swap and a shared +application transaction. Required capabilities fail closed instead of silently +downgrading a requested guarantee. + +## 4. Accept, restart, and process one event + + +```python +from pathlib import Path +import sys + +import determa.state as ds + + +def open_host(machine_path, database_path): + bundle = ds.load_bundle(Path(machine_path).read_text()) + resolver = ds.MemoryArtifactResolver( + definitions={bundle.fingerprint: bundle} + ) + registry = ds.ExecutionStoreRegistry() + ds.register_bundled_execution_stores( + registry, include_postgresql=False + ) + uri = ( + f"sqlite://{Path(database_path).resolve()}" + "?replay_retention=permanent&outbox_retention=strict" + ) + store = registry.resolve(uri) + store.setup_schema() + required = { + ds.DURABLE_SINGLE_WRITER, + ds.ROOT_IDENTITY_RETENTION, + ds.PERMANENT_RECEIPT_RETENTION, + ds.PERMANENT_OUTBOX_TERMINAL_RETENTION, + } + host = ds.ExecutionHost( + store, + resolver, + required_capabilities=required, + profile="exactly_once_committed_processing", + ) + return bundle, host + + +def delivery(checkpoint): + aggregate = checkpoint["root_record"]["aggregate_state"] + return { + "root_instance_id": checkpoint["root_instance_id"], + "delivery_mode": "input", + "origin": {"kind": "host_input"}, + "envelope": ds.portable_envelope( + "increment", + "counter:increment:1", + { + "root": { + "root_instance_id": checkpoint["root_instance_id"], + "root_runtime_id": aggregate["root_runtime_id"], + } + }, + {"request_id": "request-1", "amount": 4}, + ), + } + + +machine_path, database_path = sys.argv[1:] +database = Path(database_path) +if database.exists(): + database.unlink() + +bundle, host = open_host(machine_path, database) +created = host.create( + bundle, + machine_id="counter", + root_instance_id="counter-1", + creation_id="counter-1:create", + bindings={}, +) +assert created["result"] == "committed" + +checkpoint = host.read_checkpoint("counter-1").document +candidate = delivery(checkpoint) +pending = host.accept_delivery( + "counter-1", + candidate, + expected_revision=checkpoint["revision"], + expected_checkpoint_digest=checkpoint["execution_checkpoint_digest"], +) +assert pending["result"] == "pending" + +# Recreate the store and host to prove the accepted event was not process memory. +bundle, restarted = open_host(machine_path, database) +accepted = restarted.read_checkpoint("counter-1").document +assert len(accepted["pending_deliveries"]) == 1 +committed = restarted.process_pending_delivery( + "counter-1", + candidate, + expected_revision=accepted["revision"], + expected_checkpoint_digest=accepted["execution_checkpoint_digest"], +) +assert committed["result"] == "committed" +assert committed["receipt"]["outcome"]["disposition"] == "handled" + +final = restarted.read_checkpoint("counter-1") +assert final.aggregate is not None +root = final.aggregate.state["runtimes"][ + final.aggregate.state["root_runtime_id"] +] +assert root["scopes"]["root"]["count"] == 4 +assert final.document["revision"] == "2" +assert len(final.document["pending_deliveries"]) == 0 +assert len(final.document["operation_receipts"]) == 2 +assert len(final.document["pending_outbox_intents"]) == 1 + +replay = restarted.accept_delivery( + "counter-1", + candidate, + expected_revision=checkpoint["revision"], + expected_checkpoint_digest=checkpoint["execution_checkpoint_digest"], +) +assert replay == committed +print( + "revision=2; count=4; receipts=2; " + "pending=0; outbox=1; replay=committed" +) +``` + +Save it as `app.py`, then run: + +```sh +python app.py counter.yaml state.db +``` + +Expected output: + +```text +revision=2; count=4; receipts=2; pending=0; outbox=1; replay=committed +``` + +Creation commits revision `0`. Accepting the event commits revision `1` with the full +envelope in `pending_deliveries`. Processing it commits revision `2`, consumes the +pending item, adds a durable receipt, updates the aggregate, and adds the complete +external intent to the outbox. Re-presenting the same event ID and bytes returns the +committed receipt without calling the engine again. Reusing the ID with different +content is a conflict. + +## 5. Choose the foreground boundary deliberately + +`accept_delivery` followed by `process_pending_delivery` is useful when acceptance and +execution happen at different times. `foreground_process_delivery` performs both in +one checkpoint transaction. Both paths have the same committed receipt and replay +rules. + +An application may also skip `ExecutionHost` and call the pure `create`, `dispatch`, +serialization, and migration functions inside its own transaction. The optional host +is a library layer, not a daemon and not a required executable. + +Every mutation uses the expected checkpoint revision and digest. A stale writer fails +instead of replacing newer work. PostgreSQL applications can compose one checkpoint +mutation with their own rows in a shared serializable transaction. SQLite provides a +durable single-writer profile, not cross-process distributed ACID. + +## 6. Treat the outbox as unfinished work + +External output records move through an explicit lifecycle. A delivery worker may +claim an intent, record success, record a known failure, or record an ambiguous result +when it cannot know whether the remote side accepted the request. Strict retention +keeps terminal records; compact retention keeps identity evidence while allowing full +terminal payloads to be removed. + +Exactly-once **committed processing** means an accepted event ID is committed once +within one authorized store scope. It does not mean an HTTP request, broker publish, or +payment happens exactly once. External delivery still needs `effect_id` idempotency and +reconciliation. Broker acknowledgement happens only after the checkpoint transaction +commits. + +A checkpoint can remain dormant indefinitely because no hidden engine worker must be +kept alive. Before pausing a host, stop new claims and account for already active +adapter calls. The portable checkpoint records pending and ambiguous intent state, not +the transient call stack of an adapter. + +## 7. Retention, terminal roots, and migration + +Permanent receipt retention preserves replay decisions and root non-reuse. Bounded +retention deliberately weakens those guarantees after its declared horizon. Completed +or faulted roots can be replaced by a tombstone only after pending delivery and outbox +requirements are satisfied; a tombstoned root identity cannot be recreated. + +Definition migration remains the pure, explicit process taught in the +[persistence and migration tutorial](persistence-and-migration.md). A checkpoint host +can apply a keyed migration operation and retain its receipt and ordered audit in the +same transaction. It never guesses that the latest YAML is compatible. + +Store scopes are host-selected trust boundaries. Scope identity and authorization are +not fields in portable machine, aggregate, event, intent, or checkpoint bytes. Equal +portable identities may exist independently in two correctly isolated scopes. + +## 8. What 0.2.0 deliberately does not provide + +The released checkpoint host does not provide a broker, delivery daemon, socket +service, remote client, native effect handler, timer scheduler, backup/relocation +protocol, or candidate-enabledness API. It also does not make active adapter calls +serializable. Those are separate host concerns or future work, not implied by this +tutorial. + +Timer durability is reserved for future design. Today a machine can emit a declared +scheduling intent and later accept a declared event from an external scheduler, as +shown in [effects, faults, and hosting](effects-faults-hosting.md). No timer record is +part of execution-checkpoint schema version 1. + +## Normative coverage + +This guide explains the released execution-checkpoint contract: + +- [§17 portable execution checkpoints and hosting adapters](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#17-portable-execution-checkpoints-and-hosting-adapters) +- [§17.1 scope and compatibility](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#171-scope-and-compatibility) +- [§17.2 closed checkpoint artifact](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#172-closed-checkpoint-artifact) +- [§17.3 durable operation receipts and replay](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#173-durable-operation-receipts-and-replay) +- [§17.4 unified pending deliveries](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#174-unified-pending-deliveries) +- [§17.5 maintenance-migration operations](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#175-maintenance-migration-operations) +- [§17.6 durable outbox lifecycle](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#176-durable-outbox-lifecycle) +- [§17.7 migration audit and canonical ordering](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#177-migration-audit-and-canonical-ordering) +- [§17.8 replay retention and root lifecycle](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#178-replay-retention-and-root-lifecycle) +- [§17.9 transaction and concurrency ordering](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#179-transaction-and-concurrency-ordering) +- [§17.10 execution-store registration and resolution](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1710-execution-store-registration-and-resolution) +- [§17.11 execution-store capabilities and composed host profiles](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1711-execution-store-capabilities-and-composed-host-profiles) +- [§17.12 exact guarantee boundary](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1712-exact-guarantee-boundary) +- [§17.13 cluster checkpoint composition](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1713-cluster-checkpoint-composition) +- [§17.14 future timer durability](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1714-future-timer-durability) + +The released optional profile groups its low-level vectors into three user-facing +scenarios: + +- [checkpoint-01 delivery lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/profiles/execution-checkpoint/checkpoint-01-delivery-lifecycle) +- [checkpoint-02 outbox lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/profiles/execution-checkpoint/checkpoint-02-outbox-lifecycle) +- [checkpoint-03 retention and root lifecycle](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/profiles/execution-checkpoint/checkpoint-03-retention-and-root-lifecycle) diff --git a/docs/guides/persistence-and-migration.md b/docs/guides/persistence-and-migration.md index 73af142..4f09496 100644 --- a/docs/guides/persistence-and-migration.md +++ b/docs/guides/persistence-and-migration.md @@ -5,8 +5,8 @@ It stores a portable aggregate, ignores a duplicate input, records an output int restarts between commands, and lazily upgrades a live order from machine version 1 to version 2. -The tutorial uses Determa State 0.1.0 and numeric `format: 1`. The normative rules are -in [specification section 16](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#16-portable-persistence-and-definition-migration). +The tutorial uses Determa State 0.2.0 and numeric `format: 1`. The normative rules are +in [specification section 16](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#16-portable-persistence-and-definition-migration). ## 1. Create an empty project @@ -15,7 +15,7 @@ mkdir determa-persistence-tutorial cd determa-persistence-tutorial python3 -m venv .venv . .venv/bin/activate -python -m pip install determa-state==0.1.0 +python -m pip install determa-state==0.2.0 mkdir -p rust/src ``` @@ -220,7 +220,7 @@ The host stores definitions and descriptors once under their content digests. An aggregate row stores only canonical aggregate bytes. One SQLite transaction owns the inbox decision, aggregate replacement, ordered outbox inserts, and migration audit. This implements the -[lazy transactional host order in specification §16.11](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1611-lazy-transactional-host-ordering). +[lazy transactional host order in specification §16.11](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1611-lazy-transactional-host-ordering). ```python @@ -688,12 +688,12 @@ database concern rather than a Rust engine result. ```toml [package] name = "determa-persistence-migration-tutorial" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = false [dependencies] -determa-state = "=0.1.0" +determa-state = "=0.2.0" serde_json = "1" ``` @@ -905,14 +905,14 @@ This focused example covers round-trip encoding, definition resolution, unchange restoration, explicit active-state remapping, deleted-state totality, counter and identity preservation, rollback, migration plus dispatch, and the host transaction order demonstrated by conformance cases -[94](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/94-aggregate-wire-round-trip), -[96](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/96-definition-resolution), -[98](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/98-unchanged-definition-resume), -[100](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/100-explicit-active-state-remap), -[101](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/101-deleted-active-state-totality), -[106](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/106-counter-and-identity-preservation), -[108](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/108-migration-retry-and-rollback), and -[109](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/109-migration-then-dispatch). +[94](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/94-aggregate-wire-round-trip), +[96](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/96-definition-resolution), +[98](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/98-unchanged-definition-resume), +[100](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/100-explicit-active-state-remap), +[101](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/101-deleted-active-state-totality), +[106](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/106-counter-and-identity-preservation), +[108](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/108-migration-retry-and-rollback), and +[109](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/109-migration-then-dispatch). Continue with the [persistence and migration reference lab](persistence-migration-reference.md) for diff --git a/docs/guides/persistence-migration-reference.md b/docs/guides/persistence-migration-reference.md index f83c35e..6be96d1 100644 --- a/docs/guides/persistence-migration-reference.md +++ b/docs/guides/persistence-migration-reference.md @@ -2,11 +2,11 @@ The [SQLite tutorial](persistence-and-migration.md) is the shortest path from an empty directory to a durable application. This lab is the next step. It executes every -portable persistence and migration vector released with Determa State 0.1.0 and then +portable persistence and migration vector released with Determa State 0.2.0 and then inspects the fixtures so you can see which property each group protects. The normative contract is -[specification section 16](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#16-portable-persistence-and-definition-migration). +[specification section 16](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#16-portable-persistence-and-definition-migration). This chapter explains that contract; it does not add new behavior. ## 1. Check prerequisites @@ -15,7 +15,7 @@ You need: - Python 3.11 or newer; - Git and network access to clone the four immutable release sources; and -- a Rust toolchain compatible with Determa State 0.1.0. The released repositories +- a Rust toolchain compatible with Determa State 0.2.0. The released repositories validate with Rust 1.95. Check them before creating files: @@ -37,12 +37,12 @@ cd determa-persistence-reference python3 -m venv .venv . .venv/bin/activate python -m pip install \ - determa-state==0.1.0 pytest==8.4.2 ruamel.yaml==0.19.1 + determa-state==0.2.0 pytest==8.4.2 ruamel.yaml==0.19.1 ``` Create the following script. It downloads the immutable released sources, checks their exact commits, runs the Python package's persistence vectors against the installed -0.1.0 package, runs the Rust 0.1.0 crate's matching vectors, and finally runs the +0.2.0 package, runs the Rust 0.2.0 crate's matching vectors, and finally runs the property inspector created in the next section. @@ -93,7 +93,7 @@ chmod +x run.sh The two engine harnesses compare exact success bytes, aggregate values, audit arrays, resolver contents, emissions, dispositions, stable failure codes, and caller ownership -for 105 vectors in cases 94 through 115. This is deliberately stronger than a smoke +for 108 vectors in cases 94 through 115. This is deliberately stronger than a smoke test. ## 3. Inspect what the vectors prove @@ -157,13 +157,17 @@ def variable_values(path: Path, suffix: str): directories = [case(number) for number in range(94, 116)] assert len(directories) == 22 -assert sum(len(vectors(number)) for number in range(94, 116)) == 105 +assert sum(len(vectors(number)) for number in range(94, 116)) == 108 -# Every pure failure returns one exact code and leaves the source artifact caller-owned. +# Aggregate operations leave the source artifact caller-owned on every pure failure. +# Descriptor-only decoding has no aggregate argument to return. for number in range(94, 116): for item in vectors(number): expected = item["expect"] if expected["result"] == "failure": + if item["operation"] == "decode_selected_migration_descriptor": + assert set(expected) == {"result", "code"} + continue assert set(expected) == { "result", "code", @@ -192,6 +196,7 @@ assert wire_documents == { "malformed-float.json": "invalid_aggregate_state", "unknown-field.json": "invalid_aggregate_state", "unsupported-format.json": "unsupported_aggregate_state_format", + "legacy-0.0.6-snapshot.json": "unsupported_aggregate_state_format", "unsupported-schema-version.json": ( "unsupported_aggregate_state_schema_version" ), @@ -313,6 +318,13 @@ failure_codes = { item["expect"]["code"] for item in vectors(113) } +legacy_descriptor = vector( + 113, "legacy_snapshot_rejected_by_selected_descriptor_decoder" +) +assert legacy_descriptor["expect"] == { + "result": "failure", + "code": "unsupported_migration_descriptor_format", +} assert failure_codes == { "invalid_migration_request", "migration_transform_fault", @@ -380,7 +392,7 @@ assert activation == ( ) print( - "105 vectors; package=trusted transport; transforms=total and local; " + "108 vectors; package=trusted transport; transforms=total and local; " "terminal=preserved; limits=deterministic; decimals=lossless" ) ``` @@ -394,99 +406,99 @@ Run it directly whenever you want the shorter, explanatory report: Expected output: ```text -105 vectors; package=trusted transport; transforms=total and local; terminal=preserved; limits=deterministic; decimals=lossless +108 vectors; package=trusted transport; transforms=total and local; terminal=preserved; limits=deterministic; decimals=lossless ``` ## 4. Know the three independent identities -[Section 16.1](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#161-independent-artifact-identities) +[Section 16.1](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#161-independent-artifact-identities) separates the machine definition, aggregate, and migration descriptor. A definition fingerprint identifies normalized machine content. An aggregate digest identifies one complete ownership tree at one point in time. A descriptor digest identifies one immutable, declarative migration step. -[Canonical encoding in §16.2](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#162-canonical-values-and-aggregate-encoding) +[Canonical encoding in §16.2](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#162-canonical-values-and-aggregate-encoding) uses RFC 8785 JSON and tagged values. Integers and identity counters are canonical decimal strings, which is why the lab checks values above JavaScript's safe integer limit rather than accepting rounded numbers. Malformed relations, unknown fields, unsupported discriminators, and unsupported schema versions fail with exact codes; the input bytes remain caller-owned. See -[case 95](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/95-aggregate-wire-rejection) +[case 95](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/95-aggregate-wire-rejection) and -[case 115](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/115-target-identity-decimal-projections). +[case 115](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/115-target-identity-decimal-projections). -[The complete aggregate in §16.3](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#163-complete-root-ownership-aggregate) +[The complete aggregate in §16.3](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#163-complete-root-ownership-aggregate) contains the root, components, owned spawned descendants, variables, history, counters, faults, and nominal references. It is one transaction boundary. Do not store or advance an owned child independently. ## 5. Bind immutable identity to an approved definition -[Section 16.4](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#164-immutable-identity-and-mutable-definition-binding) +[Section 16.4](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#164-immutable-identity-and-mutable-definition-binding) keeps creation and runtime identity immutable while allowing `current_definition` to advance. -[Section 16.5](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#165-content-addressed-definition-registry) +[Section 16.5](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#165-content-addressed-definition-registry) requires the resolver to return the exact hash-valid, trusted artifact requested. -[Section 16.6](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#166-aggregate-shape-fingerprint) +[Section 16.6](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#166-aggregate-shape-fingerprint) distinguishes a compatible definition-only update from a state-bearing transform. -[Case 99](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/99-compatible-definition-upgrade) +[Case 99](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/99-compatible-definition-upgrade) shows the compatible path: runtime identity and logical state stay fixed while the definition binding, aggregate digest, migration sequence, and audit advance. ## 6. Treat migration as closed data -[Descriptors in §16.7](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#167-immutable-declarative-migration-descriptors) +[Descriptors in §16.7](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#167-immutable-declarative-migration-descriptors) are immutable data, not code. Their restricted CEL transforms cannot call Python, Rust, JavaScript, shell commands, plugins, files, clocks, networks, credentials, or author actions. -[The route algorithm in §16.8](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#168-exact-route-and-migration-algorithm) +[The route algorithm in §16.8](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#168-exact-route-and-migration-algorithm) uses exactly the ordered digest list supplied by deployment. It does not search for a newer or shorter route. Every intermediate candidate is validated in memory and only the final result may commit. -[Case 107](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/107-migration-chain) +[Case 107](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/107-migration-chain) checks exact no-op bytes, a two-hop audit, wrong ordering, missing routes, and cycles. -[The total transform matrix in §16.9](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#169-total-transform-matrix) +[The total transform matrix in §16.9](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#169-total-transform-matrix) requires every retained source occurrence and required target occurrence to be accounted for. The vectors demonstrate: - variable copy, transform, initialize, and destructive drop in - [case 102](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/102-variable-migration); + [case 102](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/102-variable-migration); - null, deep, and shallow history in - [case 103](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/103-history-migration); + [case 103](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/103-history-migration); - component placement and activation identity in - [case 104](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/104-component-migration); + [case 104](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/104-component-migration); - owned-runtime binding, lifetime holder, and nominal reference preservation in - [case 105](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/105-owned-runtime-migration); and + [case 105](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/105-owned-runtime-migration); and - independent rule application for repeated runtimes and activations in - [case 114](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/114-occurrence-local-transform-binding). + [case 114](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/114-occurrence-local-transform-binding). Rules read one immutable pre-descriptor snapshot. They cannot combine values from different runtimes or observe another rule's output. ## 7. Keep terminal aggregates terminal -[Section 16.10](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1610-terminal-aggregates) +[Section 16.10](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1610-terminal-aggregates) requires `maintenance_mode: true` for a non-empty terminal migration. The descriptor must preserve the matching terminal policy. A completed aggregate remains completed; a faulted aggregate preserves its diagnostic tree and fault anchors. Neither migration reactivates a runtime or emits an event. -[Case 110](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/110-completed-terminal-migration) +[Case 110](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/110-completed-terminal-migration) checks the completed path. -[Case 111](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/111-faulted-terminal-migration) +[Case 111](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/111-faulted-terminal-migration) checks fault preservation and policy rejection. ## 8. Separate pure failures from host quarantine The SQLite tutorial implements -[the transactional ordering in §16.11](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1611-lazy-transactional-host-ordering): +[the transactional ordering in §16.11](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1611-lazy-transactional-host-ordering): resolve immutable artifacts before the transaction, lock aggregate and inbox, migrate and dispatch once, then commit aggregate, inbox, outbox, and audit together. -[Section 16.12](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1612-failure-rollback-quarantine-and-audit) +[Section 16.12](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1612-failure-rollback-quarantine-and-audit) separates two layers: - the pure engine failure is only `{code}` and leaves the exact aggregate bytes with @@ -496,18 +508,18 @@ separates two layers: Installing a corrected trusted route may release the blocked item. It does not erase the failure audit. This is not an engine fault, dead letter, or aggregate status. -[Case 113](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/113-migration-failure-completeness) +[Case 113](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/113-migration-failure-completeness) checks the closed failure surface; the SQLite guide checks the database transaction. ## 9. Move aggregates without inventing imports -[Package transport in §16.13](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1613-package-transport) +[Package transport in §16.13](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1613-package-transport) is an archive or transfer envelope containing one aggregate plus optional definition and descriptor attachments. Attachments must reproduce their digests, satisfy all cross-references, and seed a resolver with put-if-absent semantics. They never override an existing digest and are not part of the aggregate digest. -[Case 97](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/97-aggregate-package-attachments) +[Case 97](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/97-aggregate-package-attachments) checks integrity, duplicate attachments, unsupported package versions, resolver seeding, idempotency, and collision refusal. This transport does **not** enable package imports in machine YAML. Portable package imports remain unsupported format-1 @@ -515,12 +527,12 @@ semantics. ## 10. Set limits before loading untrusted artifacts -[Section 16.14](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md#1614-security-and-resource-limits) +[Section 16.14](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md#1614-security-and-resource-limits) requires digest checks, pinned trust, retained referenced definitions, and configurable limits for aggregate and artifact size, JSON shape, runtime/state/value counts, route and rule counts, and migration CEL work. -[Case 112](https://github.com/fruwehq/determa-state-conformance/tree/v0.1.0/conformance/core/112-migration-security-limits) +[Case 112](https://github.com/fruwehq/determa-state-conformance/tree/v0.2.0/conformance/core/112-migration-security-limits) proves the minimum supported floors succeed and every lower configured dimension fails with `migration_resource_limit_exceeded`. Understated descriptor requirements fail; the engine never truncates a transform. Every failed vector returns no candidate or diff --git a/docs/index.md b/docs/index.md index 5a132f6..b96b1e1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ Determa State runs the same state machine definition consistently across languag You define behavior once in YAML or JSON, then use a foreground engine call to create and advance a machine. -This tutorial targets **Determa State 0.1.0** and numeric **`format: 1`**. +This tutorial targets **Determa State 0.2.0** and numeric **`format: 1`**. This site owns the manual and progressive tutorial. Independent, fully working real-world applications live in @@ -38,6 +38,7 @@ explains public effect intents, correlation, deterministic results, terminal sta and the boundary between the portable core and host infrastructure. Finish the released format-1 progression with the +[durable execution-checkpoint tutorial](guides/execution-checkpoint-hosting.md) and [SQLite persistence and migration tutorial](guides/persistence-and-migration.md), then use the [advanced persistence reference lab](guides/persistence-migration-reference.md) for packages, complete transforms, terminal maintenance, deterministic failure @@ -52,4 +53,4 @@ brokers, and schedulers belong to the host around that core. The [coverage status](reference/coverage.md) maps every released specification section and core case to its guide or a specific non-user-facing classification. Normative details always come from the -[v0.1.0 specification](https://github.com/fruwehq/determa-state-spec/blob/v0.1.0/SPEC.md). +[v0.2.0 specification](https://github.com/fruwehq/determa-state-spec/blob/v0.2.0/SPEC.md). diff --git a/docs/reference/coverage.md b/docs/reference/coverage.md index 1acd8d5..5b539d2 100644 --- a/docs/reference/coverage.md +++ b/docs/reference/coverage.md @@ -3,8 +3,9 @@ [`coverage.yaml`](https://github.com/fruwehq/determa-state-docs/blob/main/coverage.yaml) is the machine-readable source of truth for tutorial coverage. -It inventories every normative section and every actual core conformance case at the -pinned Determa State 0.1.0 revisions. +It inventories every normative section, every actual core conformance case, and every +released execution-checkpoint profile case directory at the pinned Determa State 0.2.0 +revisions. Each entry is: @@ -12,8 +13,9 @@ Each entry is: - **non-user-facing** when it is specification or test-suite machinery rather than a behavior to teach. -Repository validation compares the matrix with the pinned specification headings and -conformance case directories. Missing, stale, or duplicate entries fail the build. +Repository validation compares the matrix with the pinned specification headings, +core case directories, and execution-checkpoint profile case directories. Missing, +stale, or duplicate entries fail the build. The current tutorial covers the first guarded foreground machine, [core statechart structure and control flow](../guides/core-statecharts.md), the @@ -25,10 +27,12 @@ adds the portable aggregate, content-addressed definition registry, SQLite inbox/state/outbox transaction, deterministic quarantine, deleted-state failure, and explicit lazy remap. The [persistence reference lab](../guides/persistence-migration-reference.md) executes all -105 released Python and Rust persistence vectors and teaches package transport, +108 released Python and Rust persistence vectors and teaches package transport, variable/history/component/owned-runtime transforms, exact multi-descriptor routes, terminal maintenance migration, failure completeness, resource limits, occurrence-local binding, and large decimal identities. +The [durable checkpoint host](../guides/execution-checkpoint-hosting.md) covers all +three released profile scenarios and executes the complete profile in both engines. There are no planned entries. Aggregate package transport is covered; portable package imports in machine definitions remain unsupported. diff --git a/mkdocs.yml b/mkdocs.yml index 59b0ea2..6ea1497 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,6 +54,7 @@ nav: - Components and spawning: guides/components-and-spawning.md - Effects, faults, and hosting: guides/effects-faults-hosting.md - Persistence and migration: + - Durable checkpoint host: guides/execution-checkpoint-hosting.md - SQLite tutorial: guides/persistence-and-migration.md - Reference lab: guides/persistence-migration-reference.md - Reference: diff --git a/requirements.txt b/requirements.txt index 3b14bfa..dd715ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -determa-state==0.1.0 +determa-state==0.2.0 jsonschema==4.26.0 markdown-it-py==4.2.0 mkdocs==1.6.1 diff --git a/scripts/check_latest.py b/scripts/check_latest.py index ac1dc55..4a0f89a 100644 --- a/scripts/check_latest.py +++ b/scripts/check_latest.py @@ -69,7 +69,11 @@ def main() -> None: print(f"{name}: v{lock['state_version']}") planned_issues: dict[str, tuple[str, str, int]] = {} - for group in ("specification", "conformance"): + for group in ( + "specification", + "conformance", + "execution_checkpoint_profile", + ): for entry in coverage[group]: if entry["status"] != "planned": continue diff --git a/scripts/validate.py b/scripts/validate.py index 04cdf09..8b1c516 100644 --- a/scripts/validate.py +++ b/scripts/validate.py @@ -30,7 +30,7 @@ ) CONFORMANCE_CASE_LINK = re.compile( r"https://github\.com/fruwehq/determa-state-conformance/tree/" - r"v([^/]+)/conformance/core/([0-9]{2}-[A-Za-z0-9-]+)" + r"v([^/]+)/conformance/core/([0-9]+-[A-Za-z0-9-]+)" ) CORE_STATECHARTS_CHAPTER = "docs/guides/core-statecharts.md" CORE_STATECHARTS_SPECIFICATION_SECTIONS = ( @@ -79,6 +79,7 @@ "62-parsed-value-model", "63-entry-stop-interruption", "84-choice-stop-chain", + "116-legacy-format-policy", ) LANGUAGE_BY_SUFFIX = { ".json": "json", @@ -107,6 +108,23 @@ "16.13", "16.14", }, + "docs/guides/execution-checkpoint-hosting.md": { + "17", + "17.1", + "17.2", + "17.3", + "17.4", + "17.5", + "17.6", + "17.7", + "17.8", + "17.9", + "17.10", + "17.11", + "17.12", + "17.13", + "17.14", + }, } PERSISTENCE_MIGRATION_CASES_BY_CHAPTER = { "docs/guides/persistence-and-migration.md": { @@ -152,6 +170,21 @@ "16.12": "1612-failure-rollback-quarantine-and-audit", "16.13": "1613-package-transport", "16.14": "1614-security-and-resource-limits", + "17": "17-portable-execution-checkpoints-and-hosting-adapters", + "17.1": "171-scope-and-compatibility", + "17.2": "172-closed-checkpoint-artifact", + "17.3": "173-durable-operation-receipts-and-replay", + "17.4": "174-unified-pending-deliveries", + "17.5": "175-maintenance-migration-operations", + "17.6": "176-durable-outbox-lifecycle", + "17.7": "177-migration-audit-and-canonical-ordering", + "17.8": "178-replay-retention-and-root-lifecycle", + "17.9": "179-transaction-and-concurrency-ordering", + "17.10": "1710-execution-store-registration-and-resolution", + "17.11": "1711-execution-store-capabilities-and-composed-host-profiles", + "17.12": "1712-exact-guarantee-boundary", + "17.13": "1713-cluster-checkpoint-composition", + "17.14": "1714-future-timer-durability", } COMPONENTS_AND_SPAWNING_SPECIFICATION = {"7", "7.1", "7.2", "7.3"} COMPONENTS_AND_SPAWNING_CASES = { @@ -253,6 +286,7 @@ "12": "12-inspection-and-visualization", "13": "13-deliberately-unsupported-in-format-1", } +EXECUTION_CHECKPOINT_CHAPTER = "docs/guides/execution-checkpoint-hosting.md" def yaml_loader() -> YAML: @@ -412,6 +446,19 @@ def conformance_cases(conformance: Path) -> list[str]: ) +def execution_checkpoint_profile_cases(conformance: Path) -> list[str]: + profile = ( + conformance + / "conformance" + / "profiles" + / "execution-checkpoint" + ) + return sorted( + (path.name for path in profile.iterdir() if path.is_dir()), + key=lambda value: value.encode("utf-8"), + ) + + def check_dispositions( entries: Iterable[object], key: str, @@ -454,6 +501,7 @@ def check_coverage( ) -> None: spec_sections = specification_sections(specification) cases = conformance_cases(conformance) + execution_checkpoint_cases = execution_checkpoint_profile_cases(conformance) check_dispositions( require_list(coverage.get("specification"), "specification coverage"), "id", @@ -466,16 +514,69 @@ def check_coverage( cases, "conformance", ) + check_dispositions( + require_list( + coverage.get("execution_checkpoint_profile"), + "execution-checkpoint profile coverage", + ), + "case", + execution_checkpoint_cases, + "execution-checkpoint profile", + ) planned = [ f"{label}:{require_map(entry, f'{label} entry').get(key)}" - for label, key in (("specification", "id"), ("conformance", "case")) + for label, key in ( + ("specification", "id"), + ("conformance", "case"), + ("execution_checkpoint_profile", "case"), + ) for entry in require_list(coverage.get(label), f"{label} coverage") if require_map(entry, f"{label} entry").get("status") == "planned" ] if planned: raise ValueError(f"released documentation still has planned coverage: {planned}") check_core_statecharts_coverage(coverage) - print(f"coverage: {len(spec_sections)} spec sections, {len(cases)} core cases") + print( + f"coverage: {len(spec_sections)} spec sections, {len(cases)} core cases, " + f"{len(execution_checkpoint_cases)} execution-checkpoint profile cases" + ) + + +def check_execution_checkpoint_profile_coverage( + coverage: dict[str, object], conformance: Path +) -> None: + cases = execution_checkpoint_profile_cases(conformance) + entries = { + require_map(entry, "execution-checkpoint profile entry")["case"]: require_map( + entry, "execution-checkpoint profile entry" + ) + for entry in require_list( + coverage.get("execution_checkpoint_profile"), + "execution-checkpoint profile coverage", + ) + } + chapter = (ROOT / EXECUTION_CHECKPOINT_CHAPTER).read_text() + state_version = coverage.get("state_version") + if not isinstance(state_version, str): + raise ValueError("coverage state_version must be a string") + for case in cases: + entry = entries[case] + if ( + entry.get("status") != "covered" + or entry.get("chapter") != EXECUTION_CHECKPOINT_CHAPTER + ): + raise ValueError( + f"execution-checkpoint profile case is not covered: {case}" + ) + url = ( + "https://github.com/fruwehq/determa-state-conformance/tree/" + f"v{state_version}/conformance/profiles/execution-checkpoint/{case}" + ) + if chapter.count(url) != 1: + raise ValueError( + "execution-checkpoint profile link must occur once: " f"{case}" + ) + print(f"execution-checkpoint coverage: {len(cases)} profile cases") def check_components_and_spawning_coverage(coverage: dict[str, object]) -> None: @@ -555,10 +656,13 @@ def check_cel_and_actions_coverage(coverage: dict[str, object]) -> None: f"actual={sorted(mapped_cases)}" ) chapter = (ROOT / chapter_path).read_text() + state_version = coverage.get("state_version") + if not isinstance(state_version, str): + raise ValueError("coverage state_version must be a string") for case in CEL_AND_ACTIONS_CASES: link = ( "https://github.com/fruwehq/determa-state-conformance/" - f"tree/v0.1.0/conformance/core/{case}" + f"tree/v{state_version}/conformance/core/{case}" ) if f"]({link})" not in chapter: raise ValueError(f"CEL/actions chapter does not link conformance {case}") @@ -1099,20 +1203,37 @@ def run_traces(destination: Path, conformance: Path) -> None: ) print("traces: Python host and Rust engine persistence paths passed") + checkpoint_root = destination / "checkpoint-tutorial" + checkpoint_output = run( + sys.executable, + str(checkpoint_root / "app.py"), + str(checkpoint_root / "counter.yaml"), + str(checkpoint_root / "state.db"), + ) + checkpoint_expected = ( + "revision=2; count=4; receipts=2; " + "pending=0; outbox=1; replay=committed" + ) + if checkpoint_output != checkpoint_expected: + raise ValueError( + f"execution checkpoint tutorial mismatch: {checkpoint_output!r}" + ) + print("execution checkpoint tutorial: durable accept, restart, and replay passed") + reference_output = run( sys.executable, str(destination / "persistence-reference" / "inspect_vectors.py"), str(conformance), ) reference_expected = ( - "105 vectors; package=trusted transport; transforms=total and local; " + "108 vectors; package=trusted transport; transforms=total and local; " "terminal=preserved; limits=deterministic; decimals=lossless" ) if reference_output != reference_expected: raise ValueError( f"persistence reference inspection mismatch: {reference_output!r}" ) - print("persistence reference: all 105 vector properties inspected") + print("persistence reference: all 108 vector properties inspected") def run_released_persistence_gates(paths: dict[str, Path]) -> None: @@ -1140,6 +1261,24 @@ def run_released_persistence_gates(paths: dict[str, Path]) -> None: cwd=ROOT, env=environment, ) + run( + sys.executable, + "-m", + "pytest", + str( + python + / "conformance" + / "test_conformance.py::test_execution_checkpoint_profile" + ), + str( + python + / "conformance" + / "test_conformance.py::test_execution_checkpoint_artifact" + ), + "-q", + cwd=ROOT, + env=environment, + ) rust_copy = ROOT / ".cache" / "rust-persistence-source" if rust_copy.exists(): @@ -1167,9 +1306,19 @@ def run_released_persistence_gates(paths: dict[str, Path]) -> None: "persistence_conformance", env=cargo_environment, ) + run( + "cargo", + "test", + "--quiet", + "--manifest-path", + str(rust_copy / "Cargo.toml"), + "--test", + "checkpoint_conformance", + env=cargo_environment, + ) print( - "released persistence gates: conformance artifacts and all 105 vectors " - "passed in Python and Rust" + "released persistence gates: all 108 persistence vectors and the complete " + "execution-checkpoint profile passed in Python and Rust" ) @@ -1194,6 +1343,7 @@ def main() -> None: check_cel_and_actions_coverage(coverage) check_effects_faults_hosting_coverage(coverage) check_persistence_migration_coverage(coverage) + check_execution_checkpoint_profile_coverage(coverage, paths["conformance"]) check_local_links() with tempfile.TemporaryDirectory(prefix="determa-examples-") as temporary: destination = Path(temporary) diff --git a/sources.lock.yaml b/sources.lock.yaml index 3c1b5bf..99cbb7a 100644 --- a/sources.lock.yaml +++ b/sources.lock.yaml @@ -1,22 +1,22 @@ -state_version: "0.1.0" +state_version: "0.2.0" repositories: specification: repository: fruwehq/determa-state-spec - tag: v0.1.0 - commit: c1635d74e6a216301a8986d37be8ce7e7111dfd7 + tag: v0.2.0 + commit: 7782671b56165a59caa61a65c29fefc63105ebf8 checkout: determa-state-spec conformance: repository: fruwehq/determa-state-conformance - tag: v0.1.0 - commit: 600523ca08c3b8a6ee790439a32dc4ce47f71b95 + tag: v0.2.0 + commit: d6a45d31614ee25de20476ed93f10e14997d882c checkout: determa-state-conformance python: repository: fruwehq/determa-state-python - tag: v0.1.0 - commit: 7b17d788b48049648e7e463aa3d35ba13dc1aa6e + tag: v0.2.0 + commit: bc4b5bc7fee746e15aec9082341e85da60918f6d checkout: determa-state-python rust: repository: fruwehq/determa-state-rust - tag: v0.1.0 - commit: d17480c8b281dcd17953f59afcf6b5d23ff44efd + tag: v0.2.0 + commit: 7cf09a9c063da19966eaa9663faf72ba8253a76c checkout: determa-state-rust