deterministic-scenario-engine 1.0.0__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deterministic_scenario_engine-1.0.0/src/deterministic_scenario_engine.egg-info → deterministic_scenario_engine-2.0.0}/PKG-INFO +24 -6
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/README.md +23 -5
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/api.md +36 -2
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/determinism.md +10 -0
- deterministic_scenario_engine-2.0.0/docs/phase2-architecture.md +315 -0
- deterministic_scenario_engine-2.0.0/docs/phase2-public-contract.md +120 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/quickstart.md +21 -1
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/reproducibility.md +8 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/security-and-non-goals.md +16 -3
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/testing-oracle.md +17 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/pyproject.toml +3 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0/src/deterministic_scenario_engine.egg-info}/PKG-INFO +24 -6
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/deterministic_scenario_engine.egg-info/SOURCES.txt +67 -1
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/deterministic_scenario_engine.egg-info/entry_points.txt +3 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/_version.py +4 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/batch/__init__.py +32 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/batch/canonical.py +39 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/batch/errors.py +57 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/batch/models.py +220 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/batch/runtime.py +248 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/cli/__init__.py +6 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/cli/__main__.py +6 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/cli/main.py +496 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/__init__.py +66 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/canonical.py +60 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/errors.py +67 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/models.py +107 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/parser.py +148 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/resolver.py +408 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/composition/runtime.py +71 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/__init__.py +20 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/compare.py +181 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/errors.py +23 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/models.py +130 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/render.py +33 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/diff/serialization.py +53 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/domain_packs/__init__.py +36 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/domain_packs/canonical.py +43 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/domain_packs/errors.py +23 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/domain_packs/models.py +152 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/domain_packs/registry.py +94 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/__init__.py +35 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/errors.py +27 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/explain.py +75 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/inspect.py +342 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/models.py +148 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/redaction.py +50 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/inspection/serialization.py +77 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/manifest.py +1 -2
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/__init__.py +26 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/canonical.py +57 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/errors.py +39 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/expand.py +67 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/filtering.py +70 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/models.py +121 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/matrix/runtime.py +99 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/oracle_assertions/__init__.py +28 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/oracle_assertions/errors.py +23 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/oracle_assertions/evaluate.py +253 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/oracle_assertions/models.py +130 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/oracle_assertions/serialization.py +65 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/suite/__init__.py +70 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/suite/errors.py +51 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/suite/models.py +429 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/suite/read.py +149 -0
- deterministic_scenario_engine-2.0.0/src/scenario_engine/suite/serialization.py +223 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_1_0e_packaging_release_candidate.py +4 -3
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_10_workflow_demonstrators.py +211 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_11_performance_scale_hardening.py +357 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_12_public_contract_docs_freeze.py +193 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_13_packaging_fresh_install_rc.py +118 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_1_models_serialization.py +168 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_1_v1_read_contract.py +129 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_2_composition.py +386 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_3_matrix.py +252 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_4_batch.py +292 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_5_inspect_explain.py +154 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_6_structured_semantic_diff.py +229 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_7_cli_product_surface.py +249 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_8_domain_pack_foundation.py +212 -0
- deterministic_scenario_engine-2.0.0/tests/test_phase_2_9_oracle_assertions.py +189 -0
- deterministic_scenario_engine-1.0.0/src/scenario_engine/_version.py +0 -3
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/LICENSE +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/MANIFEST.in +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/compatibility.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/dsl-reference.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/hypothesis.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/plugins.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/schemathesis.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/sqlalchemy.md +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/api_scenario.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/cart.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/control_flow.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/ecommerce.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/openapi.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/oracle_fault.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_1b_cart.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_3_resources.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_4_control_flow.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_5_oracle_fault.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_6_sqlalchemy_rows.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_7_ecommerce_plugin.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_8_api_scenario.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/phase0_8_openapi.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/resources.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/examples/sqlalchemy_rows.yaml +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/setup.cfg +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/deterministic_scenario_engine.egg-info/dependency_links.txt +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/deterministic_scenario_engine.egg-info/requires.txt +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/deterministic_scenario_engine.egg-info/top_level.txt +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/__init__.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/adapters/__init__.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/adapters/json_file.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/adapters/sqlalchemy.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/address.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/artifacts.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/canonical.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/clock.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/context.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/control_flow.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/__init__.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/compiler.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/errors.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/models.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/parser.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/dsl/runtime.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/errors.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/expressions.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/faults.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/history.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/ids.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/integrations/__init__.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/integrations/hypothesis.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/integrations/schemathesis.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/invariants.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/oracle.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/plugins.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/provenance.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/pytest_plugin.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/reference_packs/__init__.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/reference_packs/ecommerce.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/resources.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/result.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/rng.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/runner.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/state.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/validation.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/src/scenario_engine/values.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_1a_semantic_kernel.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_1b_linear_dsl.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_1c_integrated_phase0_1.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_1c_r1_missing_sentinel_repair.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_2a_reproducible_results.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_2b_json_pytest_integration.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_3_resources_constraints.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_4_control_flow.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_5_oracle_faults.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_6_sqlalchemy_materializer.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_7_plugins_ecommerce.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_0_8_hypothesis_schemathesis.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_1_0b_public_api_error_contract.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_1_0c_dsl_compatibility_contract.py +0 -0
- {deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/tests/test_phase_1_0d_documentation_examples.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deterministic-scenario-engine
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Reproducible, state-consistent business scenarios with deterministic ground truth
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Keywords: deterministic,scenario,testing,fixtures,replay
|
|
@@ -33,8 +33,12 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
**Generate test scenarios, not just test records.**
|
|
35
35
|
|
|
36
|
-
Deterministic Scenario Engine creates reproducible, state-consistent
|
|
37
|
-
histories
|
|
36
|
+
Deterministic Scenario Engine (DSE) creates reproducible, state-consistent
|
|
37
|
+
business histories and deterministic scenario suites with ground truth for
|
|
38
|
+
testing. The Phase 2 contract is frozen in this source tree as an unpublished
|
|
39
|
+
2.0.0 release candidate; no PyPI or GitHub release has occurred yet. Its
|
|
40
|
+
distribution version is 2.0.0 while its deterministic compatibility version
|
|
41
|
+
remains `ENGINE_VERSION == "1.0.0"` and its DSL version remains integer 1.
|
|
38
42
|
|
|
39
43
|
## Why it exists
|
|
40
44
|
|
|
@@ -58,9 +62,18 @@ make expected behavior explicit.
|
|
|
58
62
|
- an explicit, versioned plugin boundary and a reference ecommerce plugin pack
|
|
59
63
|
- a JSON-file adapter
|
|
60
64
|
- optional pytest, SQLAlchemy Core, Hypothesis, and Schemathesis integrations
|
|
65
|
+
- secure, explicit local-file composition with namespaced modules
|
|
66
|
+
- ordered Cartesian matrices with stable case IDs and original indexes
|
|
67
|
+
- immutable ordered batch plans and worker-independent results
|
|
68
|
+
- structured, redacted inspect/explain evidence and typed RFC 6901 semantic diff
|
|
69
|
+
- nine-command `scenario` CLI for local and CI workflows
|
|
70
|
+
- explicit immutable Domain Pack registries and pure Oracle Assertions
|
|
61
71
|
|
|
62
72
|
Core execution does not require a database, network service, plugin, or property
|
|
63
73
|
testing framework. See [security assumptions and non-goals](docs/security-and-non-goals.md).
|
|
74
|
+
Phase 2 adds no hidden discovery, network, randomness, wall-clock, or ambient
|
|
75
|
+
environment semantics. Its public imports, CLI contract, bounds, compatibility
|
|
76
|
+
posture, and adoption guidance are frozen in the [Phase 2 public contract](docs/phase2-public-contract.md).
|
|
64
77
|
|
|
65
78
|
## Installation
|
|
66
79
|
|
|
@@ -80,7 +93,7 @@ Install only the named optional integrations you need:
|
|
|
80
93
|
/tmp/scenario-engine-docs-venv/bin/python -m pip install '.[schemathesis]'
|
|
81
94
|
```
|
|
82
95
|
|
|
83
|
-
The distribution is `deterministic-scenario-engine`
|
|
96
|
+
The release-candidate distribution is `deterministic-scenario-engine` 2.0.0. Install the package
|
|
84
97
|
with `pip install deterministic-scenario-engine`, or select an optional integration
|
|
85
98
|
with a command such as `pip install 'deterministic-scenario-engine[pytest]'`.
|
|
86
99
|
|
|
@@ -139,8 +152,13 @@ Unsupported cross-version replay fails explicitly. See the [determinism model](d
|
|
|
139
152
|
- [Public Python API](docs/api.md)
|
|
140
153
|
- [Security assumptions and non-goals](docs/security-and-non-goals.md)
|
|
141
154
|
- [Compatibility contract](docs/compatibility.md)
|
|
155
|
+
- [Phase 2 public contract, CLI, and hard bounds](docs/phase2-public-contract.md)
|
|
142
156
|
|
|
143
157
|
## Status
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
Distribution release identity and deterministic engine compatibility are
|
|
160
|
+
separate contracts: this unpublished candidate has distribution version 2.0.0,
|
|
161
|
+
but generated core manifests retain `ENGINE_VERSION` 1.0.0 and DSL 1. Phase 2
|
|
162
|
+
suite, composition, matrix, inspection, diff, Domain Pack, and Oracle Assertion
|
|
163
|
+
contracts keep their own explicit schema versions. No 2.0.0 tag or publication
|
|
164
|
+
has occurred. The project is licensed under Apache-2.0.
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
**Generate test scenarios, not just test records.**
|
|
4
4
|
|
|
5
|
-
Deterministic Scenario Engine creates reproducible, state-consistent
|
|
6
|
-
histories
|
|
5
|
+
Deterministic Scenario Engine (DSE) creates reproducible, state-consistent
|
|
6
|
+
business histories and deterministic scenario suites with ground truth for
|
|
7
|
+
testing. The Phase 2 contract is frozen in this source tree as an unpublished
|
|
8
|
+
2.0.0 release candidate; no PyPI or GitHub release has occurred yet. Its
|
|
9
|
+
distribution version is 2.0.0 while its deterministic compatibility version
|
|
10
|
+
remains `ENGINE_VERSION == "1.0.0"` and its DSL version remains integer 1.
|
|
7
11
|
|
|
8
12
|
## Why it exists
|
|
9
13
|
|
|
@@ -27,9 +31,18 @@ make expected behavior explicit.
|
|
|
27
31
|
- an explicit, versioned plugin boundary and a reference ecommerce plugin pack
|
|
28
32
|
- a JSON-file adapter
|
|
29
33
|
- optional pytest, SQLAlchemy Core, Hypothesis, and Schemathesis integrations
|
|
34
|
+
- secure, explicit local-file composition with namespaced modules
|
|
35
|
+
- ordered Cartesian matrices with stable case IDs and original indexes
|
|
36
|
+
- immutable ordered batch plans and worker-independent results
|
|
37
|
+
- structured, redacted inspect/explain evidence and typed RFC 6901 semantic diff
|
|
38
|
+
- nine-command `scenario` CLI for local and CI workflows
|
|
39
|
+
- explicit immutable Domain Pack registries and pure Oracle Assertions
|
|
30
40
|
|
|
31
41
|
Core execution does not require a database, network service, plugin, or property
|
|
32
42
|
testing framework. See [security assumptions and non-goals](docs/security-and-non-goals.md).
|
|
43
|
+
Phase 2 adds no hidden discovery, network, randomness, wall-clock, or ambient
|
|
44
|
+
environment semantics. Its public imports, CLI contract, bounds, compatibility
|
|
45
|
+
posture, and adoption guidance are frozen in the [Phase 2 public contract](docs/phase2-public-contract.md).
|
|
33
46
|
|
|
34
47
|
## Installation
|
|
35
48
|
|
|
@@ -49,7 +62,7 @@ Install only the named optional integrations you need:
|
|
|
49
62
|
/tmp/scenario-engine-docs-venv/bin/python -m pip install '.[schemathesis]'
|
|
50
63
|
```
|
|
51
64
|
|
|
52
|
-
The distribution is `deterministic-scenario-engine`
|
|
65
|
+
The release-candidate distribution is `deterministic-scenario-engine` 2.0.0. Install the package
|
|
53
66
|
with `pip install deterministic-scenario-engine`, or select an optional integration
|
|
54
67
|
with a command such as `pip install 'deterministic-scenario-engine[pytest]'`.
|
|
55
68
|
|
|
@@ -108,8 +121,13 @@ Unsupported cross-version replay fails explicitly. See the [determinism model](d
|
|
|
108
121
|
- [Public Python API](docs/api.md)
|
|
109
122
|
- [Security assumptions and non-goals](docs/security-and-non-goals.md)
|
|
110
123
|
- [Compatibility contract](docs/compatibility.md)
|
|
124
|
+
- [Phase 2 public contract, CLI, and hard bounds](docs/phase2-public-contract.md)
|
|
111
125
|
|
|
112
126
|
## Status
|
|
113
127
|
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
Distribution release identity and deterministic engine compatibility are
|
|
129
|
+
separate contracts: this unpublished candidate has distribution version 2.0.0,
|
|
130
|
+
but generated core manifests retain `ENGINE_VERSION` 1.0.0 and DSL 1. Phase 2
|
|
131
|
+
suite, composition, matrix, inspection, diff, Domain Pack, and Oracle Assertion
|
|
132
|
+
contracts keep their own explicit schema versions. No 2.0.0 tag or publication
|
|
133
|
+
has occurred. The project is licensed under Apache-2.0.
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Public Python API
|
|
2
2
|
|
|
3
|
-
This is the canonical top-level Phase 1.0 contract
|
|
4
|
-
symbols not listed here are not
|
|
3
|
+
This is the canonical top-level Phase 1.0 contract, preserved unchanged by the
|
|
4
|
+
Phase 2 freeze. Importable implementation symbols not listed here are not
|
|
5
|
+
implicitly promoted to top-level public API. Specialized Phase 2 APIs are
|
|
6
|
+
public through the explicit subpackages documented below, not package-root
|
|
7
|
+
convenience exports.
|
|
5
8
|
|
|
6
9
|
## Constants and value objects
|
|
7
10
|
|
|
@@ -151,3 +154,34 @@ These are explicitly separate from the top-level contract:
|
|
|
151
154
|
|
|
152
155
|
Internal dataclass field layouts beyond frozen normalized result/manifest schemas
|
|
153
156
|
are not promised. See [compatibility](compatibility.md).
|
|
157
|
+
|
|
158
|
+
## Phase 2 public subpackages
|
|
159
|
+
|
|
160
|
+
The complete machine-frozen names are each subpackage's `__all__`; these import
|
|
161
|
+
paths are stable while helpers outside `__all__` are intentionally internal.
|
|
162
|
+
|
|
163
|
+
- `scenario_engine.suite` — versioned run/suite/matrix/batch manifests and
|
|
164
|
+
bounded non-executing v1 result/manifest readers.
|
|
165
|
+
- `scenario_engine.composition` — `ComposedSuite`, `load_composed_suite()`,
|
|
166
|
+
`execute_composed_suite()`, hashes, frozen bounds, and composition errors.
|
|
167
|
+
- `scenario_engine.matrix` — `MatrixDimension`, `MatrixPlan`, expansion,
|
|
168
|
+
selection and execution with ordered Cartesian semantics, stable case IDs,
|
|
169
|
+
and retained original Cartesian indexes.
|
|
170
|
+
- `scenario_engine.batch` — immutable `RunRequest`/`BatchPlan`, ordered
|
|
171
|
+
`execute_batch()`/`stream_batch()` results, stable failures, and bounds.
|
|
172
|
+
- `scenario_engine.inspection` — immutable inspection/explanation documents,
|
|
173
|
+
read-only normalization, canonical serializers, and default secret redaction.
|
|
174
|
+
- `scenario_engine.diff` — typed `SemanticDiff`/`DiffRecord` values using RFC
|
|
175
|
+
6901 paths, deterministic `first`/`complete` modes and prefix truncation.
|
|
176
|
+
- `scenario_engine.cli` — `CLIExitCode` and `main`; command behavior is in the
|
|
177
|
+
[Phase 2 public contract](phase2-public-contract.md#cli-contract).
|
|
178
|
+
- `scenario_engine.domain_packs` — immutable declarative `DomainPack` values,
|
|
179
|
+
caller-created `DomainPackRegistry`, exact deterministic resolution, semantic
|
|
180
|
+
identity, and declarative plugin requirements. There is no discovery, global
|
|
181
|
+
registry, or pack dependency mechanism.
|
|
182
|
+
- `scenario_engine.oracle_assertions` — pure post-result structured assertion
|
|
183
|
+
models, evaluation, serializers, outcomes, and bounds; evaluation never reruns
|
|
184
|
+
or replays a scenario.
|
|
185
|
+
|
|
186
|
+
The schema/version constants and all exact export manifests are executable
|
|
187
|
+
contract tests. See the [complete Phase 2 contract](phase2-public-contract.md).
|
{deterministic_scenario_engine-1.0.0 → deterministic_scenario_engine-2.0.0}/docs/determinism.md
RENAMED
|
@@ -71,5 +71,15 @@ declarative derivations are dependency-resolved rather than source-key ordered.
|
|
|
71
71
|
Canonical JSON uses sorted mapping keys. Do not use mapping insertion order to
|
|
72
72
|
encode business sequencing; use an ordered DSL list.
|
|
73
73
|
|
|
74
|
+
Phase 2 composition resolves modules by explicit alias and hashes semantic
|
|
75
|
+
content without physical paths. Matrix order is declaration-order Cartesian
|
|
76
|
+
order with the last dimension changing fastest; retained cases keep their
|
|
77
|
+
original pre-filter index. Batch members have independent execution contexts and
|
|
78
|
+
results are emitted in plan order regardless of worker completion. Inspection,
|
|
79
|
+
diff, and assertion evaluation are pure consumers of immutable normalized
|
|
80
|
+
evidence. Worker scheduling, filesystem enumeration, host paths, locale defaults,
|
|
81
|
+
environment variables, network responses, and process history are not semantic
|
|
82
|
+
coordinates.
|
|
83
|
+
|
|
74
84
|
See [reproducibility](reproducibility.md) for recorded context and
|
|
75
85
|
[compatibility](compatibility.md) for the normative replay contract.
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Phase 2 Product Scope and Architecture Freeze
|
|
2
|
+
|
|
3
|
+
Status: frozen by checkpoint 2.0A. This document authorizes design direction only. It does not authorize Phase 2 implementation.
|
|
4
|
+
|
|
5
|
+
The product thesis is **generate test scenarios, not just test records**. The Phase 2 direction is to compose, generate, inspect, diff, and replay entire deterministic scenario suites without weakening the published v1 contract.
|
|
6
|
+
|
|
7
|
+
## Baseline and Immutable V1
|
|
8
|
+
|
|
9
|
+
The immutable source baseline is commit `ee29f52f714e84f17e1048ce24192fcf1c69345a`, tree `2a61915d578dcb1c4ec94049350a24d2cabdf721`, and annotated tag `1.0.0` peeled to that commit. The distribution is `deterministic-scenario-engine==1.0.0`, import package `scenario_engine`, under Apache-2.0. Its published wheel SHA-256 is `4a5dfe8666fdf82233ad2fecd1aa54a190291bf731a3929faca26047b5eab511`; its sdist SHA-256 is `3264bbbb1956ff183c01cd85f379fe1a9afdf31d9375be7f95c003aff1a1800e`.
|
|
10
|
+
|
|
11
|
+
The v1 DSL, top-level API, error families, deterministic addressing, RNG and ID algorithms, canonical semantic values and JSON bytes, result and manifest schemas, resource/input hashes, exact-version replay checks, plugin behavior, package metadata, and three published result hashes remain frozen. Phase 2 extensions must preserve v1 behavior when no new feature is used. Existing v1 results must retain byte identity under the v1 artifact; a future release must never claim compatible execution replay unless its complete compatibility tuple is supported deliberately.
|
|
12
|
+
|
|
13
|
+
No Phase 2 semantic coordinate may depend on an absolute machine path, directory enumeration, unordered-container iteration, ambient locale, environment variable, wall clock, global random stream, network response, worker scheduling, or process history.
|
|
14
|
+
|
|
15
|
+
## Architecture Inventory
|
|
16
|
+
|
|
17
|
+
The status column uses exactly the authorized classifications. “Public” means supported top-level or documented adapter/integration behavior; “internal” means implementation detail even when importable by module path.
|
|
18
|
+
|
|
19
|
+
| Item | Classification | Location and status | Basis and Phase 2 consequence | Stable dependencies |
|
|
20
|
+
|---|---|---|---|---|
|
|
21
|
+
| parser | FROZEN_V1_CONTRACT | `src/scenario_engine/dsl/parser.py`; public through `parse_yaml`/`parse_yaml_file` | Safe YAML and strict DSL 1 grammar are contract-tested. Additive syntax may extend it, but valid v1 meaning and rejection safety cannot be reinterpreted. | semantic values, DSL errors, models |
|
|
22
|
+
| compiler | INTERNAL_EXTENSION_POINT | `src/scenario_engine/dsl/compiler.py`; top-level entry public, internals private | Compilation is the proper static-resolution boundary. Composition should resolve to compiled library models, while existing documents compile identically. | parser models, expressions, runner specs, control validation |
|
|
23
|
+
| runtime | FROZEN_V1_CONTRACT | `src/scenario_engine/dsl/runtime.py`; public run/evaluate/replay functions | Execution and exact replay determine golden bytes. New suite APIs orchestrate this engine rather than duplicating it. | compiler, runner, manifest, resources, plugins, oracle |
|
|
24
|
+
| execution address | FROZEN_V1_CONTRACT | `src/scenario_engine/address.py`; `ExecutionAddress` is public | Address-derived isolation is central to RNG/ID stability. New matrix identity must map deterministically to an explicit run index without changing v1 address serialization. | scenario ID, run index, subflow/repeat/step paths |
|
|
25
|
+
| RNG | SHOULD_NOT_CHANGE | `src/scenario_engine/rng.py`; internal | Versioned addressed SHA-256 generation is frozen behavior. Batch members get independent addressed streams; no shared stream is allowed. | root seed, execution address, RNG version |
|
|
26
|
+
| LogicalID | FROZEN_V1_CONTRACT | `src/scenario_engine/ids.py`; `LogicalID` public, provider internal | Normalization and deterministic identity are public result semantics. Existing algorithm/version stay unchanged. | root seed, address, ID version, canonical values |
|
|
27
|
+
| state | SHOULD_NOT_CHANGE | `src/scenario_engine/state.py`; internal | In-memory atomic semantic state is a protected design boundary. Suite features operate above it and exporters remain downstream. | normalize/freeze semantics, runner commits |
|
|
28
|
+
| history | FROZEN_V1_CONTRACT | `src/scenario_engine/history.py`, `src/scenario_engine/result.py`; observable public result | Ordered committed history and trace shape are result contracts and primary inspection data. Add new observations outside the v1 snapshot rather than altering v1 records. | execution address, state fingerprints, clock, artifacts |
|
|
29
|
+
| canonicalization | FROZEN_V1_CONTRACT | `src/scenario_engine/values.py`, `src/scenario_engine/canonical.py`; public scenario APIs and result bytes | Hashes, replay, equality, JSON, Decimal/datetime/MISSING encodings depend on exact behavior. Composition needs a new suite/module envelope without changing single-file v1 payloads. | parser semantic model, sorted mappings, UTF-8 JSON, SHA-256 |
|
|
30
|
+
| ScenarioResult | FROZEN_V1_CONTRACT | `src/scenario_engine/result.py`; public | Exact normalized keys and bytes are contract-tested. Matrix/batch metadata belongs in new wrapper records, not retrofitted into v1 results. | runner snapshot, manifest, normalize, provenance |
|
|
31
|
+
| ReproducibilityManifest | FROZEN_V1_CONTRACT | `src/scenario_engine/manifest.py`; public | Field names, order, normalization, validation, and exact engine compatibility are frozen. Composition/matrix/batch require a versioned suite manifest envelope rather than changing this dataclass. | engine/DSL/RNG/ID/plugin versions, resource hashes, clock/run context |
|
|
32
|
+
| replay | FROZEN_V1_CONTRACT | `replay_scenario` in `src/scenario_engine/dsl/runtime.py`; public | v1 requires exact compatibility and rejects active domain packs. Future suite replay is a distinct library API and must reject unsupported v1 execution explicitly. | parser/compiler, canonical hash, manifest tuple, explicit inputs/plugins |
|
|
33
|
+
| resources | FROZEN_V1_CONTRACT | `src/scenario_engine/resources.py`; public behavior, internal resolved type | Ordered dependency resolution, explicit inputs, immutable snapshots, and hashes are tested. Parameters remain a suite-level assignment feeding explicit inputs; imports do not create hidden lookup paths. | canonical values, input maps, validators/constraints |
|
|
34
|
+
| expressions | FROZEN_V1_CONTRACT | `src/scenario_engine/expressions.py`; DSL behavior and some module APIs | Typed arithmetic, lookup, ordering, derivation, and deterministic errors are compatibility-sensitive. New assertion selectors may consume normalized data but do not expand expression authority casually. | Decimal context, semantic equality, state/resource/scope namespaces |
|
|
35
|
+
| validators | FROZEN_V1_CONTRACT | `src/scenario_engine/validation.py`, parser/compiler; DSL public | Resource shape/type checks own input validity, not outcome assertions. Their current order and errors remain stable. | resolved resources, semantic types |
|
|
36
|
+
| constraints | FROZEN_V1_CONTRACT | validation plus runtime; DSL public | Pre-execution resource/business preconditions and violations already have oracle/provenance meaning. They must not become post-result assertions. | expressions, resources, faults, oracle |
|
|
37
|
+
| control flow | FROZEN_V1_CONTRACT | `src/scenario_engine/control_flow.py`, compiler/runtime; DSL public | Nonrecursive subflows, ordered first-match branches, bounded repeats, and addresses are frozen. Imported subflows are namespaced declarations resolved before this layer. | compiler graph checks, scopes, addresses, repeat limits |
|
|
38
|
+
| invariants | FROZEN_V1_CONTRACT | `src/scenario_engine/invariants.py`; DSL public | Atomic per-step candidate-state checks own transition safety. Final/history assertions belong to oracle expectations, not invariants. | runner candidate commit, expressions, provenance |
|
|
39
|
+
| faults | FROZEN_V1_CONTRACT | `src/scenario_engine/faults.py`; DSL public | Explicit deterministic fault selection/application and expectation contribution are tested. Inspection reads recorded provenance; no hidden trace hook is added. | addresses, state/resources, invariants/oracle |
|
|
40
|
+
| oracle | PHASE2_EXTENSION_CANDIDATE | `src/scenario_engine/oracle.py` and runtime; DSL/public evaluation | Existing expected constraint/invariant violations are narrow. A bounded additive expectation vocabulary can cover final state and committed records in the same oracle layer. | ScenarioResult observations, semantic comparison, provenance, replay |
|
|
41
|
+
| provenance | FROZEN_V1_CONTRACT | `src/scenario_engine/provenance.py`; observable result/evaluation data | Ordered deterministic records already explain faults/checks/oracle. New suite resolution records should be immutable structured data outside hidden mutable tracing. | addresses, stable identifiers, normalized details |
|
|
42
|
+
| plugins | FROZEN_V1_CONTRACT | `src/scenario_engine/plugins.py`; public explicit registry | Trusted, explicit, versioned generator algorithms have no discovery/global registry. Composition and packs may aggregate explicit registries but cannot auto-load code. | deterministic context, manifest generator versions, semantic values |
|
|
43
|
+
| JSON adapter | INTERNAL_EXTENSION_POINT | `src/scenario_engine/adapters/json_file.py`; documented submodule API | Atomic downstream single-result export is the pattern for new exporters. Existing overwrite behavior remains; suite exporters consume wrapper results. | ScenarioResult JSON bytes, filesystem caller path |
|
|
44
|
+
| SQLAlchemy adapter | SHOULD_NOT_CHANGE | `src/scenario_engine/adapters/sqlalchemy.py`; documented optional API | Transactional post-result materialization is deliberately outside state/execution. It gains no matrix/batch semantics in Phase 2. | committed artifacts, explicit table bindings, SQLAlchemy transaction |
|
|
45
|
+
| pytest integration | INTERNAL_EXTENSION_POINT | `src/scenario_engine/pytest_plugin.py`; packaged entry point and documented fixture | Thin harness over public APIs is the model for CLI/CI. It must not become a separate engine or implicit discovery system. | parser/compiler/run/replay, optional dependency boundary |
|
|
46
|
+
| Hypothesis integration | INTERNAL_EXTENSION_POINT | `src/scenario_engine/integrations/hypothesis.py`; documented optional API | It already models independently replayable explicit run indexes/inputs. Matrix/batch abstractions may be composed with it later without changing draw semantics. | explicit strategies, run API, manifest |
|
|
47
|
+
| Schemathesis integration | SHOULD_NOT_CHANGE | `src/scenario_engine/integrations/schemathesis.py`; documented optional API | Local case binding only; automatic HTTP execution is a protected non-goal. Phase 2 CLI does not absorb network execution. | ScenarioResult, explicit bindings, Hypothesis/Schemathesis |
|
|
48
|
+
| reference/domain packs | PHASE2_EXTENSION_CANDIDATE | `src/scenario_engine/reference_packs/ecommerce.py`; explicit plugin registry; `domain_pack_versions` reserved-empty | Ecommerce is a reference plugin pack, not yet a domain-pack contract. A declarative explicit bundle can activate the reserved concept without changing plugin semantics. | explicit registry, pack identity/version, manifest envelope, trust boundary |
|
|
49
|
+
| public API | FROZEN_V1_CONTRACT | `src/scenario_engine/__init__.py`; exact `__all__` | Existing exports and errors are exact. Phase 2 favors new submodules; any additive top-level exports require a deliberate public-contract checkpoint. | import laziness, error root, packaging |
|
|
50
|
+
| packaging | FROZEN_V1_CONTRACT | `pyproject.toml`, `MANIFEST.in`, `_version.py`; public distribution | v1 identity, dependencies, pytest entry point, and version remain unchanged now. Future CLI entry point is an intentional package change only in implementation. | setuptools metadata, optional dependency isolation, license |
|
|
51
|
+
| documentation | PHASE2_EXTENSION_CANDIDATE | `README.md`, `docs/`; public | Normative v1 documentation is frozen; this document becomes the Phase 2 design authority. Future docs must distinguish old and new contracts. | implemented behavior, local-link validation |
|
|
52
|
+
| examples | SHOULD_NOT_CHANGE | `examples/`; public canonical examples | Current examples enforce golden behavior and remain byte-stable. New examples are added only alongside implemented features, never as placeholders. | parser/runtime, documentation tests, goldens |
|
|
53
|
+
|
|
54
|
+
## CLI Architecture
|
|
55
|
+
|
|
56
|
+
The distribution will add the console entry point `scenario = scenario_engine.cli:main`. A single shared application owns argument parsing, input decoding, rendering, and exception translation; command handlers invoke public library capabilities. The hierarchy is frozen as `scenario validate`, `run`, `replay`, `hash`, `inspect`, `explain`, and `diff`. `matrix` and `batch` are separate commands because matrix expands one declarative suite while batch executes an explicit heterogeneous run plan; neither is an alias for `run`.
|
|
57
|
+
|
|
58
|
+
One positional path is accepted, with `-` meaning stdin. Commands needing two documents use two positional sources, each independently allowing `-` only when at most one stdin stream is required. Relative composition paths are legal only when the root source is a file and an explicit `--root` is supplied or defaults to that file's parent; composed stdin requires explicit root. There is no environment search path.
|
|
59
|
+
|
|
60
|
+
Human output is the default and is concise, stable in section/order but not a canonical hash input. `--json` emits one canonical UTF-8 JSON value plus one LF to stdout; JSON schemas are versioned library serialization contracts. Successful payloads go only to stdout. Diagnostics go only to stderr, redact supplied values/paths unless verbosity explicitly requests safe details, and never include tracebacks by default. Deterministic commands produce byte-identical JSON for identical explicit inputs; progress, timing, host paths, colors, and worker completion order are excluded from machine output.
|
|
61
|
+
|
|
62
|
+
Exit families are: `0` success/equal; `1` valid comparison with differences or oracle mismatch; `2` CLI usage/input-source error; `3` parse/schema/compile/validation error; `4` execution/constraint/invariant/oracle failure; `5` replay compatibility rejection; `6` security/bound violation; `7` I/O/export error; `8` unexpected internal error. The CLI maps the library error hierarchy deterministically and never changes business semantics. CI uses `--json`, explicit roots/seeds/inputs, bounded expansion, and captured manifests/results. `replay` validates recorded contracts before execution. `inspect` renders structured observations; `explain` renders causal records; `diff` renders the library semantic diff. Command names map to cohesive library operations, not necessarily one top-level function each.
|
|
63
|
+
|
|
64
|
+
## Deterministic Multi-File Composition
|
|
65
|
+
|
|
66
|
+
The single mechanism is named **composition**, expressed by a root-level ordered mapping:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
composition:
|
|
70
|
+
modules:
|
|
71
|
+
checkout: modules/checkout.yaml
|
|
72
|
+
catalog: modules/catalog.yaml
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Imported files are **modules**; there are no `include` or `import` aliases. A module is DSL 1 YAML with `dsl_version`, `module`, and declaration sections (`resources`, `validators`, `constraints`, `subflows`, `invariants`, `faults`, and reusable oracle fragments where supported), but no executable root scenario, clock, initial state, steps, or nested composition. The root remains the only executable scenario and root identity is its `scenario` value. Logical module identity is the explicit alias, an ASCII identifier matching `[a-z][a-z0-9_]*`; physical filenames are never semantic identities.
|
|
76
|
+
|
|
77
|
+
The graph is a depth-one root-to-module DAG in Phase 2: modules cannot compose other modules. This intentionally eliminates transitive lookup and cycles; any module composition key is a schema error. The ordered YAML mapping is accepted for authorship, but resolution order is sorted by alias and therefore source mapping order has no semantics. Duplicate alias keys are rejected by the YAML parser. Duplicate canonical content under distinct aliases is allowed and remains distinct because alias is identity. Aliases namespace every imported declaration as `alias.name`; imported declarations are private except through that qualified name. Root unqualified declarations remain root-local. Any duplicate fully qualified declaration or collision with an explicitly dotted root declaration is a compile error; no shadowing, wildcard visibility, or implicit merge exists. Imported resources may refer to declarations in their own alias or explicit other aliases, and dependency resolution remains sorted and cycle-checked. Root/subflow calls use qualified names. Plugin names remain their existing globally namespaced identifiers; modules only declare requirements. Domain packs are explicit compilation inputs, never file imports.
|
|
78
|
+
|
|
79
|
+
The caller supplies an allowed filesystem root. Each module spelling must use `/`, be nonempty relative POSIX syntax, contain no empty, `.` or `..` segment, no backslash, drive prefix, leading slash, NUL, URI scheme, or network URL. Resolution joins the spelling beneath the allowed root, performs component-wise `lstat`, rejects every symlink, requires a regular file, resolves both root and candidate, and verifies containment. The same policy applies on every platform; paths are case-sensitive semantic spellings even on case-insensitive filesystems, and aliases—not paths—are coordinates. Case-fold-colliding spellings are rejected for portability. Absolute paths, symlink escapes, environment-derived paths, implicit current-directory search, dynamic imports, URI schemes, network retrieval, and remote composition are forbidden.
|
|
80
|
+
|
|
81
|
+
Each module has SHA-256 over its canonical semantic declaration payload. The composed scenario hash is SHA-256 over a versioned canonical envelope containing the unchanged canonical root scenario payload and the alias-sorted list of `{alias, content_hash, payload}`; no physical path is included. A new `SuiteManifest` records composition schema version, root scenario identity, composed hash, and alias-to-content-hash mapping, alongside the unchanged per-run v1 `ReproducibilityManifest`. Replay requires the caller to supply local root/module bytes and rejects any hash/identity mismatch before execution. This yields cross-machine reproduction independent of path layout. Limits are 64 modules, depth 1, 1 MiB per YAML file, and 16 MiB canonical composed payload.
|
|
82
|
+
|
|
83
|
+
## Parameters and Scenario Matrices
|
|
84
|
+
|
|
85
|
+
Parameters are suite-owned named explicit values. They are not resources: an assignment is transformed deterministically into the existing runtime `inputs` mapping, and resource declarations remain the only bridge from inputs into a scenario. The root seed, run index, locale, and reference clock are execution context, not parameters or dimensions. The scenario's clock remains DSL-owned.
|
|
86
|
+
|
|
87
|
+
The root may add a `matrix` section containing an ordered list of dimensions, each with a unique ASCII name and a nonempty ordered `values` sequence. Dimension declaration order is semantic; value list order is semantic; mappings/sets/filesystem enumeration are forbidden as dimension sources. Expansion is lexicographic odometer order with the last dimension changing fastest. It is the Cartesian product followed by ordered pure filters expressed in the restricted expression model over the complete parameter assignment. A filter retains only exact boolean true and cannot access state, time, environment, resources, plugins, or randomness.
|
|
88
|
+
|
|
89
|
+
`MatrixCase` stores `case_index`, ordered assignment, and `case_id`. The ID is lowercase SHA-256 of a versioned canonical assignment envelope including the composed scenario hash; duplicate canonical assignments are rejected, not coalesced. No dimensions means one empty-assignment case. Any dimension with zero values is invalid, so a declared matrix can produce zero cases only through filters; zero cases is valid for inspection but `matrix run` exits as no-work unless explicitly allowed. Maximum dimensions are 16, values per dimension 1,000, pre-filter Cartesian cardinality 100,000, and executable retained cases 10,000; bounds are checked with overflow-safe multiplication before materialization.
|
|
90
|
+
|
|
91
|
+
For execution, `run_index` equals `case_index` in the unfiltered Cartesian expansion, preserving stable identity if a filter removes another case. Root seed is identical across cases; addressed RNG isolation through run index makes each case independent. Seed derivation is forbidden. Matrix assignment, original Cartesian index, case ID, bounds/version, root seed, locale, input hashes, composition identity, and each child manifest participate in a new matrix bundle manifest. The unchanged single-scenario hash excludes matrix declarations; the suite hash includes canonical matrix declarations. One case can be reproduced from suite bytes, root seed, and case ID with its recorded original index. Replay of one case validates that identity and child manifest; replay of a matrix validates the suite manifest and returns results sorted by original case index.
|
|
92
|
+
|
|
93
|
+
## Deterministic Batch Execution
|
|
94
|
+
|
|
95
|
+
The library-first model is `BatchPlan`, an immutable ordered sequence of `RunRequest` records, executed by `execute_batch` into `BatchResult`. A request contains explicit run ID, resolved scenario/suite reference, root seed, run index, locale, inputs/parameter case, plugins/domain packs supplied by the caller, and execution mode. Run IDs are unique nonempty portable ASCII labels and are the batch coordinate; request order determines result order only, not random generation.
|
|
96
|
+
|
|
97
|
+
Every request invokes the same single-run/matrix library APIs with its own seed and run index. There is no shared RNG, ID provider, state, resource cache with mutable semantics, or sequential seed derivation. Reordering, omitting, adding, or parallelizing requests cannot alter any individual outcome. Results are emitted in plan order regardless of worker completion. Each `BatchItemResult` is a tagged success with result/manifest or failure with stable error family/code/safe message; tracebacks and exception objects are not serialized.
|
|
98
|
+
|
|
99
|
+
Default behavior is continue-on-error. `fail_fast=True` stops scheduling after the first failure in plan order, cancels only not-yet-started work, and records deterministic `NOT_RUN` entries for every omitted request. Because concurrency can make “already started” timing nondeterministic, fail-fast requires one worker; parallel fail-fast is rejected. Aggregation preserves all item statuses and summary counts. Each successful member is independently replayable. A batch bundle manifest records plan schema, canonical request identities/hashes, ordered child manifest hashes, statuses, and plan hash; it is not an execution-state store.
|
|
100
|
+
|
|
101
|
+
Bounds are 10,000 requests, maximum 64 workers, and an explicit aggregate retained-result byte budget defaulting to 256 MiB. The executor supports an ordered sink/iterator mode so completed results can be buffered only until their preceding sequence positions are emitted. Exceeding request/result bounds yields a deterministic bound error. Worker count and completion times never appear in semantic output.
|
|
102
|
+
|
|
103
|
+
## Inspect and Explain
|
|
104
|
+
|
|
105
|
+
Inspection is a library model separated from rendering. `inspect_result`, `inspect_manifest`, and suite equivalents produce immutable, versioned `InspectionDocument` sections. `explain_result` produces ordered `ExplanationRecord` values with kind, stable path/address, subject ID, outcome, and normalized details. CLI human/JSON renderers consume these values only.
|
|
106
|
+
|
|
107
|
+
The models expose ScenarioResult schema/hash, manifest tuple, final state, history, artifacts, trace, provenance, resource/input hashes, root seed, run index, locale, reference clock, engine/RNG/ID/generator/plugin/domain-pack versions, logical timestamps, transitions, fault applications, invariant/constraint failures, oracle evaluation, and generated-value addresses where recorded. Suite records add composition module identities/hashes/resolution order, matrix case/index/assignment, batch run identity/status, and child manifest links. Branch and repeat decisions not present in v1 records are inferred only where unambiguous from committed addresses/history; the model must label unavailable evidence rather than invent it. Replay rejection is represented from structured compatibility fields and stable errors.
|
|
108
|
+
|
|
109
|
+
No hidden mutable tracing is introduced. Phase 2 may add explicit immutable suite-level resolution/expansion records before execution, but must not change v1 result bytes. Secret-prone input values are omitted by default; only hashes are shown unless the caller explicitly provides and requests values.
|
|
110
|
+
|
|
111
|
+
## Structured Diff
|
|
112
|
+
|
|
113
|
+
The library defines `SemanticDiff`, containing comparison kind, equality, truncation metadata, and an ordered tuple of `DiffRecord`. A record has stable JSON Pointer path (RFC 6901 escaping), operation (`add`, `remove`, `replace`, or `type`), left/right presence flags, left/right semantic types, and normalized values subject to redaction. Presence flags distinguish MISSING from JSON null; semantic MISSING itself uses the existing `{"$missing":true}` encoding.
|
|
114
|
+
|
|
115
|
+
Inputs are normalized typed result, manifest, inspection, or suite-manifest models—not raw text. Mappings compare by Unicode key and records are emitted in path order. Sequences compare by index with no heuristic moves; removal/addition preserves index paths. Type differences are differences even when host-language equality says otherwise (therefore boolean differs from integer). Decimal compares by normalized engine semantic representation, preserving decimal type and scale as encoded. Datetimes compare after existing UTC normalization. Ordered history/artifacts/trace remain sequences. Unordered version/hash maps are normalized mappings.
|
|
116
|
+
|
|
117
|
+
Supported sections include scenario/composed hash, manifest, state, history, artifacts, trace, provenance, input/resource hashes, root seed, run index, locale, reference clock, engine/generator/plugin/domain-pack versions, composition identity, and matrix/batch identity. `mode="first"` returns the first stable record. `mode="complete"` defaults to 10,000 records and requires a caller maximum no greater than 100,000; on overflow it returns the deterministic prefix plus `truncated=true` and omitted count when known. Canonical JSON uses versioned schemas, sorted object keys, typed values, and no host paths. Human rendering is downstream and is never the comparison model.
|
|
118
|
+
|
|
119
|
+
## Oracle and Assertion Expansion
|
|
120
|
+
|
|
121
|
+
Oracle/assertion expansion is classified **SHOULD_HAVE_PHASE2**. The existing layers remain distinct: validators validate resource shape/type; constraints enforce pre-execution resource/business conditions; invariants protect every candidate state transition; oracle expectations judge observed execution outcomes.
|
|
122
|
+
|
|
123
|
+
Phase 2 adds assertion families to the existing oracle layer, not a new assertion engine: final-state path comparison/presence; history and artifact count; ordered subsequence; occurrence count of a typed predicate over normalized records; transition occurrence/order; and logical-time comparison. History assertions also cover committed branch/repeat effects only through stable recorded fields. “Artifact assertions” select normalized artifact records. Assertions use stable IDs, restricted pure selectors/comparators, explicit MISSING, and bounded scans; they cannot call Python, plugins, network, filesystem, clock, or randomness.
|
|
124
|
+
|
|
125
|
+
DSL 1 gains an additive `oracle.assertions` ordered list. Existing valid oracle syntax retains meaning and bytes when no new syntax is used. Reports add assertion observations only in a future evaluation wrapper/schema; v1 `ScenarioResult` is unchanged. Replay reevaluates assertions from the reproduced deterministic result and verifies oracle-definition hashes through the suite/scenario hash. Count, occurrence, ordering, transition, and logical-time assertions are operators in this one family, not separate abstractions. Compatibility risk is moderate because parser/canonical/oracle/error contracts change additively; the feature follows result inspection and diff foundations.
|
|
126
|
+
|
|
127
|
+
## Domain Packs
|
|
128
|
+
|
|
129
|
+
A domain pack is an explicitly registered, immutable, versioned bundle of declarative assets: namespaced resource templates, validators, constraints, oracle fragments, documentation metadata, and an optional explicit `PluginRegistry` supplied by trusted Python packaging. It differs from a plugin: a plugin is one generator algorithm callable; a pack composes declarations and may reference a set of plugins but cannot itself execute, access I/O, or create a registry implicitly.
|
|
130
|
+
|
|
131
|
+
Pack identity uses the plugin-style lowercase dotted namespace and an exact nonempty version. The caller constructs/registers `DomainPack` objects into an immutable `DomainPackRegistry`; scenarios declare exact `pack@version` requirements and qualified asset references. No entry-point loading, package scan, automatic discovery, global registry, dynamic YAML import, or network retrieval exists. Duplicate identities or conflicting versions fail before compilation. Pack assets join composition under a reserved `pack:<identity>` namespace; root/modules cannot shadow them.
|
|
132
|
+
|
|
133
|
+
Activated pack identities/versions and canonical asset hashes are recorded in the suite manifest and copied into each new-run compatibility envelope. The reserved v1 `domain_pack_versions` field remains empty for v1 execution; it is not silently activated because v1 replay explicitly rejects it. Future pack-aware replay requires explicit trusted registry, exact version, and asset hash. Distribution is ordinary separately installed Python packages or engine-shipped reference modules imported explicitly by application code. Packs and plugins are trusted, unsandboxed code boundaries; declarative assets still pass the safe parser. The public API is initially a new `scenario_engine.domain_packs` submodule, not an automatic top-level export.
|
|
134
|
+
|
|
135
|
+
## Reference Pack Strategy
|
|
136
|
+
|
|
137
|
+
Retain ecommerce and deepen it to demonstrate explicit domain-pack registration, composed catalog/checkout/fulfillment modules, parameterized regional/customer cases, order-lifecycle batch runs, oracle lifecycle assertions, inspection, replay, and semantic diff. Add one deep **payments/order-lifecycle** reference pack only if it exercises materially different fault, transition-order, Decimal, idempotency, and replay/diff behavior. Do not add SaaS, user, inventory-only, or API packs in Phase 2. Reference packs are **OPTIONAL_PHASE2** and are the first content feature deferred when core foundations need schedule protection.
|
|
138
|
+
|
|
139
|
+
## Export Adapters
|
|
140
|
+
|
|
141
|
+
Export adapters are **OPTIONAL_PHASE2** and downstream from `ScenarioResult`, `MatrixResult`, or `BatchResult`. Supported candidates are canonical multi-result JSON, JSONL, fixture directories, and manifest bundles. CSV is deferred because nested typed values force a lossy/ambiguous schema unless a later explicit flattening contract is designed.
|
|
142
|
+
|
|
143
|
+
JSON/multi-result/bundle typed values use existing normalization: MISSING as `{"$missing":true}`, Decimal as `{"$decimal":"..."}`, datetime as UTC `{"$datetime":"...Z"}`, duration/LogicalID per existing normalization, sorted object fields, and ordered result sequences. JSONL contains one canonical compact object plus LF per ordered result. Fixture filenames are zero-padded sequence plus a lowercase SHA-256 stable ID, never scenario text or host paths. Bundle layout is `bundle.json`, `manifests/<id>.json`, and `results/<id>.json`; the root index records every content hash and relationship. Writes reject existing destinations by default; explicit `overwrite=True` uses atomic replacement. Exporters execute nothing, resolve no state, and never become replay/state stores.
|
|
144
|
+
|
|
145
|
+
## CI and Developer Workflow
|
|
146
|
+
|
|
147
|
+
Generic workflows use library APIs or the CLI: validate all explicit roots; hash suite definitions; execute matrix/batch with explicit seed and limits; preserve canonical results/manifests/bundle as artifacts; replay selected or all members; semantic-diff against approved artifacts; and emit JSON diagnostics on failure. CI compares semantic hashes/diffs, not terminal text. Failure records include stable run/case IDs, error family, relevant addresses/paths, and redacted deterministic details.
|
|
148
|
+
|
|
149
|
+
GitHub Actions configuration remains documentation/examples. No CI-provider environment variables, annotations, artifact API, status API, or secret mechanism enters core semantics. Provider wrappers may map the generic exit families externally.
|
|
150
|
+
|
|
151
|
+
## Performance and Scale Targets
|
|
152
|
+
|
|
153
|
+
Security/safety bounds are hard deterministic validation limits; performance targets are measured goals and never change output semantics.
|
|
154
|
+
|
|
155
|
+
| Area | Safety bound | Baseline target on one CPython 3.11+ process |
|
|
156
|
+
|---|---:|---|
|
|
157
|
+
| root steps | 10,000 | 1,000 simple committed steps in under 1 s |
|
|
158
|
+
| resources | 10,000 declarations / 16 MiB normalized | 1,000-node DAG resolution in under 250 ms |
|
|
159
|
+
| composition | 64 modules, depth 1, 1 MiB/file, 16 MiB canonical | 32 modules / 8 MiB validate+hash under 2 s |
|
|
160
|
+
| repeat | existing per-repeat maximum remains authoritative; aggregate executed steps 100,000 | 10,000 repeated simple steps under 5 s |
|
|
161
|
+
| matrix | 16 dimensions, 1,000 values/dimension, 100,000 prefilter, 10,000 retained | expand/hash 10,000 cases under 1 s excluding runs |
|
|
162
|
+
| batch | 10,000 requests, 64 workers | 1,000 trivial runs with deterministic ordered sink under 30 s single worker |
|
|
163
|
+
| history | 100,000 records/run | canonicalize 10,000 records under 2 s |
|
|
164
|
+
| artifacts | 100,000/run and explicit 256 MiB aggregate budget | 10,000 small artifacts under 2 s serialization |
|
|
165
|
+
| trace/provenance | combined 100,000 records/run / 64 MiB | inspect 10,000 records under 1 s |
|
|
166
|
+
| canonical serialization | 256 MiB input/output | 16 MiB under 2 s and under 3x payload peak memory |
|
|
167
|
+
| diff | default 10,000; hard 100,000 records | first diff under 250 ms; 10,000 diffs under 2 s for 16 MiB inputs |
|
|
168
|
+
|
|
169
|
+
Benchmark fixtures cover linear steps, deep semantic values, wide resource DAG, maximum legal composition, filtered matrix, heterogeneous batch failures, artifact-heavy results, provenance-heavy oracle evaluation, equal canonicalization, first difference, and bounded complete difference. Repeat × matrix × batch aggregate work is checked before execution against an explicit run/step budget. Optimization may stream and cache immutable content hashes, but cannot change order, bytes, error precedence, or addressing.
|
|
170
|
+
|
|
171
|
+
## Version, DSL, and API Strategy
|
|
172
|
+
|
|
173
|
+
The eventual release strategy is **2.0.0**. Although valid v1 DSL remains accepted unchanged, suite composition/matrix manifests, CLI machine schemas, diff models, domain-pack activation, and replay policy create a materially larger public contract. Keeping this as 1.x would understate result/manifest ecosystem and replay compatibility impact. No package version changes in 2.0A.
|
|
174
|
+
|
|
175
|
+
DSL version remains **1**. Composition and matrix are additive root syntax with unambiguous absence defaults, and oracle assertions are additive. Existing valid DSL 1 cannot be reinterpreted, its canonical payload/result remains identical when new keys are absent, and unknown future forms still fail. A DSL version increment is required only if valid DSL 1 meaning or canonical semantics must change.
|
|
176
|
+
|
|
177
|
+
Existing top-level exports stay supported. Phase 2 first exposes composition, suite, batch, inspection, diff, and domain-pack types through explicit new submodules to preserve import laziness. A later API freeze may add a deliberately small set of top-level exports. New errors inherit `ScenarioEngineError` and stable category families. V1 `ScenarioResult` and `ReproducibilityManifest` schemas and canonical JSON do not change; new versioned wrapper schemas carry composition, matrix, batch, diff, and pack metadata.
|
|
178
|
+
|
|
179
|
+
## V1 to V2 Replay Posture
|
|
180
|
+
|
|
181
|
+
Choose policy **A**: explicitly reject execution replay when compatibility is not guaranteed. Phase 2 will parse/read v1 manifest JSON into a versioned read model, inspect v1 results/manifests, diff two v1 artifacts, and diff v1 against Phase 2 artifacts through normalized inspection models. These operations do not execute scenarios and do not promise byte reproduction.
|
|
182
|
+
|
|
183
|
+
Phase 2 does not preserve a complete hidden v1 executor and does not promise a compatibility executor. Direct execution replay of a manifest whose recorded engine version is `1.0.0` is rejected before execution by `ReplayCompatibilityError` (or additive subclass `UnsupportedReplayContractError`) with stable code `replay.engine_version_unsupported`, recorded version `1.0.0`, and supported execution contract(s), without a traceback or migration claim. Users needing exact v1 execution install the frozen, hash-verified v1 artifact. If implementation later proves unchanged algorithms satisfy complete compatibility, enabling v1 execution replay requires a separately reviewed explicit compatibility checkpoint; this freeze does not promise it.
|
|
184
|
+
|
|
185
|
+
## Security Guardrails
|
|
186
|
+
|
|
187
|
+
- Prevent path traversal: reject `..`, `.`, empty path components, absolute/drive/UNC paths, backslashes, URI schemes, NUL, nonregular files, and portability case-fold collisions. Path resolution must fail closed and must not escape the authorized composition root.
|
|
188
|
+
- Prevent symlink traversal: reject symlinks at every component, check resolved targets rather than merely lexical paths, and forbid escape from the allowed filesystem root. Require an explicit local filesystem root; absolute machine-specific filesystem paths are not deterministic semantic coordinates, and environment/PATH/home/current-directory searches are never implicit.
|
|
189
|
+
- Forbid network URLs, network imports, remote composition, hidden network access, dynamic import from YAML, YAML tags/aliases/merges, arbitrary execution from YAML, and unsafe deserialization. Composition reads bounded local UTF-8 files only and cannot become an indirect arbitrary-code execution mechanism.
|
|
190
|
+
- Preserve no automatic plugin/domain-pack discovery, no entry-point or plugin auto-loading (the pytest integration entry point is not plugin discovery), no global registries, and no dynamic YAML imports. Plugin and domain-pack registration is explicit and immutable.
|
|
191
|
+
- Prevent unbounded expansion: apply explicit safe bounds where applicable to composition, repeat, matrix, batch, history/artifact, semantic-diff, files/modules/depth, aggregate semantic bytes, resource DAG, steps, workers, provenance, retained bytes, and serialization before allocation or execution where practical. Determinism does not justify unlimited resource consumption.
|
|
192
|
+
- Keep state in memory and engine-owned; no database-backed state, ORM-owned state, raw SQL DSL, recursive subflows, unbounded loops, automatic Schemathesis HTTP execution, hidden network, wall clock, randomness, or implicit environmental state.
|
|
193
|
+
- Plugins and Python-packaged domain packs are explicit trust boundaries and remain trusted and unsandboxed. Validate outputs and versions but never claim sandboxing. Declarative pack data retains the safe, explicit DSL parsing model established by v1 and remains hashed.
|
|
194
|
+
- Prevent environment leakage: environment-dependent paths, variables, wall-clock state, locale defaults, and other implicit environmental state must not silently influence deterministic semantics.
|
|
195
|
+
- Prevent secret leakage: CLI diagnostics, inspect/explain output, exceptions, manifests, and CI output must not unnecessarily expose secrets supplied through inputs or the surrounding environment. Machine diagnostics omit input values, host paths, tracebacks, chained exception text, tokens, and headers by default; stable errors expose only bounded safe context, and explicit verbose rendering still redacts configured keys.
|
|
196
|
+
- Export destinations use caller paths, no semantic path coordinates, reject overwrite by default, avoid path interpolation from untrusted IDs, and write atomically.
|
|
197
|
+
- Reading/inspection/diff of older artifacts never triggers code loading, plugin invocation, network access, or scenario execution.
|
|
198
|
+
- Indefinite incompatible cross-major replay is not promised. Determinism and bounded failure outrank throughput.
|
|
199
|
+
|
|
200
|
+
## Feature Dependency Graph
|
|
201
|
+
|
|
202
|
+
Canonical textual graph (an arrow means “must precede”):
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
V1 contract preservation -> Suite model/schema foundation
|
|
206
|
+
Suite model/schema foundation -> Composition -> Matrix -> Batch
|
|
207
|
+
Suite model/schema foundation -> InspectExplain -> StructuredDiff
|
|
208
|
+
InspectExplain -> OracleExpansion
|
|
209
|
+
Composition + explicit registry model + suite manifest -> DomainPacks
|
|
210
|
+
Composition + Matrix + Batch + InspectExplain -> CLI completion
|
|
211
|
+
CLI + replay + StructuredDiff -> CIDeveloperWorkflow
|
|
212
|
+
Composition + Matrix + Batch + DomainPacks + OracleExpansion -> ReferencePacks
|
|
213
|
+
Matrix + Batch + suite manifests -> ExportAdapters
|
|
214
|
+
all MUST_HAVE implementations -> PerformanceScale -> API/docs freeze -> RC -> acceptance -> publication
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The true foundation is a versioned suite/run wrapper and manifest schema that preserves v1 objects, followed by secure composition. Matrix depends on composed suite identity; batch depends on stable single/matrix run identities. Inspect/explain can proceed in parallel after the wrapper schema, followed by diff. Domain packs are blocked by composition namespace and manifest decisions. CLI parsing can start early, but command completion is blocked by library capabilities. Export and CI are low-risk downstream work. Oracle expansion and reference content are deferrable. The likely critical path is suite schema → composition/security → matrix/address mapping → batch/bundles → CLI/replay integration → hardening/contracts/RC.
|
|
218
|
+
|
|
219
|
+
## Scope Classification
|
|
220
|
+
|
|
221
|
+
| Feature | Classification | Rationale | Dependencies |
|
|
222
|
+
|---|---|---|---|
|
|
223
|
+
| CLI | MUST_HAVE_PHASE2 | Provides one coherent end-to-end product surface while remaining library orchestration. | library APIs, all core result schemas |
|
|
224
|
+
| Composition | MUST_HAVE_PHASE2 | Enables deterministic scenario suites and is the central new product capability. | suite schema, parser/compiler, security model |
|
|
225
|
+
| Matrix | MUST_HAVE_PHASE2 | Turns explicit parameters into deterministic scenario-case suites. | composition identity, inputs/resources, addressing |
|
|
226
|
+
| Batch | MUST_HAVE_PHASE2 | Executes complete heterogeneous suites without order-dependent outcomes. | stable run/matrix identities, bundle schema |
|
|
227
|
+
| InspectExplain | MUST_HAVE_PHASE2 | Makes deterministic records operable and supplies structured diagnostics. | result/manifest read models, suite records |
|
|
228
|
+
| StructuredDiff | MUST_HAVE_PHASE2 | Gives semantic change detection needed for replay and CI workflows. | inspection/normalization models |
|
|
229
|
+
| OracleExpansion | SHOULD_HAVE_PHASE2 | Materially strengthens scenario truth but core suite generation remains useful without it. | inspect/result selectors, bounded assertion model |
|
|
230
|
+
| DomainPacks | MUST_HAVE_PHASE2 | Activates reusable explicit domain semantics with a boundary distinct from plugins. | composition namespace, explicit registries, suite manifest |
|
|
231
|
+
| ReferencePacks | OPTIONAL_PHASE2 | Deep examples prove cohesion but do not define the core architecture. | core features; domain packs/oracle for deepest value |
|
|
232
|
+
| ExportAdapters | OPTIONAL_PHASE2 | Useful downstream portability; canonical JSON already provides a base. | matrix/batch results and bundle manifests |
|
|
233
|
+
| CIDeveloperWorkflow | SHOULD_HAVE_PHASE2 | Generic documented workflow makes CLI/diff/replay materially useful without provider semantics. | CLI, replay, diff, exports optional |
|
|
234
|
+
| PerformanceScale | SHOULD_HAVE_PHASE2 | Bounds and benchmarks are release integrity; optimization beyond targets is deferrable. | completed must-have paths |
|
|
235
|
+
|
|
236
|
+
## Final Phase 2 Product Definition
|
|
237
|
+
|
|
238
|
+
Phase 2 adds a deterministic suite layer that v1 does not have: a developer can securely compose namespaced local scenario modules, expand explicit parameter matrices, execute independent ordered batches, record/replay exact suite cases, inspect causal deterministic evidence, and semantically diff results/manifests through one library-first CLI, while explicitly registering reusable domain packs. End to end, a developer validates a suite, hashes it, runs all or one reproducible case locally or in CI, preserves canonical bundles, explains a failure, verifies replay compatibility, and obtains a typed bounded diff without creating a second execution engine or changing v1 semantics.
|
|
239
|
+
|
|
240
|
+
## Implementation Roadmap
|
|
241
|
+
|
|
242
|
+
No checkpoint below is authorized by this document; each requires separate authorization.
|
|
243
|
+
|
|
244
|
+
| Checkpoint | Objective and bounded scope | Explicit non-goals | Predecessor / acceptance gate | Public/API/DSL and migration/replay |
|
|
245
|
+
|---|---|---|---|---|
|
|
246
|
+
| 2.0A — Product Scope + Architecture Freeze | This docs-only decision artifact and v1 evidence. | Runtime, tests, package/version/release changes. | Exact v1 baseline; document and regression validation. | No changes. |
|
|
247
|
+
| 2.1 — Suite Models + Read Contracts | Versioned run/suite/matrix/batch manifest envelopes, bounded read-only v1 artifact models, error families. | Composition execution, CLI commands, v1 executor. | 2.0A; canonical schemas/round trips and unchanged v1 bytes. | New submodule APIs possible; no DSL; define read/replay rejection. |
|
|
248
|
+
| 2.2 — Secure Deterministic Composition | One module syntax, resolver, namespaces, canonical composed hash, filesystem guardrails. | Nested/remote imports, discovery, execution redesign. | 2.1; traversal/symlink/cross-machine and hash tests. | Additive DSL 1 and APIs; suite replay metadata. |
|
|
249
|
+
| 2.3 — Parameters + Matrix | Parameter assignments, deterministic bounded expansion/filtering, stable case IDs/indexes, single-case replay. | Dynamic/environment dimensions, distributed scheduler. | 2.2; ordering/cardinality/address-isolation tests. | Additive DSL 1/APIs; matrix bundle migration is versioned only. |
|
|
250
|
+
| 2.4 — Deterministic Batch | Immutable plans/results, errors, ordered serial/parallel execution, bundles and streaming sink. | Queue service, remote workers, shared RNG, parallel fail-fast. | 2.3; worker/reorder independence and memory-bound gates. | New submodule API/schema; child replay links. |
|
|
251
|
+
| 2.5 — Inspect + Explain | Immutable inspection/explanation models for v1/new results, manifests, suites, failures. | Hidden tracing, terminal renderer as model. | 2.1 and suite records through 2.4; evidence completeness/redaction tests. | New APIs/schemas; read-only v1 compatibility. |
|
|
252
|
+
| 2.6 — Structured Semantic Diff | Typed bounded JSON-Pointer diffs and human renderer library hook. | Raw text as model, heuristic sequence moves. | 2.5; typed/MISSING/order/bound cross-version tests. | New APIs/schemas; v1-v1 and v1-new reading only. |
|
|
253
|
+
| 2.7 — CLI Product Surface | Console entry and validate/run/matrix/batch/replay/hash/inspect/explain/diff, streams, exits, JSON. | Any duplicate execution semantics, provider-specific CI. | 2.2–2.6; fresh CLI end-to-end and byte-stable machine output. | CLI/public packaging changes; no DSL beyond predecessors; replay rejection exposed. |
|
|
254
|
+
| 2.8 — Domain-Pack Foundation | Explicit pack/registry/assets/version/hash/manifest integration. | Discovery, auto-load, dynamic YAML, untrusted sandbox claim. | 2.2 and 2.1; exact registration/replay/trust tests. | New submodule and additive declarations; v1 reserved field unchanged. |
|
|
255
|
+
| 2.9 — Oracle Assertions | Bounded final/history/artifact/count/order/occurrence/transition/time oracle operators. | New assertion layer or arbitrary query language. | 2.5; deterministic reports/replay and existing-oracle compatibility. | Additive DSL 1/API schemas; no v1 reinterpretation. |
|
|
256
|
+
| 2.10 — Workflow + Optional Demonstrators | Generic CI docs; deepen ecommerce; only if capacity, payments pack and JSONL/multi-JSON/bundle exports. | Provider semantics, broad pack catalog, CSV. | 2.7–2.9; documented end-to-end suite acceptance. | Additive docs/submodules; explicit bundle versions. |
|
|
257
|
+
| 2.11 — Performance + Scale Hardening | Benchmarks, aggregate bounds, streaming/memory verification, safe optimizations. | Throughput that weakens ordering/bounds. | All retained product features; targets and deterministic limit failures. | Tightening only within predeclared safety bounds; document limits. |
|
|
258
|
+
| 2.12 — Public Contract + Docs Freeze | Freeze exports/errors/DSL/schemas/CLI/docs/security/replay migration notes. | New features. | 2.11; complete contracts and backward tests. | Final additive API/DSL decisions; explicit replay posture. |
|
|
259
|
+
| 2.13 — Packaging + Fresh-Install RC | Version/package/console entry, build wheel/sdist, clean Python 3.11–3.14 installs. | Publication/tag/release. | 2.12; reproducible artifacts and full matrices. | Set RC/final 2.0 strategy; verify v1 remains installable separately. |
|
|
260
|
+
| 2.14 — Independent RC Acceptance | Independent source/artifact/hash/security/replay/CLI acceptance. | Repairs hidden in acceptance, publication. | 2.13; all independent gates green. | None except blocker reporting. |
|
|
261
|
+
| 2.15 — Explicit Publication | Authorized tag, PyPI upload, GitHub release, post-publish verification. | Force push, tag rewrite, further implementation. | 2.14 plus explicit authorization; immutable public hashes. | Publish 2.0.0 only when all contracts pass. |
|
|
262
|
+
|
|
263
|
+
## Velocity-Based Estimate
|
|
264
|
+
|
|
265
|
+
Repository evidence: v1 comprises 17 focused commits over roughly 72 hours, about 3,552 source lines, 280 collected tests plus 136 subtests, and successive implementation/freeze/repair loops. That cadence demonstrates very fast bounded vertical slices, but Phase 2 has deeper shared-schema, composition security, cross-version read, concurrency/order, CLI packaging, and release-review coupling than the mostly sequential Phase 0/1 slices. Estimates assume the same focused single-maintainer velocity but include explicit repair and independent acceptance loops.
|
|
266
|
+
|
|
267
|
+
- **Aggressive:** 5–7 weeks for must-haves, generic CI docs, bounds, and release gates; optional exports/reference additions deferred.
|
|
268
|
+
- **Likely:** 8–12 weeks for all must-haves, should-haves, one deepened reference pack, and robust fresh-install/independent RC loops.
|
|
269
|
+
- **Contingency:** 14–18 weeks if composition portability/security, manifest schema, parallel batch determinism, or replay/read compatibility requires redesign.
|
|
270
|
+
- **Highest risk:** deterministic multi-file composition, because identity, canonical hash, filesystem security, namespace resolution, manifests, replay, and every downstream suite feature converge there.
|
|
271
|
+
- **Critical path:** suite schemas → composition → matrix → batch/bundles → CLI/replay → scale/contracts → RC/acceptance/publication.
|
|
272
|
+
- **Easiest deferrals:** payments reference pack, export adapters, then oracle expansion depth; retain generic CI documentation and hard safety bounds.
|
|
273
|
+
|
|
274
|
+
From the 2026-09-03 freeze, the likely range is roughly late October through late November 2026; therefore late September 2026 is not supported by the measured likely range and is not a target.
|
|
275
|
+
|
|
276
|
+
## V1 Contract Validation
|
|
277
|
+
|
|
278
|
+
Pre-mutation validation ran from repository root `/Users/smshahinulislam/Developer/scenario-engine` on branch `main`. HEAD/main/origin-main were `ee29f52f714e84f17e1048ce24192fcf1c69345a`, tree `2a61915d578dcb1c4ec94049350a24d2cabdf721`, divergence `0/0`, with zero staged, unstaged, or untracked paths. The sole remote was `origin`, resolving to public `imshahinul/deterministic-scenario-engine`; tag `1.0.0` peeled to the baseline and its tree.
|
|
279
|
+
|
|
280
|
+
Validation used CPython 3.14.6 in isolated environment `/tmp/dse-phase2-0a-venv`, pytest 9.1.1, PyYAML 6.0.3, SQLAlchemy 2.0.52, Hypothesis 6.167.1, and Schemathesis 4.25.2, with repository `src` on `PYTHONPATH`. Canonical validation is `python -m pytest -q`; collection is `python -m pytest --collect-only -q`. It collected 280 tests and the full run passed: `280 passed, 136 subtests passed` in 41.94 seconds. Focused golden enforcement passed 4 tests and 3 subtests.
|
|
281
|
+
|
|
282
|
+
The actively enforced SHA-256 result goldens are:
|
|
283
|
+
|
|
284
|
+
| Case | SHA-256 | Enforcement |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| Cart | `cffc2e482f304ab18d39f96166e3e1be78b117a86bf0ce8ad0e22973677001b5` | Phase 1.0c result/canonical contract and Phase 1.0e RC test |
|
|
287
|
+
| Structured control flow | `86511d8c750272283eb1039a6e1039c8faa11cb5945c76aec41d9f5a71588e2b` | Phase 1.0c literal flow hash and Phase 1.0e RC test |
|
|
288
|
+
| Oracle/provenance | `5760aee1293d2d264d841621de08734358b3eb4ca54ef3e08e5a0b97f8f16cdd` | Phase 1.0c advanced result and Phase 1.0e RC test |
|
|
289
|
+
|
|
290
|
+
The Phase 1.0b tests enforce exact top-level exports, errors, lazy optional imports, and the primary journey. Phase 1.0c enforces YAML/DSL 1, Decimal semantics, result/manifest schema, canonical bytes, and exact replay compatibility. Phase 1.0d enforces documentation, examples, links, goldens, and the normative compatibility contract. Phase 1.0e enforces package/distribution/version/license/dependencies/pytest entry point. Public GitHub identity and PyPI 1.0.0 identity were independently confirmed; PyPI artifact hashes equal the immutable values above.
|
|
291
|
+
|
|
292
|
+
## Frozen Decision Register
|
|
293
|
+
|
|
294
|
+
| Decision | Frozen Value | Rationale |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| CLI | MUST_HAVE; `scenario` with validate/run/replay/hash/inspect/explain/diff/matrix/batch; library orchestration | Coherent end-to-end product without a second engine. |
|
|
297
|
+
| Composition | MUST_HAVE; one local namespaced `composition.modules` mechanism, depth-one, alias/content identity | Minimizes highest-risk semantics and makes suites reproducible. |
|
|
298
|
+
| Matrix | MUST_HAVE; ordered Cartesian expansion, pure filters, original index addressing, bounded stable case ID | Cases remain independently reproducible and order-safe. |
|
|
299
|
+
| Batch | MUST_HAVE; immutable explicit plans, independent contexts, plan-ordered results, bounded streaming | Worker/order independence is mandatory. |
|
|
300
|
+
| InspectExplain | MUST_HAVE; immutable structured library evidence, downstream renderers, no hidden trace | Existing deterministic records are sufficient authority. |
|
|
301
|
+
| StructuredDiff | MUST_HAVE; typed JSON-Pointer records, first/complete bounded modes | Semantic comparison, not raw text, supports CI and replay diagnosis. |
|
|
302
|
+
| OracleExpansion | SHOULD_HAVE; additive oracle assertions for result records | Existing oracle is the correct layer; no redundant abstraction. |
|
|
303
|
+
| DomainPacks | MUST_HAVE; explicit versioned declarative bundles distinct from generator plugins | Activates reusable domain semantics without discovery. |
|
|
304
|
+
| ReferencePacks | OPTIONAL; deepen ecommerce, at most one payments lifecycle addition | Demonstration value, not breadth. |
|
|
305
|
+
| ExportAdapters | OPTIONAL; JSONL/multi-JSON/fixture/bundle; CSV deferred | Downstream portability without alternate state/execution. |
|
|
306
|
+
| CIDeveloperWorkflow | SHOULD_HAVE; generic CLI/library docs and artifacts | Makes product operable without provider semantics. |
|
|
307
|
+
| PerformanceScale | SHOULD_HAVE; frozen hard bounds and baseline targets before optimization | Bounded deterministic behavior is release integrity. |
|
|
308
|
+
| ReleaseVersionStrategy | Eventual package 2.0.0; no version change in 2.0A | New suite/manifest/CLI contract is materially major. |
|
|
309
|
+
| DSLVersionStrategy | Retain DSL version 1 with additive, non-reinterpreting syntax | Package and DSL compatibility are separate. |
|
|
310
|
+
| V1ManifestReading | Supported through non-executing versioned read model | Enables diagnostics without replay promise. |
|
|
311
|
+
| V1Inspection | Supported | Structured read is safe and useful. |
|
|
312
|
+
| V1Diff | Supported, including v1-to-future normalized artifacts | Diff compatibility does not imply execution compatibility. |
|
|
313
|
+
| V1ExecutionReplay | Explicitly rejected by default under policy A; frozen v1 installation remains executor | No complete v1 executor is promised inside Phase 2. |
|
|
314
|
+
| NetworkImports | Forbidden | Network state cannot be deterministic or safely bounded here. |
|
|
315
|
+
| AutomaticDiscovery | Forbidden for plugins and domain packs; no entry-point/global/dynamic loading | Explicit registration preserves trust and reproducibility. |
|