crackerjack 0.33.0__py3-none-any.whl → 0.33.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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (198) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +4 -13
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +104 -204
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +171 -174
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +44 -8
  74. crackerjack/managers/test_command_builder.py +1 -15
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +98 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +17 -16
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +173 -32
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +8 -10
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +0 -2
  109. crackerjack/mixins/error_handling.py +1 -70
  110. crackerjack/models/config.py +12 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +122 -122
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  115. crackerjack/monitoring/metrics_collector.py +426 -0
  116. crackerjack/monitoring/regression_prevention.py +8 -8
  117. crackerjack/monitoring/websocket_server.py +643 -0
  118. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  119. crackerjack/orchestration/coverage_improvement.py +3 -3
  120. crackerjack/orchestration/execution_strategies.py +26 -6
  121. crackerjack/orchestration/test_progress_streamer.py +8 -5
  122. crackerjack/plugins/base.py +2 -2
  123. crackerjack/plugins/hooks.py +7 -0
  124. crackerjack/plugins/managers.py +11 -8
  125. crackerjack/security/__init__.py +0 -1
  126. crackerjack/security/audit.py +6 -35
  127. crackerjack/services/anomaly_detector.py +392 -0
  128. crackerjack/services/api_extractor.py +615 -0
  129. crackerjack/services/backup_service.py +2 -2
  130. crackerjack/services/bounded_status_operations.py +15 -152
  131. crackerjack/services/cache.py +127 -1
  132. crackerjack/services/changelog_automation.py +395 -0
  133. crackerjack/services/config.py +15 -9
  134. crackerjack/services/config_merge.py +19 -80
  135. crackerjack/services/config_template.py +506 -0
  136. crackerjack/services/contextual_ai_assistant.py +48 -22
  137. crackerjack/services/coverage_badge_service.py +171 -0
  138. crackerjack/services/coverage_ratchet.py +27 -25
  139. crackerjack/services/debug.py +3 -3
  140. crackerjack/services/dependency_analyzer.py +460 -0
  141. crackerjack/services/dependency_monitor.py +14 -11
  142. crackerjack/services/documentation_generator.py +491 -0
  143. crackerjack/services/documentation_service.py +675 -0
  144. crackerjack/services/enhanced_filesystem.py +6 -5
  145. crackerjack/services/enterprise_optimizer.py +865 -0
  146. crackerjack/services/error_pattern_analyzer.py +676 -0
  147. crackerjack/services/file_hasher.py +1 -1
  148. crackerjack/services/git.py +8 -25
  149. crackerjack/services/health_metrics.py +10 -8
  150. crackerjack/services/heatmap_generator.py +735 -0
  151. crackerjack/services/initialization.py +11 -30
  152. crackerjack/services/input_validator.py +5 -97
  153. crackerjack/services/intelligent_commit.py +327 -0
  154. crackerjack/services/log_manager.py +15 -12
  155. crackerjack/services/logging.py +4 -3
  156. crackerjack/services/lsp_client.py +628 -0
  157. crackerjack/services/memory_optimizer.py +19 -87
  158. crackerjack/services/metrics.py +42 -33
  159. crackerjack/services/parallel_executor.py +9 -67
  160. crackerjack/services/pattern_cache.py +1 -1
  161. crackerjack/services/pattern_detector.py +6 -6
  162. crackerjack/services/performance_benchmarks.py +18 -59
  163. crackerjack/services/performance_cache.py +20 -81
  164. crackerjack/services/performance_monitor.py +27 -95
  165. crackerjack/services/predictive_analytics.py +510 -0
  166. crackerjack/services/quality_baseline.py +234 -0
  167. crackerjack/services/quality_baseline_enhanced.py +646 -0
  168. crackerjack/services/quality_intelligence.py +785 -0
  169. crackerjack/services/regex_patterns.py +618 -524
  170. crackerjack/services/regex_utils.py +43 -123
  171. crackerjack/services/secure_path_utils.py +5 -164
  172. crackerjack/services/secure_status_formatter.py +30 -141
  173. crackerjack/services/secure_subprocess.py +11 -92
  174. crackerjack/services/security.py +9 -41
  175. crackerjack/services/security_logger.py +12 -24
  176. crackerjack/services/server_manager.py +124 -16
  177. crackerjack/services/status_authentication.py +16 -159
  178. crackerjack/services/status_security_manager.py +4 -131
  179. crackerjack/services/thread_safe_status_collector.py +19 -125
  180. crackerjack/services/unified_config.py +21 -13
  181. crackerjack/services/validation_rate_limiter.py +5 -54
  182. crackerjack/services/version_analyzer.py +459 -0
  183. crackerjack/services/version_checker.py +1 -1
  184. crackerjack/services/websocket_resource_limiter.py +10 -144
  185. crackerjack/services/zuban_lsp_service.py +390 -0
  186. crackerjack/slash_commands/__init__.py +2 -7
  187. crackerjack/slash_commands/run.md +2 -2
  188. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  189. crackerjack/tools/validate_regex_patterns.py +19 -48
  190. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/METADATA +196 -25
  191. crackerjack-0.33.2.dist-info/RECORD +229 -0
  192. crackerjack/CLAUDE.md +0 -207
  193. crackerjack/RULES.md +0 -380
  194. crackerjack/py313.py +0 -234
  195. crackerjack-0.33.0.dist-info/RECORD +0 -187
  196. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/WHEEL +0 -0
  197. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/entry_points.txt +0 -0
  198. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,3 @@
