omnibase_infra 0.2.1__py3-none-any.whl → 0.2.2__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 (116) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/adapters/adapter_onex_tool_execution.py +446 -0
  3. omnibase_infra/cli/commands.py +1 -1
  4. omnibase_infra/configs/widget_mapping.yaml +176 -0
  5. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +4 -1
  6. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +4 -1
  7. omnibase_infra/errors/error_compute_registry.py +4 -1
  8. omnibase_infra/errors/error_event_bus_registry.py +4 -1
  9. omnibase_infra/errors/error_infra.py +3 -1
  10. omnibase_infra/errors/error_policy_registry.py +4 -1
  11. omnibase_infra/handlers/handler_db.py +2 -1
  12. omnibase_infra/handlers/handler_graph.py +10 -5
  13. omnibase_infra/handlers/handler_mcp.py +736 -63
  14. omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
  15. omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
  16. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +301 -4
  17. omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
  18. omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
  19. omnibase_infra/mixins/mixin_node_introspection.py +24 -7
  20. omnibase_infra/mixins/mixin_retry_execution.py +1 -1
  21. omnibase_infra/models/handlers/__init__.py +10 -0
  22. omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
  23. omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
  24. omnibase_infra/models/mcp/__init__.py +15 -0
  25. omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
  26. omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
  27. omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
  28. omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
  29. omnibase_infra/models/registration/model_node_capabilities.py +11 -0
  30. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
  31. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
  32. omnibase_infra/nodes/effects/contract.yaml +0 -5
  33. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
  34. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
  35. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
  36. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
  37. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
  38. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
  39. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +46 -25
  40. omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
  41. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
  42. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +24 -19
  43. omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
  44. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
  45. omnibase_infra/plugins/plugin_compute_base.py +16 -2
  46. omnibase_infra/protocols/protocol_event_projector.py +1 -1
  47. omnibase_infra/runtime/__init__.py +51 -1
  48. omnibase_infra/runtime/binding_config_resolver.py +102 -37
  49. omnibase_infra/runtime/constants_notification.py +75 -0
  50. omnibase_infra/runtime/contract_handler_discovery.py +6 -1
  51. omnibase_infra/runtime/handler_bootstrap_source.py +514 -0
  52. omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
  53. omnibase_infra/runtime/handler_contract_source.py +289 -167
  54. omnibase_infra/runtime/handler_plugin_loader.py +4 -2
  55. omnibase_infra/runtime/mixin_semver_cache.py +25 -1
  56. omnibase_infra/runtime/mixins/__init__.py +7 -0
  57. omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
  58. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
  59. omnibase_infra/runtime/models/__init__.py +24 -0
  60. omnibase_infra/runtime/models/model_health_check_result.py +2 -1
  61. omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
  62. omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
  63. omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
  64. omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
  65. omnibase_infra/runtime/projector_plugin_loader.py +1 -1
  66. omnibase_infra/runtime/projector_shell.py +229 -1
  67. omnibase_infra/runtime/protocols/__init__.py +10 -0
  68. omnibase_infra/runtime/registry/registry_protocol_binding.py +3 -2
  69. omnibase_infra/runtime/registry_policy.py +9 -326
  70. omnibase_infra/runtime/secret_resolver.py +4 -2
  71. omnibase_infra/runtime/service_kernel.py +10 -2
  72. omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
  73. omnibase_infra/runtime/service_runtime_host_process.py +225 -15
  74. omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
  75. omnibase_infra/runtime/transition_notification_publisher.py +764 -0
  76. omnibase_infra/runtime/util_container_wiring.py +6 -5
  77. omnibase_infra/runtime/util_wiring.py +5 -1
  78. omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
  79. omnibase_infra/services/mcp/__init__.py +31 -0
  80. omnibase_infra/services/mcp/mcp_server_lifecycle.py +443 -0
  81. omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
  82. omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
  83. omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
  84. omnibase_infra/services/registry_api/__init__.py +40 -0
  85. omnibase_infra/services/registry_api/main.py +243 -0
  86. omnibase_infra/services/registry_api/models/__init__.py +66 -0
  87. omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
  88. omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
  89. omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
  90. omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
  91. omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
  92. omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
  93. omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
  94. omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
  95. omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
  96. omnibase_infra/services/registry_api/models/model_warning.py +49 -0
  97. omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
  98. omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
  99. omnibase_infra/services/registry_api/routes.py +371 -0
  100. omnibase_infra/services/registry_api/service.py +846 -0
  101. omnibase_infra/services/service_capability_query.py +4 -4
  102. omnibase_infra/services/service_health.py +3 -2
  103. omnibase_infra/services/service_timeout_emitter.py +13 -2
  104. omnibase_infra/utils/util_dsn_validation.py +1 -1
  105. omnibase_infra/validation/__init__.py +3 -19
  106. omnibase_infra/validation/contracts/security.validation.yaml +114 -0
  107. omnibase_infra/validation/infra_validators.py +35 -24
  108. omnibase_infra/validation/validation_exemptions.yaml +113 -9
  109. omnibase_infra/validation/validator_chain_propagation.py +2 -2
  110. omnibase_infra/validation/validator_runtime_shape.py +1 -1
  111. omnibase_infra/validation/validator_security.py +473 -370
  112. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/METADATA +2 -2
  113. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/RECORD +116 -74
  114. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/WHEEL +0 -0
  115. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/entry_points.txt +0 -0
  116. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -10,18 +10,28 @@ Available Protocols:
10
10
  The scheduler is the single source of truth for 'now' across orchestrators.
11
11
  It emits RuntimeTick events at configured intervals.
12
12
 
13
+ ProtocolTransitionNotificationPublisher: Interface for transition notification
14
+ publishing. Used by TransitionNotificationOutbox for delivering state
15
+ transition notifications to event buses.
16
+
13
17
  Related:
14
18
  - OMN-953: RuntimeTick scheduler implementation
19
+ - OMN-1139: TransitionNotificationOutbox implementation
15
20
  - See also: runtime.dispatcher_registry.ProtocolMessageDispatcher
16
21
  - See also: runtime.protocol_policy.ProtocolPolicy
17
22
  """
18
23
 
19
24
  from __future__ import annotations
20
25
 
26
+ # Re-export from omnibase_core for convenience
27
+ from omnibase_core.protocols.notifications import (
28
+ ProtocolTransitionNotificationPublisher,
29
+ )
21
30
  from omnibase_infra.runtime.protocols.protocol_runtime_scheduler import (
22
31
  ProtocolRuntimeScheduler,
23
32
  )
24
33
 
25
34
  __all__: list[str] = [
26
35
  "ProtocolRuntimeScheduler",
36
+ "ProtocolTransitionNotificationPublisher",
27
37
  ]
@@ -65,7 +65,7 @@ from __future__ import annotations
65
65
 
66
66
  import threading
67
67
  import warnings
68
- from typing import TYPE_CHECKING
68
+ from typing import TYPE_CHECKING, Any, cast
69
69
 
70
70
  from omnibase_infra.errors import ModelInfraErrorContext, RuntimeHostError
71
71
 
@@ -115,10 +115,11 @@ class RegistryError(RuntimeHostError):
115
115
  if protocol_type is not None:
116
116
  extra_context["protocol_type"] = protocol_type
117
117
 
118
+ # NOTE: Cast required for mypy - **dict[str, object] doesn't satisfy **context: Any
118
119
  super().__init__(
119
120
  message=message,
120
121
  context=context,
121
- **extra_context,
122
+ **cast("dict[str, Any]", extra_context),
122
123
  )
123
124
 
124
125
 
@@ -80,15 +80,12 @@ Integration Points:
80
80
 
81
81
  from __future__ import annotations
82
82
 
83
- import functools
84
83
  import threading
85
84
  import warnings
86
- from collections.abc import Callable
87
85
  from typing import TYPE_CHECKING
88
86
 
89
87
  from pydantic import ValidationError
90
88
 
91
- from omnibase_core.errors import ModelOnexError
92
89
  from omnibase_core.models.primitives import ModelSemVer
93
90
  from omnibase_infra.enums import EnumInfraTransportType, EnumPolicyType
94
91
  from omnibase_infra.errors import PolicyRegistryError, ProtocolConfigurationError
@@ -892,330 +889,16 @@ class RegistryPolicy(MixinPolicyValidation, MixinSemverCache):
892
889
  return matches[0][1]
893
890
 
894
891
  # ==========================================================================
895
- # Semver Cache Configuration Methods
892
+ # Semver Methods (inherited from MixinSemverCache)
896
893
  # ==========================================================================
897
-
898
- @classmethod
899
- def configure_semver_cache(cls, maxsize: int) -> None:
900
- """Configure semver cache size. Must be called before first parse.
901
-
902
- This method allows configuring the LRU cache size for semver parsing
903
- in large deployments with many policy versions. For most deployments,
904
- the default of 128 entries is sufficient.
905
-
906
- When to Increase Cache Size:
907
- - Very large deployments with > 100 unique policy versions
908
- - High-frequency lookups across many version combinations
909
- - Observed cache eviction causing performance regression
910
-
911
- Args:
912
- maxsize: Maximum cache entries (default: 128).
913
- Recommended range: 64-512 for most deployments.
914
- Each entry uses ~100 bytes.
915
-
916
- Raises:
917
- ProtocolConfigurationError: If cache already initialized (first parse already occurred)
918
-
919
- Example:
920
- >>> # Configure before any registry operations
921
- >>> RegistryPolicy.configure_semver_cache(maxsize=256)
922
- >>> registry = RegistryPolicy()
923
-
924
- Note:
925
- For testing purposes, use _reset_semver_cache() to clear the cache
926
- and allow reconfiguration.
927
- """
928
- with cls._semver_cache_lock:
929
- if cls._semver_cache is not None:
930
- context = ModelInfraErrorContext.with_correlation(
931
- transport_type=EnumInfraTransportType.RUNTIME,
932
- operation="configure_semver_cache",
933
- )
934
- raise ProtocolConfigurationError(
935
- "Cannot reconfigure semver cache after first use. "
936
- "Set RegistryPolicy.SEMVER_CACHE_SIZE before creating any "
937
- "registry instances, or use _reset_semver_cache() for testing.",
938
- context=context,
939
- )
940
- cls.SEMVER_CACHE_SIZE = maxsize
941
-
942
- @classmethod
943
- def _reset_semver_cache(cls) -> None:
944
- """Reset semver cache. For testing only.
945
-
946
- Clears the cached semver parser, allowing reconfiguration of cache size.
947
- This should only be used in test fixtures to ensure test isolation.
948
-
949
- Thread Safety:
950
- This method is thread-safe and uses the class-level lock. The reset
951
- operation is atomic - either the cache is fully reset or not at all.
952
-
953
- In-flight Operations:
954
- If other threads have already obtained a reference to the cache
955
- via _get_semver_parser(), they will continue using the old cache
956
- until they complete. This is safe because the old cache remains
957
- a valid callable until garbage collected. New operations after
958
- reset will get the new cache instance when created.
959
-
960
- Memory Reclamation:
961
- The old cache's internal LRU entries are explicitly cleared via
962
- cache_clear() before the reference is released. This ensures
963
- prompt memory reclamation rather than waiting for garbage
964
- collection.
965
-
966
- Concurrent Reset:
967
- Multiple concurrent reset calls are safe. Each reset will clear
968
- the current cache (if any) and set the reference to None. The
969
- lock ensures only one reset executes at a time.
970
-
971
- Example:
972
- >>> # In test fixture
973
- >>> RegistryPolicy._reset_semver_cache()
974
- >>> RegistryPolicy.SEMVER_CACHE_SIZE = 64
975
- >>> # Now cache will be initialized with size 64 on next use
976
- """
977
- with cls._semver_cache_lock:
978
- # Clear the inner LRU-cached function (has the actual cache)
979
- inner_cache = cls._semver_cache_inner
980
- if inner_cache is not None:
981
- # Clear internal LRU cache entries before releasing reference.
982
- # This ensures prompt memory reclamation rather than waiting
983
- # for garbage collection of the orphaned function object.
984
- # Note: cache_clear() is added by @lru_cache decorator but not
985
- # reflected in Callable type annotation. This is a known mypy
986
- # limitation with lru_cache wrappers.
987
- inner_cache.cache_clear() # type: ignore[attr-defined]
988
- cls._semver_cache = None
989
- cls._semver_cache_inner = None
990
-
991
- @classmethod
992
- def _get_semver_parser(cls) -> Callable[[str], ModelSemVer]:
993
- """Get or create the semver parser with configured cache size.
994
-
995
- This method implements lazy initialization of the LRU-cached semver parser.
996
- The cache size is determined by SEMVER_CACHE_SIZE at initialization time.
997
-
998
- Thread Safety:
999
- Uses double-checked locking pattern for thread-safe lazy initialization.
1000
- The fast path stores the cache reference in a local variable to prevent
1001
- TOCTOU (time-of-check-time-of-use) race conditions where another thread
1002
- could call _reset_semver_cache() between the None check and the return.
1003
-
1004
- Cache Key Normalization:
1005
- Version strings are normalized BEFORE being used as cache keys to ensure
1006
- that equivalent versions (e.g., "1.0" and "1.0.0") share the same cache
1007
- entry. This prevents cache fragmentation and improves hit rates.
1008
-
1009
- Returns:
1010
- Cached semver parsing function that returns ModelSemVer instances.
1011
- The returned function accepts a version string and returns a ModelSemVer.
1012
-
1013
- Raises:
1014
- ProtocolConfigurationError: Raised by the returned parsing function if
1015
- the version format is invalid (e.g., non-numeric components,
1016
- negative numbers, or more than 3 version parts).
1017
-
1018
- Performance:
1019
- - First call: Creates LRU-cached function (one-time cost)
1020
- - Subsequent calls: Returns cached function reference (O(1))
1021
- - Cache hit rate improved by normalizing keys before lookup
1022
- """
1023
- # Fast path: cache already initialized
1024
- # CRITICAL: Store in local variable to prevent TOCTOU race condition.
1025
- # Without this, another thread could call _reset_semver_cache() between
1026
- # the None check and the return, causing this method to return None.
1027
- cache = cls._semver_cache
1028
- if cache is not None:
1029
- return cache
1030
-
1031
- # Slow path: initialize with lock
1032
- with cls._semver_cache_lock:
1033
- # Double-check after acquiring lock
1034
- if cls._semver_cache is not None:
1035
- return cls._semver_cache
1036
-
1037
- # Create LRU-cached parser with configured size
1038
- # The cache key is the NORMALIZED version string to prevent
1039
- # fragmentation (e.g., "1.0" and "1.0.0" share the same entry)
1040
- @functools.lru_cache(maxsize=cls.SEMVER_CACHE_SIZE)
1041
- def _parse_semver_cached(normalized_version: str) -> ModelSemVer:
1042
- """Parse normalized semantic version string into ModelSemVer.
1043
-
1044
- This function receives ALREADY NORMALIZED version strings.
1045
- The normalization is done by the wrapper function before
1046
- caching to ensure equivalent versions share cache entries.
1047
-
1048
- Args:
1049
- normalized_version: Pre-normalized version in "x.y.z" or
1050
- "x.y.z-prerelease" format
1051
-
1052
- Returns:
1053
- ModelSemVer instance for comparison
1054
-
1055
- Raises:
1056
- ProtocolConfigurationError: If version format is invalid
1057
- """
1058
- # ModelOnexError is imported at module level
1059
- try:
1060
- return ModelSemVer.parse(normalized_version)
1061
- except ModelOnexError as e:
1062
- context = ModelInfraErrorContext.with_correlation(
1063
- transport_type=EnumInfraTransportType.RUNTIME,
1064
- operation="parse_semver",
1065
- )
1066
- raise ProtocolConfigurationError(
1067
- str(e),
1068
- version=normalized_version,
1069
- context=context,
1070
- ) from e
1071
- except ValueError as e:
1072
- context = ModelInfraErrorContext.with_correlation(
1073
- transport_type=EnumInfraTransportType.RUNTIME,
1074
- operation="parse_semver",
1075
- )
1076
- raise ProtocolConfigurationError(
1077
- str(e),
1078
- version=normalized_version,
1079
- context=context,
1080
- ) from e
1081
-
1082
- def _parse_semver_impl(version: str) -> ModelSemVer:
1083
- """Parse semantic version string into ModelSemVer.
1084
-
1085
- Implementation moved here to support configurable cache size.
1086
- See _parse_semver docstring for full documentation.
1087
-
1088
- IMPORTANT: This wrapper normalizes version strings BEFORE
1089
- passing to the LRU-cached parsing function. This ensures that
1090
- equivalent versions (e.g., "1.0" and "1.0.0", "v1.0.0" and "1.0.0")
1091
- share the same cache entry, improving cache hit rates.
1092
-
1093
- All validation (empty strings, prerelease suffix, format) is
1094
- delegated to _normalize_version to eliminate code duplication.
1095
- """
1096
- # Delegate all validation to _normalize_version (single source of truth)
1097
- # This eliminates duplicated validation logic (empty check, prerelease suffix)
1098
- normalized = RegistryPolicy._normalize_version(version)
1099
-
1100
- # Now call the cached function with the NORMALIZED version
1101
- # This ensures "1.0", "1.0.0", "v1.0.0" all use the same cache entry
1102
- return _parse_semver_cached(normalized)
1103
-
1104
- # Store both the outer wrapper and inner cached function
1105
- # The wrapper is what callers use (_semver_cache)
1106
- # The inner function is needed for cache_clear() access (_semver_cache_inner)
1107
- cls._semver_cache = _parse_semver_impl
1108
- cls._semver_cache_inner = _parse_semver_cached
1109
- return cls._semver_cache
1110
-
1111
- @classmethod
1112
- def _parse_semver(cls, version: str) -> ModelSemVer:
1113
- """Parse semantic version string into ModelSemVer for comparison.
1114
-
1115
- This method implements SEMANTIC VERSION SORTING, not lexicographic sorting.
1116
- This is critical for correct "latest version" selection.
1117
-
1118
- Why This Matters (PR #36 feedback):
1119
- Lexicographic sorting (string comparison):
1120
- "1.10.0" < "1.9.0" WRONG (because '1' < '9' in strings)
1121
- "10.0.0" < "2.0.0" WRONG (because '1' < '2' in strings)
1122
-
1123
- Semantic version sorting (integer comparison):
1124
- 1.10.0 > 1.9.0 CORRECT (because 10 > 9 as integers)
1125
- 10.0.0 > 2.0.0 CORRECT (because 10 > 2 as integers)
1126
-
1127
- Implementation:
1128
- - Returns ModelSemVer instance with integer major, minor, patch
1129
- - ModelSemVer implements comparison operators for correct ordering
1130
- - Prerelease is parsed but NOT used in comparisons (major.minor.patch only)
1131
- - "1.0.0-alpha" and "1.0.0" compare as EQUAL (same major.minor.patch)
1132
-
1133
- Supported Formats:
1134
- - Full: "1.2.3", "1.2.3-beta"
1135
- - Partial: "1" -> (1, 0, 0), "1.2" -> (1, 2, 0)
1136
- - Prerelease: "1.0.0-alpha", "2.1.0-rc.1"
1137
-
1138
- Validation:
1139
- - Rejects empty strings
1140
- - Rejects non-numeric components
1141
- - Rejects negative numbers
1142
- - Rejects >3 version parts (e.g., "1.2.3.4")
1143
-
1144
- Performance:
1145
- This method uses an LRU cache with configurable size (default: 128)
1146
- to avoid re-parsing the same version strings repeatedly, improving
1147
- performance for lookups that compare multiple versions.
1148
-
1149
- Cache Size Configuration:
1150
- For large deployments, configure before first use:
1151
- RegistryPolicy.configure_semver_cache(maxsize=256)
1152
-
1153
- Cache Size Rationale (default 128):
1154
- - Typical registry: 10-50 unique policy versions
1155
- - Peak scenarios: 50-100 versions across multiple policy types
1156
- - Each cache entry: ~200 bytes (string key + ModelSemVer instance)
1157
- - Total memory: ~25.6KB worst case (negligible overhead)
1158
- - Hit rate: >95% for repeated get() calls with version comparisons
1159
- - Eviction: Rare in practice, LRU ensures least-used versions purged
1160
-
1161
- Args:
1162
- version: Semantic version string (e.g., "1.2.3" or "1.0.0-beta")
1163
-
1164
- Returns:
1165
- ModelSemVer instance for comparison.
1166
- Components are INTEGERS (not strings) for correct semantic sorting.
1167
- Prerelease is parsed and stored but ignored in version comparisons.
1168
-
1169
- Raises:
1170
- ProtocolConfigurationError: If version format is invalid
1171
-
1172
- Examples:
1173
- >>> RegistryPolicy._parse_semver("1.9.0")
1174
- ModelSemVer(major=1, minor=9, patch=0, prerelease='')
1175
- >>> RegistryPolicy._parse_semver("1.10.0")
1176
- ModelSemVer(major=1, minor=10, patch=0, prerelease='')
1177
- >>> RegistryPolicy._parse_semver("1.10.0") > RegistryPolicy._parse_semver("1.9.0")
1178
- True
1179
- >>> RegistryPolicy._parse_semver("10.0.0") > RegistryPolicy._parse_semver("2.0.0")
1180
- True
1181
- >>> RegistryPolicy._parse_semver("1.0.0-alpha")
1182
- ModelSemVer(major=1, minor=0, patch=0, prerelease='alpha')
1183
- >>> # Prerelease is parsed but NOT used in comparisons:
1184
- >>> RegistryPolicy._parse_semver("1.0.0-alpha") == RegistryPolicy._parse_semver("1.0.0")
1185
- True # Same major.minor.patch, prerelease ignored
1186
- """
1187
- parser = cls._get_semver_parser()
1188
- return parser(version)
1189
-
1190
- @classmethod
1191
- def _get_semver_cache_info(cls) -> functools._CacheInfo | None:
1192
- """Get cache statistics for the semver parser. For testing only.
1193
-
1194
- Returns the cache_info() from the inner LRU-cached function.
1195
- This allows tests to verify cache behavior without accessing
1196
- internal implementation details.
1197
-
1198
- Returns:
1199
- functools._CacheInfo with hits, misses, maxsize, currsize,
1200
- or None if cache not yet initialized.
1201
-
1202
- Example:
1203
- >>> RegistryPolicy._reset_semver_cache()
1204
- >>> RegistryPolicy._parse_semver("1.0.0")
1205
- >>> info = RegistryPolicy._get_semver_cache_info()
1206
- >>> info.misses # First call is a miss
1207
- 1
1208
- >>> RegistryPolicy._parse_semver("1.0.0")
1209
- >>> info = RegistryPolicy._get_semver_cache_info()
1210
- >>> info.hits # Second call is a hit
1211
- 1
1212
- """
1213
- if cls._semver_cache_inner is None:
1214
- return None
1215
- # cache_info() is added by @lru_cache decorator
1216
- # The return type is functools._CacheInfo
1217
- result: functools._CacheInfo = cls._semver_cache_inner.cache_info() # type: ignore[attr-defined]
1218
- return result
894
+ # The following methods are inherited from MixinSemverCache:
895
+ # - configure_semver_cache(maxsize: int) -> None
896
+ # - _reset_semver_cache() -> None
897
+ # - _get_semver_parser() -> Callable[[str], ModelSemVer]
898
+ # - _parse_semver(version: str) -> ModelSemVer
899
+ # - _get_semver_cache_info() -> functools._CacheInfo | None
900
+ #
901
+ # See MixinSemverCache for full documentation of these methods.
1219
902
 
1220
903
  def _list_internal(self) -> list[tuple[str, str, str]]:
1221
904
  """Internal list method (assumes lock is held).
@@ -131,7 +131,7 @@ import time
131
131
  from collections import defaultdict, deque
132
132
  from datetime import UTC, datetime, timedelta
133
133
  from pathlib import Path
134
- from typing import TYPE_CHECKING, Protocol, runtime_checkable
134
+ from typing import TYPE_CHECKING, Protocol, cast, runtime_checkable
135
135
  from uuid import UUID, uuid4
136
136
 
137
137
  from pydantic import SecretStr
@@ -1847,7 +1847,9 @@ class SecretResolver:
1847
1847
  }
1848
1848
 
1849
1849
  try:
1850
- result = await self._vault_handler.execute(envelope)
1850
+ result = await self._vault_handler.execute(
1851
+ cast("dict[str, object]", envelope)
1852
+ )
1851
1853
 
1852
1854
  # Extract secret data from handler response
1853
1855
  # Response format: {"status": "success", "payload": {"data": {...}, "metadata": {...}}}
@@ -1376,24 +1376,32 @@ async def bootstrap() -> int:
1376
1376
 
1377
1377
  except ProtocolConfigurationError as e:
1378
1378
  # Configuration errors already have proper context and chaining
1379
+ error_code = getattr(getattr(e, "model", None), "error_code", None)
1380
+ error_code_name = getattr(error_code, "name", None)
1379
1381
  logger.exception(
1380
1382
  "ONEX runtime configuration failed (correlation_id=%s)",
1381
1383
  correlation_id,
1382
1384
  extra={
1383
1385
  "error_type": type(e).__name__,
1384
- "error_code": e.model.error_code.name if hasattr(e, "model") else None,
1386
+ "error_code": str(error_code_name)
1387
+ if error_code_name is not None
1388
+ else None,
1385
1389
  },
1386
1390
  )
1387
1391
  return 1
1388
1392
 
1389
1393
  except RuntimeHostError as e:
1390
1394
  # Runtime host errors already have proper structure
1395
+ error_code = getattr(getattr(e, "model", None), "error_code", None)
1396
+ error_code_name = getattr(error_code, "name", None)
1391
1397
  logger.exception(
1392
1398
  "ONEX runtime host error (correlation_id=%s)",
1393
1399
  correlation_id,
1394
1400
  extra={
1395
1401
  "error_type": type(e).__name__,
1396
- "error_code": e.model.error_code.name if hasattr(e, "model") else None,
1402
+ "error_code": str(error_code_name)
1403
+ if error_code_name is not None
1404
+ else None,
1397
1405
  },
1398
1406
  )
1399
1407
  return 1
@@ -1512,7 +1512,9 @@ class MessageDispatchEngine:
1512
1512
 
1513
1513
  if context is not None:
1514
1514
  # Context-aware sync dispatcher
1515
- sync_ctx_dispatcher = cast(_SyncContextAwareDispatcherFunc, dispatcher)
1515
+ sync_ctx_dispatcher = cast(
1516
+ "_SyncContextAwareDispatcherFunc", dispatcher
1517
+ )
1516
1518
  return await loop.run_in_executor(
1517
1519
  None,
1518
1520
  sync_ctx_dispatcher,
@@ -1524,7 +1526,7 @@ class MessageDispatchEngine:
1524
1526
  else:
1525
1527
  # Cast to sync-only type - safe because iscoroutinefunction check above
1526
1528
  # guarantees this branch only executes for non-async callables
1527
- sync_dispatcher = cast(_SyncDispatcherFunc, dispatcher)
1529
+ sync_dispatcher = cast("_SyncDispatcherFunc", dispatcher)
1528
1530
  return await loop.run_in_executor(
1529
1531
  None,
1530
1532
  sync_dispatcher,