tnfr 4.5.1__py3-none-any.whl → 6.0.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.
Files changed (170) hide show
  1. tnfr/__init__.py +270 -90
  2. tnfr/__init__.pyi +40 -0
  3. tnfr/_compat.py +11 -0
  4. tnfr/_version.py +7 -0
  5. tnfr/_version.pyi +7 -0
  6. tnfr/alias.py +631 -0
  7. tnfr/alias.pyi +140 -0
  8. tnfr/cache.py +732 -0
  9. tnfr/cache.pyi +232 -0
  10. tnfr/callback_utils.py +381 -0
  11. tnfr/callback_utils.pyi +105 -0
  12. tnfr/cli/__init__.py +89 -0
  13. tnfr/cli/__init__.pyi +47 -0
  14. tnfr/cli/arguments.py +199 -0
  15. tnfr/cli/arguments.pyi +33 -0
  16. tnfr/cli/execution.py +322 -0
  17. tnfr/cli/execution.pyi +80 -0
  18. tnfr/cli/utils.py +34 -0
  19. tnfr/cli/utils.pyi +8 -0
  20. tnfr/config/__init__.py +12 -0
  21. tnfr/config/__init__.pyi +8 -0
  22. tnfr/config/constants.py +104 -0
  23. tnfr/config/constants.pyi +12 -0
  24. tnfr/config/init.py +36 -0
  25. tnfr/config/init.pyi +8 -0
  26. tnfr/config/operator_names.py +106 -0
  27. tnfr/config/operator_names.pyi +28 -0
  28. tnfr/config/presets.py +104 -0
  29. tnfr/config/presets.pyi +7 -0
  30. tnfr/constants/__init__.py +228 -0
  31. tnfr/constants/__init__.pyi +104 -0
  32. tnfr/constants/core.py +158 -0
  33. tnfr/constants/core.pyi +17 -0
  34. tnfr/constants/init.py +31 -0
  35. tnfr/constants/init.pyi +12 -0
  36. tnfr/constants/metric.py +102 -0
  37. tnfr/constants/metric.pyi +19 -0
  38. tnfr/constants_glyphs.py +16 -0
  39. tnfr/constants_glyphs.pyi +12 -0
  40. tnfr/dynamics/__init__.py +136 -0
  41. tnfr/dynamics/__init__.pyi +83 -0
  42. tnfr/dynamics/adaptation.py +201 -0
  43. tnfr/dynamics/aliases.py +22 -0
  44. tnfr/dynamics/coordination.py +343 -0
  45. tnfr/dynamics/dnfr.py +2315 -0
  46. tnfr/dynamics/dnfr.pyi +33 -0
  47. tnfr/dynamics/integrators.py +561 -0
  48. tnfr/dynamics/integrators.pyi +35 -0
  49. tnfr/dynamics/runtime.py +521 -0
  50. tnfr/dynamics/sampling.py +34 -0
  51. tnfr/dynamics/sampling.pyi +7 -0
  52. tnfr/dynamics/selectors.py +680 -0
  53. tnfr/execution.py +216 -0
  54. tnfr/execution.pyi +65 -0
  55. tnfr/flatten.py +283 -0
  56. tnfr/flatten.pyi +28 -0
  57. tnfr/gamma.py +320 -89
  58. tnfr/gamma.pyi +40 -0
  59. tnfr/glyph_history.py +337 -0
  60. tnfr/glyph_history.pyi +53 -0
  61. tnfr/grammar.py +23 -153
  62. tnfr/grammar.pyi +13 -0
  63. tnfr/helpers/__init__.py +151 -0
  64. tnfr/helpers/__init__.pyi +66 -0
  65. tnfr/helpers/numeric.py +88 -0
  66. tnfr/helpers/numeric.pyi +12 -0
  67. tnfr/immutable.py +214 -0
  68. tnfr/immutable.pyi +37 -0
  69. tnfr/initialization.py +199 -0
  70. tnfr/initialization.pyi +73 -0
  71. tnfr/io.py +311 -0
  72. tnfr/io.pyi +11 -0
  73. tnfr/locking.py +37 -0
  74. tnfr/locking.pyi +7 -0
  75. tnfr/metrics/__init__.py +41 -0
  76. tnfr/metrics/__init__.pyi +20 -0
  77. tnfr/metrics/coherence.py +1469 -0
  78. tnfr/metrics/common.py +149 -0
  79. tnfr/metrics/common.pyi +15 -0
  80. tnfr/metrics/core.py +259 -0
  81. tnfr/metrics/core.pyi +13 -0
  82. tnfr/metrics/diagnosis.py +840 -0
  83. tnfr/metrics/diagnosis.pyi +89 -0
  84. tnfr/metrics/export.py +151 -0
  85. tnfr/metrics/glyph_timing.py +369 -0
  86. tnfr/metrics/reporting.py +152 -0
  87. tnfr/metrics/reporting.pyi +12 -0
  88. tnfr/metrics/sense_index.py +294 -0
  89. tnfr/metrics/sense_index.pyi +9 -0
  90. tnfr/metrics/trig.py +216 -0
  91. tnfr/metrics/trig.pyi +12 -0
  92. tnfr/metrics/trig_cache.py +105 -0
  93. tnfr/metrics/trig_cache.pyi +10 -0
  94. tnfr/node.py +255 -177
  95. tnfr/node.pyi +161 -0
  96. tnfr/observers.py +154 -150
  97. tnfr/observers.pyi +46 -0
  98. tnfr/ontosim.py +135 -134
  99. tnfr/ontosim.pyi +33 -0
  100. tnfr/operators/__init__.py +452 -0
  101. tnfr/operators/__init__.pyi +31 -0
  102. tnfr/operators/definitions.py +181 -0
  103. tnfr/operators/definitions.pyi +92 -0
  104. tnfr/operators/jitter.py +266 -0
  105. tnfr/operators/jitter.pyi +11 -0
  106. tnfr/operators/registry.py +80 -0
  107. tnfr/operators/registry.pyi +15 -0
  108. tnfr/operators/remesh.py +569 -0
  109. tnfr/presets.py +10 -23
  110. tnfr/presets.pyi +7 -0
  111. tnfr/py.typed +0 -0
  112. tnfr/rng.py +440 -0
  113. tnfr/rng.pyi +14 -0
  114. tnfr/selector.py +217 -0
  115. tnfr/selector.pyi +19 -0
  116. tnfr/sense.py +307 -142
  117. tnfr/sense.pyi +30 -0
  118. tnfr/structural.py +69 -164
  119. tnfr/structural.pyi +46 -0
  120. tnfr/telemetry/__init__.py +13 -0
  121. tnfr/telemetry/verbosity.py +37 -0
  122. tnfr/tokens.py +61 -0
  123. tnfr/tokens.pyi +41 -0
  124. tnfr/trace.py +520 -95
  125. tnfr/trace.pyi +68 -0
  126. tnfr/types.py +382 -17
  127. tnfr/types.pyi +145 -0
  128. tnfr/utils/__init__.py +158 -0
  129. tnfr/utils/__init__.pyi +133 -0
  130. tnfr/utils/cache.py +755 -0
  131. tnfr/utils/cache.pyi +156 -0
  132. tnfr/utils/data.py +267 -0
  133. tnfr/utils/data.pyi +73 -0
  134. tnfr/utils/graph.py +87 -0
  135. tnfr/utils/graph.pyi +10 -0
  136. tnfr/utils/init.py +746 -0
  137. tnfr/utils/init.pyi +85 -0
  138. tnfr/utils/io.py +157 -0
  139. tnfr/utils/io.pyi +10 -0
  140. tnfr/utils/validators.py +130 -0
  141. tnfr/utils/validators.pyi +19 -0
  142. tnfr/validation/__init__.py +25 -0
  143. tnfr/validation/__init__.pyi +17 -0
  144. tnfr/validation/compatibility.py +59 -0
  145. tnfr/validation/compatibility.pyi +8 -0
  146. tnfr/validation/grammar.py +149 -0
  147. tnfr/validation/grammar.pyi +11 -0
  148. tnfr/validation/rules.py +194 -0
  149. tnfr/validation/rules.pyi +18 -0
  150. tnfr/validation/syntax.py +151 -0
  151. tnfr/validation/syntax.pyi +7 -0
  152. tnfr-6.0.0.dist-info/METADATA +135 -0
  153. tnfr-6.0.0.dist-info/RECORD +157 -0
  154. tnfr/cli.py +0 -322
  155. tnfr/config.py +0 -41
  156. tnfr/constants.py +0 -277
  157. tnfr/dynamics.py +0 -814
  158. tnfr/helpers.py +0 -264
  159. tnfr/main.py +0 -47
  160. tnfr/metrics.py +0 -597
  161. tnfr/operators.py +0 -525
  162. tnfr/program.py +0 -176
  163. tnfr/scenarios.py +0 -34
  164. tnfr/validators.py +0 -38
  165. tnfr-4.5.1.dist-info/METADATA +0 -221
  166. tnfr-4.5.1.dist-info/RECORD +0 -28
  167. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
  168. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
  169. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
  170. {tnfr-4.5.1.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
tnfr/cli/execution.pyi ADDED
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+ from typing import Any, Optional
6
+
7
+ import networkx as nx
8
+
9
+ from ..constants import METRIC_DEFAULTS
10
+ from ..dynamics import (
11
+ run,
12
+ default_glyph_selector,
13
+ parametric_glyph_selector,
14
+ validate_canon,
15
+ )
16
+ from ..execution import CANONICAL_PRESET_NAME, play, seq
17
+ from ..flatten import parse_program_tokens
18
+ from ..glyph_history import ensure_history
19
+ from ..io import read_structured_file, safe_write, StructuredFileError
20
+ from ..metrics import (
21
+ register_metrics_callbacks,
22
+ glyph_top,
23
+ export_metrics,
24
+ build_metrics_summary,
25
+ )
26
+ from ..metrics.core import _metrics_step
27
+ from ..ontosim import prepare_network
28
+ from ..sense import register_sigma_callback
29
+ from ..trace import register_trace
30
+ from ..types import Glyph, ProgramTokens
31
+ from ..utils import get_logger, json_dumps
32
+ from ..config import apply_config
33
+ from ..config.presets import get_preset
34
+
35
+ from .arguments import _args_to_dict
36
+
37
+ DEFAULT_SUMMARY_SERIES_LIMIT: int
38
+ logger: Any
39
+
40
+
41
+ def _save_json(path: str, data: Any) -> None: ...
42
+
43
+ def _attach_callbacks(G: nx.Graph) -> None: ...
44
+
45
+ def _persist_history(G: nx.Graph, args: argparse.Namespace) -> None: ...
46
+
47
+ def build_basic_graph(args: argparse.Namespace) -> nx.Graph: ...
48
+
49
+ def apply_cli_config(G: nx.Graph, args: argparse.Namespace) -> None: ...
50
+
51
+ def register_callbacks_and_observer(G: nx.Graph) -> None: ...
52
+
53
+ def _build_graph_from_args(args: argparse.Namespace) -> nx.Graph: ...
54
+
55
+ def _load_sequence(path: Path) -> ProgramTokens: ...
56
+
57
+ def resolve_program(
58
+ args: argparse.Namespace, default: Optional[ProgramTokens] = ...
59
+ ) -> Optional[ProgramTokens]: ...
60
+
61
+ def run_program(
62
+ G: Optional[nx.Graph],
63
+ program: Optional[ProgramTokens],
64
+ args: argparse.Namespace,
65
+ ) -> nx.Graph: ...
66
+
67
+ def _run_cli_program(
68
+ args: argparse.Namespace,
69
+ *,
70
+ default_program: Optional[ProgramTokens] = ...,
71
+ graph: Optional[nx.Graph] = ...,
72
+ ) -> tuple[int, Optional[nx.Graph]]: ...
73
+
74
+ def _log_run_summaries(G: nx.Graph, args: argparse.Namespace) -> None: ...
75
+
76
+ def cmd_run(args: argparse.Namespace) -> int: ...
77
+
78
+ def cmd_sequence(args: argparse.Namespace) -> int: ...
79
+
80
+ def cmd_metrics(args: argparse.Namespace) -> int: ...
tnfr/cli/utils.py ADDED
@@ -0,0 +1,34 @@
1
+ """Utilities for CLI modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ def spec(opt: str, /, **kwargs: Any) -> tuple[str, dict[str, Any]]:
9
+ """Create an argument specification pair.
10
+
11
+ Parameters
12
+ ----------
13
+ opt:
14
+ Option string to register, e.g. ``"--foo"``.
15
+ **kwargs:
16
+ Keyword arguments forwarded to
17
+ :meth:`argparse.ArgumentParser.add_argument`.
18
+
19
+ Returns
20
+ -------
21
+ tuple[str, dict[str, Any]]
22
+ A pair suitable for collecting into argument specification sequences.
23
+ If ``dest`` is not provided it is
24
+ derived from ``opt`` by stripping leading dashes and replacing dots and
25
+ hyphens with underscores. ``default`` defaults to ``None`` so missing
26
+ options can be filtered easily.
27
+ """
28
+
29
+ kwargs = dict(kwargs)
30
+ kwargs.setdefault(
31
+ "dest", opt.lstrip("-").replace("-", "_").replace(".", "_")
32
+ )
33
+ kwargs.setdefault("default", None)
34
+ return opt, kwargs
tnfr/cli/utils.pyi ADDED
@@ -0,0 +1,8 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ annotations: Any
8
+ spec: Any
@@ -0,0 +1,12 @@
1
+ """Configuration package for TNFR.
2
+
3
+ This package groups helpers and canonical defaults that orchestrate how
4
+ configuration payloads interact with the engine. The public API mirrors the
5
+ previous module level functions so downstream importers remain stable.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from .init import apply_config, load_config
11
+
12
+ __all__ = ("load_config", "apply_config")
@@ -0,0 +1,8 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ apply_config: Any
8
+ load_config: Any
@@ -0,0 +1,104 @@
1
+ """Canonical glyph constants tied to configuration presets."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from types import MappingProxyType
7
+ from typing import Mapping
8
+
9
+ from ..types import Glyph
10
+
11
+ # -------------------------
12
+ # Canonical order and functional classifications
13
+ # -------------------------
14
+
15
+ GLYPHS_CANONICAL: tuple[str, ...] = (
16
+ Glyph.AL.value, # 0
17
+ Glyph.EN.value, # 1
18
+ Glyph.IL.value, # 2
19
+ Glyph.OZ.value, # 3
20
+ Glyph.UM.value, # 4
21
+ Glyph.RA.value, # 5
22
+ Glyph.SHA.value, # 6
23
+ Glyph.VAL.value, # 7
24
+ Glyph.NUL.value, # 8
25
+ Glyph.THOL.value, # 9
26
+ Glyph.ZHIR.value, # 10
27
+ Glyph.NAV.value, # 11
28
+ Glyph.REMESH.value, # 12
29
+ )
30
+
31
+ GLYPHS_CANONICAL_SET: frozenset[str] = frozenset(GLYPHS_CANONICAL)
32
+
33
+ STABILIZERS: tuple[str, ...] = (
34
+ Glyph.IL.value,
35
+ Glyph.RA.value,
36
+ Glyph.UM.value,
37
+ Glyph.SHA.value,
38
+ )
39
+
40
+ DISRUPTORS: tuple[str, ...] = (
41
+ Glyph.OZ.value,
42
+ Glyph.ZHIR.value,
43
+ Glyph.NAV.value,
44
+ Glyph.THOL.value,
45
+ )
46
+
47
+ # General map of glyph groupings for cross-reference.
48
+ #
49
+ # Spanish keys (``estabilizadores`` / ``disruptivos``) were removed in TNFR 7.0
50
+ # to keep the public surface English-only. Code that still referenced those
51
+ # identifiers must switch to the canonical ``stabilizers`` / ``disruptors``
52
+ # entries or maintain a private compatibility layer.
53
+ GLYPH_GROUPS: Mapping[str, tuple[str, ...]] = MappingProxyType(
54
+ {
55
+ "stabilizers": STABILIZERS,
56
+ "disruptors": DISRUPTORS,
57
+ # Auxiliary groups for morphosyntactic metrics
58
+ "ID": (Glyph.OZ.value,),
59
+ "CM": (Glyph.ZHIR.value, Glyph.NAV.value),
60
+ "NE": (Glyph.IL.value, Glyph.THOL.value),
61
+ "PP_num": (Glyph.SHA.value,),
62
+ "PP_den": (Glyph.REMESH.value,),
63
+ }
64
+ )
65
+
66
+ # -------------------------
67
+ # Glyph angle map
68
+ # -------------------------
69
+
70
+ # Canonical angles for all recognised glyphs. They are computed from the
71
+ # canonical order and orientation rules for the "stabilizers" and
72
+ # "disruptors" categories.
73
+
74
+
75
+ def _build_angle_map() -> dict[str, float]:
76
+ """Build the angle map in the σ-plane."""
77
+
78
+ step = 2 * math.pi / len(GLYPHS_CANONICAL)
79
+ canonical = {g: i * step for i, g in enumerate(GLYPHS_CANONICAL)}
80
+ angles = dict(canonical)
81
+
82
+ # Orientation rules
83
+ for idx, g in enumerate(STABILIZERS):
84
+ angles[g] = idx * math.pi / 4
85
+ for idx, g in enumerate(DISRUPTORS):
86
+ angles[g] = math.pi + idx * math.pi / 4
87
+
88
+ # Manual exceptions
89
+ angles[Glyph.VAL.value] = canonical[Glyph.RA.value]
90
+ angles[Glyph.NUL.value] = canonical[Glyph.ZHIR.value]
91
+ angles[Glyph.AL.value] = 0.0
92
+ return angles
93
+
94
+
95
+ ANGLE_MAP: Mapping[str, float] = MappingProxyType(_build_angle_map())
96
+
97
+ __all__ = (
98
+ "GLYPHS_CANONICAL",
99
+ "GLYPHS_CANONICAL_SET",
100
+ "STABILIZERS",
101
+ "DISRUPTORS",
102
+ "GLYPH_GROUPS",
103
+ "ANGLE_MAP",
104
+ )
@@ -0,0 +1,12 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ ANGLE_MAP: Any
8
+ DISRUPTORS: Any
9
+ STABILIZERS: Any
10
+ GLYPHS_CANONICAL: Any
11
+ GLYPHS_CANONICAL_SET: Any
12
+ GLYPH_GROUPS: Any
tnfr/config/init.py ADDED
@@ -0,0 +1,36 @@
1
+ """Core configuration helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from ..constants import inject_defaults
10
+ from ..io import read_structured_file
11
+
12
+ if TYPE_CHECKING: # pragma: no cover - only for type checkers
13
+ import networkx as nx
14
+
15
+ __all__ = ("load_config", "apply_config")
16
+
17
+
18
+ def load_config(path: str | Path) -> Mapping[str, Any]:
19
+ """Read a JSON/YAML file and return a mapping with parameters."""
20
+
21
+ path_obj = path if isinstance(path, Path) else Path(path)
22
+ data = read_structured_file(path_obj)
23
+ if not isinstance(data, Mapping):
24
+ raise ValueError("Configuration file must contain an object")
25
+ return data
26
+
27
+
28
+ def apply_config(G: "nx.Graph", path: str | Path) -> None:
29
+ """Inject parameters from ``path`` into ``G.graph``.
30
+
31
+ Reuses :func:`tnfr.constants.inject_defaults` to keep canonical default
32
+ semantics.
33
+ """
34
+
35
+ cfg = load_config(path)
36
+ inject_defaults(G, cfg, override=True)
tnfr/config/init.pyi ADDED
@@ -0,0 +1,8 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ apply_config: Any
8
+ load_config: Any
@@ -0,0 +1,106 @@
1
+ """Canonical operator name constants and reusable sets."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ # Canonical operator identifiers (English tokens)
9
+ EMISSION = "emission"
10
+ RECEPTION = "reception"
11
+ COHERENCE = "coherence"
12
+ DISSONANCE = "dissonance"
13
+ COUPLING = "coupling"
14
+ RESONANCE = "resonance"
15
+ SILENCE = "silence"
16
+ EXPANSION = "expansion"
17
+ CONTRACTION = "contraction"
18
+ SELF_ORGANIZATION = "self_organization"
19
+ MUTATION = "mutation"
20
+ TRANSITION = "transition"
21
+ RECURSIVITY = "recursivity"
22
+
23
+
24
+ # Canonical collections -------------------------------------------------------
25
+
26
+ CANONICAL_OPERATOR_NAMES = frozenset(
27
+ {
28
+ EMISSION,
29
+ RECEPTION,
30
+ COHERENCE,
31
+ DISSONANCE,
32
+ COUPLING,
33
+ RESONANCE,
34
+ SILENCE,
35
+ EXPANSION,
36
+ CONTRACTION,
37
+ SELF_ORGANIZATION,
38
+ MUTATION,
39
+ TRANSITION,
40
+ RECURSIVITY,
41
+ }
42
+ )
43
+
44
+ ALL_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES
45
+ ENGLISH_OPERATOR_NAMES = CANONICAL_OPERATOR_NAMES
46
+
47
+ VALID_START_OPERATORS = frozenset({EMISSION, RECURSIVITY})
48
+ INTERMEDIATE_OPERATORS = frozenset({DISSONANCE, COUPLING, RESONANCE})
49
+ VALID_END_OPERATORS = frozenset({SILENCE, TRANSITION, RECURSIVITY})
50
+ SELF_ORGANIZATION_CLOSURES = frozenset({SILENCE, CONTRACTION})
51
+
52
+
53
+ _LEGACY_COLLECTION_ALIASES: dict[str, str] = {
54
+ "INICIO_VALIDOS": "VALID_START_OPERATORS",
55
+ "TRAMO_INTERMEDIO": "INTERMEDIATE_OPERATORS",
56
+ "CIERRE_VALIDO": "VALID_END_OPERATORS",
57
+ "AUTOORGANIZACION_CIERRES": "SELF_ORGANIZATION_CLOSURES",
58
+ }
59
+
60
+ def canonical_operator_name(name: str) -> str:
61
+ """Return the canonical operator token for ``name``."""
62
+
63
+ return name
64
+
65
+
66
+ def operator_display_name(name: str) -> str:
67
+ """Return the display label for ``name`` (currently the canonical token)."""
68
+
69
+ return canonical_operator_name(name)
70
+
71
+
72
+ __all__ = [
73
+ "EMISSION",
74
+ "RECEPTION",
75
+ "COHERENCE",
76
+ "DISSONANCE",
77
+ "COUPLING",
78
+ "RESONANCE",
79
+ "SILENCE",
80
+ "EXPANSION",
81
+ "CONTRACTION",
82
+ "SELF_ORGANIZATION",
83
+ "MUTATION",
84
+ "TRANSITION",
85
+ "RECURSIVITY",
86
+ "CANONICAL_OPERATOR_NAMES",
87
+ "ENGLISH_OPERATOR_NAMES",
88
+ "ALL_OPERATOR_NAMES",
89
+ "VALID_START_OPERATORS",
90
+ "INTERMEDIATE_OPERATORS",
91
+ "VALID_END_OPERATORS",
92
+ "SELF_ORGANIZATION_CLOSURES",
93
+ "canonical_operator_name",
94
+ "operator_display_name",
95
+ ]
96
+
97
+
98
+ def __getattr__(name: str) -> Any:
99
+ """Provide guidance for legacy operator collection aliases."""
100
+
101
+ canonical = _LEGACY_COLLECTION_ALIASES.get(name)
102
+ if canonical is not None:
103
+ raise AttributeError(
104
+ f"module '{__name__}' has no attribute '{name}'; use '{canonical}' instead."
105
+ )
106
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
@@ -0,0 +1,28 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ ALL_OPERATOR_NAMES: Any
8
+ CANONICAL_OPERATOR_NAMES: Any
9
+ COHERENCE: Any
10
+ CONTRACTION: Any
11
+ COUPLING: Any
12
+ DISSONANCE: Any
13
+ EMISSION: Any
14
+ ENGLISH_OPERATOR_NAMES: Any
15
+ EXPANSION: Any
16
+ INTERMEDIATE_OPERATORS: Any
17
+ MUTATION: Any
18
+ RECEPTION: Any
19
+ RECURSIVITY: Any
20
+ RESONANCE: Any
21
+ SELF_ORGANIZATION: Any
22
+ SELF_ORGANIZATION_CLOSURES: Any
23
+ SILENCE: Any
24
+ TRANSITION: Any
25
+ VALID_END_OPERATORS: Any
26
+ VALID_START_OPERATORS: Any
27
+ canonical_operator_name: Any
28
+ operator_display_name: Any
tnfr/config/presets.py ADDED
@@ -0,0 +1,104 @@
1
+ """Predefined TNFR configuration sequences.
2
+
3
+ Only the canonical English preset identifiers are recognised.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from ..execution import (
9
+ CANONICAL_PRESET_NAME,
10
+ CANONICAL_PROGRAM_TOKENS,
11
+ block,
12
+ seq,
13
+ wait,
14
+ )
15
+ from ..types import Glyph, PresetTokens
16
+
17
+ __all__ = (
18
+ "get_preset",
19
+ "PREFERRED_PRESET_NAMES",
20
+ "legacy_preset_guidance",
21
+ )
22
+
23
+
24
+ _PRIMARY_PRESETS: dict[str, PresetTokens] = {
25
+ "resonant_bootstrap": seq(
26
+ Glyph.AL,
27
+ Glyph.EN,
28
+ Glyph.IL,
29
+ Glyph.RA,
30
+ Glyph.VAL,
31
+ Glyph.UM,
32
+ wait(3),
33
+ Glyph.SHA,
34
+ ),
35
+ "contained_mutation": seq(
36
+ Glyph.AL,
37
+ Glyph.EN,
38
+ block(Glyph.OZ, Glyph.ZHIR, Glyph.IL, repeat=2),
39
+ Glyph.RA,
40
+ Glyph.SHA,
41
+ ),
42
+ "coupling_exploration": seq(
43
+ Glyph.AL,
44
+ Glyph.EN,
45
+ Glyph.IL,
46
+ Glyph.VAL,
47
+ Glyph.UM,
48
+ block(Glyph.OZ, Glyph.NAV, Glyph.IL, repeat=1),
49
+ Glyph.RA,
50
+ Glyph.SHA,
51
+ ),
52
+ "fractal_expand": seq(
53
+ block(Glyph.THOL, Glyph.VAL, Glyph.UM, repeat=2, close=Glyph.NUL),
54
+ Glyph.RA,
55
+ ),
56
+ "fractal_contract": seq(
57
+ block(Glyph.THOL, Glyph.NUL, Glyph.UM, repeat=2, close=Glyph.SHA),
58
+ Glyph.RA,
59
+ ),
60
+ CANONICAL_PRESET_NAME: list(CANONICAL_PROGRAM_TOKENS),
61
+ }
62
+
63
+ PREFERRED_PRESET_NAMES: tuple[str, ...] = tuple(_PRIMARY_PRESETS.keys())
64
+
65
+ _PRESETS: dict[str, PresetTokens] = {**_PRIMARY_PRESETS}
66
+
67
+
68
+ _LEGACY_PRESET_ALIASES: dict[str, str] = {
69
+ "arranque_resonante": "resonant_bootstrap",
70
+ "mutacion_contenida": "contained_mutation",
71
+ "exploracion_acople": "coupling_exploration",
72
+ "ejemplo_canonico": CANONICAL_PRESET_NAME,
73
+ }
74
+
75
+
76
+ def legacy_preset_guidance(name: str) -> str | None:
77
+ """Return CLI guidance for historical preset aliases.
78
+
79
+ Parameters
80
+ ----------
81
+ name:
82
+ Identifier received from the CLI.
83
+
84
+ Returns
85
+ -------
86
+ str | None
87
+ A human readable guidance string when ``name`` matches a removed
88
+ alias. ``None`` when no dedicated guidance is available.
89
+ """
90
+
91
+ canonical = _LEGACY_PRESET_ALIASES.get(name)
92
+ if canonical is None:
93
+ return None
94
+ return (
95
+ f"Legacy preset identifier '{name}' was removed in TNFR 9.0. "
96
+ f"Use '{canonical}' instead."
97
+ )
98
+
99
+
100
+ def get_preset(name: str) -> PresetTokens:
101
+ try:
102
+ return _PRESETS[name]
103
+ except KeyError:
104
+ raise KeyError(f"Preset not found: {name}") from None
@@ -0,0 +1,7 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ get_preset: Any