1
- """Resource lifecycle management protocols.
2
-
3
- Defines protocols and interfaces for comprehensive resource management
4
- patterns throughout the crackerjack codebase.
5
- """
6
-
7
1
  import typing as t
8
2
  from abc import ABC, abstractmethod
9
3
  from types import TracebackType
@@ -14,184 +8,104 @@ if t.TYPE_CHECKING:
14
8
 
15
9
 
16
10
  class AsyncCleanupProtocol(t.Protocol):
17
- """Protocol for resources that support async cleanup."""
18
-
19
- async def cleanup(self) -> None:
20
- """Clean up the resource asynchronously."""
21
- ...
11
+ async def cleanup(self) -> None: ...
22
12
 
23
13
 
24
14
  class SyncCleanupProtocol(t.Protocol):
25
- """Protocol for resources that support synchronous cleanup."""
26
-
27
- def cleanup(self) -> None:
28
- """Clean up the resource synchronously."""
29
- ...
15
+ def cleanup(self) -> None: ...
30
16
 
31
17
 
32
18
  class ResourceLifecycleProtocol(t.Protocol):
33
- """Protocol for resources with full lifecycle management."""
34
-
35
- async def initialize(self) -> None:
36
- """Initialize the resource."""
37
- ...
19
+ async def initialize(self) -> None: ...
38
20
 
39
- async def cleanup(self) -> None:
40
- """Clean up the resource."""
41
- ...
21
+ async def cleanup(self) -> None: ...
42
22
 
43
- def is_initialized(self) -> bool:
44
- """Check if the resource is initialized."""
45
- ...
23
+ def is_initialized(self) -> bool: ...
46
24
 
47
- def is_closed(self) -> bool:
48
- """Check if the resource is closed."""
49
- ...
25
+ def is_closed(self) -> bool: ...
50
26
 
51
27
 
52
28
  class AsyncContextProtocol(t.Protocol):
53
- """Protocol for async context managers."""
54
-
55
- async def __aenter__(self) -> t.Self:
56
- """Enter async context."""
57
- ...
29
+ async def __aenter__(self) -> t.Self: ...
58
30
 
59
31
  async def __aexit__(
60
32
  self,
61
33
  exc_type: type[BaseException] | None,
62
34
  exc_val: BaseException | None,
63
35
  exc_tb: TracebackType | None,
64
- ) -> None:
65
- """Exit async context."""
66
- ...
36
+ ) -> None: ...
67
37
 
68
38
 
69
39
  class ResourceManagerProtocol(t.Protocol):
70
- """Protocol for resource managers."""
71
-
72
- def register_resource(self, resource: AsyncCleanupProtocol) -> None:
73
- """Register a resource for management."""
74
- ...
40
+ def register_resource(self, resource: AsyncCleanupProtocol) -> None: ...
75
41
 
76
42
  def register_cleanup_callback(
77
43
  self, callback: t.Callable[[], t.Awaitable[None]]
78
- ) -> None:
79
- """Register a cleanup callback."""
80
- ...
44
+ ) -> None: ...
81
45
 
82
- async def cleanup_all(self) -> None:
83
- """Clean up all managed resources."""
84
- ...
46
+ async def cleanup_all(self) -> None: ...
85
47
 
86
48
 
87
49
  class FileResourceProtocol(t.Protocol):
88
- """Protocol for file-based resources."""
89
-
90
50
  @property
91
- def path(self) -> "Path":
92
- """Get the file path."""
93
- ...
51
+ def path(self) -> "Path": ...
94
52
 
95
- def exists(self) -> bool:
96
- """Check if the file exists."""
97
- ...
53
+ def exists(self) -> bool: ...
98
54
 
99
- async def cleanup(self) -> None:
100
- """Clean up the file resource."""
101
- ...
55
+ async def cleanup(self) -> None: ...
102
56
 
103
57
 
104
58
  class ProcessResourceProtocol(t.Protocol):
105
- """Protocol for process-based resources."""
106
-
107
59
  @property
108
- def pid(self) -> int:
109
- """Get the process ID."""
110
- ...
60
+ def pid(self) -> int: ...
111
61
 
112
- def is_running(self) -> bool:
113
- """Check if the process is running."""
114
- ...
62
+ def is_running(self) -> bool: ...
115
63
 
116
- async def cleanup(self) -> None:
117
- """Clean up the process resource."""
118
- ...
64
+ async def cleanup(self) -> None: ...
119
65
 
120
66
 
121
67
  class TaskResourceProtocol(t.Protocol):
122
- """Protocol for asyncio task resources."""
123
-
124
68
  @property
125
- def task(self) -> "asyncio.Task[t.Any]":
126
- """Get the asyncio task."""
127
- ...
69
+ def task(self) -> "asyncio.Task[t.Any]": ...
128
70
 
129
- def is_done(self) -> bool:
130
- """Check if the task is done."""
131
- ...
71
+ def is_done(self) -> bool: ...
132
72
 
133
- def is_cancelled(self) -> bool:
134
- """Check if the task is cancelled."""
135
- ...
73
+ def is_cancelled(self) -> bool: ...
136
74
 
137
- async def cleanup(self) -> None:
138
- """Clean up the task resource."""
139
- ...
75
+ async def cleanup(self) -> None: ...
140
76
 
141
77
 
142
78
  class NetworkResourceProtocol(t.Protocol):
143
- """Protocol for network-based resources."""
144
-
145
79
  @property
146
- def is_connected(self) -> bool:
147
- """Check if the resource is connected."""
148
- ...
80
+ def is_connected(self) -> bool: ...
149
81
 
150
- async def disconnect(self) -> None:
151
- """Disconnect the resource."""
152
- ...
82
+ async def disconnect(self) -> None: ...
153
83
 
154
- async def cleanup(self) -> None:
155
- """Clean up the network resource."""
156
- ...
84
+ async def cleanup(self) -> None: ...
157
85
 
158
86
 
159
87
  class CacheResourceProtocol(t.Protocol):
160
- """Protocol for cache-based resources."""
161
-
162
- def clear(self) -> None:
163
- """Clear the cache."""
164
- ...
88
+ def clear(self) -> None: ...
165
89
 
166
- def get_size(self) -> int:
167
- """Get the cache size."""
168
- ...
90
+ def get_size(self) -> int: ...
169
91
 
170
- async def cleanup(self) -> None:
171
- """Clean up the cache resource."""
172
- ...
92
+ async def cleanup(self) -> None: ...
173
93
 
174
94
 
175
- # Abstract base classes for resource implementations
176
95
  class AbstractManagedResource(ABC):
177
- """Abstract base class for managed resources."""
178
-
179
96
  def __init__(self) -> None:
180
97
  self._initialized = False
181
98
  self._closed = False
182
99
 
183
100
  @abstractmethod
184
101
  async def _do_initialize(self) -> None:
185
- """Perform resource initialization. Override in subclasses."""
186
102
  pass
187
103
 
188
104
  @abstractmethod
189
105
  async def _do_cleanup(self) -> None:
190
- """Perform resource cleanup. Override in subclasses."""
191
106
  pass
192
107
 
193
108
  async def initialize(self) -> None:
194
- """Initialize the resource if not already initialized."""
195
109
  if self._initialized:
196
110
  return
197
111
 
@@ -203,7 +117,6 @@ class AbstractManagedResource(ABC):
203
117
  raise
204
118
 
205
119
  async def cleanup(self) -> None:
206
- """Clean up the resource if not already closed."""
207
120
  if self._closed:
208
121
  return
209
122
 
@@ -211,7 +124,6 @@ class AbstractManagedResource(ABC):
211
124
  try:
212
125
  await self._do_cleanup()
213
126
  except Exception:
214
- # Log but don't re-raise during cleanup
215
127
  import logging
216
128
 
217
129
  logging.getLogger(__name__).warning(
@@ -219,15 +131,12 @@ class AbstractManagedResource(ABC):
219
131
  )
220
132
 
221
133
  def is_initialized(self) -> bool:
222
- """Check if the resource is initialized."""
223
134
  return self._initialized
224
135
 
225
136
  def is_closed(self) -> bool:
226
- """Check if the resource is closed."""
227
137
  return self._closed
228
138
 
229
139
  async def __aenter__(self) -> t.Self:
230
- """Enter async context and initialize."""
231
140
  await self.initialize()
232
141
  return self
233
142
 
@@ -237,41 +146,32 @@ class AbstractManagedResource(ABC):
237
146
  exc_val: BaseException | None,
238
147
  exc_tb: TracebackType | None,
239
148
  ) -> None:
240
- """Exit async context and cleanup."""
241
149
  await self.cleanup()
242
150
 
243
151
 
244
152
  class AbstractFileResource(AbstractManagedResource):
245
- """Abstract base class for file-based resources."""
246
-
247
153
  def __init__(self, path: "Path") -> None:
248
154
  super().__init__()
249
155
  self._path = path
250
156
 
251
157
  @property
252
158
  def path(self) -> "Path":
253
- """Get the file path."""
254
159
  return self._path
255
160
 
256
161
  def exists(self) -> bool:
257
- """Check if the file exists."""
258
162
  return self._path.exists()
259
163
 
260
164
 
261
165
  class AbstractProcessResource(AbstractManagedResource):
262
- """Abstract base class for process-based resources."""
263
-
264
166
  def __init__(self, pid: int) -> None:
265
167
  super().__init__()
266
168
  self._pid = pid
267
169
 
268
170
  @property
269
171
  def pid(self) -> int:
270
- """Get the process ID."""
271
172
  return self._pid
272
173
 
273
174
  def is_running(self) -> bool:
274
- """Check if the process is running."""
275
175
  try:
276
176
  import os
277
177
 
@@ -282,59 +182,49 @@ class AbstractProcessResource(AbstractManagedResource):
282
182
 
283
183
 
284
184
  class AbstractTaskResource(AbstractManagedResource):
285
- """Abstract base class for asyncio task resources."""
286
-
287
185
  def __init__(self, task: "asyncio.Task[t.Any]") -> None:
288
186
  super().__init__()
289
187
  self._task = task
290
188
 
291
189
  @property
292
190
  def task(self) -> "asyncio.Task[t.Any]":
293
- """Get the asyncio task."""
294
191
  return self._task
295
192
 
296
193
  def is_done(self) -> bool:
297
- """Check if the task is done."""
298
194
  return self._task.done()
299
195
 
300
196
  def is_cancelled(self) -> bool:
301
- """Check if the task is cancelled."""
302
197
  return self._task.cancelled()
303
198
 
304
199
 
305
200
  class AbstractNetworkResource(AbstractManagedResource):
