diff --git a/docs/guides/getting-started.md b/docs/guides/getting-started.md index 425552c..e91ac78 100644 --- a/docs/guides/getting-started.md +++ b/docs/guides/getting-started.md @@ -425,7 +425,7 @@ From here, explore the [example models](../examples/index.md) or the [Rosetta St ## Interactive Notebook /// marimo-embed-file - filepath: packages/gds-examples/guides/getting_started/notebook.py + filepath: packages/gds-examples/notebooks/getting_started.py height: 800px mode: read /// @@ -433,22 +433,22 @@ From here, explore the [example models](../examples/index.md) or the [Rosetta St To run the notebook locally: ```bash -uv run marimo run packages/gds-examples/guides/getting_started/notebook.py +uv run marimo run packages/gds-examples/notebooks/getting_started.py ``` Run the test suite: ```bash -uv run --package gds-examples pytest packages/gds-examples/guides/getting_started/ -v +uv run --package gds-examples pytest packages/gds-examples/tests/test_getting_started.py -v ``` ## Source Files | File | Purpose | |------|---------| -| [`stage1_minimal.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/stage1_minimal.py) | Minimal heater model | -| [`stage2_feedback.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/stage2_feedback.py) | Feedback loop with policies | -| [`stage3_dsl.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/stage3_dsl.py) | gds-control DSL version | -| [`stage4_verify_viz.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/stage4_verify_viz.py) | Verification and visualization | -| [`stage5_query.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/stage5_query.py) | SpecQuery API | -| [`notebook.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/getting_started/notebook.py) | Interactive marimo notebook | +| [`stage1_minimal.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/getting_started/stage1_minimal.py) | Minimal heater model | +| [`stage2_feedback.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/getting_started/stage2_feedback.py) | Feedback loop with policies | +| [`stage3_dsl.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/getting_started/stage3_dsl.py) | gds-control DSL version | +| [`stage4_verify_viz.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/getting_started/stage4_verify_viz.py) | Verification and visualization | +| [`stage5_query.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/getting_started/stage5_query.py) | SpecQuery API | +| [`getting_started.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/notebooks/getting_started.py) | Interactive marimo notebook | diff --git a/docs/guides/interoperability.md b/docs/guides/interoperability.md index ae08c3e..c8c0582 100644 --- a/docs/guides/interoperability.md +++ b/docs/guides/interoperability.md @@ -235,7 +235,7 @@ This validates GDS as an **interoperability substrate**, not just a modeling fra ### Nash Equilibrium Analysis /// marimo-embed-file - filepath: packages/gds-examples/guides/nash_equilibrium/notebook.py + filepath: packages/gds-examples/notebooks/nash_equilibrium.py height: 800px mode: read /// @@ -244,8 +244,7 @@ To run locally: ```bash uv sync --all-packages --extra nash -cd packages/gds-examples && \ - uv run marimo run guides/nash_equilibrium/notebook.py +uv run marimo run packages/gds-examples/notebooks/nash_equilibrium.py ``` ```bash @@ -257,7 +256,7 @@ uv run --package gds-examples pytest \ ### Evolution of Trust Simulation /// marimo-embed-file - filepath: packages/gds-examples/guides/evolution_of_trust/notebook.py + filepath: packages/gds-examples/notebooks/evolution_of_trust.py height: 800px mode: read /// @@ -265,8 +264,7 @@ uv run --package gds-examples pytest \ To run locally: ```bash -cd packages/gds-examples && \ - uv run marimo run guides/evolution_of_trust/notebook.py +uv run marimo run packages/gds-examples/notebooks/evolution_of_trust.py ``` ```bash @@ -283,8 +281,8 @@ uv run --package gds-examples pytest \ | `games/evolution_of_trust/model.py` | OGS structure with Nicky Case payoffs | | `games/evolution_of_trust/strategies.py` | 8 strategy implementations | | `games/evolution_of_trust/tournament.py` | Match, tournament, evolutionary dynamics | -| `guides/nash_equilibrium/notebook.py` | Interactive Nash analysis notebook | -| `guides/evolution_of_trust/notebook.py` | Interactive simulation notebook | +| `notebooks/nash_equilibrium.py` | Interactive Nash analysis notebook | +| `notebooks/evolution_of_trust.py` | Interactive simulation notebook | All paths relative to `packages/gds-examples/`. diff --git a/docs/guides/rosetta-stone.md b/docs/guides/rosetta-stone.md index 856f556..e536afe 100644 --- a/docs/guides/rosetta-stone.md +++ b/docs/guides/rosetta-stone.md @@ -308,7 +308,7 @@ h_theta : X -> X where h = f . g This is the "Rosetta Stone" -- the same mathematical structure expressed in different domain languages, all grounded in GDS theory. ```python -from guides.rosetta.comparison import canonical_spectrum_table +from gds_examples.rosetta.comparison import canonical_spectrum_table print(canonical_spectrum_table()) ``` @@ -316,7 +316,7 @@ print(canonical_spectrum_table()) ## Interactive Notebook /// marimo-embed-file - filepath: packages/gds-examples/guides/rosetta/notebook.py + filepath: packages/gds-examples/notebooks/rosetta.py height: 800px mode: read /// @@ -324,21 +324,21 @@ print(canonical_spectrum_table()) To run the notebook locally: ```bash -uv run marimo run packages/gds-examples/guides/rosetta/notebook.py +uv run marimo run packages/gds-examples/notebooks/rosetta.py ``` Run the test suite: ```bash -uv run --package gds-examples pytest packages/gds-examples/guides/rosetta/ -v +uv run --package gds-examples pytest packages/gds-examples/tests/test_rosetta.py -v ``` ## Source Files | File | Purpose | |------|---------| -| [`stockflow_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/rosetta/stockflow_view.py) | Stock-flow DSL model | -| [`control_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/rosetta/control_view.py) | Control DSL model | -| [`game_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/rosetta/game_view.py) | Game theory DSL model | -| [`comparison.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/rosetta/comparison.py) | Cross-domain canonical comparison | -| [`notebook.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/rosetta/notebook.py) | Interactive marimo notebook | +| [`stockflow_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/rosetta/stockflow_view.py) | Stock-flow DSL model | +| [`control_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/rosetta/control_view.py) | Control DSL model | +| [`game_view.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/rosetta/game_view.py) | Game theory DSL model | +| [`comparison.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/rosetta/comparison.py) | Cross-domain canonical comparison | +| [`rosetta.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/notebooks/rosetta.py) | Interactive marimo notebook | diff --git a/docs/guides/verification.md b/docs/guides/verification.md index a9088da..4a2f4b0 100644 --- a/docs/guides/verification.md +++ b/docs/guides/verification.md @@ -118,7 +118,7 @@ The core workflow: build a broken model, run checks, inspect findings, fix error ```python from gds.verification.engine import verify -from guides.verification.broken_models import ( +from gds_examples.verification.broken_models import ( dangling_wiring_system, fixed_pipeline_system, ) @@ -375,7 +375,7 @@ for finding in report.findings: ## Interactive Notebook /// marimo-embed-file - filepath: packages/gds-examples/guides/verification/notebook.py + filepath: packages/gds-examples/notebooks/verification.py height: 800px mode: read /// @@ -383,20 +383,20 @@ for finding in report.findings: To run the notebook locally: ```bash -uv run marimo run packages/gds-examples/guides/verification/notebook.py +uv run marimo run packages/gds-examples/notebooks/verification.py ``` Run the test suite: ```bash -uv run --package gds-examples pytest packages/gds-examples/guides/verification/ -v +uv run --package gds-examples pytest packages/gds-examples/tests/test_verification_guide.py -v ``` ## Source Files | File | Purpose | |------|---------| -| [`broken_models.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/verification/broken_models.py) | Deliberately broken models for each check | -| [`verification_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/verification/verification_demo.py) | Generic and semantic check demos | -| [`domain_checks_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/verification/domain_checks_demo.py) | StockFlow domain check demos | -| [`notebook.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/verification/notebook.py) | Interactive marimo notebook | +| [`broken_models.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/verification/broken_models.py) | Deliberately broken models for each check | +| [`verification_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/verification/verification_demo.py) | Generic and semantic check demos | +| [`domain_checks_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/verification/domain_checks_demo.py) | StockFlow domain check demos | +| [`notebook.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/notebooks/verification.py) | Interactive marimo notebook | diff --git a/docs/guides/visualization.md b/docs/guides/visualization.md index 9694e88..97bde42 100644 --- a/docs/guides/visualization.md +++ b/docs/guides/visualization.md @@ -206,7 +206,7 @@ mermaid_str = system_to_mermaid(system, theme="dark") ## Interactive Notebook /// marimo-embed-file - filepath: packages/gds-examples/guides/visualization/notebook.py + filepath: packages/gds-examples/notebooks/visualization.py height: 800px mode: read /// @@ -214,20 +214,20 @@ mermaid_str = system_to_mermaid(system, theme="dark") To run the notebook locally: ```bash -uv run marimo run packages/gds-examples/guides/visualization/notebook.py +uv run marimo run packages/gds-examples/notebooks/visualization.py ``` Run the test suite: ```bash -uv run --package gds-examples pytest packages/gds-examples/guides/visualization/ -v +uv run --package gds-examples pytest packages/gds-examples/tests/test_visualization_guide.py -v ``` ## Source Files | File | Purpose | |------|---------| -| [`all_views_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/visualization/all_views_demo.py) | All 6 view types on the SIR model | -| [`theme_customization.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/visualization/theme_customization.py) | 5 built-in theme demos | -| [`cross_dsl_views.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/visualization/cross_dsl_views.py) | Cross-DSL visualization comparison | -| [`notebook.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/guides/visualization/notebook.py) | Interactive marimo notebook | +| [`all_views_demo.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/visualization/all_views_demo.py) | All 6 view types on the SIR model | +| [`theme_customization.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/visualization/theme_customization.py) | 5 built-in theme demos | +| [`cross_dsl_views.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/gds_examples/visualization/cross_dsl_views.py) | Cross-DSL visualization comparison | +| [`visualization.py`](https://github.com/BlockScience/gds-core/blob/main/packages/gds-examples/notebooks/visualization.py) | Interactive marimo notebook | diff --git a/packages/gds-examples/guides/__init__.py b/packages/gds-examples/gds_examples/__init__.py similarity index 100% rename from packages/gds-examples/guides/__init__.py rename to packages/gds-examples/gds_examples/__init__.py diff --git a/packages/gds-examples/guides/getting_started/__init__.py b/packages/gds-examples/gds_examples/getting_started/__init__.py similarity index 100% rename from packages/gds-examples/guides/getting_started/__init__.py rename to packages/gds-examples/gds_examples/getting_started/__init__.py diff --git a/packages/gds-examples/guides/getting_started/stage1_minimal.py b/packages/gds-examples/gds_examples/getting_started/stage1_minimal.py similarity index 100% rename from packages/gds-examples/guides/getting_started/stage1_minimal.py rename to packages/gds-examples/gds_examples/getting_started/stage1_minimal.py diff --git a/packages/gds-examples/guides/getting_started/stage2_feedback.py b/packages/gds-examples/gds_examples/getting_started/stage2_feedback.py similarity index 100% rename from packages/gds-examples/guides/getting_started/stage2_feedback.py rename to packages/gds-examples/gds_examples/getting_started/stage2_feedback.py diff --git a/packages/gds-examples/guides/getting_started/stage3_dsl.py b/packages/gds-examples/gds_examples/getting_started/stage3_dsl.py similarity index 100% rename from packages/gds-examples/guides/getting_started/stage3_dsl.py rename to packages/gds-examples/gds_examples/getting_started/stage3_dsl.py diff --git a/packages/gds-examples/guides/getting_started/stage4_verify_viz.py b/packages/gds-examples/gds_examples/getting_started/stage4_verify_viz.py similarity index 98% rename from packages/gds-examples/guides/getting_started/stage4_verify_viz.py rename to packages/gds-examples/gds_examples/getting_started/stage4_verify_viz.py index d571819..b4b8d0f 100644 --- a/packages/gds-examples/guides/getting_started/stage4_verify_viz.py +++ b/packages/gds-examples/gds_examples/getting_started/stage4_verify_viz.py @@ -131,7 +131,7 @@ def generate_canonical_view(spec: GDSSpec) -> str: if __name__ == "__main__": - from guides.getting_started.stage3_dsl import build_spec, build_system + from gds_examples.getting_started.stage3_dsl import build_spec, build_system spec = build_spec() system = build_system() diff --git a/packages/gds-examples/guides/getting_started/stage5_query.py b/packages/gds-examples/gds_examples/getting_started/stage5_query.py similarity index 96% rename from packages/gds-examples/guides/getting_started/stage5_query.py rename to packages/gds-examples/gds_examples/getting_started/stage5_query.py index 1f14b92..d317e09 100644 --- a/packages/gds-examples/guides/getting_started/stage5_query.py +++ b/packages/gds-examples/gds_examples/getting_started/stage5_query.py @@ -22,7 +22,7 @@ def build_query(spec: GDSSpec | None = None) -> SpecQuery: """Create a SpecQuery for the thermostat model.""" if spec is None: - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() return SpecQuery(spec) @@ -80,7 +80,7 @@ def show_dependency_graph(query: SpecQuery) -> dict[str, set[str]]: if __name__ == "__main__": - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() query = build_query(spec) diff --git a/packages/gds-examples/guides/evolution_of_trust/__init__.py b/packages/gds-examples/gds_examples/rosetta/__init__.py similarity index 100% rename from packages/gds-examples/guides/evolution_of_trust/__init__.py rename to packages/gds-examples/gds_examples/rosetta/__init__.py diff --git a/packages/gds-examples/guides/rosetta/comparison.py b/packages/gds-examples/gds_examples/rosetta/comparison.py similarity index 93% rename from packages/gds-examples/guides/rosetta/comparison.py rename to packages/gds-examples/gds_examples/rosetta/comparison.py index 040a9e2..373f257 100644 --- a/packages/gds-examples/guides/rosetta/comparison.py +++ b/packages/gds-examples/gds_examples/rosetta/comparison.py @@ -16,9 +16,9 @@ """ from gds.canonical import CanonicalGDS, project_canonical -from guides.rosetta.control_view import build_spec as build_control_spec -from guides.rosetta.game_view import build_spec as build_game_spec -from guides.rosetta.stockflow_view import build_spec as build_sf_spec +from gds_examples.rosetta.control_view import build_spec as build_control_spec +from gds_examples.rosetta.game_view import build_spec as build_game_spec +from gds_examples.rosetta.stockflow_view import build_spec as build_sf_spec def build_all_canonicals() -> dict[str, CanonicalGDS]: diff --git a/packages/gds-examples/guides/rosetta/control_view.py b/packages/gds-examples/gds_examples/rosetta/control_view.py similarity index 100% rename from packages/gds-examples/guides/rosetta/control_view.py rename to packages/gds-examples/gds_examples/rosetta/control_view.py diff --git a/packages/gds-examples/guides/rosetta/game_view.py b/packages/gds-examples/gds_examples/rosetta/game_view.py similarity index 100% rename from packages/gds-examples/guides/rosetta/game_view.py rename to packages/gds-examples/gds_examples/rosetta/game_view.py diff --git a/packages/gds-examples/guides/rosetta/stockflow_view.py b/packages/gds-examples/gds_examples/rosetta/stockflow_view.py similarity index 100% rename from packages/gds-examples/guides/rosetta/stockflow_view.py rename to packages/gds-examples/gds_examples/rosetta/stockflow_view.py diff --git a/packages/gds-examples/guides/nash_equilibrium/__init__.py b/packages/gds-examples/gds_examples/verification/__init__.py similarity index 100% rename from packages/gds-examples/guides/nash_equilibrium/__init__.py rename to packages/gds-examples/gds_examples/verification/__init__.py diff --git a/packages/gds-examples/guides/verification/broken_models.py b/packages/gds-examples/gds_examples/verification/broken_models.py similarity index 100% rename from packages/gds-examples/guides/verification/broken_models.py rename to packages/gds-examples/gds_examples/verification/broken_models.py diff --git a/packages/gds-examples/guides/verification/domain_checks_demo.py b/packages/gds-examples/gds_examples/verification/domain_checks_demo.py similarity index 100% rename from packages/gds-examples/guides/verification/domain_checks_demo.py rename to packages/gds-examples/gds_examples/verification/domain_checks_demo.py diff --git a/packages/gds-examples/guides/verification/verification_demo.py b/packages/gds-examples/gds_examples/verification/verification_demo.py similarity index 99% rename from packages/gds-examples/guides/verification/verification_demo.py rename to packages/gds-examples/gds_examples/verification/verification_demo.py index 8bc9d1f..53ef962 100644 --- a/packages/gds-examples/guides/verification/verification_demo.py +++ b/packages/gds-examples/gds_examples/verification/verification_demo.py @@ -29,7 +29,7 @@ check_completeness, check_determinism, ) -from guides.verification.broken_models import ( +from gds_examples.verification.broken_models import ( covariant_cycle_system, dangling_wiring_system, empty_canonical_spec, diff --git a/packages/gds-examples/guides/rosetta/__init__.py b/packages/gds-examples/gds_examples/visualization/__init__.py similarity index 100% rename from packages/gds-examples/guides/rosetta/__init__.py rename to packages/gds-examples/gds_examples/visualization/__init__.py diff --git a/packages/gds-examples/guides/visualization/all_views_demo.py b/packages/gds-examples/gds_examples/visualization/all_views_demo.py similarity index 100% rename from packages/gds-examples/guides/visualization/all_views_demo.py rename to packages/gds-examples/gds_examples/visualization/all_views_demo.py diff --git a/packages/gds-examples/guides/visualization/cross_dsl_views.py b/packages/gds-examples/gds_examples/visualization/cross_dsl_views.py similarity index 100% rename from packages/gds-examples/guides/visualization/cross_dsl_views.py rename to packages/gds-examples/gds_examples/visualization/cross_dsl_views.py diff --git a/packages/gds-examples/guides/visualization/theme_customization.py b/packages/gds-examples/gds_examples/visualization/theme_customization.py similarity index 100% rename from packages/gds-examples/guides/visualization/theme_customization.py rename to packages/gds-examples/gds_examples/visualization/theme_customization.py diff --git a/packages/gds-examples/guides/evolution_of_trust/conftest.py b/packages/gds-examples/guides/evolution_of_trust/conftest.py deleted file mode 100644 index 34ce60c..0000000 --- a/packages/gds-examples/guides/evolution_of_trust/conftest.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Path setup for Evolution of Trust guide tests. - -Adds the games/ directory to sys.path so that imports like -``from evolution_of_trust.model import ...`` resolve correctly. -""" - -import sys -from pathlib import Path - -_examples_root = Path(__file__).resolve().parent.parent.parent - -for subdir in ("games",): - path = str(_examples_root / subdir) - if path not in sys.path: - sys.path.insert(0, path) diff --git a/packages/gds-examples/guides/getting_started/README.md b/packages/gds-examples/guides/getting_started/README.md deleted file mode 100644 index a00a084..0000000 --- a/packages/gds-examples/guides/getting_started/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Build Your First Model - -A progressive tutorial that walks through the GDS framework using a -thermostat/heater system as the running example. Each stage builds on the -previous one, introducing new concepts incrementally. - -## Prerequisites - -- Python 3.12+ -- `gds-framework`, `gds-viz`, and `gds-control` installed - (`uv sync --all-packages` from the repo root) - -## Learning Path - -| Stage | File | Concepts | -|-------|------|----------| -| 1 | `stage1_minimal.py` | Entity, BoundaryAction, Mechanism, `>>` composition, GDSSpec | -| 2 | `stage2_feedback.py` | Policy, `.loop()` temporal composition, parameters | -| 3 | `stage3_dsl.py` | gds-control DSL: ControlModel, compile_model, compile_to_system | -| 4 | `stage4_verify_viz.py` | Generic checks (G-001..G-006), semantic checks, Mermaid visualization | -| 5 | `stage5_query.py` | SpecQuery API: parameter influence, entity updates, causal chains | - -## Running - -Run any stage directly to see its output: - -```bash -uv run python -m guides.getting_started.stage1_minimal -``` - -Run the test suite: - -```bash -uv run --package gds-examples pytest packages/gds-examples/guides/getting_started/ -v -``` diff --git a/packages/gds-examples/guides/nash_equilibrium/conftest.py b/packages/gds-examples/guides/nash_equilibrium/conftest.py deleted file mode 100644 index 74269f3..0000000 --- a/packages/gds-examples/guides/nash_equilibrium/conftest.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Path setup for Nash equilibrium guide tests. - -Adds the games/ directory to sys.path so that imports like -``from prisoners_dilemma_nash.model import ...`` resolve correctly. -""" - -import sys -from pathlib import Path - -_examples_root = Path(__file__).resolve().parent.parent.parent - -for subdir in ("games",): - path = str(_examples_root / subdir) - if path not in sys.path: - sys.path.insert(0, path) diff --git a/packages/gds-examples/guides/rosetta/README.md b/packages/gds-examples/guides/rosetta/README.md deleted file mode 100644 index e960f4a..0000000 --- a/packages/gds-examples/guides/rosetta/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Cross-Domain Rosetta Stone - -Three views of the same resource pool problem, each compiled to a GDS canonical form. - -## The Resource Pool Scenario - -A shared resource pool (water reservoir, inventory, commons) that agents interact -with through supply, consumption, or extraction. The same real-world system is -modeled through three different DSL lenses. - -## Views - -| View | Module | DSL | Character | -|------|--------|-----|-----------| -| Stock-Flow | `stockflow_view.py` | `stockflow` | Dynamical -- accumulation via rates | -| Control | `control_view.py` | `gds_control` | Dynamical -- regulation toward setpoint | -| Game Theory | `game_view.py` | `ogs` | Strategic -- stateless extraction game | - -## Canonical Spectrum - -All three views compile to `GDSSpec` and project to the canonical `h = f . g` -decomposition. The comparison table (`comparison.py`) shows how they differ: - -``` -View |X| |U| |g| |f| Form Character ------------------------------------------------------------------------ -Stock-Flow 1 2 3 1 h_theta = f_theta . g_theta Dynamical -Control 1 1 2 1 h_theta = f_theta . g_theta Dynamical -Game Theory 0 1 3 0 h = g Strategic -``` - -Key insight: **the same GDS composition algebra underlies all three**, but each -DSL decomposes the problem differently: - -- **Stock-Flow**: State `X` is the resource level, updated by net flow rates. - Two exogenous parameters (supply rate, consumption rate) drive the dynamics. -- **Control**: State `X` is the resource level, regulated by a feedback controller - that tracks an exogenous reference setpoint. -- **Game Theory**: No state -- pure strategic interaction. Two agents simultaneously - choose extraction amounts; a payoff function determines the outcome. - -## Running - -```bash -# Run all tests -uv run --package gds-examples pytest packages/gds-examples/guides/rosetta/ -v - -# Print the comparison table -uv run --package gds-examples python -m guides.rosetta.comparison -``` - -## Unified Transition Calculus - -The GDS canonical form provides a unified notation for all three: - -``` -h_theta : X -> X where h = f . g -``` - -- When `|f| > 0` and `|g| > 0`: **Dynamical** system (stock-flow, control) -- When `|f| = 0` and `|g| > 0`: **Strategic** system (game theory) -- When `|g| = 0` and `|f| > 0`: **Autonomous** system (no policy) - -This is the "Rosetta Stone" -- the same mathematical structure expressed in -different domain languages, all grounded in GDS theory. diff --git a/packages/gds-examples/guides/verification/__init__.py b/packages/gds-examples/guides/verification/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/packages/gds-examples/guides/visualization/__init__.py b/packages/gds-examples/guides/visualization/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/packages/gds-examples/guides/visualization/conftest.py b/packages/gds-examples/guides/visualization/conftest.py deleted file mode 100644 index e0a8a8d..0000000 --- a/packages/gds-examples/guides/visualization/conftest.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Path setup for visualization guide tests. - -Adds the stockflow/ and control/ directories to sys.path so that -imports like ``from sir_epidemic.model import ...`` and -``from double_integrator.model import ...`` resolve correctly. -""" - -import sys -from pathlib import Path - -_examples_root = Path(__file__).resolve().parent.parent.parent - -for subdir in ("stockflow", "control"): - path = str(_examples_root / subdir) - if path not in sys.path: - sys.path.insert(0, path) diff --git a/packages/gds-examples/guides/evolution_of_trust/notebook.py b/packages/gds-examples/notebooks/evolution_of_trust.py similarity index 98% rename from packages/gds-examples/guides/evolution_of_trust/notebook.py rename to packages/gds-examples/notebooks/evolution_of_trust.py index bb47475..6349e5a 100644 --- a/packages/gds-examples/guides/evolution_of_trust/notebook.py +++ b/packages/gds-examples/notebooks/evolution_of_trust.py @@ -5,11 +5,19 @@ built on an OGS game structure. Run interactively: - uv run marimo edit guides/evolution_of_trust/notebook.py + uv run marimo edit notebooks/evolution_of_trust.py Run as read-only app: - uv run marimo run guides/evolution_of_trust/notebook.py + uv run marimo run notebooks/evolution_of_trust.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "plotly>=5.0", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -35,7 +43,7 @@ def model_setup(): import sys from pathlib import Path - _examples_root = Path(__file__).resolve().parent.parent.parent + _examples_root = Path(__file__).resolve().parent.parent _games_path = str(_examples_root / "games") if _games_path not in sys.path: sys.path.insert(0, _games_path) diff --git a/packages/gds-examples/guides/getting_started/notebook.py b/packages/gds-examples/notebooks/getting_started.py similarity index 90% rename from packages/gds-examples/guides/getting_started/notebook.py rename to packages/gds-examples/notebooks/getting_started.py index c73e884..d419f04 100644 --- a/packages/gds-examples/guides/getting_started/notebook.py +++ b/packages/gds-examples/notebooks/getting_started.py @@ -1,8 +1,15 @@ """Interactive Getting Started guide for GDS — marimo notebook. A progressive 5-stage tutorial that teaches GDS fundamentals using a -thermostat control system. Run with: marimo run notebook.py +thermostat control system. Run with: marimo run notebooks/getting_started.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -84,8 +91,10 @@ def _(mo): @app.cell def _(mo): - from guides.getting_started.stage1_minimal import build_spec as _build_spec_s1 - from guides.getting_started.stage1_minimal import build_system as _build_system_s1 + from gds_examples.getting_started.stage1_minimal import build_spec as _build_spec_s1 + from gds_examples.getting_started.stage1_minimal import ( + build_system as _build_system_s1, + ) _spec_s1 = _build_spec_s1() _system_s1 = _build_system_s1() @@ -146,10 +155,10 @@ def _(mo): @app.cell def _(mo): - from guides.getting_started.stage2_feedback import ( + from gds_examples.getting_started.stage2_feedback import ( build_spec as _build_spec_s2, ) - from guides.getting_started.stage2_feedback import ( + from gds_examples.getting_started.stage2_feedback import ( build_system as _build_system_s2, ) @@ -211,13 +220,13 @@ def _(mo): @app.cell def _(mo): - from guides.getting_started.stage3_dsl import ( + from gds_examples.getting_started.stage3_dsl import ( build_canonical as _build_canonical_s3, ) - from guides.getting_started.stage3_dsl import ( + from gds_examples.getting_started.stage3_dsl import ( build_spec as _build_spec_s3, ) - from guides.getting_started.stage3_dsl import ( + from gds_examples.getting_started.stage3_dsl import ( build_system as _build_system_s3, ) @@ -287,25 +296,25 @@ def _(mo): @app.cell def _(mo): - from guides.getting_started.stage3_dsl import ( + from gds_examples.getting_started.stage3_dsl import ( build_spec as _build_spec_s4, ) - from guides.getting_started.stage3_dsl import ( + from gds_examples.getting_started.stage3_dsl import ( build_system as _build_system_s4, ) - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage4_verify_viz import ( generate_architecture_view as _gen_arch, ) - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage4_verify_viz import ( generate_canonical_view as _gen_canon, ) - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage4_verify_viz import ( generate_structural_view as _gen_struct, ) - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage4_verify_viz import ( run_generic_checks as _run_generic, ) - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage4_verify_viz import ( run_semantic_checks as _run_semantic, ) @@ -383,22 +392,22 @@ def _(mo): @app.cell def _(mo): - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( build_query as _build_query, ) - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( show_blocks_by_role as _show_blocks_by_role, ) - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( show_causal_chain as _show_causal_chain, ) - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( show_dependency_graph as _show_dep_graph, ) - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( show_entity_updates as _show_entity_updates, ) - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( show_param_influence as _show_param_influence, ) diff --git a/packages/gds-examples/guides/nash_equilibrium/notebook.py b/packages/gds-examples/notebooks/nash_equilibrium.py similarity index 97% rename from packages/gds-examples/guides/nash_equilibrium/notebook.py rename to packages/gds-examples/notebooks/nash_equilibrium.py index 72a2984..a284d52 100644 --- a/packages/gds-examples/guides/nash_equilibrium/notebook.py +++ b/packages/gds-examples/notebooks/nash_equilibrium.py @@ -4,11 +4,19 @@ Nash equilibrium computation -> dominance and Pareto analysis. Run interactively: - uv run marimo edit guides/nash_equilibrium/notebook.py + uv run marimo edit notebooks/nash_equilibrium.py Run as read-only app: - uv run marimo run guides/nash_equilibrium/notebook.py + uv run marimo run notebooks/nash_equilibrium.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "nashpy>=0.0.41", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -34,7 +42,7 @@ def model_setup(): import sys from pathlib import Path - _examples_root = Path(__file__).resolve().parent.parent.parent + _examples_root = Path(__file__).resolve().parent.parent _games_path = str(_examples_root / "games") if _games_path not in sys.path: sys.path.insert(0, _games_path) diff --git a/packages/gds-examples/guides/rosetta/notebook.py b/packages/gds-examples/notebooks/rosetta.py similarity index 96% rename from packages/gds-examples/guides/rosetta/notebook.py rename to packages/gds-examples/notebooks/rosetta.py index 124f10d..10781ba 100644 --- a/packages/gds-examples/guides/rosetta/notebook.py +++ b/packages/gds-examples/notebooks/rosetta.py @@ -4,8 +4,15 @@ (Stock-Flow, Control, Game Theory), showing how they all map to the GDS canonical form. -Run with: marimo run guides/rosetta/notebook.py +Run with: marimo run notebooks/rosetta.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -322,10 +329,11 @@ def _(): @app.cell def _(): + from gds_examples.rosetta import comparison, game_view + from gds_examples.rosetta import control_view as ctrl_view + from gds_examples.rosetta import stockflow_view as sf_view + import gds_viz - from guides.rosetta import comparison, game_view - from guides.rosetta import control_view as ctrl_view - from guides.rosetta import stockflow_view as sf_view return comparison, ctrl_view, game_view, gds_viz, sf_view diff --git a/packages/gds-examples/guides/verification/notebook.py b/packages/gds-examples/notebooks/verification.py similarity index 96% rename from packages/gds-examples/guides/verification/notebook.py rename to packages/gds-examples/notebooks/verification.py index b201c23..48e92f2 100644 --- a/packages/gds-examples/guides/verification/notebook.py +++ b/packages/gds-examples/notebooks/verification.py @@ -5,11 +5,18 @@ fix-and-reverify workflow in action. Run interactively: - uv run marimo edit guides/verification/notebook.py + uv run marimo edit notebooks/verification.py Run as read-only app: - uv run marimo run guides/verification/notebook.py + uv run marimo run notebooks/verification.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -88,6 +95,14 @@ def generic_selector(mo): @app.cell def run_generic_check(mo, generic_dropdown): + from gds_examples.verification.broken_models import ( + covariant_cycle_system, + dangling_wiring_system, + direction_contradiction_system, + incomplete_signature_system, + type_mismatch_system, + ) + from gds.verification.engine import verify from gds.verification.generic_checks import ( check_g001_domain_codomain_matching, @@ -97,13 +112,6 @@ def run_generic_check(mo, generic_dropdown): check_g005_sequential_type_compatibility, check_g006_covariant_acyclicity, ) - from guides.verification.broken_models import ( - covariant_cycle_system, - dangling_wiring_system, - direction_contradiction_system, - incomplete_signature_system, - type_mismatch_system, - ) _models = { "dangling": ( @@ -196,14 +204,15 @@ def fix_reverify_header(mo): @app.cell def fix_reverify_demo(mo): - from gds.verification.engine import verify as _verify - from guides.verification.broken_models import ( + from gds_examples.verification.broken_models import ( dangling_wiring_system as _dangling_wiring_system, ) - from guides.verification.broken_models import ( + from gds_examples.verification.broken_models import ( fixed_pipeline_system, ) + from gds.verification.engine import verify as _verify + _broken_report = _verify(_dangling_wiring_system()) _fixed_report = _verify(fixed_pipeline_system()) @@ -289,16 +298,17 @@ def semantic_selector(mo): @app.cell def run_semantic_check(mo, semantic_dropdown): + from gds_examples.verification.broken_models import ( + empty_canonical_spec, + orphan_state_spec, + write_conflict_spec, + ) + from gds.verification.spec_checks import ( check_canonical_wellformedness, check_completeness, check_determinism, ) - from guides.verification.broken_models import ( - empty_canonical_spec, - orphan_state_spec, - write_conflict_spec, - ) _specs = { "orphan": ( @@ -370,7 +380,7 @@ def comparison_header(mo): @app.cell def comparison_demo(mo): - from guides.verification.verification_demo import ( + from gds_examples.verification.verification_demo import ( demo_generic_vs_semantic, ) @@ -444,11 +454,12 @@ def domain_selector(mo): @app.cell def run_domain_check(mo, domain_dropdown): - from guides.verification.domain_checks_demo import ( + from gds_examples.verification.domain_checks_demo import ( cyclic_auxiliary_model, orphan_stock_model, unused_converter_model, ) + from stockflow.verification.checks import ( check_sf001_orphan_stocks, check_sf003_auxiliary_acyclicity, @@ -538,12 +549,13 @@ def combined_selector(mo): @app.cell def run_combined(mo, combined_dropdown): - from guides.verification.domain_checks_demo import ( + from gds_examples.verification.domain_checks_demo import ( good_stockflow_model, ) - from guides.verification.domain_checks_demo import ( + from gds_examples.verification.domain_checks_demo import ( orphan_stock_model as _orphan_stock_model, ) + from stockflow.verification.engine import verify as sf_verify if combined_dropdown.value == "good": diff --git a/packages/gds-examples/guides/visualization/notebook.py b/packages/gds-examples/notebooks/visualization.py similarity index 98% rename from packages/gds-examples/guides/visualization/notebook.py rename to packages/gds-examples/notebooks/visualization.py index e414841..3aa2450 100644 --- a/packages/gds-examples/guides/visualization/notebook.py +++ b/packages/gds-examples/notebooks/visualization.py @@ -5,11 +5,18 @@ as you change selections. Run interactively: - uv run marimo edit guides/visualization/notebook.py + uv run marimo edit notebooks/visualization.py Run as read-only app: - uv run marimo run guides/visualization/notebook.py + uv run marimo run notebooks/visualization.py """ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "gds-examples", +# "marimo>=0.20.0", +# ] +# /// import marimo @@ -59,7 +66,7 @@ def build_sir(): from pathlib import Path # Add stockflow/ and control/ to path for model imports - _examples_root = Path(__file__).resolve().parent.parent.parent + _examples_root = Path(__file__).resolve().parent.parent for _subdir in ("stockflow", "control"): _path = str(_examples_root / _subdir) if _path not in sys.path: diff --git a/packages/gds-examples/pyproject.toml b/packages/gds-examples/pyproject.toml index b2ca391..89cd0af 100644 --- a/packages/gds-examples/pyproject.toml +++ b/packages/gds-examples/pyproject.toml @@ -74,7 +74,7 @@ only-include = [ "thermostat_dsl", "double_integrator", "software", - "guides", + "gds_examples", ] [tool.pytest.ini_options] @@ -100,7 +100,7 @@ files = [ "thermostat", "thermostat_dsl", "double_integrator", - "guides", + "gds_examples", "software", "visualize_examples.py", ] diff --git a/packages/gds-examples/tests/conftest.py b/packages/gds-examples/tests/conftest.py new file mode 100644 index 0000000..14e93ae --- /dev/null +++ b/packages/gds-examples/tests/conftest.py @@ -0,0 +1,15 @@ +"""Shared test fixtures for guide tests. + +Adds domain example directories (games/, stockflow/, control/) to sys.path +so that tests can import models like ``sir_epidemic.model``. +""" + +import sys +from pathlib import Path + +_examples_root = Path(__file__).resolve().parent.parent + +for _subdir in ("games", "stockflow", "control"): + _path = str(_examples_root / _subdir) + if _path not in sys.path: + sys.path.insert(0, _path) diff --git a/packages/gds-examples/guides/getting_started/test_getting_started.py b/packages/gds-examples/tests/test_getting_started.py similarity index 77% rename from packages/gds-examples/guides/getting_started/test_getting_started.py rename to packages/gds-examples/tests/test_getting_started.py index 587dfe1..f1ccbca 100644 --- a/packages/gds-examples/guides/getting_started/test_getting_started.py +++ b/packages/gds-examples/tests/test_getting_started.py @@ -28,20 +28,20 @@ class TestStage1Minimal: def test_spec_builds(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() assert spec.name == "Minimal Thermostat" def test_spec_has_one_entity(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() assert len(spec.entities) == 1 assert "Room" in spec.entities def test_spec_has_two_blocks(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() assert len(spec.blocks) == 2 @@ -49,39 +49,39 @@ def test_spec_has_two_blocks(self): assert "Update Temperature" in spec.blocks def test_block_roles(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() assert isinstance(spec.blocks["Heater"], BoundaryAction) assert isinstance(spec.blocks["Update Temperature"], Mechanism) def test_spec_validates(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() errors = spec.validate_spec() assert errors == [], f"Validation errors: {errors}" def test_system_compiles(self): - from guides.getting_started.stage1_minimal import build_system + from gds_examples.getting_started.stage1_minimal import build_system system = build_system() assert system.name == "Minimal Thermostat" assert len(system.blocks) == 2 def test_system_has_wiring(self): - from guides.getting_started.stage1_minimal import build_system + from gds_examples.getting_started.stage1_minimal import build_system system = build_system() assert len(system.wirings) >= 1 def test_mechanism_updates_room(self): - from guides.getting_started.stage1_minimal import update_temperature + from gds_examples.getting_started.stage1_minimal import update_temperature assert update_temperature.updates == [("Room", "temperature")] def test_heater_has_no_forward_in(self): - from guides.getting_started.stage1_minimal import heater + from gds_examples.getting_started.stage1_minimal import heater assert heater.interface.forward_in == () @@ -93,60 +93,60 @@ def test_heater_has_no_forward_in(self): class TestStage2Feedback: def test_spec_builds(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() assert spec.name == "Thermostat with Feedback" def test_spec_has_four_blocks(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() assert len(spec.blocks) == 4 def test_spec_has_policy_blocks(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() assert isinstance(spec.blocks["Sensor"], Policy) assert isinstance(spec.blocks["Controller"], Policy) def test_spec_has_setpoint_parameter(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() assert "setpoint" in spec.parameters def test_spec_validates(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() errors = spec.validate_spec() assert errors == [], f"Validation errors: {errors}" def test_system_compiles(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() assert system.name == "Thermostat with Feedback" assert len(system.blocks) == 4 def test_system_has_temporal_wiring(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() temporal = [w for w in system.wirings if w.is_temporal] assert len(temporal) == 1 def test_temporal_wiring_is_covariant(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() temporal = [w for w in system.wirings if w.is_temporal] assert temporal[0].direction == FlowDirection.COVARIANT def test_temporal_wiring_connects_mechanism_to_sensor(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() temporal = [w for w in system.wirings if w.is_temporal] @@ -154,7 +154,7 @@ def test_temporal_wiring_connects_mechanism_to_sensor(self): assert temporal[0].target == "Sensor" def test_no_feedback_wirings(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() feedback = [w for w in system.wirings if w.is_feedback] @@ -168,61 +168,61 @@ def test_no_feedback_wirings(self): class TestStage3DSL: def test_model_builds(self): - from guides.getting_started.stage3_dsl import build_model + from gds_examples.getting_started.stage3_dsl import build_model model = build_model() assert model.name == "Thermostat DSL" def test_model_has_one_state(self): - from guides.getting_started.stage3_dsl import build_model + from gds_examples.getting_started.stage3_dsl import build_model model = build_model() assert len(model.states) == 1 assert model.states[0].name == "temperature" def test_model_has_one_input(self): - from guides.getting_started.stage3_dsl import build_model + from gds_examples.getting_started.stage3_dsl import build_model model = build_model() assert len(model.inputs) == 1 assert model.inputs[0].name == "heater" def test_model_has_one_sensor(self): - from guides.getting_started.stage3_dsl import build_model + from gds_examples.getting_started.stage3_dsl import build_model model = build_model() assert len(model.sensors) == 1 assert model.sensors[0].name == "temp_sensor" def test_model_has_one_controller(self): - from guides.getting_started.stage3_dsl import build_model + from gds_examples.getting_started.stage3_dsl import build_model model = build_model() assert len(model.controllers) == 1 assert model.controllers[0].name == "thermo" def test_spec_compiles(self): - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() errors = spec.validate_spec() assert errors == [], f"Validation errors: {errors}" def test_spec_has_one_entity(self): - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() assert len(spec.entities) == 1 assert "temperature" in spec.entities def test_spec_has_four_blocks(self): - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() assert len(spec.blocks) == 4 def test_spec_block_roles(self): - from guides.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage3_dsl import build_spec spec = build_spec() boundaries = [b for b in spec.blocks.values() if isinstance(b, BoundaryAction)] @@ -233,20 +233,20 @@ def test_spec_block_roles(self): assert len(mechanisms) == 1 def test_system_compiles(self): - from guides.getting_started.stage3_dsl import build_system + from gds_examples.getting_started.stage3_dsl import build_system system = build_system() assert system.name == "Thermostat DSL" def test_system_has_temporal_loop(self): - from guides.getting_started.stage3_dsl import build_system + from gds_examples.getting_started.stage3_dsl import build_system system = build_system() temporal = [w for w in system.wirings if w.is_temporal] assert len(temporal) == 1 def test_canonical_projection(self): - from guides.getting_started.stage3_dsl import build_canonical + from gds_examples.getting_started.stage3_dsl import build_canonical canonical = build_canonical() assert len(canonical.state_variables) == 1 @@ -262,24 +262,24 @@ def test_canonical_projection(self): class TestStage4VerifyViz: def test_generic_checks_pass(self): - from guides.getting_started.stage3_dsl import build_system - from guides.getting_started.stage4_verify_viz import run_generic_checks + from gds_examples.getting_started.stage3_dsl import build_system + from gds_examples.getting_started.stage4_verify_viz import run_generic_checks system = build_system() report = run_generic_checks(system) assert report.errors == 0, [f.message for f in report.findings if not f.passed] def test_semantic_checks_produce_output(self): - from guides.getting_started.stage3_dsl import build_spec - from guides.getting_started.stage4_verify_viz import run_semantic_checks + from gds_examples.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage4_verify_viz import run_semantic_checks spec = build_spec() results = run_semantic_checks(spec) assert len(results) > 0 def test_semantic_checks_all_pass(self): - from guides.getting_started.stage3_dsl import build_spec - from guides.getting_started.stage4_verify_viz import run_semantic_checks + from gds_examples.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage4_verify_viz import run_semantic_checks spec = build_spec() results = run_semantic_checks(spec) @@ -287,8 +287,8 @@ def test_semantic_checks_all_pass(self): assert failures == [], f"Semantic check failures: {failures}" def test_structural_view_is_mermaid(self): - from guides.getting_started.stage3_dsl import build_system - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage3_dsl import build_system + from gds_examples.getting_started.stage4_verify_viz import ( generate_structural_view, ) @@ -298,8 +298,8 @@ def test_structural_view_is_mermaid(self): assert "heater" in mermaid.lower() or "temp_sensor" in mermaid.lower() def test_architecture_view_is_mermaid(self): - from guides.getting_started.stage3_dsl import build_spec - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage4_verify_viz import ( generate_architecture_view, ) @@ -309,8 +309,8 @@ def test_architecture_view_is_mermaid(self): assert "subgraph" in mermaid def test_canonical_view_is_mermaid(self): - from guides.getting_started.stage3_dsl import build_spec - from guides.getting_started.stage4_verify_viz import ( + from gds_examples.getting_started.stage3_dsl import build_spec + from gds_examples.getting_started.stage4_verify_viz import ( generate_canonical_view, ) @@ -327,13 +327,13 @@ def test_canonical_view_is_mermaid(self): class TestStage5Query: def test_query_builds(self): - from guides.getting_started.stage5_query import build_query + from gds_examples.getting_started.stage5_query import build_query query = build_query() assert query is not None def test_entity_update_map(self): - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( build_query, show_entity_updates, ) @@ -345,7 +345,7 @@ def test_entity_update_map(self): assert len(updates["temperature"]["value"]) == 1 def test_blocks_by_role(self): - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( build_query, show_blocks_by_role, ) @@ -357,7 +357,7 @@ def test_blocks_by_role(self): assert len(by_role["mechanism"]) == 1 def test_causal_chain(self): - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( build_query, show_causal_chain, ) @@ -367,7 +367,7 @@ def test_causal_chain(self): assert "temperature Dynamics" in affecting def test_dependency_graph(self): - from guides.getting_started.stage5_query import ( + from gds_examples.getting_started.stage5_query import ( build_query, show_dependency_graph, ) @@ -388,7 +388,7 @@ class TestCrossStageVerification: the same structural and semantic checks as the DSL model.""" def test_stage1_generic_checks(self): - from guides.getting_started.stage1_minimal import build_system + from gds_examples.getting_started.stage1_minimal import build_system system = build_system() checks = [ @@ -399,21 +399,21 @@ def test_stage1_generic_checks(self): assert report.errors == 0, [f.message for f in report.findings if not f.passed] def test_stage1_completeness(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() findings = check_completeness(spec) assert all(f.passed for f in findings) def test_stage1_determinism(self): - from guides.getting_started.stage1_minimal import build_spec + from gds_examples.getting_started.stage1_minimal import build_spec spec = build_spec() findings = check_determinism(spec) assert all(f.passed for f in findings) def test_stage2_generic_checks(self): - from guides.getting_started.stage2_feedback import build_system + from gds_examples.getting_started.stage2_feedback import build_system system = build_system() checks = [ @@ -424,14 +424,14 @@ def test_stage2_generic_checks(self): assert report.errors == 0, [f.message for f in report.findings if not f.passed] def test_stage2_completeness(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() findings = check_completeness(spec) assert all(f.passed for f in findings) def test_stage2_canonical_wellformedness(self): - from guides.getting_started.stage2_feedback import build_spec + from gds_examples.getting_started.stage2_feedback import build_spec spec = build_spec() findings = check_canonical_wellformedness(spec) @@ -442,7 +442,7 @@ def test_stage2_canonical_wellformedness(self): # Marimo Notebook # ══════════════════════════════════════════════════════════════ -_NOTEBOOK = Path(__file__).resolve().parent / "notebook.py" +_NOTEBOOK = Path(__file__).resolve().parent.parent / "notebooks" / "getting_started.py" class TestMarimoNotebook: diff --git a/packages/gds-examples/guides/rosetta/test_rosetta.py b/packages/gds-examples/tests/test_rosetta.py similarity index 95% rename from packages/gds-examples/guides/rosetta/test_rosetta.py rename to packages/gds-examples/tests/test_rosetta.py index 174fbea..bf3d493 100644 --- a/packages/gds-examples/guides/rosetta/test_rosetta.py +++ b/packages/gds-examples/tests/test_rosetta.py @@ -7,56 +7,60 @@ from pathlib import Path -from gds.blocks.roles import BoundaryAction, Mechanism, Policy -from gds.ir.models import FlowDirection -from gds.verification.engine import verify -from gds.verification.generic_checks import ( - check_g001_domain_codomain_matching, - check_g003_direction_consistency, - check_g004_dangling_wirings, - check_g005_sequential_type_compatibility, - check_g006_covariant_acyclicity, +from gds_examples.rosetta.comparison import ( + build_all_canonicals, + canonical_spectrum_table, ) -from gds.verification.spec_checks import ( - check_completeness, - check_determinism, - check_type_safety, -) -from guides.rosetta.comparison import build_all_canonicals, canonical_spectrum_table -from guides.rosetta.control_view import ( +from gds_examples.rosetta.control_view import ( build_canonical as build_control_canonical, ) -from guides.rosetta.control_view import ( +from gds_examples.rosetta.control_view import ( build_model as build_control_model, ) -from guides.rosetta.control_view import ( +from gds_examples.rosetta.control_view import ( build_spec as build_control_spec, ) -from guides.rosetta.control_view import ( +from gds_examples.rosetta.control_view import ( build_system as build_control_system, ) -from guides.rosetta.game_view import ( +from gds_examples.rosetta.game_view import ( build_canonical as build_game_canonical, ) -from guides.rosetta.game_view import ( +from gds_examples.rosetta.game_view import ( build_pattern, ) -from guides.rosetta.game_view import ( +from gds_examples.rosetta.game_view import ( build_spec as build_game_spec, ) -from guides.rosetta.stockflow_view import ( +from gds_examples.rosetta.stockflow_view import ( build_canonical as build_sf_canonical, ) -from guides.rosetta.stockflow_view import ( +from gds_examples.rosetta.stockflow_view import ( build_model as build_sf_model, ) -from guides.rosetta.stockflow_view import ( +from gds_examples.rosetta.stockflow_view import ( build_spec as build_sf_spec, ) -from guides.rosetta.stockflow_view import ( +from gds_examples.rosetta.stockflow_view import ( build_system as build_sf_system, ) +from gds.blocks.roles import BoundaryAction, Mechanism, Policy +from gds.ir.models import FlowDirection +from gds.verification.engine import verify +from gds.verification.generic_checks import ( + check_g001_domain_codomain_matching, + check_g003_direction_consistency, + check_g004_dangling_wirings, + check_g005_sequential_type_compatibility, + check_g006_covariant_acyclicity, +) +from gds.verification.spec_checks import ( + check_completeness, + check_determinism, + check_type_safety, +) + # ── Stock-Flow View ────────────────────────────────────────────── @@ -459,7 +463,7 @@ def test_state_dimensions_differ(self): class TestMarimoNotebook: """Validate the interactive marimo notebook for the Rosetta Stone guide.""" - NOTEBOOK = Path(__file__).resolve().parent / "notebook.py" + NOTEBOOK = Path(__file__).resolve().parent.parent / "notebooks" / "rosetta.py" def test_file_exists(self): assert self.NOTEBOOK.exists(), f"Notebook not found: {self.NOTEBOOK}" diff --git a/packages/gds-examples/guides/verification/test_verification_guide.py b/packages/gds-examples/tests/test_verification_guide.py similarity index 98% rename from packages/gds-examples/guides/verification/test_verification_guide.py rename to packages/gds-examples/tests/test_verification_guide.py index b3ae93e..3ee2776 100644 --- a/packages/gds-examples/guides/verification/test_verification_guide.py +++ b/packages/gds-examples/tests/test_verification_guide.py @@ -11,22 +11,7 @@ import importlib.util from pathlib import Path -from gds.verification.engine import verify -from gds.verification.findings import Severity -from gds.verification.generic_checks import ( - check_g001_domain_codomain_matching, - check_g002_signature_completeness, - check_g003_direction_consistency, - check_g004_dangling_wirings, - check_g005_sequential_type_compatibility, - check_g006_covariant_acyclicity, -) -from gds.verification.spec_checks import ( - check_canonical_wellformedness, - check_completeness, - check_determinism, -) -from guides.verification.broken_models import ( +from gds_examples.verification.broken_models import ( covariant_cycle_system, dangling_wiring_system, direction_contradiction_system, @@ -38,7 +23,7 @@ type_mismatch_system, write_conflict_spec, ) -from guides.verification.domain_checks_demo import ( +from gds_examples.verification.domain_checks_demo import ( cyclic_auxiliary_model, demo_broken_domain_full_verification, demo_cyclic_auxiliaries, @@ -49,7 +34,7 @@ orphan_stock_model, unused_converter_model, ) -from guides.verification.verification_demo import ( +from gds_examples.verification.verification_demo import ( demo_covariant_cycle, demo_dangling_wiring, demo_empty_canonical, @@ -60,6 +45,22 @@ demo_type_mismatch, demo_write_conflict, ) + +from gds.verification.engine import verify +from gds.verification.findings import Severity +from gds.verification.generic_checks import ( + check_g001_domain_codomain_matching, + check_g002_signature_completeness, + check_g003_direction_consistency, + check_g004_dangling_wirings, + check_g005_sequential_type_compatibility, + check_g006_covariant_acyclicity, +) +from gds.verification.spec_checks import ( + check_canonical_wellformedness, + check_completeness, + check_determinism, +) from stockflow.verification.checks import ( check_sf001_orphan_stocks, check_sf003_auxiliary_acyclicity, @@ -402,7 +403,7 @@ def test_severity_levels(self): # Marimo Notebook tests # ══════════════════════════════════════════════════════════════════ -_NOTEBOOK_PATH = Path(__file__).parent / "notebook.py" +_NOTEBOOK_PATH = Path(__file__).parent.parent / "notebooks" / "verification.py" class TestMarimoNotebook: diff --git a/packages/gds-examples/guides/visualization/test_visualization_guide.py b/packages/gds-examples/tests/test_visualization_guide.py similarity index 97% rename from packages/gds-examples/guides/visualization/test_visualization_guide.py rename to packages/gds-examples/tests/test_visualization_guide.py index 6747d38..4429bfe 100644 --- a/packages/gds-examples/guides/visualization/test_visualization_guide.py +++ b/packages/gds-examples/tests/test_visualization_guide.py @@ -9,8 +9,7 @@ from pathlib import Path import pytest - -from guides.visualization.all_views_demo import ( +from gds_examples.visualization.all_views_demo import ( generate_all_views, view_1_structural, view_2_canonical, @@ -19,12 +18,12 @@ view_5_parameter_influence, view_6_traceability, ) -from guides.visualization.cross_dsl_views import ( +from gds_examples.visualization.cross_dsl_views import ( double_integrator_views, generate_cross_dsl_views, sir_views, ) -from guides.visualization.theme_customization import ( +from gds_examples.visualization.theme_customization import ( ALL_THEMES, demo_all_themes, demo_default_vs_dark, @@ -257,7 +256,7 @@ def test_all_themes_produce_nonempty_output(self, theme): # ── Marimo Notebook ────────────────────────────────────────── -_NOTEBOOK_PATH = Path(__file__).parent / "notebook.py" +_NOTEBOOK_PATH = Path(__file__).parent.parent / "notebooks" / "visualization.py" class TestMarimoNotebook: