crackerjack 0.31.10__py3-none-any.whl → 0.31.13__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 crackerjack might be problematic. Click here for more details.

Files changed (155) hide show
  1. crackerjack/CLAUDE.md +288 -705
  2. crackerjack/__main__.py +22 -8
  3. crackerjack/agents/__init__.py +0 -3
  4. crackerjack/agents/architect_agent.py +0 -43
  5. crackerjack/agents/base.py +1 -9
  6. crackerjack/agents/coordinator.py +2 -148
  7. crackerjack/agents/documentation_agent.py +109 -81
  8. crackerjack/agents/dry_agent.py +122 -97
  9. crackerjack/agents/formatting_agent.py +3 -16
  10. crackerjack/agents/import_optimization_agent.py +1174 -130
  11. crackerjack/agents/performance_agent.py +956 -188
  12. crackerjack/agents/performance_helpers.py +229 -0
  13. crackerjack/agents/proactive_agent.py +1 -48
  14. crackerjack/agents/refactoring_agent.py +516 -246
  15. crackerjack/agents/refactoring_helpers.py +282 -0
  16. crackerjack/agents/security_agent.py +393 -90
  17. crackerjack/agents/test_creation_agent.py +1776 -120
  18. crackerjack/agents/test_specialist_agent.py +59 -15
  19. crackerjack/agents/tracker.py +0 -102
  20. crackerjack/api.py +145 -37
  21. crackerjack/cli/handlers.py +48 -30
  22. crackerjack/cli/interactive.py +11 -11
  23. crackerjack/cli/options.py +66 -4
  24. crackerjack/code_cleaner.py +808 -148
  25. crackerjack/config/global_lock_config.py +110 -0
  26. crackerjack/config/hooks.py +43 -64
  27. crackerjack/core/async_workflow_orchestrator.py +247 -97
  28. crackerjack/core/autofix_coordinator.py +192 -109
  29. crackerjack/core/enhanced_container.py +46 -63
  30. crackerjack/core/file_lifecycle.py +549 -0
  31. crackerjack/core/performance.py +9 -8
  32. crackerjack/core/performance_monitor.py +395 -0
  33. crackerjack/core/phase_coordinator.py +281 -94
  34. crackerjack/core/proactive_workflow.py +9 -58
  35. crackerjack/core/resource_manager.py +501 -0
  36. crackerjack/core/service_watchdog.py +490 -0
  37. crackerjack/core/session_coordinator.py +4 -8
  38. crackerjack/core/timeout_manager.py +504 -0
  39. crackerjack/core/websocket_lifecycle.py +475 -0
  40. crackerjack/core/workflow_orchestrator.py +343 -209
  41. crackerjack/dynamic_config.py +50 -9
  42. crackerjack/errors.py +3 -4
  43. crackerjack/executors/async_hook_executor.py +63 -13
  44. crackerjack/executors/cached_hook_executor.py +14 -14
  45. crackerjack/executors/hook_executor.py +100 -37
  46. crackerjack/executors/hook_lock_manager.py +856 -0
  47. crackerjack/executors/individual_hook_executor.py +120 -86
  48. crackerjack/intelligence/__init__.py +0 -7
  49. crackerjack/intelligence/adaptive_learning.py +13 -86
  50. crackerjack/intelligence/agent_orchestrator.py +15 -78
  51. crackerjack/intelligence/agent_registry.py +12 -59
  52. crackerjack/intelligence/agent_selector.py +31 -92
  53. crackerjack/intelligence/integration.py +1 -41
  54. crackerjack/interactive.py +9 -9
  55. crackerjack/managers/async_hook_manager.py +25 -8
  56. crackerjack/managers/hook_manager.py +9 -9
  57. crackerjack/managers/publish_manager.py +57 -59
  58. crackerjack/managers/test_command_builder.py +6 -36
  59. crackerjack/managers/test_executor.py +9 -61
  60. crackerjack/managers/test_manager.py +17 -63
  61. crackerjack/managers/test_manager_backup.py +77 -127
  62. crackerjack/managers/test_progress.py +4 -23
  63. crackerjack/mcp/cache.py +5 -12
  64. crackerjack/mcp/client_runner.py +10 -10
  65. crackerjack/mcp/context.py +64 -6
  66. crackerjack/mcp/dashboard.py +14 -11
  67. crackerjack/mcp/enhanced_progress_monitor.py +55 -55
  68. crackerjack/mcp/file_monitor.py +72 -42
  69. crackerjack/mcp/progress_components.py +103 -84
  70. crackerjack/mcp/progress_monitor.py +122 -49
  71. crackerjack/mcp/rate_limiter.py +12 -12
  72. crackerjack/mcp/server_core.py +16 -22
  73. crackerjack/mcp/service_watchdog.py +26 -26
  74. crackerjack/mcp/state.py +15 -0
  75. crackerjack/mcp/tools/core_tools.py +95 -39
  76. crackerjack/mcp/tools/error_analyzer.py +6 -32
  77. crackerjack/mcp/tools/execution_tools.py +1 -56
  78. crackerjack/mcp/tools/execution_tools_backup.py +35 -131
  79. crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
  80. crackerjack/mcp/tools/intelligence_tools.py +2 -55
  81. crackerjack/mcp/tools/monitoring_tools.py +308 -145
  82. crackerjack/mcp/tools/proactive_tools.py +12 -42
  83. crackerjack/mcp/tools/progress_tools.py +23 -15
  84. crackerjack/mcp/tools/utility_tools.py +3 -40
  85. crackerjack/mcp/tools/workflow_executor.py +40 -60
  86. crackerjack/mcp/websocket/app.py +0 -3
  87. crackerjack/mcp/websocket/endpoints.py +206 -268
  88. crackerjack/mcp/websocket/jobs.py +213 -66
  89. crackerjack/mcp/websocket/server.py +84 -6
  90. crackerjack/mcp/websocket/websocket_handler.py +137 -29
  91. crackerjack/models/config_adapter.py +3 -16
  92. crackerjack/models/protocols.py +162 -3
  93. crackerjack/models/resource_protocols.py +454 -0
  94. crackerjack/models/task.py +3 -3
  95. crackerjack/monitoring/__init__.py +0 -0
  96. crackerjack/monitoring/ai_agent_watchdog.py +25 -71
  97. crackerjack/monitoring/regression_prevention.py +28 -87
  98. crackerjack/orchestration/advanced_orchestrator.py +44 -78
  99. crackerjack/orchestration/coverage_improvement.py +10 -60
  100. crackerjack/orchestration/execution_strategies.py +16 -16
  101. crackerjack/orchestration/test_progress_streamer.py +61 -53
  102. crackerjack/plugins/base.py +1 -1
  103. crackerjack/plugins/managers.py +22 -20
  104. crackerjack/py313.py +65 -21
  105. crackerjack/services/backup_service.py +467 -0
  106. crackerjack/services/bounded_status_operations.py +627 -0
  107. crackerjack/services/cache.py +7 -9
  108. crackerjack/services/config.py +35 -52
  109. crackerjack/services/config_integrity.py +5 -16
  110. crackerjack/services/config_merge.py +542 -0
  111. crackerjack/services/contextual_ai_assistant.py +17 -19
  112. crackerjack/services/coverage_ratchet.py +44 -73
  113. crackerjack/services/debug.py +25 -39
  114. crackerjack/services/dependency_monitor.py +52 -50
  115. crackerjack/services/enhanced_filesystem.py +14 -11
  116. crackerjack/services/file_hasher.py +1 -1
  117. crackerjack/services/filesystem.py +1 -12
  118. crackerjack/services/git.py +71 -47
  119. crackerjack/services/health_metrics.py +31 -27
  120. crackerjack/services/initialization.py +276 -428
  121. crackerjack/services/input_validator.py +760 -0
  122. crackerjack/services/log_manager.py +16 -16
  123. crackerjack/services/logging.py +7 -6
  124. crackerjack/services/metrics.py +43 -43
  125. crackerjack/services/pattern_cache.py +2 -31
  126. crackerjack/services/pattern_detector.py +26 -63
  127. crackerjack/services/performance_benchmarks.py +20 -45
  128. crackerjack/services/regex_patterns.py +2887 -0
  129. crackerjack/services/regex_utils.py +537 -0
  130. crackerjack/services/secure_path_utils.py +683 -0
  131. crackerjack/services/secure_status_formatter.py +534 -0
  132. crackerjack/services/secure_subprocess.py +605 -0
  133. crackerjack/services/security.py +47 -10
  134. crackerjack/services/security_logger.py +492 -0
  135. crackerjack/services/server_manager.py +109 -50
  136. crackerjack/services/smart_scheduling.py +8 -25
  137. crackerjack/services/status_authentication.py +603 -0
  138. crackerjack/services/status_security_manager.py +442 -0
  139. crackerjack/services/thread_safe_status_collector.py +546 -0
  140. crackerjack/services/tool_version_service.py +1 -23
  141. crackerjack/services/unified_config.py +36 -58
  142. crackerjack/services/validation_rate_limiter.py +269 -0
  143. crackerjack/services/version_checker.py +9 -40
  144. crackerjack/services/websocket_resource_limiter.py +572 -0
  145. crackerjack/slash_commands/__init__.py +52 -2
  146. crackerjack/tools/__init__.py +0 -0
  147. crackerjack/tools/validate_input_validator_patterns.py +262 -0
  148. crackerjack/tools/validate_regex_patterns.py +198 -0
  149. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/METADATA +197 -12
  150. crackerjack-0.31.13.dist-info/RECORD +178 -0
  151. crackerjack/cli/facade.py +0 -104
  152. crackerjack-0.31.10.dist-info/RECORD +0 -149
  153. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/WHEEL +0 -0
  154. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/entry_points.txt +0 -0
  155. {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,3 @@
1
- """Enhanced dependency injection container with lifecycle management."""
2
-
3
1
  import inspect
4
2
  import threading
5
3
  import typing as t
@@ -12,6 +10,7 @@ from typing import Any, TypeVar
12
10
  from rich.console import Console
13
11
 
14
12
  from crackerjack.models.protocols import (
13
+ ConfigMergeServiceProtocol,
15
14
  FileSystemInterface,
16
15
  GitInterface,
17
16
  HookManager,
@@ -25,8 +24,6 @@ FactoryFunc = Callable[..., T]
25
24
 
26
25
 
27
26
  class ServiceLifetime(Enum):
28
- """Service lifetime enumeration."""
29
-
30
27
  SINGLETON = "singleton"
31
28
  TRANSIENT = "transient"
32
29
  SCOPED = "scoped"
@@ -34,8 +31,6 @@ class ServiceLifetime(Enum):
34
31
 
35
32
  @dataclass
36
33
  class ServiceDescriptor:
37
- """Describes how to create a service instance."""
38
-
39
34
  interface: type
40
35
  implementation: type | None = None
41
36
  factory: Callable[..., Any] | None = None
@@ -51,8 +46,6 @@ class ServiceDescriptor:
51
46
 
52
47
 
53
48
  class ServiceScope:
54
- """Represents a service scope for scoped services."""
55
-
56
49
  def __init__(self, name: str) -> None:
57
50
  self.name = name
58
51
  self._instances: dict[str, Any] = {}
@@ -60,18 +53,15 @@ class ServiceScope:
60
53
  self.logger = get_logger("crackerjack.container.scope")
61
54
 
62
55
  def get_instance(self, key: str) -> Any | None:
63
- """Get scoped instance."""
64
56
  with self._lock:
65
57
  return self._instances.get(key)
66
58
 
67
59
  def set_instance(self, key: str, instance: Any) -> None:
68
- """Set scoped instance."""
69
60
  with self._lock:
70
61
  self._instances[key] = instance
71
62
  self.logger.debug("Scoped instance created", scope=self.name, service=key)
72
63
 
73
64
  def dispose(self) -> None:
74
- """Dispose of all scoped instances."""
75
65
  with self._lock:
76
66
  for key, instance in self._instances.items():
77
67
  if hasattr(instance, "dispose"):
@@ -89,8 +79,6 @@ class ServiceScope:
89
79
 
90
80
 
91
81
  class DependencyResolver:
92
- """Resolves service dependencies through constructor injection."""
93
-
94
82
  def __init__(self, container: "EnhancedDependencyContainer") -> None:
95
83
  self.container = container
96
84
  self.logger = get_logger("crackerjack.container.resolver")
@@ -100,7 +88,6 @@ class DependencyResolver:
100
88
  descriptor: ServiceDescriptor,
101
89
  scope: ServiceScope | None = None,
102
90
  ) -> Any:
103
- """Create service instance with dependency injection."""
104
91
  if descriptor.instance is not None:
105
92
  return descriptor.instance
106
93
 
@@ -114,7 +101,6 @@ class DependencyResolver:
114
101
  raise ValueError(msg)
115
102
 
116
103
  def _create_from_factory(self, factory: Callable[..., Any]) -> Any:
117
- """Create instance using factory function."""
118
104
  sig = inspect.signature(factory)
119
105
  kwargs = {}
120
106
 
@@ -124,17 +110,25 @@ class DependencyResolver:
124
110
  dependency = self.container.get(param.annotation)
125
111
  kwargs[param_name] = dependency
126
112
  except Exception as e:
127
- self.logger.warning(
128
- "Could not inject dependency",
129
- parameter=param_name,
130
- type=param.annotation,
131
- error=str(e),
132
- )
113
+ # Only log as warning for required parameters, debug for optional ones with defaults
114
+ if param.default == inspect.Parameter.empty:
115
+ self.logger.warning(
116
+ "Could not inject dependency",
117
+ parameter=param_name,
118
+ type=param.annotation,
119
+ error=str(e),
120
+ )
121
+ else:
122
+ self.logger.debug(
123
+ "Could not inject optional dependency, using default",
124
+ parameter=param_name,
125
+ type=param.annotation,
126
+ default=param.default,
127
+ )
133
128
 
134
129
  return factory(**kwargs)
135
130
 
136
131
  def _create_from_class(self, implementation: type) -> Any:
137
- """Create instance using class constructor with dependency injection."""
138
132
  try:
139
133
  kwargs = self._build_constructor_kwargs(implementation)
140
134
  return self._instantiate_with_logging(implementation, kwargs)
@@ -147,7 +141,6 @@ class DependencyResolver:
147
141
  raise
148
142
 
149
143
  def _build_constructor_kwargs(self, implementation: type) -> dict[str, Any]:
150
- """Build constructor kwargs by resolving dependencies."""
151
144
  init_sig = inspect.signature(implementation.__init__)
152
145
  kwargs = {}
153
146
 
@@ -169,7 +162,6 @@ class DependencyResolver:
169
162
  param: inspect.Parameter,
170
163
  class_name: str,
171
164
  ) -> None:
172
- """Resolve a single parameter dependency."""
173
165
  try:
174
166
  dependency = self.container.get(param.annotation)
175
167
  kwargs[param_name] = dependency
@@ -192,7 +184,6 @@ class DependencyResolver:
192
184
  def _instantiate_with_logging(
193
185
  self, implementation: type, kwargs: dict[str, Any]
194
186
  ) -> Any:
195
- """Create instance and log the creation."""
196
187
  instance = implementation(**kwargs)
197
188
  self.logger.debug(
198
189
  "Instance created with DI",
@@ -202,8 +193,6 @@ class DependencyResolver:
202
193
 
203
194
 
204
195
  class EnhancedDependencyContainer:
205
- """Enhanced dependency injection container with lifecycle management."""
206
-
207
196
  def __init__(self, name: str = "default") -> None:
208
197
  self.name = name
209
198
  self._services: dict[str, ServiceDescriptor] = {}
@@ -220,7 +209,6 @@ class EnhancedDependencyContainer:
220
209
  factory: Callable[..., Any] | None = None,
221
210
  instance: Any | None = None,
222
211
  ) -> "EnhancedDependencyContainer":
223
- """Register a singleton service."""
224
212
  key = self._get_service_key(interface)
225
213
 
226
214
  descriptor = ServiceDescriptor(
@@ -243,7 +231,6 @@ class EnhancedDependencyContainer:
243
231
  implementation: type | None = None,
244
232
  factory: Callable[..., Any] | None = None,
245
233
  ) -> "EnhancedDependencyContainer":
246
- """Register a transient service."""
247
234
  key = self._get_service_key(interface)
248
235
 
249
236
  descriptor = ServiceDescriptor(
@@ -265,7 +252,6 @@ class EnhancedDependencyContainer:
265
252
  implementation: type | None = None,
266
253
  factory: Callable[..., Any] | None = None,
267
254
  ) -> "EnhancedDependencyContainer":
268
- """Register a scoped service."""
269
255
  key = self._get_service_key(interface)
270
256
 
271
257
  descriptor = ServiceDescriptor(
@@ -282,7 +268,6 @@ class EnhancedDependencyContainer:
282
268
  return self
283
269
 
284
270
  def get(self, interface: type, scope: ServiceScope | None = None) -> Any:
285
- """Get service instance."""
286
271
  key = self._get_service_key(interface)
287
272
 
288
273
  with self._lock:
@@ -295,27 +280,22 @@ class EnhancedDependencyContainer:
295
280
  return self._create_service_instance(descriptor, scope or self._current_scope)
296
281
 
297
282
  def get_optional(self, interface: type, default: Any = None) -> Any:
298
- """Get service instance or return default if not registered."""
299
283
  try:
300
284
  return self.get(interface)
301
285
  except ValueError:
302
286
  return default
303
287
 
304
288
  def is_registered(self, interface: type) -> bool:
305
- """Check if service is registered."""
306
289
  key = self._get_service_key(interface)
307
290
  return key in self._services
308
291
 
309
292
  def create_scope(self, name: str = "scope") -> ServiceScope:
310
- """Create a new service scope."""
311
293
  return ServiceScope(name)
312
294
 
313
295
  def set_current_scope(self, scope: ServiceScope | None) -> None:
314
- """Set the current service scope."""
315
296
  self._current_scope = scope
316
297
 
317
298
  def get_service_info(self) -> dict[str, Any]:
318
- """Get information about registered services."""
319
299
  info = {}
320
300
 
321
301
  with self._lock:
@@ -333,9 +313,7 @@ class EnhancedDependencyContainer:
333
313
  return info
334
314
 
335
315
  def dispose(self) -> None:
336
- """Dispose of container and all singletons."""
337
316
  with self._lock:
338
- # Dispose singletons
339
317
  for key, instance in self._singletons.items():
340
318
  if hasattr(instance, "dispose"):
341
319
  try:
@@ -349,7 +327,6 @@ class EnhancedDependencyContainer:
349
327
 
350
328
  self._singletons.clear()
351
329
 
352
- # Dispose current scope
353
330
  if self._current_scope:
354
331
  self._current_scope.dispose()
355
332
  self._current_scope = None
@@ -361,16 +338,14 @@ class EnhancedDependencyContainer:
361
338
  descriptor: ServiceDescriptor,
362
339
  scope: ServiceScope | None = None,
363
340
  ) -> Any:
364
- """Create service instance based on lifetime."""
365
341
  if descriptor.lifetime == ServiceLifetime.SINGLETON:
366
342
  return self._get_or_create_singleton(descriptor)
367
343
  if descriptor.lifetime == ServiceLifetime.SCOPED:
368
344
  return self._get_or_create_scoped(descriptor, scope)
369
- # Transient
345
+
370
346
  return self._create_transient_instance(descriptor)
371
347
 
372
348
  def _get_or_create_singleton(self, descriptor: ServiceDescriptor) -> Any:
373
- """Get or create singleton instance."""
374
349
  key = self._get_service_key(descriptor.interface)
375
350
 
376
351
  if key in self._singletons:
@@ -388,7 +363,6 @@ class EnhancedDependencyContainer:
388
363
  descriptor: ServiceDescriptor,
389
364
  scope: ServiceScope | None,
390
365
  ) -> Any:
391
- """Get or create scoped instance."""
392
366
  if scope is None:
393
367
  msg = f"Scoped service {descriptor.interface.__name__} requires an active scope"
394
368
  raise ValueError(
@@ -406,13 +380,11 @@ class EnhancedDependencyContainer:
406
380
  return instance
407
381
 
408
382
  def _create_transient_instance(self, descriptor: ServiceDescriptor) -> Any:
409
- """Create new transient instance."""
410
383
  instance = self.resolver.create_instance(descriptor)
411
384
  descriptor.created_count += 1
412
385
  return instance
413
386
 
414
387
  def _get_service_key(self, interface: type) -> str:
415
- """Get service key from interface type."""
416
388
  return f"{interface.__module__}.{interface.__name__}"
417
389
 
418
390
  def __enter__(self):
@@ -428,35 +400,33 @@ class EnhancedDependencyContainer:
428
400
 
429
401
 
430
402
  class ServiceCollectionBuilder:
431
- """Builder pattern for configuring services."""
432
-
433
403
  def __init__(self, container: EnhancedDependencyContainer) -> None:
434
404
  self.container = container
435
405
  self.console: Console | None = None
436
406
  self.pkg_path: Path | None = None
437
407
  self.dry_run: bool = False
408
+ self.verbose: bool = False
438
409
 
439
410
  def with_console(self, console: Console) -> "ServiceCollectionBuilder":
440
- """Set console for services that need it."""
441
411
  self.console = console
442
412
  return self
443
413
 
444
414
  def with_package_path(self, pkg_path: Path) -> "ServiceCollectionBuilder":
445
- """Set package path for services that need it."""
446
415
  self.pkg_path = pkg_path
447
416
  return self
448
417
 
449
418
  def with_dry_run(self, dry_run: bool) -> "ServiceCollectionBuilder":
450
- """Set dry run mode."""
451
419
  self.dry_run = dry_run
452
420
  return self
453
421
 
422
+ def with_verbose(self, verbose: bool) -> "ServiceCollectionBuilder":
423
+ self.verbose = verbose
424
+ return self
425
+
454
426
  def add_core_services(self) -> "ServiceCollectionBuilder":
455
- """Add core Crackerjack services."""
456
427
  console = self.console or Console(force_terminal=True)
457
428
  pkg_path = self.pkg_path or Path.cwd()
458
429
 
459
- # Enhanced filesystem service
460
430
  from crackerjack.services.enhanced_filesystem import EnhancedFileSystemService
461
431
 
462
432
  self.container.register_singleton(
@@ -464,7 +434,6 @@ class ServiceCollectionBuilder:
464
434
  factory=EnhancedFileSystemService,
465
435
  )
466
436
 
467
- # Git service
468
437
  from crackerjack.services.git import GitService
469
438
 
470
439
  self.container.register_transient(
@@ -472,15 +441,15 @@ class ServiceCollectionBuilder:
472
441
  factory=lambda: GitService(console=console, pkg_path=pkg_path),
473
442
  )
474
443
 
475
- # Async hook manager
476
- from crackerjack.managers.async_hook_manager import AsyncHookManager
444
+ from crackerjack.managers.hook_manager import HookManagerImpl
477
445
 
478
- self.container.register_scoped(
446
+ self.container.register_transient(
479
447
  HookManager,
480
- factory=lambda: AsyncHookManager(console=console, pkg_path=pkg_path),
448
+ factory=lambda: HookManagerImpl(
449
+ console=console, pkg_path=pkg_path, verbose=self.verbose
450
+ ),
481
451
  )
482
452
 
483
- # Test manager
484
453
  from crackerjack.managers.test_manager import TestManagementImpl
485
454
 
486
455
  self.container.register_transient(
@@ -488,7 +457,6 @@ class ServiceCollectionBuilder:
488
457
  factory=lambda: TestManagementImpl(console=console, pkg_path=pkg_path),
489
458
  )
490
459
 
491
- # Publish manager
492
460
  from crackerjack.managers.publish_manager import PublishManagerImpl
493
461
 
494
462
  self.container.register_transient(
@@ -503,11 +471,9 @@ class ServiceCollectionBuilder:
503
471
  return self
504
472
 
505
473
  def add_configuration_services(self) -> "ServiceCollectionBuilder":
506
- """Add configuration services."""
507
474
  console = self.console or Console(force_terminal=True)
508
475
  pkg_path = self.pkg_path or Path.cwd()
509
476
 
510
- # Unified configuration service
511
477
  from crackerjack.services.unified_config import UnifiedConfigurationService
512
478
 
513
479
  self.container.register_singleton(
@@ -515,10 +481,26 @@ class ServiceCollectionBuilder:
515
481
  factory=lambda: UnifiedConfigurationService(console, pkg_path),
516
482
  )
517
483
 
484
+ # Register ConfigMergeService for smart configuration merging
485
+ from crackerjack.services.config_merge import ConfigMergeService
486
+
487
+ def create_config_merge_service() -> ConfigMergeService:
488
+ filesystem = self.container.get(FileSystemInterface)
489
+ git_service = self.container.get(GitInterface)
490
+ return ConfigMergeService(
491
+ console=console,
492
+ filesystem=filesystem,
493
+ git_service=git_service,
494
+ )
495
+
496
+ self.container.register_transient(
497
+ ConfigMergeServiceProtocol,
498
+ factory=create_config_merge_service,
499
+ )
500
+
518
501
  return self
519
502
 
520
503
  def build(self) -> EnhancedDependencyContainer:
521
- """Build the configured container."""
522
504
  return self.container
523
505
 
524
506
 
@@ -526,15 +508,16 @@ def create_enhanced_container(
526
508
  console: Console | None = None,
527
509
  pkg_path: Path | None = None,
528
510
  dry_run: bool = False,
511
+ verbose: bool = False,
529
512
  name: str = "crackerjack",
530
513
  ) -> EnhancedDependencyContainer:
531
- """Create enhanced dependency injection container with default services."""
532
514
  container = EnhancedDependencyContainer(name)
533
515
 
534
516
  builder = ServiceCollectionBuilder(container)
535
517
  builder.with_console(console or Console(force_terminal=True))
536
518
  builder.with_package_path(pkg_path or Path.cwd())
537
519
  builder.with_dry_run(dry_run)
520
+ builder.with_verbose(verbose)
538
521
 
539
522
  builder.add_core_services()
540
523
  builder.add_configuration_services()