306
- """Abstract base class for network-based resources."""
307
-
308
201
  def __init__(self) -> None:
309
202
  super().__init__()
310
203
  self._connected = False
311
204
 
312
205
  @property
313
206
  def is_connected(self) -> bool:
314
- """Check if the resource is connected."""
315
207
  return self._connected and not self._closed
316
208
 
317
209
  async def disconnect(self) -> None:
318
- """Disconnect the resource."""
319
210
  if self._connected:
320
211
  self._connected = False
321
212
  await self._do_disconnect()
322
213
 
323
214
  @abstractmethod
324
215
  async def _do_disconnect(self) -> None:
325
- """Perform disconnection. Override in subclasses."""
326
216
  pass
327
217
 
328
218
  async def _do_cleanup(self) -> None:
329
- """Cleanup includes disconnection."""
330
219
  await self.disconnect()
331
220
 
332
221
 
333
- # Resource lifecycle decorators
334
- def with_resource_cleanup(resource_attr: str):
335
- """Decorator to ensure resource cleanup on method exit."""
336
-
337
- def decorator(func: t.Callable[..., t.Awaitable[t.Any]]):
222
+ def with_resource_cleanup(
223
+ resource_attr: str,
224
+ ) -> t.Callable[..., t.Callable[..., t.Awaitable[t.Any]]]:
225
+ def decorator(
226
+ func: t.Callable[..., t.Awaitable[t.Any]],
227
+ ) -> t.Callable[..., t.Awaitable[t.Any]]:
338
228
  async def wrapper(self: t.Any, *args: t.Any, **kwargs: t.Any) -> t.Any:
339
229
  resource = getattr(self, resource_attr, None)
340
230
  try:
@@ -348,10 +238,12 @@ def with_resource_cleanup(resource_attr: str):
348
238
  return decorator
349
239
 
350
240
 
351
- def ensure_initialized(resource_attr: str):
352
- """Decorator to ensure resource is initialized before method execution."""
353
-
354
- def decorator(func: t.Callable[..., t.Awaitable[t.Any]]):
241
+ def ensure_initialized(
242
+ resource_attr: str,
243
+ ) -> t.Callable[..., t.Callable[..., t.Awaitable[t.Any]]]:
244
+ def decorator(
245
+ func: t.Callable[..., t.Awaitable[t.Any]],
246
+ ) -> t.Callable[..., t.Awaitable[t.Any]]:
355
247
  async def wrapper(self: t.Any, *args: t.Any, **kwargs: t.Any) -> t.Any:
356
248
  resource = getattr(self, resource_attr, None)
357
249
  if resource and hasattr(resource, "initialize"):
@@ -363,92 +255,45 @@ def ensure_initialized(resource_attr: str):
363
255
  return decorator
364
256
 
365
257
 
366
- # Resource health monitoring protocols
367
258
  class HealthCheckProtocol(t.Protocol):
368
- """Protocol for health checking resources."""
369
-
370
- async def health_check(self) -> dict[str, t.Any]:
371
- """Perform health check and return status."""
372
- ...
259
+ async def health_check(self) -> dict[str, t.Any]: ...
373
260
 
374
- def is_healthy(self) -> bool:
375
- """Quick health check."""
376
- ...
261
+ def is_healthy(self) -> bool: ...
377
262
 
378
263
 
379
264
  class MonitorableResourceProtocol(t.Protocol):
380
- """Protocol for resources that can be monitored."""
265
+ def get_metrics(self) -> dict[str, t.Any]: ...
381
266
 
382
- def get_metrics(self) -> dict[str, t.Any]:
383
- """Get resource metrics."""
384
- ...
267
+ def get_status(self) -> str: ...
385
268
 
386
- def get_status(self) -> str:
387
- """Get resource status string."""
388
- ...
269
+ async def health_check(self) -> dict[str, t.Any]: ...
389
270
 
390
- async def health_check(self) -> dict[str, t.Any]:
391
- """Perform health check."""
392
- ...
393
271
 
394
-
395
- # Resource factory protocols
396
272
  class ResourceFactoryProtocol(t.Protocol):
397
- """Protocol for resource factories."""
398
-
399
- async def create_resource(self, **kwargs: t.Any) -> AsyncCleanupProtocol:
400
- """Create a new resource instance."""
401
- ...
273
+ async def create_resource(self, **kwargs: t.Any) -> AsyncCleanupProtocol: ...
402
274
 
403
- def get_resource_type(self) -> str:
404
- """Get the resource type name."""
405
- ...
275
+ def get_resource_type(self) -> str: ...
406
276
 
407
277
 
408
278
  class PooledResourceProtocol(t.Protocol):
409
- """Protocol for pooled resources."""
410
-
411
- async def acquire(self) -> AsyncCleanupProtocol:
412
- """Acquire a resource from the pool."""
413
- ...
279
+ async def acquire(self) -> AsyncCleanupProtocol: ...
414
280
 
415
- async def release(self, resource: AsyncCleanupProtocol) -> None:
416
- """Release a resource back to the pool."""
417
- ...
281
+ async def release(self, resource: AsyncCleanupProtocol) -> None: ...
418
282
 
419
- def get_pool_size(self) -> int:
420
- """Get current pool size."""
421
- ...
283
+ def get_pool_size(self) -> int: ...
422
284
 
423
- def get_active_count(self) -> int:
424
- """Get count of active resources."""
425
- ...
285
+ def get_active_count(self) -> int: ...
426
286
 
427
287
 
428
- # Error handling protocols
429
288
  class ResourceErrorProtocol(t.Protocol):
430
- """Protocol for resource error handling."""
289
+ def handle_error(self, error: Exception) -> bool: ...
431
290
 
432
- def handle_error(self, error: Exception) -> bool:
433
- """Handle resource error. Return True if error was handled."""
434
- ...
291
+ def should_retry(self, error: Exception) -> bool: ...
435
292
 
436
- def should_retry(self, error: Exception) -> bool:
437
- """Check if operation should be retried on this error."""
438
- ...
439
-
440
- def get_retry_delay(self, attempt: int) -> float:
441
- """Get delay before retry attempt."""
442
- ...
293
+ def get_retry_delay(self, attempt: int) -> float: ...
443
294
 
444
295
 
445
296
  class FallbackResourceProtocol(t.Protocol):
446
- """Protocol for resources with fallback capabilities."""
447
-
448
- async def get_fallback(self) -> AsyncCleanupProtocol | None:
449
- """Get fallback resource if primary fails."""
450
- ...
297
+ async def get_fallback(self) -> AsyncCleanupProtocol | None: ...
451
298
 
452
- def has_fallback(self) -> bool:
453
- """Check if fallback is available."""
454
- ...
299
+ def has_fallback(self) -> bool: ...
@@ -21,7 +21,7 @@ class AgentPerformanceMetrics:
21
21
  failed_fixes: int = 0
22
22
  average_confidence: float = 0.0
23
23
  average_execution_time: float = 0.0
24
- issue_types_handled: dict[IssueType, int] = field(default_factory=dict)
24
+ issue_types_handled: dict[IssueType, int] = field(default_factory=dict[str, t.Any])
25
25
  recent_failures: list[str] = field(default_factory=list)
26
26
  last_successful_fix: datetime | None = None
27
27
  regression_patterns: list[str] = field(default_factory=list)
@@ -34,7 +34,7 @@ class WatchdogAlert:
34
34
  agent_name: str | None = None
35
35
  issue_id: str | None = None
36
36
  timestamp: datetime = field(default_factory=datetime.now)
37
- details: dict[str, t.Any] = field(default_factory=dict)
37
+ details: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
38
38
 
39
39
 
40
40
  class AIAgentWatchdog:
@@ -54,7 +54,7 @@ class AIAgentWatchdog:
54
54
  self.min_success_rate = 0.6
55
55
  self.max_recent_failures = 3
56
56
 
57
- async def start_monitoring(self, coordinator: AgentCoordinator):
57
+ async def start_monitoring(self, coordinator: AgentCoordinator) -> None:
58
58
  self.monitoring_active = True
