crackerjack 0.18.2__py3-none-any.whl โ†’ 0.45.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 (533) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +96 -2
  3. crackerjack/__main__.py +637 -138
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +39 -0
  6. crackerjack/adapters/_output_paths.py +167 -0
  7. crackerjack/adapters/_qa_adapter_base.py +309 -0
  8. crackerjack/adapters/_tool_adapter_base.py +706 -0
  9. crackerjack/adapters/ai/README.md +65 -0
  10. crackerjack/adapters/ai/__init__.py +5 -0
  11. crackerjack/adapters/ai/claude.py +853 -0
  12. crackerjack/adapters/complexity/README.md +53 -0
  13. crackerjack/adapters/complexity/__init__.py +10 -0
  14. crackerjack/adapters/complexity/complexipy.py +641 -0
  15. crackerjack/adapters/dependency/__init__.py +22 -0
  16. crackerjack/adapters/dependency/pip_audit.py +418 -0
  17. crackerjack/adapters/format/README.md +72 -0
  18. crackerjack/adapters/format/__init__.py +11 -0
  19. crackerjack/adapters/format/mdformat.py +313 -0
  20. crackerjack/adapters/format/ruff.py +516 -0
  21. crackerjack/adapters/lint/README.md +47 -0
  22. crackerjack/adapters/lint/__init__.py +11 -0
  23. crackerjack/adapters/lint/codespell.py +273 -0
  24. crackerjack/adapters/lsp/README.md +49 -0
  25. crackerjack/adapters/lsp/__init__.py +27 -0
  26. crackerjack/adapters/lsp/_base.py +194 -0
  27. crackerjack/adapters/lsp/_client.py +358 -0
  28. crackerjack/adapters/lsp/_manager.py +193 -0
  29. crackerjack/adapters/lsp/skylos.py +283 -0
  30. crackerjack/adapters/lsp/zuban.py +557 -0
  31. crackerjack/adapters/refactor/README.md +59 -0
  32. crackerjack/adapters/refactor/__init__.py +12 -0
  33. crackerjack/adapters/refactor/creosote.py +318 -0
  34. crackerjack/adapters/refactor/refurb.py +406 -0
  35. crackerjack/adapters/refactor/skylos.py +494 -0
  36. crackerjack/adapters/sast/README.md +132 -0
  37. crackerjack/adapters/sast/__init__.py +32 -0
  38. crackerjack/adapters/sast/_base.py +201 -0
  39. crackerjack/adapters/sast/bandit.py +423 -0
  40. crackerjack/adapters/sast/pyscn.py +405 -0
  41. crackerjack/adapters/sast/semgrep.py +241 -0
  42. crackerjack/adapters/security/README.md +111 -0
  43. crackerjack/adapters/security/__init__.py +17 -0
  44. crackerjack/adapters/security/gitleaks.py +339 -0
  45. crackerjack/adapters/type/README.md +52 -0
  46. crackerjack/adapters/type/__init__.py +12 -0
  47. crackerjack/adapters/type/pyrefly.py +402 -0
  48. crackerjack/adapters/type/ty.py +402 -0
  49. crackerjack/adapters/type/zuban.py +522 -0
  50. crackerjack/adapters/utility/README.md +51 -0
  51. crackerjack/adapters/utility/__init__.py +10 -0
  52. crackerjack/adapters/utility/checks.py +884 -0
  53. crackerjack/agents/README.md +264 -0
  54. crackerjack/agents/__init__.py +66 -0
  55. crackerjack/agents/architect_agent.py +238 -0
  56. crackerjack/agents/base.py +167 -0
  57. crackerjack/agents/claude_code_bridge.py +641 -0
  58. crackerjack/agents/coordinator.py +600 -0
  59. crackerjack/agents/documentation_agent.py +520 -0
  60. crackerjack/agents/dry_agent.py +585 -0
  61. crackerjack/agents/enhanced_coordinator.py +279 -0
  62. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  63. crackerjack/agents/error_middleware.py +53 -0
  64. crackerjack/agents/formatting_agent.py +230 -0
  65. crackerjack/agents/helpers/__init__.py +9 -0
  66. crackerjack/agents/helpers/performance/__init__.py +22 -0
  67. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  68. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  69. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  70. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  71. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  72. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  73. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  74. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  75. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  76. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  77. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  78. crackerjack/agents/import_optimization_agent.py +1181 -0
  79. crackerjack/agents/performance_agent.py +325 -0
  80. crackerjack/agents/performance_helpers.py +205 -0
  81. crackerjack/agents/proactive_agent.py +55 -0
  82. crackerjack/agents/refactoring_agent.py +511 -0
  83. crackerjack/agents/refactoring_helpers.py +247 -0
  84. crackerjack/agents/security_agent.py +793 -0
  85. crackerjack/agents/semantic_agent.py +479 -0
  86. crackerjack/agents/semantic_helpers.py +356 -0
  87. crackerjack/agents/test_creation_agent.py +570 -0
  88. crackerjack/agents/test_specialist_agent.py +526 -0
  89. crackerjack/agents/tracker.py +110 -0
  90. crackerjack/api.py +647 -0
  91. crackerjack/cli/README.md +394 -0
  92. crackerjack/cli/__init__.py +24 -0
  93. crackerjack/cli/cache_handlers.py +209 -0
  94. crackerjack/cli/cache_handlers_enhanced.py +680 -0
  95. crackerjack/cli/facade.py +162 -0
  96. crackerjack/cli/formatting.py +13 -0
  97. crackerjack/cli/handlers/__init__.py +85 -0
  98. crackerjack/cli/handlers/advanced.py +103 -0
  99. crackerjack/cli/handlers/ai_features.py +62 -0
  100. crackerjack/cli/handlers/analytics.py +479 -0
  101. crackerjack/cli/handlers/changelog.py +271 -0
  102. crackerjack/cli/handlers/config_handlers.py +16 -0
  103. crackerjack/cli/handlers/coverage.py +84 -0
  104. crackerjack/cli/handlers/documentation.py +280 -0
  105. crackerjack/cli/handlers/main_handlers.py +497 -0
  106. crackerjack/cli/handlers/monitoring.py +371 -0
  107. crackerjack/cli/handlers.py +700 -0
  108. crackerjack/cli/interactive.py +488 -0
  109. crackerjack/cli/options.py +1216 -0
  110. crackerjack/cli/semantic_handlers.py +292 -0
  111. crackerjack/cli/utils.py +19 -0
  112. crackerjack/cli/version.py +19 -0
  113. crackerjack/code_cleaner.py +1307 -0
  114. crackerjack/config/README.md +472 -0
  115. crackerjack/config/__init__.py +275 -0
  116. crackerjack/config/global_lock_config.py +207 -0
  117. crackerjack/config/hooks.py +390 -0
  118. crackerjack/config/loader.py +239 -0
  119. crackerjack/config/settings.py +141 -0
  120. crackerjack/config/tool_commands.py +331 -0
  121. crackerjack/core/README.md +393 -0
  122. crackerjack/core/__init__.py +0 -0
  123. crackerjack/core/async_workflow_orchestrator.py +738 -0
  124. crackerjack/core/autofix_coordinator.py +282 -0
  125. crackerjack/core/container.py +105 -0
  126. crackerjack/core/enhanced_container.py +583 -0
  127. crackerjack/core/file_lifecycle.py +472 -0
  128. crackerjack/core/performance.py +244 -0
  129. crackerjack/core/performance_monitor.py +357 -0
  130. crackerjack/core/phase_coordinator.py +1227 -0
  131. crackerjack/core/proactive_workflow.py +267 -0
  132. crackerjack/core/resource_manager.py +425 -0
  133. crackerjack/core/retry.py +275 -0
  134. crackerjack/core/service_watchdog.py +601 -0
  135. crackerjack/core/session_coordinator.py +239 -0
  136. crackerjack/core/timeout_manager.py +563 -0
  137. crackerjack/core/websocket_lifecycle.py +410 -0
  138. crackerjack/core/workflow/__init__.py +21 -0
  139. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  140. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  141. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  142. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  143. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  144. crackerjack/core/workflow_orchestrator.py +2243 -0
  145. crackerjack/data/README.md +11 -0
  146. crackerjack/data/__init__.py +8 -0
  147. crackerjack/data/models.py +79 -0
  148. crackerjack/data/repository.py +210 -0
  149. crackerjack/decorators/README.md +180 -0
  150. crackerjack/decorators/__init__.py +35 -0
  151. crackerjack/decorators/error_handling.py +649 -0
  152. crackerjack/decorators/error_handling_decorators.py +334 -0
  153. crackerjack/decorators/helpers.py +58 -0
  154. crackerjack/decorators/patterns.py +281 -0
  155. crackerjack/decorators/utils.py +58 -0
  156. crackerjack/docs/INDEX.md +11 -0
  157. crackerjack/docs/README.md +11 -0
  158. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  159. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  160. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  161. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  162. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  163. crackerjack/documentation/README.md +11 -0
  164. crackerjack/documentation/__init__.py +31 -0
  165. crackerjack/documentation/ai_templates.py +756 -0
  166. crackerjack/documentation/dual_output_generator.py +767 -0
  167. crackerjack/documentation/mkdocs_integration.py +518 -0
  168. crackerjack/documentation/reference_generator.py +1065 -0
  169. crackerjack/dynamic_config.py +678 -0
  170. crackerjack/errors.py +378 -0
  171. crackerjack/events/README.md +11 -0
  172. crackerjack/events/__init__.py +16 -0
  173. crackerjack/events/telemetry.py +175 -0
  174. crackerjack/events/workflow_bus.py +346 -0
  175. crackerjack/exceptions/README.md +301 -0
  176. crackerjack/exceptions/__init__.py +5 -0
  177. crackerjack/exceptions/config.py +4 -0
  178. crackerjack/exceptions/tool_execution_error.py +245 -0
  179. crackerjack/executors/README.md +591 -0
  180. crackerjack/executors/__init__.py +13 -0
  181. crackerjack/executors/async_hook_executor.py +938 -0
  182. crackerjack/executors/cached_hook_executor.py +316 -0
  183. crackerjack/executors/hook_executor.py +1295 -0
  184. crackerjack/executors/hook_lock_manager.py +708 -0
  185. crackerjack/executors/individual_hook_executor.py +739 -0
  186. crackerjack/executors/lsp_aware_hook_executor.py +349 -0
  187. crackerjack/executors/progress_hook_executor.py +282 -0
  188. crackerjack/executors/tool_proxy.py +433 -0
  189. crackerjack/hooks/README.md +485 -0
  190. crackerjack/hooks/lsp_hook.py +93 -0
  191. crackerjack/intelligence/README.md +557 -0
  192. crackerjack/intelligence/__init__.py +37 -0
  193. crackerjack/intelligence/adaptive_learning.py +693 -0
  194. crackerjack/intelligence/agent_orchestrator.py +485 -0
  195. crackerjack/intelligence/agent_registry.py +377 -0
  196. crackerjack/intelligence/agent_selector.py +439 -0
  197. crackerjack/intelligence/integration.py +250 -0
  198. crackerjack/interactive.py +719 -0
  199. crackerjack/managers/README.md +369 -0
  200. crackerjack/managers/__init__.py +11 -0
  201. crackerjack/managers/async_hook_manager.py +135 -0
  202. crackerjack/managers/hook_manager.py +585 -0
  203. crackerjack/managers/publish_manager.py +631 -0
  204. crackerjack/managers/test_command_builder.py +391 -0
  205. crackerjack/managers/test_executor.py +474 -0
  206. crackerjack/managers/test_manager.py +1357 -0
  207. crackerjack/managers/test_progress.py +187 -0
  208. crackerjack/mcp/README.md +374 -0
  209. crackerjack/mcp/__init__.py +0 -0
  210. crackerjack/mcp/cache.py +352 -0
  211. crackerjack/mcp/client_runner.py +121 -0
  212. crackerjack/mcp/context.py +802 -0
  213. crackerjack/mcp/dashboard.py +657 -0
  214. crackerjack/mcp/enhanced_progress_monitor.py +493 -0
  215. crackerjack/mcp/file_monitor.py +394 -0
  216. crackerjack/mcp/progress_components.py +607 -0
  217. crackerjack/mcp/progress_monitor.py +1016 -0
  218. crackerjack/mcp/rate_limiter.py +336 -0
  219. crackerjack/mcp/server.py +24 -0
  220. crackerjack/mcp/server_core.py +526 -0
  221. crackerjack/mcp/service_watchdog.py +505 -0
  222. crackerjack/mcp/state.py +407 -0
  223. crackerjack/mcp/task_manager.py +259 -0
  224. crackerjack/mcp/tools/README.md +27 -0
  225. crackerjack/mcp/tools/__init__.py +19 -0
  226. crackerjack/mcp/tools/core_tools.py +469 -0
  227. crackerjack/mcp/tools/error_analyzer.py +283 -0
  228. crackerjack/mcp/tools/execution_tools.py +384 -0
  229. crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
  230. crackerjack/mcp/tools/intelligence_tools.py +264 -0
  231. crackerjack/mcp/tools/monitoring_tools.py +628 -0
  232. crackerjack/mcp/tools/proactive_tools.py +367 -0
  233. crackerjack/mcp/tools/progress_tools.py +222 -0
  234. crackerjack/mcp/tools/semantic_tools.py +584 -0
  235. crackerjack/mcp/tools/utility_tools.py +358 -0
  236. crackerjack/mcp/tools/workflow_executor.py +699 -0
  237. crackerjack/mcp/websocket/README.md +31 -0
  238. crackerjack/mcp/websocket/__init__.py +14 -0
  239. crackerjack/mcp/websocket/app.py +54 -0
  240. crackerjack/mcp/websocket/endpoints.py +492 -0
  241. crackerjack/mcp/websocket/event_bridge.py +188 -0
  242. crackerjack/mcp/websocket/jobs.py +406 -0
  243. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  244. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  245. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  246. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  247. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  248. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  249. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  250. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  251. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  252. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  253. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  254. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  255. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  256. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  257. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  258. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  259. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  260. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  261. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  262. crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
  263. crackerjack/mcp/websocket/server.py +174 -0
  264. crackerjack/mcp/websocket/websocket_handler.py +276 -0
  265. crackerjack/mcp/websocket_server.py +10 -0
  266. crackerjack/models/README.md +308 -0
  267. crackerjack/models/__init__.py +40 -0
  268. crackerjack/models/config.py +730 -0
  269. crackerjack/models/config_adapter.py +265 -0
  270. crackerjack/models/protocols.py +1535 -0
  271. crackerjack/models/pydantic_models.py +320 -0
  272. crackerjack/models/qa_config.py +145 -0
  273. crackerjack/models/qa_results.py +134 -0
  274. crackerjack/models/resource_protocols.py +299 -0
  275. crackerjack/models/results.py +35 -0
  276. crackerjack/models/semantic_models.py +258 -0
  277. crackerjack/models/task.py +173 -0
  278. crackerjack/models/test_models.py +60 -0
  279. crackerjack/monitoring/README.md +11 -0
  280. crackerjack/monitoring/__init__.py +0 -0
  281. crackerjack/monitoring/ai_agent_watchdog.py +405 -0
  282. crackerjack/monitoring/metrics_collector.py +427 -0
  283. crackerjack/monitoring/regression_prevention.py +580 -0
  284. crackerjack/monitoring/websocket_server.py +406 -0
  285. crackerjack/orchestration/README.md +340 -0
  286. crackerjack/orchestration/__init__.py +43 -0
  287. crackerjack/orchestration/advanced_orchestrator.py +894 -0
  288. crackerjack/orchestration/cache/README.md +312 -0
  289. crackerjack/orchestration/cache/__init__.py +37 -0
  290. crackerjack/orchestration/cache/memory_cache.py +338 -0
  291. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  292. crackerjack/orchestration/config.py +297 -0
  293. crackerjack/orchestration/coverage_improvement.py +180 -0
  294. crackerjack/orchestration/execution_strategies.py +361 -0
  295. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  296. crackerjack/orchestration/strategies/README.md +401 -0
  297. crackerjack/orchestration/strategies/__init__.py +39 -0
  298. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  299. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  300. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  301. crackerjack/orchestration/test_progress_streamer.py +647 -0
  302. crackerjack/plugins/README.md +11 -0
  303. crackerjack/plugins/__init__.py +15 -0
  304. crackerjack/plugins/base.py +200 -0
  305. crackerjack/plugins/hooks.py +254 -0
  306. crackerjack/plugins/loader.py +335 -0
  307. crackerjack/plugins/managers.py +264 -0
  308. crackerjack/py313.py +191 -0
  309. crackerjack/security/README.md +11 -0
  310. crackerjack/security/__init__.py +0 -0
  311. crackerjack/security/audit.py +197 -0
  312. crackerjack/services/README.md +374 -0
  313. crackerjack/services/__init__.py +9 -0
  314. crackerjack/services/ai/README.md +295 -0
  315. crackerjack/services/ai/__init__.py +7 -0
  316. crackerjack/services/ai/advanced_optimizer.py +878 -0
  317. crackerjack/services/ai/contextual_ai_assistant.py +542 -0
  318. crackerjack/services/ai/embeddings.py +444 -0
  319. crackerjack/services/ai/intelligent_commit.py +328 -0
  320. crackerjack/services/ai/predictive_analytics.py +510 -0
  321. crackerjack/services/anomaly_detector.py +392 -0
  322. crackerjack/services/api_extractor.py +617 -0
  323. crackerjack/services/backup_service.py +467 -0
  324. crackerjack/services/bounded_status_operations.py +530 -0
  325. crackerjack/services/cache.py +369 -0
  326. crackerjack/services/changelog_automation.py +399 -0
  327. crackerjack/services/command_execution_service.py +305 -0
  328. crackerjack/services/config_integrity.py +132 -0
  329. crackerjack/services/config_merge.py +546 -0
  330. crackerjack/services/config_service.py +198 -0
  331. crackerjack/services/config_template.py +493 -0
  332. crackerjack/services/coverage_badge_service.py +173 -0
  333. crackerjack/services/coverage_ratchet.py +381 -0
  334. crackerjack/services/debug.py +733 -0
  335. crackerjack/services/dependency_analyzer.py +460 -0
  336. crackerjack/services/dependency_monitor.py +622 -0
  337. crackerjack/services/documentation_generator.py +493 -0
  338. crackerjack/services/documentation_service.py +704 -0
  339. crackerjack/services/enhanced_filesystem.py +497 -0
  340. crackerjack/services/enterprise_optimizer.py +865 -0
  341. crackerjack/services/error_pattern_analyzer.py +676 -0
  342. crackerjack/services/file_filter.py +221 -0
  343. crackerjack/services/file_hasher.py +149 -0
  344. crackerjack/services/file_io_service.py +361 -0
  345. crackerjack/services/file_modifier.py +615 -0
  346. crackerjack/services/filesystem.py +381 -0
  347. crackerjack/services/git.py +422 -0
  348. crackerjack/services/health_metrics.py +615 -0
  349. crackerjack/services/heatmap_generator.py +744 -0
  350. crackerjack/services/incremental_executor.py +380 -0
  351. crackerjack/services/initialization.py +823 -0
  352. crackerjack/services/input_validator.py +668 -0
  353. crackerjack/services/intelligent_commit.py +327 -0
  354. crackerjack/services/log_manager.py +289 -0
  355. crackerjack/services/logging.py +228 -0
  356. crackerjack/services/lsp_client.py +628 -0
  357. crackerjack/services/memory_optimizer.py +414 -0
  358. crackerjack/services/metrics.py +587 -0
  359. crackerjack/services/monitoring/README.md +30 -0
  360. crackerjack/services/monitoring/__init__.py +9 -0
  361. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  362. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  363. crackerjack/services/monitoring/health_metrics.py +716 -0
  364. crackerjack/services/monitoring/metrics.py +587 -0
  365. crackerjack/services/monitoring/performance_benchmarks.py +410 -0
  366. crackerjack/services/monitoring/performance_cache.py +388 -0
  367. crackerjack/services/monitoring/performance_monitor.py +569 -0
  368. crackerjack/services/parallel_executor.py +527 -0
  369. crackerjack/services/pattern_cache.py +333 -0
  370. crackerjack/services/pattern_detector.py +478 -0
  371. crackerjack/services/patterns/__init__.py +142 -0
  372. crackerjack/services/patterns/agents.py +107 -0
  373. crackerjack/services/patterns/code/__init__.py +15 -0
  374. crackerjack/services/patterns/code/detection.py +118 -0
  375. crackerjack/services/patterns/code/imports.py +107 -0
  376. crackerjack/services/patterns/code/paths.py +159 -0
  377. crackerjack/services/patterns/code/performance.py +119 -0
  378. crackerjack/services/patterns/code/replacement.py +36 -0
  379. crackerjack/services/patterns/core.py +212 -0
  380. crackerjack/services/patterns/documentation/__init__.py +14 -0
  381. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  382. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  383. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  384. crackerjack/services/patterns/formatting.py +226 -0
  385. crackerjack/services/patterns/operations.py +339 -0
  386. crackerjack/services/patterns/security/__init__.py +23 -0
  387. crackerjack/services/patterns/security/code_injection.py +122 -0
  388. crackerjack/services/patterns/security/credentials.py +190 -0
  389. crackerjack/services/patterns/security/path_traversal.py +221 -0
  390. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  391. crackerjack/services/patterns/templates.py +62 -0
  392. crackerjack/services/patterns/testing/__init__.py +18 -0
  393. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  394. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  395. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  396. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  397. crackerjack/services/patterns/tool_output/other.py +97 -0
  398. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  399. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  400. crackerjack/services/patterns/url_sanitization.py +114 -0
  401. crackerjack/services/patterns/utilities.py +42 -0
  402. crackerjack/services/patterns/utils.py +339 -0
  403. crackerjack/services/patterns/validation.py +46 -0
  404. crackerjack/services/patterns/versioning.py +62 -0
  405. crackerjack/services/predictive_analytics.py +523 -0
  406. crackerjack/services/profiler.py +280 -0
  407. crackerjack/services/quality/README.md +415 -0
  408. crackerjack/services/quality/__init__.py +11 -0
  409. crackerjack/services/quality/anomaly_detector.py +392 -0
  410. crackerjack/services/quality/pattern_cache.py +333 -0
  411. crackerjack/services/quality/pattern_detector.py +479 -0
  412. crackerjack/services/quality/qa_orchestrator.py +491 -0
  413. crackerjack/services/quality/quality_baseline.py +395 -0
  414. crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
  415. crackerjack/services/quality/quality_intelligence.py +949 -0
  416. crackerjack/services/regex_patterns.py +58 -0
  417. crackerjack/services/regex_utils.py +483 -0
  418. crackerjack/services/secure_path_utils.py +524 -0
  419. crackerjack/services/secure_status_formatter.py +450 -0
  420. crackerjack/services/secure_subprocess.py +635 -0
  421. crackerjack/services/security.py +239 -0
  422. crackerjack/services/security_logger.py +495 -0
  423. crackerjack/services/server_manager.py +411 -0
  424. crackerjack/services/smart_scheduling.py +167 -0
  425. crackerjack/services/status_authentication.py +460 -0
  426. crackerjack/services/status_security_manager.py +315 -0
  427. crackerjack/services/terminal_utils.py +0 -0
  428. crackerjack/services/thread_safe_status_collector.py +441 -0
  429. crackerjack/services/tool_filter.py +368 -0
  430. crackerjack/services/tool_version_service.py +43 -0
  431. crackerjack/services/unified_config.py +115 -0
  432. crackerjack/services/validation_rate_limiter.py +220 -0
  433. crackerjack/services/vector_store.py +689 -0
  434. crackerjack/services/version_analyzer.py +461 -0
  435. crackerjack/services/version_checker.py +223 -0
  436. crackerjack/services/websocket_resource_limiter.py +438 -0
  437. crackerjack/services/zuban_lsp_service.py +391 -0
  438. crackerjack/slash_commands/README.md +11 -0
  439. crackerjack/slash_commands/__init__.py +59 -0
  440. crackerjack/slash_commands/init.md +112 -0
  441. crackerjack/slash_commands/run.md +197 -0
  442. crackerjack/slash_commands/status.md +127 -0
  443. crackerjack/tools/README.md +11 -0
  444. crackerjack/tools/__init__.py +30 -0
  445. crackerjack/tools/_git_utils.py +105 -0
  446. crackerjack/tools/check_added_large_files.py +139 -0
  447. crackerjack/tools/check_ast.py +105 -0
  448. crackerjack/tools/check_json.py +103 -0
  449. crackerjack/tools/check_jsonschema.py +297 -0
  450. crackerjack/tools/check_toml.py +103 -0
  451. crackerjack/tools/check_yaml.py +110 -0
  452. crackerjack/tools/codespell_wrapper.py +72 -0
  453. crackerjack/tools/end_of_file_fixer.py +202 -0
  454. crackerjack/tools/format_json.py +128 -0
  455. crackerjack/tools/mdformat_wrapper.py +114 -0
  456. crackerjack/tools/trailing_whitespace.py +198 -0
  457. crackerjack/tools/validate_input_validator_patterns.py +236 -0
  458. crackerjack/tools/validate_regex_patterns.py +188 -0
  459. crackerjack/ui/README.md +11 -0
  460. crackerjack/ui/__init__.py +1 -0
  461. crackerjack/ui/dashboard_renderer.py +28 -0
  462. crackerjack/ui/templates/README.md +11 -0
  463. crackerjack/utils/console_utils.py +13 -0
  464. crackerjack/utils/dependency_guard.py +230 -0
  465. crackerjack/utils/retry_utils.py +275 -0
  466. crackerjack/workflows/README.md +590 -0
  467. crackerjack/workflows/__init__.py +46 -0
  468. crackerjack/workflows/actions.py +811 -0
  469. crackerjack/workflows/auto_fix.py +444 -0
  470. crackerjack/workflows/container_builder.py +499 -0
  471. crackerjack/workflows/definitions.py +443 -0
  472. crackerjack/workflows/engine.py +177 -0
  473. crackerjack/workflows/event_bridge.py +242 -0
  474. crackerjack-0.45.2.dist-info/METADATA +1678 -0
  475. crackerjack-0.45.2.dist-info/RECORD +478 -0
  476. {crackerjack-0.18.2.dist-info โ†’ crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  477. crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
  478. crackerjack/.gitignore +0 -14
  479. crackerjack/.libcst.codemod.yaml +0 -18
  480. crackerjack/.pdm.toml +0 -1
  481. crackerjack/.pre-commit-config.yaml +0 -91
  482. crackerjack/.pytest_cache/.gitignore +0 -2
  483. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  484. crackerjack/.pytest_cache/README.md +0 -8
  485. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  486. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  487. crackerjack/.ruff_cache/.gitignore +0 -1
  488. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  489. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  490. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  491. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  492. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  493. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  494. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  495. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  496. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  497. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  498. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  499. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  500. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  501. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  502. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  503. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  504. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  505. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  506. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  507. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  508. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  509. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  510. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  511. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  512. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  513. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  514. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  515. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  516. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  517. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  518. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  519. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  520. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  521. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  522. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  523. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  524. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  525. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  526. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  527. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  528. crackerjack/crackerjack.py +0 -855
  529. crackerjack/pyproject.toml +0 -214
  530. crackerjack-0.18.2.dist-info/METADATA +0 -420
  531. crackerjack-0.18.2.dist-info/RECORD +0 -59
  532. crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
  533. {crackerjack-0.18.2.dist-info โ†’ crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,526 @@
1
+ from pathlib import Path
2
+
3
+ from ..services.regex_patterns import SAFE_PATTERNS
4
+ from .base import (
5
+ AgentContext,
6
+ FixResult,
7
+ Issue,
8
+ IssueType,
9
+ SubAgent,
10
+ agent_registry,
11
+ )
12
+
13
+
14
+ class TestSpecialistAgent(SubAgent):
15
+ def __init__(self, context: AgentContext) -> None:
16
+ super().__init__(context)
17
+ self.common_test_patterns = {
18
+ "fixture_not_found": SAFE_PATTERNS["fixture_not_found_pattern"].pattern,
19
+ "import_error": SAFE_PATTERNS["import_error_pattern"].pattern,
20
+ "assertion_error": SAFE_PATTERNS["assertion_error_pattern"].pattern,
21
+ "attribute_error": SAFE_PATTERNS["attribute_error_pattern"].pattern,
22
+ "mock_spec_error": SAFE_PATTERNS["mock_spec_error_pattern"].pattern,
23
+ "hardcoded_path": SAFE_PATTERNS["hardcoded_path_pattern"].pattern,
24
+ "missing_import": SAFE_PATTERNS["missing_name_pattern"].pattern,
25
+ "pydantic_validation": SAFE_PATTERNS["pydantic_validation_pattern"].pattern,
26
+ }
27
+
28
+ def get_supported_types(self) -> set[IssueType]:
29
+ return {IssueType.TEST_FAILURE, IssueType.IMPORT_ERROR}
30
+
31
+ async def can_handle(self, issue: Issue) -> float:
32
+ if issue.type not in self.get_supported_types():
33
+ return 0.0
34
+
35
+ perfect_match_score = self._check_perfect_test_matches(issue.message)
36
+ if perfect_match_score > 0:
37
+ return perfect_match_score
38
+
39
+ pattern_score = self._check_test_patterns(issue.message)
40
+ if pattern_score > 0:
41
+ return pattern_score
42
+
43
+ file_score = self._check_test_file_path(issue.file_path)
44
+ if file_score > 0:
45
+ return file_score
46
+
47
+ return self._check_general_test_failure(issue.type)
48
+
49
+ def _check_perfect_test_matches(self, message: str) -> float:
50
+ message_lower = message.lower()
51
+ test_keywords = [
52
+ "failed test",
53
+ "test failed",
54
+ "pytest",
55
+ "fixture",
56
+ "assertion",
57
+ "mock",
58
+ "conftest",
59
+ ]
60
+
61
+ return (
62
+ 1.0 if any(keyword in message_lower for keyword in test_keywords) else 0.0
63
+ )
64
+
65
+ def _check_test_patterns(self, message: str) -> float:
66
+ pattern_map = {
67
+ SAFE_PATTERNS[
68
+ "fixture_not_found_pattern"
69
+ ].pattern: "fixture_not_found_pattern",
70
+ SAFE_PATTERNS["import_error_pattern"].pattern: "import_error_pattern",
71
+ SAFE_PATTERNS["assertion_error_pattern"].pattern: "assertion_error_pattern",
72
+ SAFE_PATTERNS["attribute_error_pattern"].pattern: "attribute_error_pattern",
73
+ SAFE_PATTERNS["mock_spec_error_pattern"].pattern: "mock_spec_error_pattern",
74
+ SAFE_PATTERNS["hardcoded_path_pattern"].pattern: "hardcoded_path_pattern",
75
+ SAFE_PATTERNS["missing_name_pattern"].pattern: "missing_name_pattern",
76
+ SAFE_PATTERNS[
77
+ "pydantic_validation_pattern"
78
+ ].pattern: "pydantic_validation_pattern",
79
+ }
80
+
81
+ for pattern in self.common_test_patterns.values():
82
+ if pattern in pattern_map:
83
+ safe_pattern = SAFE_PATTERNS[pattern_map[pattern]]
84
+ if safe_pattern.test(message):
85
+ return 0.9
86
+ return 0.0
87
+
88
+ def _check_test_file_path(self, file_path: str | None) -> float:
89
+ if file_path and ("test_" in file_path or "/tests/" in file_path):
90
+ return 0.8
91
+ return 0.0
92
+
93
+ def _check_general_test_failure(self, issue_type: IssueType) -> float:
94
+ return 0.7 if issue_type == IssueType.TEST_FAILURE else 0.0
95
+
96
+ async def analyze_and_fix(self, issue: Issue) -> FixResult:
97
+ self.log(f"Analyzing test issue: {issue.message}")
98
+
99
+ try:
100
+ fixes_applied, files_modified = await self._apply_issue_fixes(issue)
101
+ recommendations = self._get_failure_recommendations(fixes_applied)
102
+
103
+ return self._create_fix_result(
104
+ fixes_applied,
105
+ files_modified,
106
+ recommendations,
107
+ )
108
+
109
+ except Exception as e:
110
+ self.log(f"Error fixing test issue: {e}", "ERROR")
111
+ return self._create_error_fix_result(e)
112
+
113
+ async def _apply_issue_fixes(self, issue: Issue) -> tuple[list[str], list[str]]:
114
+ fixes_applied: list[str] = []
115
+ files_modified: list[str] = []
116
+
117
+ failure_type = self._identify_failure_type(issue)
118
+ self.log(f"Identified failure type: {failure_type}")
119
+
120
+ targeted_fixes = await self._apply_targeted_fixes(failure_type, issue)
121
+ fixes_applied.extend(targeted_fixes)
122
+
123
+ file_fixes, file_modified = await self._apply_file_fixes(issue)
124
+ fixes_applied.extend(file_fixes)
125
+ if file_modified and issue.file_path:
126
+ files_modified.append(issue.file_path)
127
+
128
+ general_fixes = await self._apply_general_test_fixes()
129
+ fixes_applied.extend(general_fixes)
130
+
131
+ return fixes_applied, files_modified
132
+
133
+ async def _apply_targeted_fixes(self, failure_type: str, issue: Issue) -> list[str]:
134
+ if failure_type == "fixture_not_found":
135
+ return await self._fix_missing_fixtures(issue)
136
+ if failure_type == "import_error":
137
+ return await self._fix_import_errors(issue)
138
+ if failure_type == "hardcoded_path":
139
+ return await self._fix_hardcoded_paths(issue)
140
+ if failure_type == "mock_spec_error":
141
+ return await self._fix_mock_issues(issue)
142
+ if failure_type == "pydantic_validation":
143
+ return await self._fix_pydantic_issues(issue)
144
+ return []
145
+
146
+ async def _apply_file_fixes(self, issue: Issue) -> tuple[list[str], bool]:
147
+ if not issue.file_path or not (
148
+ "test_" in issue.file_path or "/tests/" in issue.file_path
149
+ ):
150
+ return [], False
151
+
152
+ file_fixes = await self._fix_test_file_issues(issue.file_path)
153
+ return file_fixes, len(file_fixes) > 0
154
+
155
+ def _get_failure_recommendations(self, fixes_applied: list[str]) -> list[str]:
156
+ if fixes_applied:
157
+ return []
158
+
159
+ return [
160
+ "Check test file imports and fixture definitions",
161
+ "Verify mock objects are properly configured",
162
+ "Ensure test data paths use tmp_path fixture",
163
+ "Review assertion statements for correctness",
164
+ ]
165
+
166
+ def _create_fix_result(
167
+ self,
168
+ fixes_applied: list[str],
169
+ files_modified: list[str],
170
+ recommendations: list[str],
171
+ ) -> FixResult:
172
+ success = len(fixes_applied) > 0
173
+ confidence = 0.8 if success else 0.4
174
+
175
+ return FixResult(
176
+ success=success,
177
+ confidence=confidence,
178
+ fixes_applied=fixes_applied,
179
+ files_modified=files_modified,
180
+ recommendations=recommendations,
181
+ )
182
+
183
+ def _create_error_fix_result(self, error: Exception) -> FixResult:
184
+ return FixResult(
185
+ success=False,
186
+ confidence=0.0,
187
+ remaining_issues=[f"Failed to fix test issue: {error}"],
188
+ )
189
+
190
+ def _identify_failure_type(self, issue: Issue) -> str:
191
+ message = issue.message
192
+
193
+ pattern_map = {
194
+ SAFE_PATTERNS[
195
+ "fixture_not_found_pattern"
196
+ ].pattern: "fixture_not_found_pattern",
197
+ SAFE_PATTERNS["import_error_pattern"].pattern: "import_error_pattern",
198
+ SAFE_PATTERNS["assertion_error_pattern"].pattern: "assertion_error_pattern",
199
+ SAFE_PATTERNS["attribute_error_pattern"].pattern: "attribute_error_pattern",
200
+ SAFE_PATTERNS["mock_spec_error_pattern"].pattern: "mock_spec_error_pattern",
201
+ SAFE_PATTERNS["hardcoded_path_pattern"].pattern: "hardcoded_path_pattern",
202
+ SAFE_PATTERNS["missing_name_pattern"].pattern: "missing_name_pattern",
203
+ SAFE_PATTERNS[
204
+ "pydantic_validation_pattern"
205
+ ].pattern: "pydantic_validation_pattern",
206
+ }
207
+
208
+ for pattern_name, pattern in self.common_test_patterns.items():
209
+ if pattern in pattern_map:
210
+ safe_pattern = SAFE_PATTERNS[pattern_map[pattern]]
211
+ if safe_pattern.test(message):
212
+ return pattern_name
213
+
214
+ return "unknown"
215
+
216
+ async def _fix_missing_fixtures(self, issue: Issue) -> list[str]:
217
+ fixes: list[str] = []
218
+
219
+ fixture_pattern = SAFE_PATTERNS["fixture_not_found_pattern"]
220
+ if not fixture_pattern.test(issue.message):
221
+ return fixes
222
+
223
+ match = fixture_pattern.search(issue.message)
224
+ if not match:
225
+ return fixes
226
+
227
+ fixture_name = match.group(1)
228
+ self.log(f"Attempting to fix missing fixture: {fixture_name}")
229
+
230
+ if fixture_name == "temp_pkg_path":
231
+ fixes.extend(await self._add_temp_pkg_path_fixture(issue.file_path))
232
+ elif fixture_name == "console":
233
+ fixes.extend(await self._add_console_fixture(issue.file_path))
234
+ elif fixture_name in ("tmp_path", "tmpdir"):
235
+ fixes.extend(await self._add_temp_path_fixture(issue.file_path))
236
+
237
+ return fixes
238
+
239
+ async def _fix_import_errors(self, issue: Issue) -> list[str]:
240
+ if not self._is_valid_file_path(issue.file_path) or issue.file_path is None:
241
+ return []
242
+
243
+ file_path = Path(issue.file_path)
244
+ content = self.context.get_file_content(file_path)
245
+ if not content:
246
+ return []
247
+
248
+ lines = content.split("\n")
249
+ fixes, modified = self._apply_import_fixes(lines, content, issue.file_path)
250
+
251
+ if modified:
252
+ self._save_import_fixes(file_path, lines, issue.file_path)
253
+
254
+ return fixes
255
+
256
+ def _is_valid_file_path(self, file_path: str | None) -> bool:
257
+ return file_path is not None and Path(file_path).exists()
258
+
259
+ def _apply_import_fixes(
260
+ self,
261
+ lines: list[str],
262
+ content: str,
263
+ file_path: str,
264
+ ) -> tuple[list[str], bool]:
265
+ fixes: list[str] = []
266
+ modified = False
267
+
268
+ if self._needs_pytest_import(content):
269
+ self._add_pytest_import(lines)
270
+ fixes.append(f"Added missing pytest import to {file_path}")
271
+ modified = True
272
+
273
+ if self._needs_pathlib_import(content):
274
+ lines.insert(0, "from pathlib import Path")
275
+ fixes.append(f"Added missing pathlib import to {file_path}")
276
+ modified = True
277
+
278
+ if self._needs_mock_import(content):
279
+ lines.insert(0, "from unittest.mock import Mock")
280
+ fixes.append(f"Added missing Mock import to {file_path}")
281
+ modified = True
282
+
283
+ return fixes, modified
284
+
285
+ def _needs_pytest_import(self, content: str) -> bool:
286
+ return "pytest" not in content and "import pytest" not in content
287
+
288
+ def _needs_pathlib_import(self, content: str) -> bool:
289
+ return "Path(" in content and "from pathlib import Path" not in content
290
+
291
+ def _needs_mock_import(self, content: str) -> bool:
292
+ return "Mock()" in content and "from unittest.mock import Mock" not in content
293
+
294
+ def _add_pytest_import(self, lines: list[str]) -> None:
295
+ import_section_end = self._find_import_section_end(lines)
296
+ lines.insert(import_section_end, "import pytest")
297
+
298
+ def _find_import_section_end(self, lines: list[str]) -> int:
299
+ import_section_end = 0
300
+ for i, line in enumerate(lines):
301
+ if line.strip().startswith(("import ", "from ")):
302
+ import_section_end = i + 1
303
+ elif line.strip() == "" and import_section_end > 0:
304
+ break
305
+ return import_section_end
306
+
307
+ def _save_import_fixes(
308
+ self,
309
+ file_path: Path,
310
+ lines: list[str],
311
+ file_path_str: str,
312
+ ) -> None:
313
+ if self.context.write_file_content(file_path, "\n".join(lines)):
314
+ self.log(f"Fixed imports in {file_path_str}")
315
+
316
+ async def _fix_hardcoded_paths(self, issue: Issue) -> list[str]:
317
+ fixes: list[str] = []
318
+
319
+ if not issue.file_path:
320
+ return fixes
321
+
322
+ file_path = Path(issue.file_path)
323
+ content = self.context.get_file_content(file_path)
324
+ if not content:
325
+ return fixes
326
+
327
+ original_content = content
328
+
329
+ content = (
330
+ content.replace('Path("/test/path")', "tmp_path")
331
+ .replace('"/test/path"', "str(tmp_path)")
332
+ .replace("'/test/path'", "str(tmp_path)")
333
+ )
334
+
335
+ if content != original_content:
336
+ if self.context.write_file_content(file_path, content):
337
+ fixes.append(f"Fixed hardcoded paths in {issue.file_path}")
338
+ self.log(f"Fixed hardcoded paths in {issue.file_path}")
339
+
340
+ return fixes
341
+
342
+ async def _fix_mock_issues(self, issue: Issue) -> list[str]:
343
+ fixes: list[str] = []
344
+
345
+ if (
346
+ not self._is_valid_mock_issue_file(issue.file_path)
347
+ or issue.file_path is None
348
+ ):
349
+ return fixes
350
+
351
+ file_path = Path(issue.file_path)
352
+ content = self.context.get_file_content(file_path)
353
+ if not content:
354
+ return fixes
355
+
356
+ original_content = content
357
+ content, mock_fixes = self._apply_mock_fixes_to_content(
358
+ content,
359
+ issue.file_path,
360
+ )
361
+ fixes.extend(mock_fixes)
362
+
363
+ if content != original_content:
364
+ self._save_mock_fixes(file_path, content, issue.file_path)
365
+
366
+ return fixes
367
+
368
+ def _is_valid_mock_issue_file(self, file_path: str | None) -> bool:
369
+ return file_path is not None
370
+
371
+ def _apply_mock_fixes_to_content(
372
+ self,
373
+ content: str,
374
+ file_path: str,
375
+ ) -> tuple[str, list[str]]:
376
+ fixes: list[str] = []
377
+
378
+ if self._needs_console_mock_fix(content):
379
+ content = self._fix_console_mock_usage(content)
380
+ fixes.append(f"Fixed Mock usage in {file_path}")
381
+
382
+ return content, fixes
383
+
384
+ def _needs_console_mock_fix(self, content: str) -> bool:
385
+ return "console = Mock()" in content and "Console" not in content
386
+
387
+ def _fix_console_mock_usage(self, content: str) -> str:
388
+ content = content.replace("console = Mock()", "console = Console()")
389
+ return self._ensure_console_import(content)
390
+
391
+ def _ensure_console_import(self, content: str) -> str:
392
+ if "from rich.console import Console" in content:
393
+ return content
394
+
395
+ lines = content.split("\n")
396
+ lines = self._add_console_import_to_lines(lines)
397
+ return "\n".join(lines)
398
+
399
+ def _add_console_import_to_lines(self, lines: list[str]) -> list[str]:
400
+ for i, line in enumerate(lines):
401
+ if line.startswith("from rich") or "rich" in line:
402
+ lines.insert(i + 1, "from rich.console import Console")
403
+ return lines
404
+
405
+ lines.insert(0, "from rich.console import Console")
406
+ return lines
407
+
408
+ def _save_mock_fixes(
409
+ self,
410
+ file_path: Path,
411
+ content: str,
412
+ file_path_str: str,
413
+ ) -> None:
414
+ if self.context.write_file_content(file_path, content):
415
+ self.log(f"Fixed Mock issues in {file_path_str}")
416
+
417
+ async def _fix_pydantic_issues(self, issue: Issue) -> list[str]:
418
+ return []
419
+
420
+ async def _add_temp_pkg_path_fixture(self, file_path: str | None) -> list[str]:
421
+ if not file_path:
422
+ return []
423
+
424
+ fixes: list[str] = []
425
+ path = Path(file_path)
426
+ content = self.context.get_file_content(path)
427
+ if not content:
428
+ return fixes
429
+
430
+ if "@pytest.fixture" in content and "temp_pkg_path" in content:
431
+ return fixes
432
+
433
+ fixture_code = '''
434
+ @pytest.fixture
435
+ def temp_pkg_path(tmp_path) -> Path:
436
+ """Create temporary package path."""
437
+ return tmp_path
438
+ '''
439
+
440
+ lines = content.split("\n")
441
+
442
+ for i, line in enumerate(lines):
443
+ if line.startswith("class Test") and i > 0:
444
+ lines.insert(i + 1, fixture_code)
445
+ break
446
+ else:
447
+ lines.append(fixture_code)
448
+
449
+ if self.context.write_file_content(path, "\n".join(lines)):
450
+ fixes.append(f"Added temp_pkg_path fixture to {file_path}")
451
+
452
+ return fixes
453
+
454
+ async def _add_console_fixture(self, file_path: str | None) -> list[str]:
455
+ if not file_path:
456
+ return []
457
+
458
+ fixes: list[str] = []
459
+ path = Path(file_path)
460
+ content = self.context.get_file_content(path)
461
+ if not content:
462
+ return fixes
463
+
464
+ fixture_code = '''
465
+ @pytest.fixture
466
+ def console() -> Console:
467
+ """Create console instance for testing."""
468
+ return Console()
469
+ '''
470
+
471
+ lines = content.split("\n")
472
+ lines.append(fixture_code)
473
+
474
+ if "from rich.console import Console" not in content:
475
+ lines.insert(0, "from rich.console import Console")
476
+
477
+ if self.context.write_file_content(path, "\n".join(lines)):
478
+ fixes.append(f"Added console fixture to {file_path}")
479
+
480
+ return fixes
481
+
482
+ async def _add_temp_path_fixture(self, file_path: str | None) -> list[str]:
483
+ return [
484
+ f"Note: tmp_path is a built-in pytest fixture - check fixture usage in {file_path}",
485
+ ]
486
+
487
+ async def _fix_test_file_issues(self, file_path: str) -> list[str]:
488
+ fixes: list[str] = []
489
+
490
+ path = Path(file_path)
491
+ content = self.context.get_file_content(path)
492
+ if not content:
493
+ return fixes
494
+
495
+ original_content = content
496
+
497
+ if "import pytest" not in content:
498
+ lines = content.split("\n")
499
+ lines.insert(0, "import pytest")
500
+ content = "\n".join(lines)
501
+ fixes.append(f"Added pytest import to {file_path}")
502
+
503
+ from crackerjack.services.regex_patterns import apply_test_fixes
504
+
505
+ content = apply_test_fixes(content)
506
+
507
+ if content != original_content:
508
+ if self.context.write_file_content(path, content):
509
+ self.log(f"Applied general fixes to {file_path}")
510
+
511
+ return fixes
512
+
513
+ async def _apply_general_test_fixes(self) -> list[str]:
514
+ fixes: list[str] = []
515
+
516
+ returncode, _, stderr = await self.run_command(
517
+ ["uv", "run", "python", "-m", "pytest", "--collect-only", "-q"],
518
+ )
519
+
520
+ if returncode != 0 and "ImportError" in stderr:
521
+ fixes.append("Identified import issues in test collection")
522
+
523
+ return fixes
524
+
525
+
526
+ agent_registry.register(TestSpecialistAgent)
@@ -0,0 +1,110 @@
1
+ import time
2
+ import typing as t
3
+ from collections import defaultdict
4
+ from dataclasses import dataclass, field
5
+
6
+ from .base import FixResult, Issue
7
+
8
+
9
+ @dataclass
10
+ class AgentActivity:
11
+ agent_type: str
12
+ confidence: float
13
+ status: str
14
+ current_issue: Issue | None = None
15
+ start_time: float = field(default_factory=time.time)
16
+ processing_time: float = 0.0
17
+ result: FixResult | None = None
18
+
19
+
20
+ class AgentTracker:
21
+ def __init__(self) -> None:
22
+ self.active_agents: dict[str, AgentActivity] = {}
23
+ self.completed_activities: list[AgentActivity] = []
24
+ self.performance_metrics: defaultdict[str, list[float]] = defaultdict(list)
25
+ self.cache_stats = {"hits": 0, "misses": 0}
26
+ self.total_issues_processed = 0
27
+ self.coordinator_status = "idle"
28
+ self.agent_registry: dict[str, t.Any] = {
29
+ "total_agents": 0,
30
+ "initialized_agents": 0,
31
+ "agent_types": [],
32
+ }
33
+
34
+ def set_coordinator_status(self, status: str) -> None:
35
+ self.coordinator_status = status
36
+
37
+ def register_agents(self, agent_types: list[str]) -> None:
38
+ self.agent_registry = {
39
+ "total_agents": len(agent_types),
40
+ "initialized_agents": len(agent_types),
41
+ "agent_types": agent_types,
42
+ }
43
+
44
+ def track_agent_processing(
45
+ self,
46
+ agent_type: str,
47
+ issue: Issue,
48
+ confidence: float,
49
+ ) -> None:
50
+ if agent_type in self.active_agents:
51
+ activity = self.active_agents[agent_type]
52
+ activity.status = "processing"
53
+ activity.current_issue = issue
54
+ activity.confidence = confidence
55
+ else:
56
+ self.active_agents[agent_type] = AgentActivity(
57
+ agent_type=agent_type,
58
+ confidence=confidence,
59
+ status="processing",
60
+ current_issue=issue,
61
+ )
62
+
63
+ def track_agent_complete(self, agent_type: str, result: FixResult) -> None:
64
+ if agent_type not in self.active_agents:
65
+ return
66
+
67
+ activity = self.active_agents[agent_type]
68
+ activity.status = "completed" if result.success else "failed"
69
+ activity.result = result
70
+ activity.processing_time = time.time() - activity.start_time
71
+
72
+ self.performance_metrics[agent_type].append(activity.processing_time)
73
+ self.total_issues_processed += 1
74
+
75
+ self.completed_activities.append(activity)
76
+ del self.active_agents[agent_type]
77
+
78
+ def _get_agent_emoji(self, agent_type: str) -> str:
79
+ return {
80
+ "FormattingAgent": "๐ŸŽจ",
81
+ "SecurityAgent": "๐Ÿ”’",
82
+ "TestSpecialistAgent": "๐Ÿงช",
83
+ "TestCreationAgent": "โž•",
84
+ }.get(agent_type, "๐Ÿค–")
85
+
86
+ def reset(self) -> None:
87
+ self.active_agents.clear()
88
+ self.completed_activities.clear()
89
+ self.performance_metrics.clear()
90
+ self.cache_stats = {"hits": 0, "misses": 0}
91
+ self.total_issues_processed = 0
92
+ self.coordinator_status = "idle"
93
+
94
+
95
+ _global_tracker = None
96
+
97
+
98
+ def get_agent_tracker() -> AgentTracker:
99
+ global _global_tracker
100
+ if _global_tracker is None:
101
+ _global_tracker = AgentTracker()
102
+ return _global_tracker
103
+
104
+
105
+ def reset_agent_tracker() -> None:
106
+ global _global_tracker
107
+ if _global_tracker:
108
+ _global_tracker.reset()
109
+ else:
110
+ _global_tracker = AgentTracker()