mycorrhizal 0.1.2__tar.gz → 0.2.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.
Files changed (95) hide show
  1. mycorrhizal-0.2.0/.github/workflows/test.yml +42 -0
  2. mycorrhizal-0.2.0/.gitignore +67 -0
  3. mycorrhizal-0.2.0/.readthedocs.yaml +21 -0
  4. mycorrhizal-0.2.0/PKG-INFO +335 -0
  5. mycorrhizal-0.2.0/README.md +318 -0
  6. mycorrhizal-0.2.0/docs/api/common.md +33 -0
  7. mycorrhizal-0.2.0/docs/api/hypha.md +38 -0
  8. mycorrhizal-0.2.0/docs/api/index.md +11 -0
  9. mycorrhizal-0.2.0/docs/api/rhizomorph.md +18 -0
  10. mycorrhizal-0.2.0/docs/api/septum.md +11 -0
  11. mycorrhizal-0.2.0/docs/api/spores.md +37 -0
  12. mycorrhizal-0.2.0/docs/assets/stylesheets/extra.css +3 -0
  13. mycorrhizal-0.2.0/docs/getting-started/index.md +20 -0
  14. mycorrhizal-0.2.0/docs/getting-started/installation.md +59 -0
  15. mycorrhizal-0.2.0/docs/getting-started/your-first-hypha.md +156 -0
  16. mycorrhizal-0.2.0/docs/getting-started/your-first-mycelium.md +424 -0
  17. mycorrhizal-0.2.0/docs/getting-started/your-first-rhizomorph.md +193 -0
  18. mycorrhizal-0.2.0/docs/getting-started/your-first-septum.md +155 -0
  19. mycorrhizal-0.2.0/docs/getting-started/your-first-spores.md +218 -0
  20. mycorrhizal-0.2.0/docs/guides/best-practices.md +480 -0
  21. mycorrhizal-0.2.0/docs/guides/blackboards.md +520 -0
  22. mycorrhizal-0.2.0/docs/guides/composition.md +367 -0
  23. mycorrhizal-0.2.0/docs/guides/index.md +20 -0
  24. mycorrhizal-0.2.0/docs/guides/observability.md +252 -0
  25. mycorrhizal-0.2.0/docs/guides/programmatic-hypha.md +571 -0
  26. mycorrhizal-0.2.0/docs/guides/septum-pda-guide.md +960 -0
  27. mycorrhizal-0.2.0/docs/guides/timebases.md +256 -0
  28. mycorrhizal-0.2.0/docs/hypha/index.md +352 -0
  29. mycorrhizal-0.2.0/docs/index.md +356 -0
  30. mycorrhizal-0.2.0/docs/mycelium/index.md +254 -0
  31. mycorrhizal-0.2.0/docs/rhizomorph/index.md +355 -0
  32. mycorrhizal-0.2.0/docs/septum/index.md +228 -0
  33. mycorrhizal-0.2.0/docs/septum/production.md +656 -0
  34. mycorrhizal-0.2.0/docs/septum/troubleshooting.md +720 -0
  35. mycorrhizal-0.2.0/docs/spores/index.md +332 -0
  36. mycorrhizal-0.2.0/mkdocs.yml +169 -0
  37. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/pyproject.toml +49 -1
  38. mycorrhizal-0.2.0/src/mycorrhizal/_version.py +1 -0
  39. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/common/__init__.py +15 -3
  40. mycorrhizal-0.2.0/src/mycorrhizal/common/cache.py +114 -0
  41. mycorrhizal-0.2.0/src/mycorrhizal/common/compilation.py +263 -0
  42. mycorrhizal-0.2.0/src/mycorrhizal/common/interface_detection.py +159 -0
  43. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/common/interfaces.py +3 -50
  44. mycorrhizal-0.2.0/src/mycorrhizal/common/mermaid.py +124 -0
  45. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/common/wrappers.py +1 -1
  46. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/hypha/core/builder.py +11 -1
  47. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/hypha/core/runtime.py +242 -107
  48. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/__init__.py +174 -0
  49. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/core.py +619 -0
  50. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/exceptions.py +30 -0
  51. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/hypha_bridge.py +1143 -0
  52. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/instance.py +440 -0
  53. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/pn_context.py +276 -0
  54. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/runner.py +165 -0
  55. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/spores_integration.py +655 -0
  56. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/tree_builder.py +102 -0
  57. mycorrhizal-0.2.0/src/mycorrhizal/mycelium/tree_spec.py +197 -0
  58. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/rhizomorph/README.md +82 -33
  59. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/rhizomorph/core.py +287 -119
  60. mycorrhizal-0.2.0/src/mycorrhizal/septum/TRANSITION_REFERENCE.md +385 -0
  61. {mycorrhizal-0.1.2/src/mycorrhizal/enoki → mycorrhizal-0.2.0/src/mycorrhizal/septum}/core.py +326 -100
  62. {mycorrhizal-0.1.2/src/mycorrhizal/enoki → mycorrhizal-0.2.0/src/mycorrhizal/septum}/testing_utils.py +7 -7
  63. {mycorrhizal-0.1.2/src/mycorrhizal/enoki → mycorrhizal-0.2.0/src/mycorrhizal/septum}/util.py +44 -21
  64. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/__init__.py +3 -3
  65. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/core.py +149 -28
  66. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/dsl/__init__.py +8 -8
  67. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/dsl/hypha.py +3 -15
  68. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/dsl/rhizomorph.py +3 -11
  69. mycorrhizal-0.1.2/src/mycorrhizal/spores/dsl/enoki.py → mycorrhizal-0.2.0/src/mycorrhizal/spores/dsl/septum.py +26 -77
  70. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/encoder/json.py +21 -12
  71. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/extraction.py +14 -11
  72. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/models.py +53 -20
  73. mycorrhizal-0.2.0/uv.lock +1704 -0
  74. mycorrhizal-0.1.2/.gitignore +0 -7
  75. mycorrhizal-0.1.2/PKG-INFO +0 -198
  76. mycorrhizal-0.1.2/README.md +0 -188
  77. mycorrhizal-0.1.2/src/mycorrhizal/_version.py +0 -1
  78. mycorrhizal-0.1.2/uv.lock +0 -477
  79. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/.github/workflows/python-publish.yml +0 -0
  80. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/__init__.py +0 -0
  81. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/common/interface_builder.py +0 -0
  82. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/common/timebase.py +0 -0
  83. {mycorrhizal-0.1.2/src/mycorrhizal/enoki → mycorrhizal-0.2.0/src/mycorrhizal/hypha}/__init__.py +0 -0
  84. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/hypha/core/__init__.py +0 -0
  85. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/hypha/core/specs.py +0 -0
  86. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/hypha/util.py +0 -0
  87. {mycorrhizal-0.1.2/src/mycorrhizal/hypha → mycorrhizal-0.2.0/src/mycorrhizal/rhizomorph}/__init__.py +0 -0
  88. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/rhizomorph/util.py +0 -0
  89. {mycorrhizal-0.1.2/src/mycorrhizal/rhizomorph → mycorrhizal-0.2.0/src/mycorrhizal/septum}/__init__.py +0 -0
  90. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/cache.py +0 -0
  91. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/encoder/__init__.py +0 -0
  92. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/encoder/base.py +0 -0
  93. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/transport/__init__.py +0 -0
  94. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/transport/base.py +0 -0
  95. {mycorrhizal-0.1.2 → mycorrhizal-0.2.0}/src/mycorrhizal/spores/transport/file.py +0 -0