59
59
  self.console.print("šŸ” [bold green]AI Agent Watchdog Started[/bold green]")
60
60
 
@@ -70,14 +70,14 @@ class AIAgentWatchdog:
70
70
  f"šŸ“Š Monitoring {len(coordinator.agents)} agents: {[a.__class__.__name__ for a in coordinator.agents]}"
71
71
  )
72
72
 
73
- def stop_monitoring(self):
73
+ def stop_monitoring(self) -> None:
74
74
  self.monitoring_active = False
75
75
  self.console.print("šŸ” [bold yellow]AI Agent Watchdog Stopped[/bold yellow]")
76
76
  self._generate_final_report()
77
77
 
78
78
  async def monitor_issue_handling(
79
79
  self, agent_name: str, issue: Issue, result: FixResult, execution_time: float
80
- ):
80
+ ) -> None:
81
81
  if not self.monitoring_active:
82
82
  return
83
83
 
@@ -134,7 +134,7 @@ class AIAgentWatchdog:
134
134
  result: FixResult,
135
135
  execution_time: float,
136
136
  metrics: AgentPerformanceMetrics,
137
- ):
137
+ ) -> None:
138
138
  alerts = []
139
139
 
140
140
  if execution_time > self.max_execution_time:
@@ -179,14 +179,14 @@ class AIAgentWatchdog:
179
179
  )
180
180
 
181
181
  if len(metrics.recent_failures) >= self.max_recent_failures:
182
- unique_failures = set(metrics.recent_failures)
182
+ unique_failures = set[t.Any](metrics.recent_failures)
183
183
  if len(unique_failures) == 1:
184
184
  alerts.append(
185
185
  WatchdogAlert(
186
186
  level="error",
187
187
  message=f"Agent repeating same failure {len(metrics.recent_failures)} times",
188
188
  agent_name=agent_name,
189
- details={"repeated_failure": list(unique_failures)[0]},
189
+ details={"repeated_failure": list[t.Any](unique_failures)[0]},
190
190
  )
191
191
  )
192
192
 
@@ -194,7 +194,7 @@ class AIAgentWatchdog:
194
194
  self.alerts.append(alert)
195
195
  await self._handle_alert(alert)
196
196
 
197
- async def _handle_alert(self, alert: WatchdogAlert):
197
+ async def _handle_alert(self, alert: WatchdogAlert) -> None:
198
198
  colors = {"warning": "yellow", "error": "red", "critical": "bold red"}
199
199
  color = colors.get(alert.level) or "white"
200
200
 
@@ -270,7 +270,7 @@ class AIAgentWatchdog:
270
270
  cutoff = datetime.now() - timedelta(hours=hours)
271
271
  return [alert for alert in self.alerts if alert.timestamp > cutoff]
272
272
 
273
- def _generate_final_report(self):
273
+ def _generate_final_report(self) -> None:
274
274
  self.console.print("\nšŸ“Š [bold]AI Agent Watchdog Final Report[/bold]")
275
275
 
276
276
  total_issues = sum(
@@ -314,7 +314,7 @@ class AIAgentWatchdog:
314
314
 
315
315
  self._save_monitoring_report()
316
316
 
317
- def _save_monitoring_report(self):
317
+ def _save_monitoring_report(self) -> None:
318
318
  report_data = {
319
319
  "timestamp": datetime.now().isoformat(),
320
320
  "metrics": {
@@ -351,13 +351,13 @@ class AIAgentWatchdog:
351
351
  report_file = Path(".crackerjack") / "ai_agent_monitoring_report.json"
352
352
  report_file.parent.mkdir(exist_ok=True)
353
353
 
354
- with open(report_file, "w") as f:
354
+ with report_file.open("w") as f:
355
355
  json.dump(report_data, f, indent=2)
356
356
 
357
357
  self.console.print(f"šŸ“„ Detailed report saved: {report_file}")
358
358
 
359
359
 
360
- async def run_agent_monitoring_demo():
360
+ async def run_agent_monitoring_demo() -> None:
361
361
  console = Console()
362
362
  watchdog = AIAgentWatchdog(console)
363
363