claude-mpm 4.4.3__py3-none-any.whl → 4.4.4__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 (118) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/agent_loader.py +3 -2
  3. claude_mpm/agents/agent_loader_integration.py +2 -1
  4. claude_mpm/agents/async_agent_loader.py +2 -2
  5. claude_mpm/agents/base_agent_loader.py +2 -2
  6. claude_mpm/agents/frontmatter_validator.py +1 -0
  7. claude_mpm/agents/system_agent_config.py +2 -1
  8. claude_mpm/cli/commands/doctor.py +44 -5
  9. claude_mpm/cli/commands/mpm_init.py +116 -62
  10. claude_mpm/cli/parsers/configure_parser.py +3 -1
  11. claude_mpm/cli/startup_logging.py +1 -3
  12. claude_mpm/config/agent_config.py +1 -1
  13. claude_mpm/config/paths.py +2 -1
  14. claude_mpm/core/agent_name_normalizer.py +1 -0
  15. claude_mpm/core/config.py +2 -1
  16. claude_mpm/core/config_aliases.py +2 -1
  17. claude_mpm/core/file_utils.py +0 -1
  18. claude_mpm/core/framework/__init__.py +6 -6
  19. claude_mpm/core/framework/formatters/__init__.py +2 -2
  20. claude_mpm/core/framework/formatters/capability_generator.py +19 -8
  21. claude_mpm/core/framework/formatters/content_formatter.py +8 -3
  22. claude_mpm/core/framework/formatters/context_generator.py +7 -3
  23. claude_mpm/core/framework/loaders/__init__.py +3 -3
  24. claude_mpm/core/framework/loaders/agent_loader.py +7 -3
  25. claude_mpm/core/framework/loaders/file_loader.py +16 -6
  26. claude_mpm/core/framework/loaders/instruction_loader.py +16 -6
  27. claude_mpm/core/framework/loaders/packaged_loader.py +36 -12
  28. claude_mpm/core/framework/processors/__init__.py +2 -2
  29. claude_mpm/core/framework/processors/memory_processor.py +14 -6
  30. claude_mpm/core/framework/processors/metadata_processor.py +5 -5
  31. claude_mpm/core/framework/processors/template_processor.py +12 -6
  32. claude_mpm/core/framework_loader.py +44 -20
  33. claude_mpm/core/log_manager.py +2 -1
  34. claude_mpm/core/tool_access_control.py +1 -0
  35. claude_mpm/core/unified_agent_registry.py +2 -1
  36. claude_mpm/core/unified_paths.py +1 -0
  37. claude_mpm/experimental/cli_enhancements.py +1 -0
  38. claude_mpm/hooks/base_hook.py +1 -0
  39. claude_mpm/hooks/instruction_reinforcement.py +1 -0
  40. claude_mpm/hooks/kuzu_memory_hook.py +20 -13
  41. claude_mpm/hooks/validation_hooks.py +1 -1
  42. claude_mpm/scripts/mpm_doctor.py +1 -0
  43. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
  44. claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
  45. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
  46. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
  47. claude_mpm/services/agents/management/agent_management_service.py +1 -1
  48. claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
  49. claude_mpm/services/agents/memory/memory_file_service.py +6 -2
  50. claude_mpm/services/agents/memory/memory_format_service.py +0 -1
  51. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  52. claude_mpm/services/async_session_logger.py +1 -1
  53. claude_mpm/services/claude_session_logger.py +1 -0
  54. claude_mpm/services/core/path_resolver.py +1 -0
  55. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  56. claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
  57. claude_mpm/services/diagnostics/checks/mcp_services_check.py +399 -0
  58. claude_mpm/services/diagnostics/diagnostic_runner.py +3 -0
  59. claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
  60. claude_mpm/services/event_bus/direct_relay.py +2 -1
  61. claude_mpm/services/event_bus/event_bus.py +1 -0
  62. claude_mpm/services/event_bus/relay.py +3 -2
  63. claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
  64. claude_mpm/services/infrastructure/daemon_manager.py +1 -1
  65. claude_mpm/services/mcp_config_manager.py +10 -10
  66. claude_mpm/services/mcp_gateway/core/process_pool.py +62 -23
  67. claude_mpm/services/mcp_gateway/tools/__init__.py +6 -5
  68. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +3 -1
  69. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +16 -31
  70. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  71. claude_mpm/services/project/archive_manager.py +159 -96
  72. claude_mpm/services/project/documentation_manager.py +64 -45
  73. claude_mpm/services/project/enhanced_analyzer.py +132 -89
  74. claude_mpm/services/project/project_organizer.py +225 -131
  75. claude_mpm/services/response_tracker.py +1 -1
  76. claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
  77. claude_mpm/services/unified/__init__.py +1 -1
  78. claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
  79. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
  80. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
  81. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
  82. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
  83. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
  84. claude_mpm/services/unified/config_strategies/__init__.py +111 -126
  85. claude_mpm/services/unified/config_strategies/config_schema.py +157 -111
  86. claude_mpm/services/unified/config_strategies/context_strategy.py +91 -89
  87. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +183 -173
  88. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +160 -152
  89. claude_mpm/services/unified/config_strategies/unified_config_service.py +124 -112
  90. claude_mpm/services/unified/config_strategies/validation_strategy.py +298 -259
  91. claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
  92. claude_mpm/services/unified/deployment_strategies/base.py +24 -28
  93. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
  94. claude_mpm/services/unified/deployment_strategies/local.py +49 -34
  95. claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
  96. claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
  97. claude_mpm/services/unified/interfaces.py +0 -26
  98. claude_mpm/services/unified/migration.py +17 -40
  99. claude_mpm/services/unified/strategies.py +9 -26
  100. claude_mpm/services/unified/unified_analyzer.py +48 -44
  101. claude_mpm/services/unified/unified_config.py +21 -19
  102. claude_mpm/services/unified/unified_deployment.py +21 -26
  103. claude_mpm/storage/state_storage.py +1 -0
  104. claude_mpm/utils/agent_dependency_loader.py +18 -6
  105. claude_mpm/utils/common.py +14 -12
  106. claude_mpm/utils/database_connector.py +15 -12
  107. claude_mpm/utils/error_handler.py +1 -0
  108. claude_mpm/utils/log_cleanup.py +1 -0
  109. claude_mpm/utils/path_operations.py +1 -0
  110. claude_mpm/utils/session_logging.py +1 -1
  111. claude_mpm/utils/subprocess_utils.py +1 -0
  112. claude_mpm/validation/agent_validator.py +1 -1
  113. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/METADATA +9 -3
  114. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/RECORD +118 -117
  115. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/WHEEL +0 -0
  116. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/entry_points.txt +0 -0
  117. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/licenses/LICENSE +0 -0
  118. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/top_level.txt +0 -0
@@ -3,36 +3,39 @@ Context Strategy - Context-based lifecycle management for configurations
3
3
  Part of Phase 3 Configuration Consolidation
4
4
  """
5
5
 
6
+ import threading
7
+ import weakref
6
8
  from abc import ABC, abstractmethod
7
- from typing import Any, Dict, List, Optional, Union, Callable, Set
9
+ from collections import OrderedDict
10
+ from contextlib import contextmanager
8
11
  from dataclasses import dataclass, field
12
+ from datetime import datetime, timedelta
9
13
  from enum import Enum
10
14
  from pathlib import Path
11
- import threading
12
- from datetime import datetime, timedelta
13
- from contextlib import contextmanager
14
- import weakref
15
- from collections import OrderedDict
15
+ from typing import Any, Callable, Dict, List, Optional, Set, Union
16
16
 
17
17
  from claude_mpm.core.logging_utils import get_logger
18
- from .unified_config_service import IConfigStrategy, ConfigContext
18
+
19
+ from .unified_config_service import IConfigStrategy
19
20
 
20
21
 
21
22
  class ContextScope(Enum):
22
23
  """Configuration context scopes"""
23
- GLOBAL = "global" # Application-wide
24
- SESSION = "session" # User session
25
- PROJECT = "project" # Project-specific
26
- AGENT = "agent" # Agent-specific
27
- SERVICE = "service" # Service-specific
28
- TRANSACTION = "transaction" # Transaction-specific
29
- REQUEST = "request" # Request-specific
30
- THREAD = "thread" # Thread-local
31
- TEMPORARY = "temporary" # Temporary context
24
+
25
+ GLOBAL = "global" # Application-wide
26
+ SESSION = "session" # User session
27
+ PROJECT = "project" # Project-specific
28
+ AGENT = "agent" # Agent-specific
29
+ SERVICE = "service" # Service-specific
30
+ TRANSACTION = "transaction" # Transaction-specific
31
+ REQUEST = "request" # Request-specific
32
+ THREAD = "thread" # Thread-local
33
+ TEMPORARY = "temporary" # Temporary context
32
34
 
33
35
 
34
36
  class ContextLifecycle(Enum):
35
37
  """Context lifecycle states"""
38
+
36
39
  CREATED = "created"
37
40
  INITIALIZING = "initializing"
38
41
  ACTIVE = "active"
@@ -44,6 +47,7 @@ class ContextLifecycle(Enum):
44
47
  @dataclass
45
48
  class ContextMetadata:
46
49
  """Metadata for context tracking"""
50
+
47
51
  id: str
48
52
  scope: ContextScope
49
53
  lifecycle: ContextLifecycle
@@ -59,6 +63,7 @@ class ContextMetadata:
59
63
  @dataclass
60
64
  class ContextConfig:
61
65
  """Configuration within a context"""
66
+
62
67
  context_id: str
63
68
  data: Dict[str, Any]
64
69
  overrides: Dict[str, Any] = field(default_factory=dict)
@@ -79,17 +84,14 @@ class BaseContextManager(ABC):
79
84
  @abstractmethod
80
85
  def create_context(self, scope: ContextScope, **kwargs) -> str:
81
86
  """Create a new context"""
82
- pass
83
87
 
84
88
  @abstractmethod
85
89
  def get_context(self, context_id: str) -> Optional[ContextMetadata]:
86
90
  """Get context metadata"""
87
- pass
88
91
 
89
92
  @abstractmethod
90
93
  def close_context(self, context_id: str):
91
94
  """Close a context"""
92
- pass
93
95
 
94
96
 
95
97
  class HierarchicalContextManager(BaseContextManager):
@@ -105,7 +107,7 @@ class HierarchicalContextManager(BaseContextManager):
105
107
  scope: ContextScope,
106
108
  parent_id: Optional[str] = None,
107
109
  ttl: Optional[timedelta] = None,
108
- **kwargs
110
+ **kwargs,
109
111
  ) -> str:
110
112
  """Create a new hierarchical context"""
111
113
  with self._lock:
@@ -113,7 +115,7 @@ class HierarchicalContextManager(BaseContextManager):
113
115
  context_id = self._generate_context_id(scope)
114
116
 
115
117
  # Use current context as parent if not specified
116
- if parent_id is None and hasattr(self.context_stack, 'stack'):
118
+ if parent_id is None and hasattr(self.context_stack, "stack"):
117
119
  if self.context_stack.stack:
118
120
  parent_id = self.context_stack.stack[-1]
119
121
 
@@ -127,7 +129,7 @@ class HierarchicalContextManager(BaseContextManager):
127
129
  parent_id=parent_id,
128
130
  ttl=ttl,
129
131
  expires_at=datetime.now() + ttl if ttl else None,
130
- attributes=kwargs
132
+ attributes=kwargs,
131
133
  )
132
134
 
133
135
  # Store context
@@ -142,10 +144,7 @@ class HierarchicalContextManager(BaseContextManager):
142
144
  self.context_hierarchy[parent_id].append(context_id)
143
145
 
144
146
  # Initialize context config
145
- self.configs[context_id] = ContextConfig(
146
- context_id=context_id,
147
- data={}
148
- )
147
+ self.configs[context_id] = ContextConfig(context_id=context_id, data={})
149
148
 
150
149
  # Set lifecycle to active
151
150
  metadata.lifecycle = ContextLifecycle.ACTIVE
@@ -216,6 +215,7 @@ class HierarchicalContextManager(BaseContextManager):
216
215
  def _generate_context_id(self, scope: ContextScope) -> str:
217
216
  """Generate unique context ID"""
218
217
  import uuid
218
+
219
219
  return f"{scope.value}_{uuid.uuid4().hex[:8]}"
220
220
 
221
221
  @contextmanager
@@ -224,7 +224,7 @@ class HierarchicalContextManager(BaseContextManager):
224
224
  context_id = self.create_context(scope, **kwargs)
225
225
 
226
226
  # Push to thread-local stack
227
- if not hasattr(self.context_stack, 'stack'):
227
+ if not hasattr(self.context_stack, "stack"):
228
228
  self.context_stack.stack = []
229
229
  self.context_stack.stack.append(context_id)
230
230
 
@@ -248,10 +248,7 @@ class ScopedConfigManager:
248
248
  self._lock = threading.RLock()
249
249
 
250
250
  def get_config(
251
- self,
252
- context_id: str,
253
- key: Optional[str] = None,
254
- inherit: bool = True
251
+ self, context_id: str, key: Optional[str] = None, inherit: bool = True
255
252
  ) -> Any:
256
253
  """Get configuration value from context"""
257
254
  with self._lock:
@@ -275,7 +272,7 @@ class ScopedConfigManager:
275
272
  key: str,
276
273
  value: Any,
277
274
  override: bool = False,
278
- lock: bool = False
275
+ lock: bool = False,
279
276
  ):
280
277
  """Set configuration value in context"""
281
278
  with self._lock:
@@ -330,7 +327,11 @@ class ScopedConfigManager:
330
327
  result = base.copy()
331
328
 
332
329
  for key, value in override.items():
333
- if key in result and isinstance(result[key], dict) and isinstance(value, dict):
330
+ if (
331
+ key in result
332
+ and isinstance(result[key], dict)
333
+ and isinstance(value, dict)
334
+ ):
334
335
  result[key] = self._deep_merge(result[key], value)
335
336
  else:
336
337
  result[key] = value
@@ -339,7 +340,7 @@ class ScopedConfigManager:
339
340
 
340
341
  def _get_nested_value(self, config: Dict, key: str) -> Any:
341
342
  """Get nested value using dot notation"""
342
- parts = key.split('.')
343
+ parts = key.split(".")
343
344
  current = config
344
345
 
345
346
  for part in parts:
@@ -352,7 +353,7 @@ class ScopedConfigManager:
352
353
 
353
354
  def _set_nested_value(self, config: Dict, key: str, value: Any):
354
355
  """Set nested value using dot notation"""
355
- parts = key.split('.')
356
+ parts = key.split(".")
356
357
  current = config
357
358
 
358
359
  for part in parts[:-1]:
@@ -377,8 +378,9 @@ class ScopedConfigManager:
377
378
 
378
379
  # Trigger pattern watchers
379
380
  for pattern, watchers in config.watchers.items():
380
- if '*' in pattern or '?' in pattern:
381
+ if "*" in pattern or "?" in pattern:
381
382
  import fnmatch
383
+
382
384
  if fnmatch.fnmatch(key, pattern):
383
385
  for watcher in watchers:
384
386
  try:
@@ -396,11 +398,11 @@ class IsolatedContextManager:
396
398
  self._lock = threading.RLock()
397
399
 
398
400
  def create_isolated_context(
399
- self,
400
- base_config: Optional[Dict[str, Any]] = None
401
+ self, base_config: Optional[Dict[str, Any]] = None
401
402
  ) -> str:
402
403
  """Create an isolated context with no inheritance"""
403
404
  import uuid
405
+
404
406
  context_id = f"isolated_{uuid.uuid4().hex[:8]}"
405
407
 
406
408
  with self._lock:
@@ -434,11 +436,13 @@ class ThreadLocalContextManager:
434
436
  def __init__(self):
435
437
  self.logger = get_logger(self.__class__.__name__)
436
438
  self.thread_contexts = threading.local()
437
- self._global_registry: weakref.WeakValueDictionary = weakref.WeakValueDictionary()
439
+ self._global_registry: weakref.WeakValueDictionary = (
440
+ weakref.WeakValueDictionary()
441
+ )
438
442
 
439
443
  def get_thread_context(self) -> Optional[Dict[str, Any]]:
440
444
  """Get current thread's context"""
441
- if hasattr(self.thread_contexts, 'config'):
445
+ if hasattr(self.thread_contexts, "config"):
442
446
  return self.thread_contexts.config
443
447
  return None
444
448
 
@@ -449,8 +453,8 @@ class ThreadLocalContextManager:
449
453
 
450
454
  def clear_thread_context(self):
451
455
  """Clear current thread's context"""
452
- if hasattr(self.thread_contexts, 'config'):
453
- delattr(self.thread_contexts, 'config')
456
+ if hasattr(self.thread_contexts, "config"):
457
+ delattr(self.thread_contexts, "config")
454
458
 
455
459
  @contextmanager
456
460
  def thread_context(self, config: Dict[str, Any]):
@@ -507,8 +511,7 @@ class CachingContextManager:
507
511
  """Invalidate all cached values for context"""
508
512
  with self._lock:
509
513
  keys_to_remove = [
510
- k for k in self.cache.keys()
511
- if k.startswith(f"{context_id}:")
514
+ k for k in self.cache.keys() if k.startswith(f"{context_id}:")
512
515
  ]
513
516
 
514
517
  for key in keys_to_remove:
@@ -519,12 +522,16 @@ class CachingContextManager:
519
522
  total_requests = self.hit_count + self.miss_count
520
523
 
521
524
  return {
522
- 'size': len(self.cache),
523
- 'max_size': self.max_size,
524
- 'hit_count': self.hit_count,
525
- 'miss_count': self.miss_count,
526
- 'hit_rate': (self.hit_count / total_requests * 100) if total_requests > 0 else 0,
527
- 'utilization': (len(self.cache) / self.max_size * 100) if self.max_size > 0 else 0
525
+ "size": len(self.cache),
526
+ "max_size": self.max_size,
527
+ "hit_count": self.hit_count,
528
+ "miss_count": self.miss_count,
529
+ "hit_rate": (
530
+ (self.hit_count / total_requests * 100) if total_requests > 0 else 0
531
+ ),
532
+ "utilization": (
533
+ (len(self.cache) / self.max_size * 100) if self.max_size > 0 else 0
534
+ ),
528
535
  }
529
536
 
530
537
 
@@ -548,14 +555,13 @@ class ContextStrategy(IConfigStrategy):
548
555
 
549
556
  def load(self, source: Any, **kwargs) -> Dict[str, Any]:
550
557
  """Load configuration into context"""
551
- context_scope = kwargs.get('context_scope', ContextScope.TEMPORARY)
552
- context_id = kwargs.get('context_id')
558
+ context_scope = kwargs.get("context_scope", ContextScope.TEMPORARY)
559
+ context_id = kwargs.get("context_id")
553
560
 
554
561
  if not context_id:
555
562
  # Create new context
556
563
  context_id = self.hierarchy_manager.create_context(
557
- context_scope,
558
- ttl=kwargs.get('ttl')
564
+ context_scope, ttl=kwargs.get("ttl")
559
565
  )
560
566
 
561
567
  # Load config into context
@@ -577,9 +583,7 @@ class ContextStrategy(IConfigStrategy):
577
583
  if context:
578
584
  # Apply context-specific overrides
579
585
  overrides = self.scoped_manager.get_config(
580
- context,
581
- 'transformations.overrides',
582
- inherit=True
586
+ context, "transformations.overrides", inherit=True
583
587
  )
584
588
 
585
589
  if overrides:
@@ -592,31 +596,31 @@ class ContextStrategy(IConfigStrategy):
592
596
  scope: ContextScope = ContextScope.TEMPORARY,
593
597
  parent: Optional[str] = None,
594
598
  isolated: bool = False,
595
- **kwargs
599
+ **kwargs,
596
600
  ) -> str:
597
601
  """Create a new configuration context"""
598
602
  if isolated:
599
603
  return self.isolated_manager.create_isolated_context(
600
- kwargs.get('base_config')
601
- )
602
- else:
603
- return self.hierarchy_manager.create_context(
604
- scope,
605
- parent_id=parent,
606
- **kwargs
604
+ kwargs.get("base_config")
607
605
  )
606
+ return self.hierarchy_manager.create_context(
607
+ scope, parent_id=parent, **kwargs
608
+ )
608
609
 
609
610
  def get_current_context(self) -> Optional[str]:
610
611
  """Get current active context"""
611
612
  # Check thread-local stack
612
- if hasattr(self.hierarchy_manager.context_stack, 'stack'):
613
+ if hasattr(self.hierarchy_manager.context_stack, "stack"):
613
614
  stack = self.hierarchy_manager.context_stack.stack
614
615
  if stack:
615
616
  return stack[-1]
616
617
 
617
618
  # Check for global context
618
619
  for ctx_id, metadata in self.hierarchy_manager.contexts.items():
619
- if metadata.scope == ContextScope.GLOBAL and metadata.lifecycle == ContextLifecycle.ACTIVE:
620
+ if (
621
+ metadata.scope == ContextScope.GLOBAL
622
+ and metadata.lifecycle == ContextLifecycle.ACTIVE
623
+ ):
620
624
  return ctx_id
621
625
 
622
626
  return None
@@ -624,7 +628,7 @@ class ContextStrategy(IConfigStrategy):
624
628
  def with_context(self, context_id: str, operation: Callable) -> Any:
625
629
  """Execute operation within specified context"""
626
630
  # Push context
627
- if not hasattr(self.hierarchy_manager.context_stack, 'stack'):
631
+ if not hasattr(self.hierarchy_manager.context_stack, "stack"):
628
632
  self.hierarchy_manager.context_stack.stack = []
629
633
 
630
634
  self.hierarchy_manager.context_stack.stack.append(context_id)
@@ -646,7 +650,7 @@ class ContextStrategy(IConfigStrategy):
646
650
  self,
647
651
  key: Optional[str] = None,
648
652
  context: Optional[str] = None,
649
- default: Any = None
653
+ default: Any = None,
650
654
  ) -> Any:
651
655
  """Get configuration value from context"""
652
656
  context_id = context or self.get_current_context()
@@ -669,13 +673,7 @@ class ContextStrategy(IConfigStrategy):
669
673
 
670
674
  return value if value is not None else default
671
675
 
672
- def set_config(
673
- self,
674
- key: str,
675
- value: Any,
676
- context: Optional[str] = None,
677
- **kwargs
678
- ):
676
+ def set_config(self, key: str, value: Any, context: Optional[str] = None, **kwargs):
679
677
  """Set configuration value in context"""
680
678
  context_id = context or self.get_current_context()
681
679
 
@@ -694,7 +692,7 @@ class ContextStrategy(IConfigStrategy):
694
692
  self.cache_manager.invalidate_context(context_id)
695
693
 
696
694
  # Close context
697
- if context_id.startswith('isolated_'):
695
+ if context_id.startswith("isolated_"):
698
696
  self.isolated_manager.close_isolated_context(context_id)
699
697
  else:
700
698
  self.hierarchy_manager.close_context(context_id)
@@ -704,7 +702,11 @@ class ContextStrategy(IConfigStrategy):
704
702
  result = config.copy()
705
703
 
706
704
  for key, value in overrides.items():
707
- if key in result and isinstance(result[key], dict) and isinstance(value, dict):
705
+ if (
706
+ key in result
707
+ and isinstance(result[key], dict)
708
+ and isinstance(value, dict)
709
+ ):
708
710
  result[key] = self._apply_overrides(result[key], value)
709
711
  else:
710
712
  result[key] = value
@@ -714,11 +716,11 @@ class ContextStrategy(IConfigStrategy):
714
716
  def get_statistics(self) -> Dict[str, Any]:
715
717
  """Get context strategy statistics"""
716
718
  return {
717
- 'active_contexts': len(self.hierarchy_manager.contexts),
718
- 'isolated_contexts': len(self.isolated_manager.isolated_contexts),
719
- 'cache_stats': self.cache_manager.get_statistics(),
720
- 'contexts_by_scope': self._count_by_scope(),
721
- 'contexts_by_lifecycle': self._count_by_lifecycle()
719
+ "active_contexts": len(self.hierarchy_manager.contexts),
720
+ "isolated_contexts": len(self.isolated_manager.isolated_contexts),
721
+ "cache_stats": self.cache_manager.get_statistics(),
722
+ "contexts_by_scope": self._count_by_scope(),
723
+ "contexts_by_lifecycle": self._count_by_lifecycle(),
722
724
  }
723
725
 
724
726
  def _count_by_scope(self) -> Dict[str, int]:
@@ -740,9 +742,9 @@ class ContextStrategy(IConfigStrategy):
740
742
 
741
743
  # Export main components
742
744
  __all__ = [
743
- 'ContextStrategy',
744
- 'ContextScope',
745
- 'ContextLifecycle',
746
- 'HierarchicalContextManager',
747
- 'ScopedConfigManager'
748
- ]
745
+ "ContextLifecycle",
746
+ "ContextScope",
747
+ "ContextStrategy",
748
+ "HierarchicalContextManager",
749
+ "ScopedConfigManager",
750
+ ]