@@ -0,0 +1,42 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install uv
25
+ run: pip install uv
26
+
27
+ - name: Setup virtual environment
28
+ run: uv venv
29
+
30
+ - name: Install dependencies
31
+ run: |
32
+ uv pip install -e ".[dev]"
33
+
34
+ - name: Run tests with coverage
35
+ run: |
36
+ uv run pytest --cov=src/mycorrhizal --cov-report=xml --cov-report=term
37
+
38
+ - name: Upload coverage to Codecov
39
+ uses: codecov/codecov-action@v4
40
+ with:
41
+ file: ./coverage.xml
42
+ fail_ci_if_error: false
@@ -0,0 +1,67 @@
1
+
2
+ **/__pycache__/
3
+ *.claude_todo/
4
+ *.pyclogs/
5
+
6
+ # Generated version file
7
+ src/*/_version.py
8
+
9
+ # Python
10
+ *.py[cod]
11
+ *$py.class
12
+ *.so
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ pip-wheel-metadata/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # Virtual environments
34
+ venv/
35
+ env/
36
+ ENV/
37
+ .venv
38
+
39
+ # Testing
40
+ .pytest_cache/
41
+ .coverage
42
+ .coverage.*
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .hypothesis/No
47
+ .hypothesis/
48
+
49
+ # Documentation builds
50
+ site/
51
+ .sphinx/
52
+
53
+ # IDEs
54
+ .vscode/
55
+ .idea/
56
+ *.swp
57
+ *.swo
58
+ *~
59
+
60
+ # OS
61
+ .DS_Store
62
+ Thumbs.db
63
+
64
+ # Project-specific
65
+ .claude_work/
66
+ logs/
67
+ *.log
@@ -0,0 +1,21 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.10"
7
+ jobs:
8
+ post_create_environment:
9
+ - pip install uv
10
+ post_install:
11
+ - uv pip install -e ".[docs]"
12
+
13
+ python:
14
+ install:
15
+ - method: pip
16
+ path: .
17
+
18
+ # MkDocs configuration
19
+ mkdocs:
20
+ configuration: mkdocs.yml
21
+ fail_on_warning: false
@@ -0,0 +1,335 @@
1
+ Metadata-Version: 2.4
2
+ Name: mycorrhizal
3
+ Version: 0.2.0
4
+ Summary: Utilities and DSLs for modelling and implementing safe, performant, structured systems
5
+ Author-email: Jeff Ciesielski <jeffciesielski@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: pydantic>=2.11.7
8
+ Requires-Dist: typeguard==4.4.4
9
+ Provides-Extra: docs
10
+ Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == 'docs'
11
+ Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
12
+ Requires-Dist: mkdocs-section-index>=0.3.0; extra == 'docs'
13
+ Requires-Dist: mkdocs-table-reader-plugin>=2.0.0; extra == 'docs'
14
+ Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
15
+ Requires-Dist: mkdocstrings[python]>=0.25.0; extra == 'docs'
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Mycorrhizal
19
+
20
+ [![Tests](https://github.com/Jeff-Ciesielski/mycorrhizal/actions/workflows/test.yml/badge.svg)](https://github.com/Jeff-Ciesielski/mycorrhizal/actions/workflows/test.yml)
21
+ [![codecov](https://codecov.io/gh/Jeff-Ciesielski/mycorrhizal/branch/main/graph/badge.svg)](https://codecov.io/gh/Jeff-Ciesielski/mycorrhizal)
22
+ [![Documentation Status](https://readthedocs.org/projects/mycorrhizal/badge/?version=latest)](https://mycorrhizal.readthedocs.io/en/latest/?badge=latest)
23
+ [![Python Version](https://img.shields.io/pypi/pyversions/mycorrhizal)](https://pypi.org/project/mycorrhizal/)
24
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
25
+
26
+ A Python library for building safe, structured, concurrent, event-driven systems.
27
+
28
+ ## Overview
29
+
30
+ Mycorrhizal provides four domain-specific languages (DSLs) for modeling and implementing different aspects of complex systems:
31
+
32
+ * **Hypha** - Colored Petri nets for workflow modeling and orchestration
33
+ * **Rhizomorph** - Behavior trees for decision-making and control logic
34
+ * **Septum** - Finite state machines for stateful components
35
+ * **Spores** - Event and object logging for observability and process mining
36
+
37
+ Each DSL can be used independently or combined to build sophisticated systems. All modules share common infrastructure for state management (blackboards) and time abstraction, enabling seamless composition.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install mycorrhizal
43
+ ```
44
+
45
+ Requires Python 3.10 or later.
46
+
47
+ ## Quick Start
48
+
49
+ ### Behavior Tree (Rhizomorph)
50
+
51
+ Define behavior trees using a decorator-based DSL:
52
+
53
+ ```python
54
+ from mycorrhizal.rhizomorph.core import bt, Runner, Status
55
+
56
+ @bt.tree
57
+ def ThreatResponse():
58
+ @bt.action
59
+ async def assess_threat(bb) -> Status:
60
+ # Analyze threat level
61
+ return Status.SUCCESS if bb.threat_level > 5 else Status.FAILURE
62
+
63
+ @bt.action
64
+ async def engage_countermeasures(bb) -> Status:
65
+ # Respond to threat
66
+ return Status.SUCCESS
67
+
68
+ @bt.root
69
+ @bt.sequence
70
+ def root():
71
+ yield assess_threat
72
+ yield engage_countermeasures
73
+
74
+ # Run the behavior tree
75
+ runner = Runner(ThreatResponse, bb=blackboard)
76
+ await runner.tick_until_complete()
77
+ ```
78
+
79
+ ### Petri Net (Hypha)
80
+
81
+ Model workflows with colored Petri nets:
82
+
83
+ ```python
84
+ from mycorrhizal.hypha.core import pn, Runner, PlaceType
85
+
86
+ @pn.net
87
+ def ProcessingNet(builder):
88
+ # Define places
89
+ pending = builder.place("pending", type=PlaceType.QUEUE)
90
+ processed = builder.place("processed", type=PlaceType.QUEUE)
91
+
92
+ # Define transitions
93
+ @builder.transition()
94
+ async def process(consumed, bb, timebase):
95
+ for token in consumed:
96
+ result = await handle(token)
97
+ yield {processed: result}
98
+
99
+ # Wire the net
100
+ builder.arc(pending, process).arc(processed)
101
+
102
+ # Run the Petri net
103
+ runner = Runner(ProcessingNet, bb=blackboard)
104
+ await runner.start(timebase)
105
+ ```
106
+
107
+ ### Finite State Machine (Septum)
108
+
109
+ Build stateful components with FSMs:
110
+
111
+ ```python
112
+ from mycorrhizal.septum.core import septum, StateMachine, LabeledTransition
113
+
114
+ @septum.state()
115
+ def IdleState():
116
+ @septum.on_state
117
+ async def on_state(ctx):
118
+ if ctx.msg == "start":
119
+ return Events.START
120
+ return None
121
+
122
+ @septum.transitions
123
+ def transitions():
124
+ return [
125
+ LabeledTransition(Events.START, ProcessingState),
126
+ ]
127
+
128
+ # Create and run the FSM
129
+ fsm = StateMachine(initial_state=IdleState, common_data={})
130
+ await fsm.initialize()
131
+ fsm.send_message("start")
132
+ await fsm.tick()
133
+ ```
134
+
135
+ ## Key Features
136
+
137
+ ### Shared Infrastructure
138
+
139
+ All DSLs use common building blocks:
140
+
141
+ * **Blackboards** - Typed shared state using Pydantic models
142
+ * **Interfaces** - Decorator-based access control for blackboard fields
143
+ * **Timebase** - Abstract time for simulation and testing
144
+
145
+ ### Composition
146
+
147
+ Combine DSLs to model complex systems:
148
+
149
+ * Embed behavior trees in Petri net transitions
150
+ * Run state machines within behavior tree actions
151
+ * Use Petri nets to orchestrate FSM-based components
152
+
153
+ ### Observability
154
+
155
+ The Spores module provides OCEL-compliant logging:
156
+
157
+ * Automatic event extraction from DSL execution
158
+ * Object lifecycle tracking
159
+ * Transport layer for custom backends
160
+
161
+ ## Examples
162
+
163
+ The repository contains comprehensive examples:
164
+
165
+ * `examples/hypha/` - Petri net patterns
166
+ * `examples/rhizomorph/` - Behavior tree patterns
167
+ * `examples/septum/` - State machine patterns
168
+ * `examples/spores/` - Event logging integration
169
+ * `examples/interfaces/` - Type-safe blackboard access
170
+
171
+ Run examples with:
172
+
173
+ ```bash
174
+ uv run python examples/hypha/minimal_hypha_demo.py
175
+ ```
176
+
177
+ See [examples/README.md](https://github.com/Jeff-Ciesielski/mycorrhizal/tree/main/examples/) for a complete guide.
178
+
179
+ ## Visualization
180
+
181
+ All three DSLs support Mermaid diagram export for documentation and debugging. You can generate diagrams programmatically:
182
+
183
+ ```python
184
+ # Behavior Tree
185
+ diagram = MyTree.to_mermaid()
186
+
187
+ # Petri Net
188
+ diagram = MyNet.to_mermaid()
189
+
190
+ # Finite State Machine
191
+ from mycorrhizal.septum.util import to_mermaid
192
+ diagram = to_mermaid(fsm)
193
+ ```
194
+
195
+ ### Example Diagrams
196
+
197
+ **Behavior Tree (Rhizomorph)** - A threat response system with decorators:
198
+
199
+ ```mermaid
200
+ flowchart TD
201
+ N1["Selector<br/>root"]
202
+ N1 --> N2
203
+ N2["Subtree<br/>Engage"]
204
+ N2 --> N3
205
+ N3["Sequence<br/>engage_threat"]
206
+ N3 --> N4
207
+ N4((CONDITION<br/>threat_detected))
208
+ N3 --> N5
209
+ N5["Decor<br/>Failer(Gate(cond=battery_ok)(Timeout(0.12s)(engage)))"]
210
+ N5 --> N6
211
+ N6["Decor<br/>Gate(cond=battery_ok)(Timeout(0.12s)(engage))"]
212
+ N6 --> N7
213
+ N7["Decor<br/>Timeout(0.12s)(engage)"]
214
+ N7 --> N8
215
+ N8((ACTION<br/>engage))
216
+ N1 --> N9
217
+ N9["Sequence<br/>patrol"]
218
+ N9 --> N10
219
+ N10((CONDITION<br/>has_waypoints))
220
+ N9 --> N11
221
+ N11((ACTION<br/>go_to_next))
222
+ N9 --> N12
223
+ N12["Decor<br/>Succeeder(Retry(3)(Timeout(1.0s)(scan_area)))"]
224
+ N12 --> N13
225
+ N13["Decor<br/>Retry(3)(Timeout(1.0s)(scan_area))"]
226
+ N13 --> N14
227
+ N14["Decor<br/>Timeout(1.0s)(scan_area)"]
228
+ N14 --> N15
229
+ N15((ACTION<br/>scan_area))
230
+ N1 --> N16
231
+ N16["Decor<br/>Failer(RateLimit(0.200000s)(telemetry_push))"]
232
+ N16 --> N17
233
+ N17["Decor<br/>RateLimit(0.200000s)(telemetry_push)"]
234
+ N17 --> N18
235
+ N18((ACTION<br/>telemetry_push))
236
+ ```
237
+
238
+ **Petri Net (Hypha)** - A task processing system with error handling:
239
+
240
+ ```mermaid
241
+ graph TD
242
+ subgraph TaskProcessingSystem.TaskGen
243
+ TaskProcessingSystem.TaskGen.source(("[INPUT]</br>TaskProcessingSystem.TaskGen.source"))
244
+ end
245
+ subgraph TaskProcessingSystem.TaskProc
246
+ TaskProcessingSystem.TaskProc.input(("TaskProcessingSystem.TaskProc.input"))
247
+ TaskProcessingSystem.TaskProc.processing(("TaskProcessingSystem.TaskProc.processing"))
248
+ TaskProcessingSystem.TaskProc.completed(("TaskProcessingSystem.TaskProc.completed"))
249
+ TaskProcessingSystem.TaskProc.failed(("TaskProcessingSystem.TaskProc.failed"))
250
+ TaskProcessingSystem.TaskProc.take_to_processing[TaskProcessingSystem.TaskProc.take_to_processing]
251
+ TaskProcessingSystem.TaskProc.do_processing[TaskProcessingSystem.TaskProc.do_processing]
252
+ TaskProcessingSystem.TaskProc.input --> TaskProcessingSystem.TaskProc.take_to_processing
253
+ TaskProcessingSystem.TaskProc.take_to_processing --> TaskProcessingSystem.TaskProc.processing
254
+ TaskProcessingSystem.TaskProc.processing --> TaskProcessingSystem.TaskProc.do_processing
255
+ TaskProcessingSystem.TaskProc.do_processing --> TaskProcessingSystem.TaskProc.completed
256
+ TaskProcessingSystem.TaskProc.do_processing --> TaskProcessingSystem.TaskProc.failed
257
+ end
258
+ subgraph TaskProcessingSystem.Notify
259
+ TaskProcessingSystem.Notify.input(("TaskProcessingSystem.Notify.input"))
260
+ TaskProcessingSystem.Notify.email_sink(("[OUTPUT]</br>TaskProcessingSystem.Notify.email_sink"))
261
+ TaskProcessingSystem.Notify.sms_sink(("[OUTPUT]</br>TaskProcessingSystem.Notify.sms_sink"))
262
+ TaskProcessingSystem.Notify.log_sink(("[OUTPUT]</br>TaskProcessingSystem.Notify.log_sink"))
263
+ TaskProcessingSystem.Notify.NotificationFork[TaskProcessingSystem.Notify.NotificationFork]
264
+ TaskProcessingSystem.Notify.input --> TaskProcessingSystem.Notify.NotificationFork
265
+ TaskProcessingSystem.Notify.NotificationFork --> TaskProcessingSystem.Notify.email_sink
266
+ TaskProcessingSystem.Notify.NotificationFork --> TaskProcessingSystem.Notify.sms_sink
267
+ TaskProcessingSystem.Notify.NotificationFork --> TaskProcessingSystem.Notify.log_sink
268
+ end
269
+ subgraph TaskProcessingSystem.ErrorHandle
270
+ TaskProcessingSystem.ErrorHandle.input(("TaskProcessingSystem.ErrorHandle.input"))
271
+ TaskProcessingSystem.ErrorHandle.error_log(("[OUTPUT]</br>TaskProcessingSystem.ErrorHandle.error_log"))
272
+ TaskProcessingSystem.ErrorHandle.ErrorForward[TaskProcessingSystem.ErrorHandle.ErrorForward]
273
+ TaskProcessingSystem.ErrorHandle.input --> TaskProcessingSystem.ErrorHandle.ErrorForward
274
+ TaskProcessingSystem.ErrorHandle.ErrorForward --> TaskProcessingSystem.ErrorHandle.error_log
275
+ end
276
+ TaskProcessingSystem.completion_tracker(("[OUTPUT]</br>TaskProcessingSystem.completion_tracker"))
277
+ TaskProcessingSystem.forward_source_to_input[TaskProcessingSystem.forward_source_to_input]
278
+ TaskProcessingSystem.CompletionFork[TaskProcessingSystem.CompletionFork]
279
+ TaskProcessingSystem.FailureFork[TaskProcessingSystem.FailureFork]
280
+ TaskProcessingSystem.TaskGen.source --> TaskProcessingSystem.forward_source_to_input
281
+ TaskProcessingSystem.forward_source_to_input --> TaskProcessingSystem.TaskProc.input
282
+ TaskProcessingSystem.TaskProc.completed --> TaskProcessingSystem.CompletionFork
283
+ TaskProcessingSystem.CompletionFork --> TaskProcessingSystem.Notify.input
284
+ TaskProcessingSystem.CompletionFork --> TaskProcessingSystem.completion_tracker
285
+ TaskProcessingSystem.TaskProc.failed --> TaskProcessingSystem.FailureFork
286
+ TaskProcessingSystem.FailureFork --> TaskProcessingSystem.ErrorHandle.input
287
+ TaskProcessingSystem.FailureFork --> TaskProcessingSystem.completion_tracker
288
+ ```
289
+
290
+ **Finite State Machine (Septum)** - A simple idle/processing/done workflow:
291
+
292
+ ```mermaid
293
+ flowchart TD
294
+ start((start)) --> S1
295
+ S1[IdleState]
296
+ S1 -->|"START"| S2
297
+ S1 -->|"QUIT"| S3
298
+ S2[ProcessingState]
299
+ S2 -->|"DONE"| S1
300
+ S3[DoneState (**terminal**)]
301
+ ```
302
+
303
+ ## Documentation
304
+
305
+ Full documentation is available at [https://mycorrhizal.readthedocs.io](https://mycorrhizal.readthedocs.io)
306
+
307
+ ## Development
308
+
309
+ ```bash
310
+ # Install dependencies
311
+ uv pip install -e ".[dev]"
312
+
313
+ # Run tests
314
+ pytest
315
+
316
+ # Run with coverage
317
+ pytest --cov=src/mycorrhizal --cov-report=html
318
+ ```
319
+
320
+ ## Project Status
321
+
322
+ This is a 0.1.0 release. The core APIs are stable and well-tested, but some features are still in development:
323
+
324
+ * Current: Four DSLs with decorator-based syntax
325
+ * Current: Comprehensive examples and tests
326
+ * Planned: Cross-DSL interoperability layer
327
+ * Planned: Enhanced composition patterns
328
+
329
+ ## License
330
+
331
+ MIT
332
+
333
+ ## Author
334
+
335
+ Jeff Ciesielski