tnfr 4.5.2__py3-none-any.whl → 8.5.0__py3-none-any.whl
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.
Potentially problematic release.
This version of tnfr might be problematic. Click here for more details.
- tnfr/__init__.py +334 -50
- tnfr/__init__.pyi +33 -0
- tnfr/_compat.py +10 -0
- tnfr/_generated_version.py +34 -0
- tnfr/_version.py +49 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +214 -37
- tnfr/alias.pyi +108 -0
- tnfr/backends/__init__.py +354 -0
- tnfr/backends/jax_backend.py +173 -0
- tnfr/backends/numpy_backend.py +238 -0
- tnfr/backends/optimized_numpy.py +420 -0
- tnfr/backends/torch_backend.py +408 -0
- tnfr/cache.py +149 -556
- tnfr/cache.pyi +13 -0
- tnfr/cli/__init__.py +51 -16
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +344 -32
- tnfr/cli/arguments.pyi +29 -0
- tnfr/cli/execution.py +676 -50
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/interactive_validator.py +614 -0
- tnfr/cli/utils.py +18 -3
- tnfr/cli/utils.pyi +7 -0
- tnfr/cli/validate.py +236 -0
- tnfr/compat/__init__.py +85 -0
- tnfr/compat/dataclass.py +136 -0
- tnfr/compat/jsonschema_stub.py +61 -0
- tnfr/compat/matplotlib_stub.py +73 -0
- tnfr/compat/numpy_stub.py +155 -0
- tnfr/config/__init__.py +224 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/{constants_glyphs.py → config/constants.py} +26 -20
- tnfr/config/constants.pyi +12 -0
- tnfr/config/defaults.py +54 -0
- tnfr/{constants/core.py → config/defaults_core.py} +59 -6
- tnfr/config/defaults_init.py +33 -0
- tnfr/config/defaults_metric.py +104 -0
- tnfr/config/feature_flags.py +81 -0
- tnfr/config/feature_flags.pyi +16 -0
- tnfr/config/glyph_constants.py +31 -0
- tnfr/config/init.py +77 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +254 -0
- tnfr/config/operator_names.pyi +36 -0
- tnfr/config/physics_derivation.py +354 -0
- tnfr/config/presets.py +83 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/config/security.py +927 -0
- tnfr/config/thresholds.py +114 -0
- tnfr/config/tnfr_config.py +498 -0
- tnfr/constants/__init__.py +51 -133
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +33 -0
- tnfr/constants/aliases.pyi +27 -0
- tnfr/constants/init.py +3 -1
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +9 -15
- tnfr/constants/metric.pyi +19 -0
- tnfr/core/__init__.py +33 -0
- tnfr/core/container.py +226 -0
- tnfr/core/default_implementations.py +329 -0
- tnfr/core/interfaces.py +279 -0
- tnfr/dynamics/__init__.py +213 -633
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/adaptation.pyi +7 -0
- tnfr/dynamics/adaptive_sequences.py +189 -0
- tnfr/dynamics/adaptive_sequences.pyi +14 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/aliases.pyi +19 -0
- tnfr/dynamics/bifurcation.py +232 -0
- tnfr/dynamics/canonical.py +229 -0
- tnfr/dynamics/canonical.pyi +48 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/coordination.pyi +25 -0
- tnfr/dynamics/dnfr.py +2699 -398
- tnfr/dynamics/dnfr.pyi +26 -0
- tnfr/dynamics/dynamic_limits.py +225 -0
- tnfr/dynamics/feedback.py +252 -0
- tnfr/dynamics/feedback.pyi +24 -0
- tnfr/dynamics/fused_dnfr.py +454 -0
- tnfr/dynamics/homeostasis.py +157 -0
- tnfr/dynamics/homeostasis.pyi +14 -0
- tnfr/dynamics/integrators.py +496 -102
- tnfr/dynamics/integrators.pyi +36 -0
- tnfr/dynamics/learning.py +310 -0
- tnfr/dynamics/learning.pyi +33 -0
- tnfr/dynamics/metabolism.py +254 -0
- tnfr/dynamics/nbody.py +796 -0
- tnfr/dynamics/nbody_tnfr.py +783 -0
- tnfr/dynamics/propagation.py +326 -0
- tnfr/dynamics/runtime.py +908 -0
- tnfr/dynamics/runtime.pyi +77 -0
- tnfr/dynamics/sampling.py +10 -5
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +711 -0
- tnfr/dynamics/selectors.pyi +85 -0
- tnfr/dynamics/structural_clip.py +207 -0
- tnfr/errors/__init__.py +37 -0
- tnfr/errors/contextual.py +492 -0
- tnfr/execution.py +77 -55
- tnfr/execution.pyi +45 -0
- tnfr/extensions/__init__.py +205 -0
- tnfr/extensions/__init__.pyi +18 -0
- tnfr/extensions/base.py +173 -0
- tnfr/extensions/base.pyi +35 -0
- tnfr/extensions/business/__init__.py +71 -0
- tnfr/extensions/business/__init__.pyi +11 -0
- tnfr/extensions/business/cookbook.py +88 -0
- tnfr/extensions/business/cookbook.pyi +8 -0
- tnfr/extensions/business/health_analyzers.py +202 -0
- tnfr/extensions/business/health_analyzers.pyi +9 -0
- tnfr/extensions/business/patterns.py +183 -0
- tnfr/extensions/business/patterns.pyi +8 -0
- tnfr/extensions/medical/__init__.py +73 -0
- tnfr/extensions/medical/__init__.pyi +11 -0
- tnfr/extensions/medical/cookbook.py +88 -0
- tnfr/extensions/medical/cookbook.pyi +8 -0
- tnfr/extensions/medical/health_analyzers.py +181 -0
- tnfr/extensions/medical/health_analyzers.pyi +9 -0
- tnfr/extensions/medical/patterns.py +163 -0
- tnfr/extensions/medical/patterns.pyi +8 -0
- tnfr/flatten.py +29 -50
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +66 -53
- tnfr/gamma.pyi +36 -0
- tnfr/glyph_history.py +144 -57
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +19 -0
- tnfr/glyph_runtime.pyi +8 -0
- tnfr/immutable.py +70 -30
- tnfr/immutable.pyi +36 -0
- tnfr/initialization.py +22 -16
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +5 -241
- tnfr/io.pyi +13 -0
- tnfr/locking.pyi +7 -0
- tnfr/mathematics/__init__.py +79 -0
- tnfr/mathematics/backend.py +453 -0
- tnfr/mathematics/backend.pyi +99 -0
- tnfr/mathematics/dynamics.py +408 -0
- tnfr/mathematics/dynamics.pyi +90 -0
- tnfr/mathematics/epi.py +391 -0
- tnfr/mathematics/epi.pyi +65 -0
- tnfr/mathematics/generators.py +242 -0
- tnfr/mathematics/generators.pyi +29 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/metrics.pyi +16 -0
- tnfr/mathematics/operators.py +239 -0
- tnfr/mathematics/operators.pyi +59 -0
- tnfr/mathematics/operators_factory.py +124 -0
- tnfr/mathematics/operators_factory.pyi +11 -0
- tnfr/mathematics/projection.py +87 -0
- tnfr/mathematics/projection.pyi +33 -0
- tnfr/mathematics/runtime.py +182 -0
- tnfr/mathematics/runtime.pyi +64 -0
- tnfr/mathematics/spaces.py +256 -0
- tnfr/mathematics/spaces.pyi +83 -0
- tnfr/mathematics/transforms.py +305 -0
- tnfr/mathematics/transforms.pyi +62 -0
- tnfr/metrics/__init__.py +47 -9
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/buffer_cache.py +163 -0
- tnfr/metrics/buffer_cache.pyi +24 -0
- tnfr/metrics/cache_utils.py +214 -0
- tnfr/metrics/coherence.py +1510 -330
- tnfr/metrics/coherence.pyi +129 -0
- tnfr/metrics/common.py +23 -16
- tnfr/metrics/common.pyi +35 -0
- tnfr/metrics/core.py +251 -36
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +709 -110
- tnfr/metrics/diagnosis.pyi +86 -0
- tnfr/metrics/emergence.py +245 -0
- tnfr/metrics/export.py +60 -18
- tnfr/metrics/export.pyi +7 -0
- tnfr/metrics/glyph_timing.py +233 -43
- tnfr/metrics/glyph_timing.pyi +81 -0
- tnfr/metrics/learning_metrics.py +280 -0
- tnfr/metrics/learning_metrics.pyi +21 -0
- tnfr/metrics/phase_coherence.py +351 -0
- tnfr/metrics/phase_compatibility.py +349 -0
- tnfr/metrics/reporting.py +63 -28
- tnfr/metrics/reporting.pyi +25 -0
- tnfr/metrics/sense_index.py +1126 -43
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +215 -23
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +148 -24
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/multiscale/__init__.py +32 -0
- tnfr/multiscale/hierarchical.py +517 -0
- tnfr/node.py +646 -140
- tnfr/node.pyi +139 -0
- tnfr/observers.py +160 -45
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +23 -19
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +1358 -106
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/algebra.py +277 -0
- tnfr/operators/canonical_patterns.py +420 -0
- tnfr/operators/cascade.py +267 -0
- tnfr/operators/cycle_detection.py +358 -0
- tnfr/operators/definitions.py +4108 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +1164 -0
- tnfr/operators/grammar.pyi +140 -0
- tnfr/operators/hamiltonian.py +710 -0
- tnfr/operators/health_analyzer.py +809 -0
- tnfr/operators/jitter.py +107 -38
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/lifecycle.py +314 -0
- tnfr/operators/metabolism.py +618 -0
- tnfr/operators/metrics.py +2138 -0
- tnfr/operators/network_analysis/__init__.py +27 -0
- tnfr/operators/network_analysis/source_detection.py +186 -0
- tnfr/operators/nodal_equation.py +395 -0
- tnfr/operators/pattern_detection.py +660 -0
- tnfr/operators/patterns.py +669 -0
- tnfr/operators/postconditions/__init__.py +38 -0
- tnfr/operators/postconditions/mutation.py +236 -0
- tnfr/operators/preconditions/__init__.py +1226 -0
- tnfr/operators/preconditions/coherence.py +305 -0
- tnfr/operators/preconditions/dissonance.py +236 -0
- tnfr/operators/preconditions/emission.py +128 -0
- tnfr/operators/preconditions/mutation.py +580 -0
- tnfr/operators/preconditions/reception.py +125 -0
- tnfr/operators/preconditions/resonance.py +364 -0
- tnfr/operators/registry.py +74 -0
- tnfr/operators/registry.pyi +9 -0
- tnfr/operators/remesh.py +1415 -91
- tnfr/operators/remesh.pyi +26 -0
- tnfr/operators/structural_units.py +268 -0
- tnfr/operators/unified_grammar.py +105 -0
- tnfr/parallel/__init__.py +54 -0
- tnfr/parallel/auto_scaler.py +234 -0
- tnfr/parallel/distributed.py +384 -0
- tnfr/parallel/engine.py +238 -0
- tnfr/parallel/gpu_engine.py +420 -0
- tnfr/parallel/monitoring.py +248 -0
- tnfr/parallel/partitioner.py +459 -0
- tnfr/py.typed +0 -0
- tnfr/recipes/__init__.py +22 -0
- tnfr/recipes/cookbook.py +743 -0
- tnfr/rng.py +75 -151
- tnfr/rng.pyi +26 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/sdk/__init__.py +107 -0
- tnfr/sdk/__init__.pyi +19 -0
- tnfr/sdk/adaptive_system.py +173 -0
- tnfr/sdk/adaptive_system.pyi +21 -0
- tnfr/sdk/builders.py +370 -0
- tnfr/sdk/builders.pyi +51 -0
- tnfr/sdk/fluent.py +1121 -0
- tnfr/sdk/fluent.pyi +74 -0
- tnfr/sdk/templates.py +342 -0
- tnfr/sdk/templates.pyi +41 -0
- tnfr/sdk/utils.py +341 -0
- tnfr/secure_config.py +46 -0
- tnfr/security/__init__.py +70 -0
- tnfr/security/database.py +514 -0
- tnfr/security/subprocess.py +503 -0
- tnfr/security/validation.py +290 -0
- tnfr/selector.py +59 -22
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +92 -67
- tnfr/sense.pyi +23 -0
- tnfr/services/__init__.py +17 -0
- tnfr/services/orchestrator.py +325 -0
- tnfr/sparse/__init__.py +39 -0
- tnfr/sparse/representations.py +492 -0
- tnfr/structural.py +639 -263
- tnfr/structural.pyi +83 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/cache_metrics.pyi +64 -0
- tnfr/telemetry/nu_f.py +422 -0
- tnfr/telemetry/nu_f.pyi +108 -0
- tnfr/telemetry/verbosity.py +36 -0
- tnfr/telemetry/verbosity.pyi +15 -0
- tnfr/tokens.py +2 -4
- tnfr/tokens.pyi +36 -0
- tnfr/tools/__init__.py +20 -0
- tnfr/tools/domain_templates.py +478 -0
- tnfr/tools/sequence_generator.py +846 -0
- tnfr/topology/__init__.py +13 -0
- tnfr/topology/asymmetry.py +151 -0
- tnfr/trace.py +300 -126
- tnfr/trace.pyi +42 -0
- tnfr/tutorials/__init__.py +38 -0
- tnfr/tutorials/autonomous_evolution.py +285 -0
- tnfr/tutorials/interactive.py +1576 -0
- tnfr/tutorials/structural_metabolism.py +238 -0
- tnfr/types.py +743 -12
- tnfr/types.pyi +357 -0
- tnfr/units.py +68 -0
- tnfr/units.pyi +13 -0
- tnfr/utils/__init__.py +282 -0
- tnfr/utils/__init__.pyi +215 -0
- tnfr/utils/cache.py +4223 -0
- tnfr/utils/cache.pyi +470 -0
- tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
- tnfr/utils/callbacks.pyi +49 -0
- tnfr/utils/chunks.py +108 -0
- tnfr/utils/chunks.pyi +22 -0
- tnfr/utils/data.py +428 -0
- tnfr/utils/data.pyi +74 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +821 -0
- tnfr/utils/init.pyi +80 -0
- tnfr/utils/io.py +559 -0
- tnfr/utils/io.pyi +66 -0
- tnfr/{helpers → utils}/numeric.py +51 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +257 -0
- tnfr/validation/__init__.pyi +85 -0
- tnfr/validation/compatibility.py +460 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/config.py +73 -0
- tnfr/validation/graph.py +139 -0
- tnfr/validation/graph.pyi +18 -0
- tnfr/validation/input_validation.py +755 -0
- tnfr/validation/invariants.py +712 -0
- tnfr/validation/rules.py +253 -0
- tnfr/validation/rules.pyi +44 -0
- tnfr/validation/runtime.py +279 -0
- tnfr/validation/runtime.pyi +28 -0
- tnfr/validation/sequence_validator.py +162 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +32 -0
- tnfr/validation/spectral.py +164 -0
- tnfr/validation/spectral.pyi +42 -0
- tnfr/validation/validator.py +1266 -0
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/visualization/__init__.py +98 -0
- tnfr/visualization/cascade_viz.py +256 -0
- tnfr/visualization/hierarchy.py +284 -0
- tnfr/visualization/sequence_plotter.py +784 -0
- tnfr/viz/__init__.py +60 -0
- tnfr/viz/matplotlib.py +278 -0
- tnfr/viz/matplotlib.pyi +35 -0
- tnfr-8.5.0.dist-info/METADATA +573 -0
- tnfr-8.5.0.dist-info/RECORD +353 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/collections_utils.py +0 -300
- tnfr/config.py +0 -32
- tnfr/grammar.py +0 -344
- tnfr/graph_utils.py +0 -84
- tnfr/helpers/__init__.py +0 -71
- tnfr/import_utils.py +0 -228
- tnfr/json_utils.py +0 -162
- tnfr/logging_utils.py +0 -116
- tnfr/presets.py +0 -60
- tnfr/validators.py +0 -84
- tnfr/value_utils.py +0 -59
- tnfr-4.5.2.dist-info/METADATA +0 -379
- tnfr-4.5.2.dist-info/RECORD +0 -67
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/execution.py
CHANGED
|
@@ -4,28 +4,24 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from collections import deque
|
|
6
6
|
from collections.abc import Callable, Iterable, Sequence
|
|
7
|
-
from typing import Any, Optional
|
|
7
|
+
from typing import Any, Optional, cast
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from .collections_utils import (
|
|
12
|
-
MAX_MATERIALIZE_DEFAULT,
|
|
13
|
-
ensure_collection,
|
|
14
|
-
is_non_string_sequence,
|
|
15
|
-
)
|
|
9
|
+
from ._compat import TypeAlias
|
|
16
10
|
from .constants import get_param
|
|
17
11
|
from .dynamics import step
|
|
18
12
|
from .flatten import _flatten
|
|
19
13
|
from .glyph_history import ensure_history
|
|
20
|
-
from .
|
|
21
|
-
from .
|
|
22
|
-
from .
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
AdvanceFn = Callable[[
|
|
14
|
+
from .tokens import TARGET, THOL, WAIT, OpTag, Token
|
|
15
|
+
from .types import Glyph, NodeId, TNFRGraph
|
|
16
|
+
from .utils import MAX_MATERIALIZE_DEFAULT, ensure_collection, is_non_string_sequence
|
|
17
|
+
from .validation import apply_glyph_with_grammar
|
|
18
|
+
|
|
19
|
+
AdvanceFn = Callable[[TNFRGraph], None]
|
|
20
|
+
TraceEntry = dict[str, Any]
|
|
21
|
+
ProgramTrace: TypeAlias = deque[TraceEntry]
|
|
26
22
|
HandlerFn = Callable[
|
|
27
|
-
[
|
|
28
|
-
Optional[
|
|
23
|
+
[TNFRGraph, Any, Optional[Sequence[NodeId]], ProgramTrace, AdvanceFn],
|
|
24
|
+
Optional[Sequence[NodeId]],
|
|
29
25
|
]
|
|
30
26
|
|
|
31
27
|
__all__ = [
|
|
@@ -44,25 +40,25 @@ __all__ = [
|
|
|
44
40
|
"wait",
|
|
45
41
|
]
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
CANONICAL_PRESET_NAME = "ejemplo_canonico"
|
|
43
|
+
CANONICAL_PRESET_NAME = "canonical_example"
|
|
49
44
|
CANONICAL_PROGRAM_TOKENS: tuple[Token, ...] = (
|
|
50
|
-
Glyph.SHA,
|
|
51
|
-
Glyph.AL,
|
|
52
|
-
Glyph.RA,
|
|
53
|
-
Glyph.
|
|
54
|
-
Glyph.
|
|
55
|
-
Glyph.
|
|
45
|
+
Glyph.SHA, # silence - initial stabilization
|
|
46
|
+
Glyph.AL, # emission - initiate pattern
|
|
47
|
+
Glyph.RA, # reception - capture information
|
|
48
|
+
Glyph.OZ, # dissonance - required before mutation (grammar rule)
|
|
49
|
+
Glyph.ZHIR, # mutation - phase change
|
|
50
|
+
Glyph.NUL, # contraction - compress structure
|
|
51
|
+
Glyph.THOL, # self_organization - recursive reorganization
|
|
56
52
|
)
|
|
57
53
|
|
|
58
54
|
|
|
59
|
-
def _window(G) -> int:
|
|
55
|
+
def _window(G: TNFRGraph) -> int:
|
|
60
56
|
return int(get_param(G, "GLYPH_HYSTERESIS_WINDOW"))
|
|
61
57
|
|
|
62
58
|
|
|
63
59
|
def _apply_glyph_to_targets(
|
|
64
|
-
G, g: Glyph | str, nodes: Optional[Iterable[
|
|
65
|
-
):
|
|
60
|
+
G: TNFRGraph, g: Glyph | str, nodes: Optional[Iterable[NodeId]] = None
|
|
61
|
+
) -> None:
|
|
66
62
|
"""Apply ``g`` to ``nodes`` (or all nodes) respecting the grammar."""
|
|
67
63
|
|
|
68
64
|
nodes_iter = G.nodes() if nodes is None else nodes
|
|
@@ -70,22 +66,24 @@ def _apply_glyph_to_targets(
|
|
|
70
66
|
apply_glyph_with_grammar(G, nodes_iter, g, w)
|
|
71
67
|
|
|
72
68
|
|
|
73
|
-
def _advance(G, step_fn: AdvanceFn):
|
|
69
|
+
def _advance(G: TNFRGraph, step_fn: AdvanceFn) -> None:
|
|
74
70
|
step_fn(G)
|
|
75
71
|
|
|
76
72
|
|
|
77
|
-
def _record_trace(trace:
|
|
73
|
+
def _record_trace(trace: ProgramTrace, G: TNFRGraph, op: OpTag, **data: Any) -> None:
|
|
74
|
+
"""Append an operation snapshot to ``trace`` using graph time metadata."""
|
|
75
|
+
|
|
78
76
|
trace.append({"t": float(G.graph.get("_t", 0.0)), "op": op.name, **data})
|
|
79
77
|
|
|
80
78
|
|
|
81
79
|
def _advance_and_record(
|
|
82
|
-
G,
|
|
83
|
-
trace:
|
|
80
|
+
G: TNFRGraph,
|
|
81
|
+
trace: ProgramTrace,
|
|
84
82
|
label: OpTag,
|
|
85
83
|
step_fn: AdvanceFn,
|
|
86
84
|
*,
|
|
87
85
|
times: int = 1,
|
|
88
|
-
**data,
|
|
86
|
+
**data: Any,
|
|
89
87
|
) -> None:
|
|
90
88
|
for _ in range(times):
|
|
91
89
|
_advance(G, step_fn)
|
|
@@ -93,40 +91,55 @@ def _advance_and_record(
|
|
|
93
91
|
|
|
94
92
|
|
|
95
93
|
def _handle_target(
|
|
96
|
-
G
|
|
97
|
-
|
|
94
|
+
G: TNFRGraph,
|
|
95
|
+
payload: TARGET,
|
|
96
|
+
_curr_target: Optional[Sequence[NodeId]],
|
|
97
|
+
trace: ProgramTrace,
|
|
98
|
+
_step_fn: AdvanceFn,
|
|
99
|
+
) -> Sequence[NodeId]:
|
|
98
100
|
"""Handle a ``TARGET`` token and return the active node set."""
|
|
99
101
|
|
|
100
102
|
nodes_src = G.nodes() if payload.nodes is None else payload.nodes
|
|
101
103
|
nodes = ensure_collection(nodes_src, max_materialize=None)
|
|
102
|
-
|
|
104
|
+
if is_non_string_sequence(nodes):
|
|
105
|
+
curr_target = cast(Sequence[NodeId], nodes)
|
|
106
|
+
else:
|
|
107
|
+
curr_target = tuple(nodes)
|
|
103
108
|
_record_trace(trace, G, OpTag.TARGET, n=len(curr_target))
|
|
104
109
|
return curr_target
|
|
105
110
|
|
|
106
111
|
|
|
107
112
|
def _handle_wait(
|
|
108
|
-
G
|
|
109
|
-
|
|
113
|
+
G: TNFRGraph,
|
|
114
|
+
steps: int,
|
|
115
|
+
curr_target: Optional[Sequence[NodeId]],
|
|
116
|
+
trace: ProgramTrace,
|
|
117
|
+
step_fn: AdvanceFn,
|
|
118
|
+
) -> Optional[Sequence[NodeId]]:
|
|
110
119
|
_advance_and_record(G, trace, OpTag.WAIT, step_fn, times=steps, k=steps)
|
|
111
120
|
return curr_target
|
|
112
121
|
|
|
113
122
|
|
|
114
123
|
def _handle_glyph(
|
|
115
|
-
G,
|
|
116
|
-
g: str,
|
|
117
|
-
curr_target,
|
|
118
|
-
trace:
|
|
124
|
+
G: TNFRGraph,
|
|
125
|
+
g: Glyph | str,
|
|
126
|
+
curr_target: Optional[Sequence[NodeId]],
|
|
127
|
+
trace: ProgramTrace,
|
|
119
128
|
step_fn: AdvanceFn,
|
|
120
129
|
label: OpTag = OpTag.GLYPH,
|
|
121
|
-
):
|
|
130
|
+
) -> Optional[Sequence[NodeId]]:
|
|
122
131
|
_apply_glyph_to_targets(G, g, curr_target)
|
|
123
132
|
_advance_and_record(G, trace, label, step_fn, g=g)
|
|
124
133
|
return curr_target
|
|
125
134
|
|
|
126
135
|
|
|
127
136
|
def _handle_thol(
|
|
128
|
-
G
|
|
129
|
-
|
|
137
|
+
G: TNFRGraph,
|
|
138
|
+
g: Glyph | str | None,
|
|
139
|
+
curr_target: Optional[Sequence[NodeId]],
|
|
140
|
+
trace: ProgramTrace,
|
|
141
|
+
step_fn: AdvanceFn,
|
|
142
|
+
) -> Optional[Sequence[NodeId]]:
|
|
130
143
|
return _handle_glyph(
|
|
131
144
|
G, g or Glyph.THOL.value, curr_target, trace, step_fn, label=OpTag.THOL
|
|
132
145
|
)
|
|
@@ -141,20 +154,23 @@ HANDLERS: dict[OpTag, HandlerFn] = {
|
|
|
141
154
|
|
|
142
155
|
|
|
143
156
|
def play(
|
|
144
|
-
G, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = None
|
|
157
|
+
G: TNFRGraph, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = None
|
|
145
158
|
) -> None:
|
|
146
159
|
"""Execute a canonical sequence on graph ``G``."""
|
|
147
160
|
|
|
148
161
|
step_fn = step_fn or step
|
|
149
162
|
|
|
150
|
-
curr_target: Optional[
|
|
163
|
+
curr_target: Optional[Sequence[NodeId]] = None
|
|
151
164
|
|
|
152
165
|
history = ensure_history(G)
|
|
153
166
|
maxlen = int(get_param(G, "PROGRAM_TRACE_MAXLEN"))
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
trace_obj = history.get("program_trace")
|
|
168
|
+
trace: ProgramTrace
|
|
169
|
+
if not isinstance(trace_obj, deque) or trace_obj.maxlen != maxlen:
|
|
170
|
+
trace = cast(ProgramTrace, deque(trace_obj or [], maxlen=maxlen))
|
|
157
171
|
history["program_trace"] = trace
|
|
172
|
+
else:
|
|
173
|
+
trace = cast(ProgramTrace, trace_obj)
|
|
158
174
|
|
|
159
175
|
for op, payload in _flatten(sequence):
|
|
160
176
|
handler: HandlerFn | None = HANDLERS.get(op)
|
|
@@ -174,28 +190,34 @@ def compile_sequence(
|
|
|
174
190
|
|
|
175
191
|
|
|
176
192
|
def seq(*tokens: Token) -> list[Token]:
|
|
193
|
+
"""Return a mutable list of ``tokens`` for explicit sequence editing."""
|
|
194
|
+
|
|
177
195
|
return list(tokens)
|
|
178
196
|
|
|
179
197
|
|
|
180
|
-
def block(
|
|
181
|
-
|
|
182
|
-
|
|
198
|
+
def block(*tokens: Token, repeat: int = 1, close: Optional[Glyph] = None) -> THOL:
|
|
199
|
+
"""Build a THOL block with optional repetition and forced closure."""
|
|
200
|
+
|
|
183
201
|
return THOL(body=list(tokens), repeat=repeat, force_close=close)
|
|
184
202
|
|
|
185
203
|
|
|
186
|
-
def target(nodes: Optional[Iterable[
|
|
204
|
+
def target(nodes: Optional[Iterable[NodeId]] = None) -> TARGET:
|
|
205
|
+
"""Return a TARGET token selecting ``nodes`` (defaults to all nodes)."""
|
|
206
|
+
|
|
187
207
|
return TARGET(nodes=nodes)
|
|
188
208
|
|
|
189
209
|
|
|
190
210
|
def wait(steps: int = 1) -> WAIT:
|
|
211
|
+
"""Return a WAIT token forcing ``steps`` structural updates before resuming."""
|
|
212
|
+
|
|
191
213
|
return WAIT(steps=max(1, int(steps)))
|
|
192
214
|
|
|
193
215
|
|
|
194
216
|
def basic_canonical_example() -> list[Token]:
|
|
195
|
-
"""
|
|
217
|
+
"""Return the canonical preset sequence.
|
|
196
218
|
|
|
197
219
|
Returns a copy of the canonical preset tokens to keep CLI defaults aligned
|
|
198
|
-
with :func:`tnfr.presets.get_preset`.
|
|
220
|
+
with :func:`tnfr.config.presets.get_preset`.
|
|
199
221
|
"""
|
|
200
222
|
|
|
201
223
|
return list(CANONICAL_PROGRAM_TOKENS)
|
tnfr/execution.pyi
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import deque
|
|
4
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from ._compat import TypeAlias
|
|
8
|
+
from .tokens import TARGET, THOL, WAIT, OpTag, Token
|
|
9
|
+
from .types import Glyph, NodeId, TNFRGraph
|
|
10
|
+
|
|
11
|
+
__all__: list[str]
|
|
12
|
+
|
|
13
|
+
def __getattr__(name: str) -> Any: ...
|
|
14
|
+
|
|
15
|
+
AdvanceFn = Callable[[TNFRGraph], None]
|
|
16
|
+
TraceEntry = dict[str, Any]
|
|
17
|
+
ProgramTrace: TypeAlias = deque[TraceEntry]
|
|
18
|
+
HandlerFn = Callable[
|
|
19
|
+
[TNFRGraph, Any, Sequence[NodeId] | None, ProgramTrace, AdvanceFn],
|
|
20
|
+
Sequence[NodeId] | None,
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
CANONICAL_PRESET_NAME: str
|
|
24
|
+
CANONICAL_PROGRAM_TOKENS: tuple[Token, ...]
|
|
25
|
+
HANDLERS: dict[OpTag, HandlerFn]
|
|
26
|
+
|
|
27
|
+
def _apply_glyph_to_targets(
|
|
28
|
+
G: TNFRGraph, g: Glyph | str, nodes: Iterable[NodeId] | None = ...
|
|
29
|
+
) -> None: ...
|
|
30
|
+
def _record_trace(
|
|
31
|
+
trace: ProgramTrace, G: TNFRGraph, op: OpTag, **data: Any
|
|
32
|
+
) -> None: ...
|
|
33
|
+
def compile_sequence(
|
|
34
|
+
sequence: Iterable[Token] | Sequence[Token] | Any,
|
|
35
|
+
*,
|
|
36
|
+
max_materialize: int | None = ...,
|
|
37
|
+
) -> list[tuple[OpTag, Any]]: ...
|
|
38
|
+
def play(
|
|
39
|
+
G: TNFRGraph, sequence: Sequence[Token], step_fn: Optional[AdvanceFn] = ...
|
|
40
|
+
) -> None: ...
|
|
41
|
+
def seq(*tokens: Token) -> list[Token]: ...
|
|
42
|
+
def block(*tokens: Token, repeat: int = ..., close: Glyph | None = ...) -> THOL: ...
|
|
43
|
+
def target(nodes: Iterable[NodeId] | None = ...) -> TARGET: ...
|
|
44
|
+
def wait(steps: int = ...) -> WAIT: ...
|
|
45
|
+
def basic_canonical_example() -> list[Token]: ...
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Extension registry for TNFR domain extensions.
|
|
2
|
+
|
|
3
|
+
Manages registration, discovery, and access to community-contributed domain
|
|
4
|
+
extensions. Maintains a global registry of extensions while ensuring thread-safe
|
|
5
|
+
access and validation of extension requirements.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, List, Optional, Type
|
|
9
|
+
from .base import TNFRExtension, PatternDefinition, CookbookRecipe
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExtensionRegistry:
|
|
13
|
+
"""Registry for managing TNFR domain extensions.
|
|
14
|
+
|
|
15
|
+
Provides centralized registration and discovery of domain extensions,
|
|
16
|
+
ensuring extensions are properly validated and accessible to the TNFR
|
|
17
|
+
engine and user applications.
|
|
18
|
+
|
|
19
|
+
Examples
|
|
20
|
+
--------
|
|
21
|
+
>>> from tnfr.extensions import registry
|
|
22
|
+
>>> from tnfr.extensions.medical import MedicalExtension
|
|
23
|
+
>>>
|
|
24
|
+
>>> # Register extension
|
|
25
|
+
>>> ext = MedicalExtension()
|
|
26
|
+
>>> registry.register_extension(ext)
|
|
27
|
+
>>>
|
|
28
|
+
>>> # List available domains
|
|
29
|
+
>>> domains = registry.list_extensions()
|
|
30
|
+
>>> print(domains) # ['medical', ...]
|
|
31
|
+
>>>
|
|
32
|
+
>>> # Get domain patterns
|
|
33
|
+
>>> patterns = registry.get_domain_patterns("medical")
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self) -> None:
|
|
37
|
+
"""Initialize empty extension registry."""
|
|
38
|
+
self._extensions: Dict[str, TNFRExtension] = {}
|
|
39
|
+
|
|
40
|
+
def register_extension(self, extension: TNFRExtension) -> None:
|
|
41
|
+
"""Register a new domain extension.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
extension : TNFRExtension
|
|
46
|
+
Extension instance to register.
|
|
47
|
+
|
|
48
|
+
Raises
|
|
49
|
+
------
|
|
50
|
+
ValueError
|
|
51
|
+
If extension with same domain name already registered.
|
|
52
|
+
TypeError
|
|
53
|
+
If extension does not inherit from TNFRExtension.
|
|
54
|
+
"""
|
|
55
|
+
if not isinstance(extension, TNFRExtension):
|
|
56
|
+
raise TypeError(
|
|
57
|
+
f"Extension must inherit from TNFRExtension, got {type(extension)}"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
domain_name = extension.get_domain_name()
|
|
61
|
+
|
|
62
|
+
if domain_name in self._extensions:
|
|
63
|
+
raise ValueError(f"Extension for domain '{domain_name}' already registered")
|
|
64
|
+
|
|
65
|
+
self._extensions[domain_name] = extension
|
|
66
|
+
|
|
67
|
+
def unregister_extension(self, domain_name: str) -> None:
|
|
68
|
+
"""Unregister an extension.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
domain_name : str
|
|
73
|
+
Domain name of extension to remove.
|
|
74
|
+
|
|
75
|
+
Raises
|
|
76
|
+
------
|
|
77
|
+
KeyError
|
|
78
|
+
If domain not found in registry.
|
|
79
|
+
"""
|
|
80
|
+
if domain_name not in self._extensions:
|
|
81
|
+
raise KeyError(f"Extension '{domain_name}' not found in registry")
|
|
82
|
+
|
|
83
|
+
del self._extensions[domain_name]
|
|
84
|
+
|
|
85
|
+
def get_extension(self, domain_name: str) -> Optional[TNFRExtension]:
|
|
86
|
+
"""Get extension by domain name.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
domain_name : str
|
|
91
|
+
Domain name identifier.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
Optional[TNFRExtension]
|
|
96
|
+
Extension instance if found, None otherwise.
|
|
97
|
+
"""
|
|
98
|
+
return self._extensions.get(domain_name)
|
|
99
|
+
|
|
100
|
+
def list_extensions(self) -> List[str]:
|
|
101
|
+
"""List all registered extension domain names.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
List[str]
|
|
106
|
+
Sorted list of registered domain names.
|
|
107
|
+
"""
|
|
108
|
+
return sorted(self._extensions.keys())
|
|
109
|
+
|
|
110
|
+
def get_domain_patterns(self, domain_name: str) -> Dict[str, PatternDefinition]:
|
|
111
|
+
"""Get pattern definitions for a specific domain.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
domain_name : str
|
|
116
|
+
Domain name identifier.
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
Dict[str, PatternDefinition]
|
|
121
|
+
Mapping of pattern names to definitions.
|
|
122
|
+
|
|
123
|
+
Raises
|
|
124
|
+
------
|
|
125
|
+
KeyError
|
|
126
|
+
If domain not found in registry.
|
|
127
|
+
"""
|
|
128
|
+
extension = self.get_extension(domain_name)
|
|
129
|
+
if extension is None:
|
|
130
|
+
raise KeyError(f"Extension '{domain_name}' not found in registry")
|
|
131
|
+
|
|
132
|
+
return extension.get_pattern_definitions()
|
|
133
|
+
|
|
134
|
+
def get_domain_health_analyzers(self, domain_name: str) -> Dict[str, Type]:
|
|
135
|
+
"""Get health analyzers for a specific domain.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
domain_name : str
|
|
140
|
+
Domain name identifier.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
Dict[str, Type]
|
|
145
|
+
Mapping of analyzer names to analyzer classes.
|
|
146
|
+
|
|
147
|
+
Raises
|
|
148
|
+
------
|
|
149
|
+
KeyError
|
|
150
|
+
If domain not found in registry.
|
|
151
|
+
"""
|
|
152
|
+
extension = self.get_extension(domain_name)
|
|
153
|
+
if extension is None:
|
|
154
|
+
raise KeyError(f"Extension '{domain_name}' not found in registry")
|
|
155
|
+
|
|
156
|
+
return extension.get_health_analyzers()
|
|
157
|
+
|
|
158
|
+
def get_domain_recipes(self, domain_name: str) -> Dict[str, CookbookRecipe]:
|
|
159
|
+
"""Get cookbook recipes for a specific domain.
|
|
160
|
+
|
|
161
|
+
Parameters
|
|
162
|
+
----------
|
|
163
|
+
domain_name : str
|
|
164
|
+
Domain name identifier.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
Dict[str, CookbookRecipe]
|
|
169
|
+
Mapping of recipe names to recipe definitions.
|
|
170
|
+
|
|
171
|
+
Raises
|
|
172
|
+
------
|
|
173
|
+
KeyError
|
|
174
|
+
If domain not found in registry.
|
|
175
|
+
"""
|
|
176
|
+
extension = self.get_extension(domain_name)
|
|
177
|
+
if extension is None:
|
|
178
|
+
raise KeyError(f"Extension '{domain_name}' not found in registry")
|
|
179
|
+
|
|
180
|
+
return extension.get_cookbook_recipes()
|
|
181
|
+
|
|
182
|
+
def get_all_patterns(self) -> Dict[str, Dict[str, PatternDefinition]]:
|
|
183
|
+
"""Get all patterns from all registered extensions.
|
|
184
|
+
|
|
185
|
+
Returns
|
|
186
|
+
-------
|
|
187
|
+
Dict[str, Dict[str, PatternDefinition]]
|
|
188
|
+
Nested mapping: domain_name -> pattern_name -> PatternDefinition.
|
|
189
|
+
"""
|
|
190
|
+
all_patterns = {}
|
|
191
|
+
for domain_name, extension in self._extensions.items():
|
|
192
|
+
all_patterns[domain_name] = extension.get_pattern_definitions()
|
|
193
|
+
|
|
194
|
+
return all_patterns
|
|
195
|
+
|
|
196
|
+
def clear(self) -> None:
|
|
197
|
+
"""Clear all registered extensions.
|
|
198
|
+
|
|
199
|
+
Primarily useful for testing and reinitialization.
|
|
200
|
+
"""
|
|
201
|
+
self._extensions.clear()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# Global registry instance
|
|
205
|
+
registry = ExtensionRegistry()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Type stubs for tnfr.extensions"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, List, Optional, Type
|
|
4
|
+
from .base import TNFRExtension, PatternDefinition, CookbookRecipe
|
|
5
|
+
|
|
6
|
+
class ExtensionRegistry:
|
|
7
|
+
def __init__(self) -> None: ...
|
|
8
|
+
def register_extension(self, extension: TNFRExtension) -> None: ...
|
|
9
|
+
def unregister_extension(self, domain_name: str) -> None: ...
|
|
10
|
+
def get_extension(self, domain_name: str) -> Optional[TNFRExtension]: ...
|
|
11
|
+
def list_extensions(self) -> List[str]: ...
|
|
12
|
+
def get_domain_patterns(self, domain_name: str) -> Dict[str, PatternDefinition]: ...
|
|
13
|
+
def get_domain_health_analyzers(self, domain_name: str) -> Dict[str, Type]: ...
|
|
14
|
+
def get_domain_recipes(self, domain_name: str) -> Dict[str, CookbookRecipe]: ...
|
|
15
|
+
def get_all_patterns(self) -> Dict[str, Dict[str, PatternDefinition]]: ...
|
|
16
|
+
def clear(self) -> None: ...
|
|
17
|
+
|
|
18
|
+
registry: ExtensionRegistry
|
tnfr/extensions/base.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Base classes for TNFR domain extensions.
|
|
2
|
+
|
|
3
|
+
This module provides the foundation for community-contributed domain extensions
|
|
4
|
+
to TNFR Grammar 2.0. Extensions allow domain experts to add specialized patterns,
|
|
5
|
+
health analyzers, and tools while maintaining canonical TNFR invariants.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import Any, Dict, List, Optional, Type
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class PatternDefinition:
|
|
15
|
+
"""Definition of a domain-specific structural pattern.
|
|
16
|
+
|
|
17
|
+
Captures a validated sequence of structural operators and its domain context,
|
|
18
|
+
ensuring patterns maintain TNFR canonical requirements while providing
|
|
19
|
+
domain-specific semantics.
|
|
20
|
+
|
|
21
|
+
Attributes
|
|
22
|
+
----------
|
|
23
|
+
name : str
|
|
24
|
+
Unique identifier for the pattern within its domain.
|
|
25
|
+
sequence : List[str]
|
|
26
|
+
Ordered list of structural operator identifiers.
|
|
27
|
+
description : str
|
|
28
|
+
Human-readable explanation of what the pattern achieves.
|
|
29
|
+
use_cases : List[str]
|
|
30
|
+
Real-world scenarios where this pattern applies.
|
|
31
|
+
health_requirements : Dict[str, float]
|
|
32
|
+
Minimum health metrics (C(t), Si) required for pattern validity.
|
|
33
|
+
domain_context : Dict[str, Any]
|
|
34
|
+
Domain-specific metadata explaining real-world mapping.
|
|
35
|
+
examples : List[Dict[str, Any]]
|
|
36
|
+
Validated examples demonstrating pattern effectiveness.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
name: str
|
|
40
|
+
sequence: List[str]
|
|
41
|
+
description: str
|
|
42
|
+
use_cases: List[str] = field(default_factory=list)
|
|
43
|
+
health_requirements: Dict[str, float] = field(default_factory=dict)
|
|
44
|
+
domain_context: Dict[str, Any] = field(default_factory=dict)
|
|
45
|
+
examples: List[Dict[str, Any]] = field(default_factory=list)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class CookbookRecipe:
|
|
50
|
+
"""Validated recipe for a common domain scenario.
|
|
51
|
+
|
|
52
|
+
Provides a tested sequence configuration with parameters and expected outcomes,
|
|
53
|
+
allowing practitioners to apply proven patterns to their specific contexts.
|
|
54
|
+
|
|
55
|
+
Attributes
|
|
56
|
+
----------
|
|
57
|
+
name : str
|
|
58
|
+
Unique identifier for the recipe.
|
|
59
|
+
description : str
|
|
60
|
+
What this recipe achieves in domain terms.
|
|
61
|
+
sequence : List[str]
|
|
62
|
+
Structural operator sequence.
|
|
63
|
+
parameters : Dict[str, Any]
|
|
64
|
+
Recommended parameters (νf, phase, etc.).
|
|
65
|
+
expected_health : Dict[str, float]
|
|
66
|
+
Expected health metrics (C(t), Si) for successful application.
|
|
67
|
+
validation : Dict[str, Any]
|
|
68
|
+
Validation metadata (test count, success rate, notes).
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
name: str
|
|
72
|
+
description: str
|
|
73
|
+
sequence: List[str]
|
|
74
|
+
parameters: Dict[str, Any] = field(default_factory=dict)
|
|
75
|
+
expected_health: Dict[str, float] = field(default_factory=dict)
|
|
76
|
+
validation: Dict[str, Any] = field(default_factory=dict)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class TNFRExtension(ABC):
|
|
80
|
+
"""Abstract base class for TNFR domain extensions.
|
|
81
|
+
|
|
82
|
+
Domain extensions provide specialized patterns, health analyzers, and tools
|
|
83
|
+
for specific application domains while maintaining TNFR canonical invariants.
|
|
84
|
+
All extensions must implement the core abstract methods to ensure consistent
|
|
85
|
+
structure and discoverability.
|
|
86
|
+
|
|
87
|
+
Examples
|
|
88
|
+
--------
|
|
89
|
+
>>> class MedicalExtension(TNFRExtension):
|
|
90
|
+
... def get_domain_name(self) -> str:
|
|
91
|
+
... return "medical"
|
|
92
|
+
...
|
|
93
|
+
... def get_pattern_definitions(self) -> Dict[str, PatternDefinition]:
|
|
94
|
+
... return {
|
|
95
|
+
... "therapeutic_alliance": PatternDefinition(
|
|
96
|
+
... name="therapeutic_alliance",
|
|
97
|
+
... sequence=["emission", "reception", "coherence"],
|
|
98
|
+
... description="Establishing therapeutic trust",
|
|
99
|
+
... use_cases=["Initial therapy session", "Crisis intervention"],
|
|
100
|
+
... )
|
|
101
|
+
... }
|
|
102
|
+
...
|
|
103
|
+
... def get_health_analyzers(self) -> Dict[str, Type]:
|
|
104
|
+
... from .health_analyzers import TherapeuticHealthAnalyzer
|
|
105
|
+
... return {"therapeutic": TherapeuticHealthAnalyzer}
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
def get_domain_name(self) -> str:
|
|
110
|
+
"""Return the unique domain identifier.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
str
|
|
115
|
+
Domain name (lowercase, underscore-separated).
|
|
116
|
+
"""
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
@abstractmethod
|
|
120
|
+
def get_pattern_definitions(self) -> Dict[str, PatternDefinition]:
|
|
121
|
+
"""Return domain-specific pattern definitions.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
Dict[str, PatternDefinition]
|
|
126
|
+
Mapping of pattern names to their definitions.
|
|
127
|
+
"""
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
@abstractmethod
|
|
131
|
+
def get_health_analyzers(self) -> Dict[str, Type]:
|
|
132
|
+
"""Return domain-specific health analyzer classes.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
Dict[str, Type]
|
|
137
|
+
Mapping of analyzer names to analyzer classes.
|
|
138
|
+
"""
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
def get_cookbook_recipes(self) -> Dict[str, CookbookRecipe]:
|
|
142
|
+
"""Return validated recipes for common scenarios.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
Dict[str, CookbookRecipe]
|
|
147
|
+
Mapping of recipe names to recipe definitions. Empty dict if none.
|
|
148
|
+
"""
|
|
149
|
+
return {}
|
|
150
|
+
|
|
151
|
+
def get_visualization_tools(self) -> Dict[str, Type]:
|
|
152
|
+
"""Return domain-specific visualization tools.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
Dict[str, Type]
|
|
157
|
+
Mapping of visualizer names to visualizer classes. Empty dict if none.
|
|
158
|
+
"""
|
|
159
|
+
return {}
|
|
160
|
+
|
|
161
|
+
def get_metadata(self) -> Dict[str, Any]:
|
|
162
|
+
"""Return extension metadata.
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
Dict[str, Any]
|
|
167
|
+
Metadata including version, author, description, etc.
|
|
168
|
+
"""
|
|
169
|
+
return {
|
|
170
|
+
"domain": self.get_domain_name(),
|
|
171
|
+
"version": "1.0.0",
|
|
172
|
+
"description": self.__doc__ or "No description provided",
|
|
173
|
+
}
|