crackerjack 0.37.9__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 (425) hide show
  1. crackerjack/README.md +19 -0
  2. crackerjack/__init__.py +30 -1
  3. crackerjack/__main__.py +342 -1263
  4. crackerjack/adapters/README.md +18 -0
  5. crackerjack/adapters/__init__.py +27 -5
  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/{rust_tool_manager.py → lsp/_manager.py} +3 -3
  27. crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
  28. crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
  29. crackerjack/adapters/refactor/README.md +59 -0
  30. crackerjack/adapters/refactor/__init__.py +12 -0
  31. crackerjack/adapters/refactor/creosote.py +318 -0
  32. crackerjack/adapters/refactor/refurb.py +406 -0
  33. crackerjack/adapters/refactor/skylos.py +494 -0
  34. crackerjack/adapters/sast/README.md +132 -0
  35. crackerjack/adapters/sast/__init__.py +32 -0
  36. crackerjack/adapters/sast/_base.py +201 -0
  37. crackerjack/adapters/sast/bandit.py +423 -0
  38. crackerjack/adapters/sast/pyscn.py +405 -0
  39. crackerjack/adapters/sast/semgrep.py +241 -0
  40. crackerjack/adapters/security/README.md +111 -0
  41. crackerjack/adapters/security/__init__.py +17 -0
  42. crackerjack/adapters/security/gitleaks.py +339 -0
  43. crackerjack/adapters/type/README.md +52 -0
  44. crackerjack/adapters/type/__init__.py +12 -0
  45. crackerjack/adapters/type/pyrefly.py +402 -0
  46. crackerjack/adapters/type/ty.py +402 -0
  47. crackerjack/adapters/type/zuban.py +522 -0
  48. crackerjack/adapters/utility/README.md +51 -0
  49. crackerjack/adapters/utility/__init__.py +10 -0
  50. crackerjack/adapters/utility/checks.py +884 -0
  51. crackerjack/agents/README.md +264 -0
  52. crackerjack/agents/__init__.py +40 -12
  53. crackerjack/agents/base.py +1 -0
  54. crackerjack/agents/claude_code_bridge.py +641 -0
  55. crackerjack/agents/coordinator.py +49 -53
  56. crackerjack/agents/dry_agent.py +187 -3
  57. crackerjack/agents/enhanced_coordinator.py +279 -0
  58. crackerjack/agents/enhanced_proactive_agent.py +185 -0
  59. crackerjack/agents/error_middleware.py +53 -0
  60. crackerjack/agents/formatting_agent.py +6 -8
  61. crackerjack/agents/helpers/__init__.py +9 -0
  62. crackerjack/agents/helpers/performance/__init__.py +22 -0
  63. crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
  64. crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
  65. crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
  66. crackerjack/agents/helpers/refactoring/__init__.py +22 -0
  67. crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
  68. crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
  69. crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
  70. crackerjack/agents/helpers/test_creation/__init__.py +19 -0
  71. crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
  72. crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
  73. crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
  74. crackerjack/agents/performance_agent.py +121 -1152
  75. crackerjack/agents/refactoring_agent.py +156 -655
  76. crackerjack/agents/semantic_agent.py +479 -0
  77. crackerjack/agents/semantic_helpers.py +356 -0
  78. crackerjack/agents/test_creation_agent.py +19 -1605
  79. crackerjack/api.py +5 -7
  80. crackerjack/cli/README.md +394 -0
  81. crackerjack/cli/__init__.py +1 -1
  82. crackerjack/cli/cache_handlers.py +23 -18
  83. crackerjack/cli/cache_handlers_enhanced.py +1 -4
  84. crackerjack/cli/facade.py +70 -8
  85. crackerjack/cli/formatting.py +13 -0
  86. crackerjack/cli/handlers/__init__.py +85 -0
  87. crackerjack/cli/handlers/advanced.py +103 -0
  88. crackerjack/cli/handlers/ai_features.py +62 -0
  89. crackerjack/cli/handlers/analytics.py +479 -0
  90. crackerjack/cli/handlers/changelog.py +271 -0
  91. crackerjack/cli/handlers/config_handlers.py +16 -0
  92. crackerjack/cli/handlers/coverage.py +84 -0
  93. crackerjack/cli/handlers/documentation.py +280 -0
  94. crackerjack/cli/handlers/main_handlers.py +497 -0
  95. crackerjack/cli/handlers/monitoring.py +371 -0
  96. crackerjack/cli/handlers.py +249 -49
  97. crackerjack/cli/interactive.py +8 -5
  98. crackerjack/cli/options.py +203 -110
  99. crackerjack/cli/semantic_handlers.py +292 -0
  100. crackerjack/cli/version.py +19 -0
  101. crackerjack/code_cleaner.py +60 -24
  102. crackerjack/config/README.md +472 -0
  103. crackerjack/config/__init__.py +256 -0
  104. crackerjack/config/global_lock_config.py +191 -54
  105. crackerjack/config/hooks.py +188 -16
  106. crackerjack/config/loader.py +239 -0
  107. crackerjack/config/settings.py +141 -0
  108. crackerjack/config/tool_commands.py +331 -0
  109. crackerjack/core/README.md +393 -0
  110. crackerjack/core/async_workflow_orchestrator.py +79 -53
  111. crackerjack/core/autofix_coordinator.py +22 -9
  112. crackerjack/core/container.py +10 -9
  113. crackerjack/core/enhanced_container.py +9 -9
  114. crackerjack/core/performance.py +1 -1
  115. crackerjack/core/performance_monitor.py +5 -3
  116. crackerjack/core/phase_coordinator.py +1018 -634
  117. crackerjack/core/proactive_workflow.py +3 -3
  118. crackerjack/core/retry.py +275 -0
  119. crackerjack/core/service_watchdog.py +167 -23
  120. crackerjack/core/session_coordinator.py +187 -382
  121. crackerjack/core/timeout_manager.py +161 -44
  122. crackerjack/core/workflow/__init__.py +21 -0
  123. crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
  124. crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
  125. crackerjack/core/workflow/workflow_issue_parser.py +714 -0
  126. crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
  127. crackerjack/core/workflow/workflow_security_gates.py +400 -0
  128. crackerjack/core/workflow_orchestrator.py +1247 -953
  129. crackerjack/data/README.md +11 -0
  130. crackerjack/data/__init__.py +8 -0
  131. crackerjack/data/models.py +79 -0
  132. crackerjack/data/repository.py +210 -0
  133. crackerjack/decorators/README.md +180 -0
  134. crackerjack/decorators/__init__.py +35 -0
  135. crackerjack/decorators/error_handling.py +649 -0
  136. crackerjack/decorators/error_handling_decorators.py +334 -0
  137. crackerjack/decorators/helpers.py +58 -0
  138. crackerjack/decorators/patterns.py +281 -0
  139. crackerjack/decorators/utils.py +58 -0
  140. crackerjack/docs/README.md +11 -0
  141. crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
  142. crackerjack/documentation/README.md +11 -0
  143. crackerjack/documentation/ai_templates.py +1 -1
  144. crackerjack/documentation/dual_output_generator.py +11 -9
  145. crackerjack/documentation/reference_generator.py +104 -59
  146. crackerjack/dynamic_config.py +52 -61
  147. crackerjack/errors.py +1 -1
  148. crackerjack/events/README.md +11 -0
  149. crackerjack/events/__init__.py +16 -0
  150. crackerjack/events/telemetry.py +175 -0
  151. crackerjack/events/workflow_bus.py +346 -0
  152. crackerjack/exceptions/README.md +301 -0
  153. crackerjack/exceptions/__init__.py +5 -0
  154. crackerjack/exceptions/config.py +4 -0
  155. crackerjack/exceptions/tool_execution_error.py +245 -0
  156. crackerjack/executors/README.md +591 -0
  157. crackerjack/executors/__init__.py +2 -0
  158. crackerjack/executors/async_hook_executor.py +539 -77
  159. crackerjack/executors/cached_hook_executor.py +3 -3
  160. crackerjack/executors/hook_executor.py +967 -102
  161. crackerjack/executors/hook_lock_manager.py +31 -22
  162. crackerjack/executors/individual_hook_executor.py +66 -32
  163. crackerjack/executors/lsp_aware_hook_executor.py +136 -57
  164. crackerjack/executors/progress_hook_executor.py +282 -0
  165. crackerjack/executors/tool_proxy.py +23 -7
  166. crackerjack/hooks/README.md +485 -0
  167. crackerjack/hooks/lsp_hook.py +8 -9
  168. crackerjack/intelligence/README.md +557 -0
  169. crackerjack/interactive.py +37 -10
  170. crackerjack/managers/README.md +369 -0
  171. crackerjack/managers/async_hook_manager.py +41 -57
  172. crackerjack/managers/hook_manager.py +449 -79
  173. crackerjack/managers/publish_manager.py +81 -36
  174. crackerjack/managers/test_command_builder.py +290 -12
  175. crackerjack/managers/test_executor.py +93 -8
  176. crackerjack/managers/test_manager.py +1082 -75
  177. crackerjack/managers/test_progress.py +118 -26
  178. crackerjack/mcp/README.md +374 -0
  179. crackerjack/mcp/cache.py +25 -2
  180. crackerjack/mcp/client_runner.py +35 -18
  181. crackerjack/mcp/context.py +9 -9
  182. crackerjack/mcp/dashboard.py +24 -8
  183. crackerjack/mcp/enhanced_progress_monitor.py +34 -23
  184. crackerjack/mcp/file_monitor.py +27 -6
  185. crackerjack/mcp/progress_components.py +45 -34
  186. crackerjack/mcp/progress_monitor.py +6 -9
  187. crackerjack/mcp/rate_limiter.py +11 -7
  188. crackerjack/mcp/server.py +2 -0
  189. crackerjack/mcp/server_core.py +187 -55
  190. crackerjack/mcp/service_watchdog.py +12 -9
  191. crackerjack/mcp/task_manager.py +2 -2
  192. crackerjack/mcp/tools/README.md +27 -0
  193. crackerjack/mcp/tools/__init__.py +2 -0
  194. crackerjack/mcp/tools/core_tools.py +75 -52
  195. crackerjack/mcp/tools/execution_tools.py +87 -31
  196. crackerjack/mcp/tools/intelligence_tools.py +2 -2
  197. crackerjack/mcp/tools/proactive_tools.py +1 -1
  198. crackerjack/mcp/tools/semantic_tools.py +584 -0
  199. crackerjack/mcp/tools/utility_tools.py +180 -132
  200. crackerjack/mcp/tools/workflow_executor.py +87 -46
  201. crackerjack/mcp/websocket/README.md +31 -0
  202. crackerjack/mcp/websocket/app.py +11 -1
  203. crackerjack/mcp/websocket/event_bridge.py +188 -0
  204. crackerjack/mcp/websocket/jobs.py +27 -4
  205. crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
  206. crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
  207. crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
  208. crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
  209. crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
  210. crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
  211. crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
  212. crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
  213. crackerjack/mcp/websocket/monitoring/factory.py +109 -0
  214. crackerjack/mcp/websocket/monitoring/filters.py +10 -0
  215. crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
  216. crackerjack/mcp/websocket/monitoring/models.py +90 -0
  217. crackerjack/mcp/websocket/monitoring/utils.py +171 -0
  218. crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
  219. crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
  220. crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
  221. crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
  222. crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
  223. crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
  224. crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
  225. crackerjack/mcp/websocket/server.py +1 -3
  226. crackerjack/mcp/websocket/websocket_handler.py +107 -6
  227. crackerjack/models/README.md +308 -0
  228. crackerjack/models/__init__.py +10 -1
  229. crackerjack/models/config.py +639 -22
  230. crackerjack/models/config_adapter.py +6 -6
  231. crackerjack/models/protocols.py +1167 -23
  232. crackerjack/models/pydantic_models.py +320 -0
  233. crackerjack/models/qa_config.py +145 -0
  234. crackerjack/models/qa_results.py +134 -0
  235. crackerjack/models/results.py +35 -0
  236. crackerjack/models/semantic_models.py +258 -0
  237. crackerjack/models/task.py +19 -3
  238. crackerjack/models/test_models.py +60 -0
  239. crackerjack/monitoring/README.md +11 -0
  240. crackerjack/monitoring/ai_agent_watchdog.py +5 -4
  241. crackerjack/monitoring/metrics_collector.py +4 -3
  242. crackerjack/monitoring/regression_prevention.py +4 -3
  243. crackerjack/monitoring/websocket_server.py +4 -241
  244. crackerjack/orchestration/README.md +340 -0
  245. crackerjack/orchestration/__init__.py +43 -0
  246. crackerjack/orchestration/advanced_orchestrator.py +20 -67
  247. crackerjack/orchestration/cache/README.md +312 -0
  248. crackerjack/orchestration/cache/__init__.py +37 -0
  249. crackerjack/orchestration/cache/memory_cache.py +338 -0
  250. crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
  251. crackerjack/orchestration/config.py +297 -0
  252. crackerjack/orchestration/coverage_improvement.py +13 -6
  253. crackerjack/orchestration/execution_strategies.py +6 -6
  254. crackerjack/orchestration/hook_orchestrator.py +1398 -0
  255. crackerjack/orchestration/strategies/README.md +401 -0
  256. crackerjack/orchestration/strategies/__init__.py +39 -0
  257. crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
  258. crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
  259. crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
  260. crackerjack/orchestration/test_progress_streamer.py +1 -1
  261. crackerjack/plugins/README.md +11 -0
  262. crackerjack/plugins/hooks.py +3 -2
  263. crackerjack/plugins/loader.py +3 -3
  264. crackerjack/plugins/managers.py +1 -1
  265. crackerjack/py313.py +191 -0
  266. crackerjack/security/README.md +11 -0
  267. crackerjack/services/README.md +374 -0
  268. crackerjack/services/__init__.py +8 -21
  269. crackerjack/services/ai/README.md +295 -0
  270. crackerjack/services/ai/__init__.py +7 -0
  271. crackerjack/services/ai/advanced_optimizer.py +878 -0
  272. crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
  273. crackerjack/services/ai/embeddings.py +444 -0
  274. crackerjack/services/ai/intelligent_commit.py +328 -0
  275. crackerjack/services/ai/predictive_analytics.py +510 -0
  276. crackerjack/services/api_extractor.py +5 -3
  277. crackerjack/services/bounded_status_operations.py +45 -5
  278. crackerjack/services/cache.py +249 -318
  279. crackerjack/services/changelog_automation.py +7 -3
  280. crackerjack/services/command_execution_service.py +305 -0
  281. crackerjack/services/config_integrity.py +83 -39
  282. crackerjack/services/config_merge.py +9 -6
  283. crackerjack/services/config_service.py +198 -0
  284. crackerjack/services/config_template.py +13 -26
  285. crackerjack/services/coverage_badge_service.py +6 -4
  286. crackerjack/services/coverage_ratchet.py +53 -27
  287. crackerjack/services/debug.py +18 -7
  288. crackerjack/services/dependency_analyzer.py +4 -4
  289. crackerjack/services/dependency_monitor.py +13 -13
  290. crackerjack/services/documentation_generator.py +4 -2
  291. crackerjack/services/documentation_service.py +62 -33
  292. crackerjack/services/enhanced_filesystem.py +81 -27
  293. crackerjack/services/enterprise_optimizer.py +1 -1
  294. crackerjack/services/error_pattern_analyzer.py +10 -10
  295. crackerjack/services/file_filter.py +221 -0
  296. crackerjack/services/file_hasher.py +5 -7
  297. crackerjack/services/file_io_service.py +361 -0
  298. crackerjack/services/file_modifier.py +615 -0
  299. crackerjack/services/filesystem.py +80 -109
  300. crackerjack/services/git.py +99 -5
  301. crackerjack/services/health_metrics.py +4 -6
  302. crackerjack/services/heatmap_generator.py +12 -3
  303. crackerjack/services/incremental_executor.py +380 -0
  304. crackerjack/services/initialization.py +101 -49
  305. crackerjack/services/log_manager.py +2 -2
  306. crackerjack/services/logging.py +120 -68
  307. crackerjack/services/lsp_client.py +12 -12
  308. crackerjack/services/memory_optimizer.py +27 -22
  309. crackerjack/services/monitoring/README.md +30 -0
  310. crackerjack/services/monitoring/__init__.py +9 -0
  311. crackerjack/services/monitoring/dependency_monitor.py +678 -0
  312. crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
  313. crackerjack/services/monitoring/health_metrics.py +716 -0
  314. crackerjack/services/monitoring/metrics.py +587 -0
  315. crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
  316. crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
  317. crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
  318. crackerjack/services/parallel_executor.py +166 -55
  319. crackerjack/services/patterns/__init__.py +142 -0
  320. crackerjack/services/patterns/agents.py +107 -0
  321. crackerjack/services/patterns/code/__init__.py +15 -0
  322. crackerjack/services/patterns/code/detection.py +118 -0
  323. crackerjack/services/patterns/code/imports.py +107 -0
  324. crackerjack/services/patterns/code/paths.py +159 -0
  325. crackerjack/services/patterns/code/performance.py +119 -0
  326. crackerjack/services/patterns/code/replacement.py +36 -0
  327. crackerjack/services/patterns/core.py +212 -0
  328. crackerjack/services/patterns/documentation/__init__.py +14 -0
  329. crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
  330. crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
  331. crackerjack/services/patterns/documentation/docstrings.py +89 -0
  332. crackerjack/services/patterns/formatting.py +226 -0
  333. crackerjack/services/patterns/operations.py +339 -0
  334. crackerjack/services/patterns/security/__init__.py +23 -0
  335. crackerjack/services/patterns/security/code_injection.py +122 -0
  336. crackerjack/services/patterns/security/credentials.py +190 -0
  337. crackerjack/services/patterns/security/path_traversal.py +221 -0
  338. crackerjack/services/patterns/security/unsafe_operations.py +216 -0
  339. crackerjack/services/patterns/templates.py +62 -0
  340. crackerjack/services/patterns/testing/__init__.py +18 -0
  341. crackerjack/services/patterns/testing/error_patterns.py +107 -0
  342. crackerjack/services/patterns/testing/pytest_output.py +126 -0
  343. crackerjack/services/patterns/tool_output/__init__.py +16 -0
  344. crackerjack/services/patterns/tool_output/bandit.py +72 -0
  345. crackerjack/services/patterns/tool_output/other.py +97 -0
  346. crackerjack/services/patterns/tool_output/pyright.py +67 -0
  347. crackerjack/services/patterns/tool_output/ruff.py +44 -0
  348. crackerjack/services/patterns/url_sanitization.py +114 -0
  349. crackerjack/services/patterns/utilities.py +42 -0
  350. crackerjack/services/patterns/utils.py +339 -0
  351. crackerjack/services/patterns/validation.py +46 -0
  352. crackerjack/services/patterns/versioning.py +62 -0
  353. crackerjack/services/predictive_analytics.py +21 -8
  354. crackerjack/services/profiler.py +280 -0
  355. crackerjack/services/quality/README.md +415 -0
  356. crackerjack/services/quality/__init__.py +11 -0
  357. crackerjack/services/quality/anomaly_detector.py +392 -0
  358. crackerjack/services/quality/pattern_cache.py +333 -0
  359. crackerjack/services/quality/pattern_detector.py +479 -0
  360. crackerjack/services/quality/qa_orchestrator.py +491 -0
  361. crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
  362. crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
  363. crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
  364. crackerjack/services/regex_patterns.py +58 -2987
  365. crackerjack/services/regex_utils.py +55 -29
  366. crackerjack/services/secure_status_formatter.py +42 -15
  367. crackerjack/services/secure_subprocess.py +35 -2
  368. crackerjack/services/security.py +16 -8
  369. crackerjack/services/server_manager.py +40 -51
  370. crackerjack/services/smart_scheduling.py +46 -6
  371. crackerjack/services/status_authentication.py +3 -3
  372. crackerjack/services/thread_safe_status_collector.py +1 -0
  373. crackerjack/services/tool_filter.py +368 -0
  374. crackerjack/services/tool_version_service.py +9 -5
  375. crackerjack/services/unified_config.py +43 -351
  376. crackerjack/services/vector_store.py +689 -0
  377. crackerjack/services/version_analyzer.py +6 -4
  378. crackerjack/services/version_checker.py +14 -8
  379. crackerjack/services/zuban_lsp_service.py +5 -4
  380. crackerjack/slash_commands/README.md +11 -0
  381. crackerjack/slash_commands/init.md +2 -12
  382. crackerjack/slash_commands/run.md +84 -50
  383. crackerjack/tools/README.md +11 -0
  384. crackerjack/tools/__init__.py +30 -0
  385. crackerjack/tools/_git_utils.py +105 -0
  386. crackerjack/tools/check_added_large_files.py +139 -0
  387. crackerjack/tools/check_ast.py +105 -0
  388. crackerjack/tools/check_json.py +103 -0
  389. crackerjack/tools/check_jsonschema.py +297 -0
  390. crackerjack/tools/check_toml.py +103 -0
  391. crackerjack/tools/check_yaml.py +110 -0
  392. crackerjack/tools/codespell_wrapper.py +72 -0
  393. crackerjack/tools/end_of_file_fixer.py +202 -0
  394. crackerjack/tools/format_json.py +128 -0
  395. crackerjack/tools/mdformat_wrapper.py +114 -0
  396. crackerjack/tools/trailing_whitespace.py +198 -0
  397. crackerjack/tools/validate_regex_patterns.py +7 -3
  398. crackerjack/ui/README.md +11 -0
  399. crackerjack/ui/dashboard_renderer.py +28 -0
  400. crackerjack/ui/templates/README.md +11 -0
  401. crackerjack/utils/console_utils.py +13 -0
  402. crackerjack/utils/dependency_guard.py +230 -0
  403. crackerjack/utils/retry_utils.py +275 -0
  404. crackerjack/workflows/README.md +590 -0
  405. crackerjack/workflows/__init__.py +46 -0
  406. crackerjack/workflows/actions.py +811 -0
  407. crackerjack/workflows/auto_fix.py +444 -0
  408. crackerjack/workflows/container_builder.py +499 -0
  409. crackerjack/workflows/definitions.py +443 -0
  410. crackerjack/workflows/engine.py +177 -0
  411. crackerjack/workflows/event_bridge.py +242 -0
  412. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
  413. crackerjack-0.45.2.dist-info/RECORD +478 -0
  414. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
  415. crackerjack/managers/test_manager_backup.py +0 -1075
  416. crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
  417. crackerjack/mixins/__init__.py +0 -3
  418. crackerjack/mixins/error_handling.py +0 -145
  419. crackerjack/services/config.py +0 -358
  420. crackerjack/ui/server_panels.py +0 -125
  421. crackerjack-0.37.9.dist-info/RECORD +0 -231
  422. /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
  423. /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
  424. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
  425. {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,185 @@
1
+ """
2
+ Enhanced proactive agent that integrates Claude Code external agent consultation.
3
+
4
+ This module extends the base ProactiveAgent to consult with Claude Code's external
5
+ agents (like crackerjack-architect, python-pro, security-auditor) when handling
6
+ complex issues that require specialized expertise.
7
+ """
8
+
9
+ import typing as t
10
+ from abc import abstractmethod
11
+
12
+ from .base import AgentContext, FixResult, Issue
13
+ from .claude_code_bridge import ClaudeCodeBridge
14
+ from .proactive_agent import ProactiveAgent
15
+
16
+
17
+ class EnhancedProactiveAgent(ProactiveAgent):
18
+ """
19
+ Proactive agent enhanced with Claude Code external agent consultation.
20
+
21
+ This agent follows the standard crackerjack agent pattern but adds intelligent
22
+ consultation with external Claude Code agents for complex scenarios that
23
+ require specialized expertise.
24
+ """
25
+
26
+ def __init__(self, context: AgentContext) -> None:
27
+ super().__init__(context)
28
+ self.claude_bridge = ClaudeCodeBridge(context)
29
+ self._external_consultation_enabled = True
30
+
31
+ def enable_external_consultation(self, enabled: bool = True) -> None:
32
+ """Enable or disable external Claude Code agent consultation."""
33
+ self._external_consultation_enabled = enabled
34
+
35
+ async def _execute_with_plan(
36
+ self, issue: Issue, plan: dict[str, t.Any]
37
+ ) -> FixResult:
38
+ """
39
+ Execute fix with plan, consulting external agents when appropriate.
40
+
41
+ This method enhances the base implementation by:
42
+ 1. First attempting the internal fix
43
+ 2. Evaluating if external consultation would improve the result
44
+ 3. Consulting with relevant Claude Code agents
45
+ 4. Combining internal and external guidance for better results
46
+ """
47
+ # First, get the internal fix result
48
+ internal_result = await self._execute_internal_fix(issue, plan)
49
+
50
+ # Determine if we should consult external agents
51
+ if not self._should_consult_external_agents(issue, internal_result, plan):
52
+ return internal_result
53
+
54
+ # Consult with relevant external agents
55
+ external_consultations = await self._consult_external_agents(issue, plan)
56
+
57
+ # Enhance the result with external guidance
58
+ enhanced_result = self._combine_internal_and_external_results(
59
+ internal_result, external_consultations
60
+ )
61
+
62
+ return enhanced_result
63
+
64
+ async def _execute_internal_fix(
65
+ self, issue: Issue, plan: dict[str, t.Any]
66
+ ) -> FixResult:
67
+ """Execute the internal fix using the built-in agent logic."""
68
+ # This calls the concrete agent's analyze_and_fix implementation
69
+ return await self.analyze_and_fix(issue)
70
+
71
+ def _should_consult_external_agents(
72
+ self, issue: Issue, internal_result: FixResult, plan: dict[str, t.Any]
73
+ ) -> bool:
74
+ """Determine if external consultation would be beneficial."""
75
+ if not self._external_consultation_enabled:
76
+ return False
77
+
78
+ # Consult external agents if:
79
+ # 1. Internal result has low confidence
80
+ # 2. Issue is complex and requires specialized expertise
81
+ # 3. Plan strategy indicates external specialist guidance
82
+ return (
83
+ self.claude_bridge.should_consult_external_agent(
84
+ issue, internal_result.confidence
85
+ )
86
+ or plan.get("strategy") == "external_specialist_guided"
87
+ or not internal_result.success
88
+ )
89
+
90
+ async def _consult_external_agents(
91
+ self, issue: Issue, plan: dict[str, t.Any]
92
+ ) -> list[dict[str, t.Any]]:
93
+ """Consult with relevant external Claude Code agents."""
94
+ recommended_agents = self.claude_bridge.get_recommended_external_agents(issue)
95
+ consultations = []
96
+
97
+ # Limit to top 2 agents to avoid overwhelming the system
98
+ for agent_name in recommended_agents[:2]:
99
+ if self.claude_bridge.verify_agent_availability(agent_name):
100
+ consultation = await self.claude_bridge.consult_external_agent(
101
+ issue, agent_name, {"plan": plan}
102
+ )
103
+ if consultation.get("status") == "success":
104
+ consultations.append(consultation)
105
+
106
+ return consultations
107
+
108
+ def _combine_internal_and_external_results(
109
+ self, internal_result: FixResult, external_consultations: list[dict[str, t.Any]]
110
+ ) -> FixResult:
111
+ """Combine internal fix result with external agent consultations."""
112
+ if not external_consultations:
113
+ return internal_result
114
+
115
+ # Use the bridge to create an enhanced result
116
+ enhanced_result = self.claude_bridge.create_enhanced_fix_result(
117
+ internal_result, external_consultations
118
+ )
119
+
120
+ # Add metadata about external consultation
121
+ enhanced_result.recommendations.insert(
122
+ 0,
123
+ f"Enhanced with consultation from {len(external_consultations)} Claude Code agents",
124
+ )
125
+
126
+ return enhanced_result
127
+
128
+ async def plan_before_action(self, issue: Issue) -> dict[str, t.Any]:
129
+ """
130
+ Create a plan that considers both internal and external capabilities.
131
+
132
+ This method should be implemented by concrete agents to define their
133
+ specific planning logic while having access to external consultation.
134
+ """
135
+ # Default implementation - concrete agents should override this
136
+ if self.claude_bridge.should_consult_external_agent(issue, 0.0):
137
+ return {
138
+ "strategy": "external_specialist_guided",
139
+ "approach": "consult_claude_code_experts",
140
+ "patterns": ["external_guidance"],
141
+ "validation": ["verify_with_external_agents"],
142
+ }
143
+
144
+ return {
145
+ "strategy": "internal_pattern_based",
146
+ "approach": "apply_internal_logic",
147
+ "patterns": ["standard_patterns"],
148
+ "validation": ["run_internal_checks"],
149
+ }
150
+
151
+ @abstractmethod
152
+ async def analyze_and_fix(self, issue: Issue) -> FixResult:
153
+ """
154
+ Concrete agents must implement their specific fix logic.
155
+
156
+ This method contains the core agent-specific logic for analyzing
157
+ and fixing issues. The enhanced execution framework will automatically
158
+ handle external consultation when appropriate.
159
+ """
160
+ pass
161
+
162
+
163
+ # Convenience function to enhance existing agents
164
+ def enhance_agent_with_claude_code_bridge(
165
+ agent_class: type[ProactiveAgent],
166
+ ) -> type[EnhancedProactiveAgent]:
167
+ """
168
+ Enhance an existing ProactiveAgent class with Claude Code external consultation.
169
+
170
+ This function creates a new class that inherits from both the original agent
171
+ and EnhancedProactiveAgent, providing external consultation capabilities
172
+ while preserving the original agent's logic.
173
+ """
174
+
175
+ class EnhancedAgent(EnhancedProactiveAgent, agent_class): # type: ignore[misc,valid-type]
176
+ def __init__(self, context: AgentContext) -> None:
177
+ # Initialize both parent classes
178
+ EnhancedProactiveAgent.__init__(self, context)
179
+ agent_class.__init__(self, context)
180
+
181
+ # Preserve the original class name and metadata
182
+ EnhancedAgent.__name__ = f"Enhanced{agent_class.__name__}"
183
+ EnhancedAgent.__qualname__ = f"Enhanced{agent_class.__qualname__}"
184
+
185
+ return EnhancedAgent
@@ -0,0 +1,53 @@
1
+ """Shared error-handling middleware helpers for agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typing as t
6
+ from functools import wraps
7
+
8
+ from acb.console import Console
9
+
10
+ from crackerjack.agents.base import FixResult, Issue, SubAgent
11
+
12
+ if t.TYPE_CHECKING: # pragma: no cover - typing helpers
13
+ from crackerjack.agents.coordinator import AgentCoordinator
14
+
15
+
16
+ def agent_error_boundary(
17
+ func: t.Callable[..., t.Awaitable[FixResult]],
18
+ ) -> t.Callable[..., t.Awaitable[FixResult]]:
19
+ """Decorator that centralizes error handling for agent execution.
20
+
21
+ Ensures all agent failures are logged consistently and converted into a
22
+ ``FixResult`` that upstream orchestrators can reason about without custom
23
+ ``try``/``except`` blocks.
24
+ """
25
+
26
+ @wraps(func)
27
+ async def wrapper(
28
+ self: AgentCoordinator,
29
+ agent: SubAgent,
30
+ issue: Issue,
31
+ *args: t.Any,
32
+ **kwargs: t.Any,
33
+ ) -> FixResult:
34
+ try:
35
+ return await func(self, agent, issue, *args, **kwargs)
36
+ except Exception as exc: # pragma: no cover - exercised via decorator tests
37
+ console: Console | None = getattr(self.context, "console", None)
38
+ message = f"{agent.name} encountered an error while processing issue {issue.id}: {exc}"
39
+ self.logger.exception(message, exc_info=exc)
40
+ if console is not None:
41
+ console.print(f"[red]{message}[/red]")
42
+
43
+ return FixResult(
44
+ success=False,
45
+ confidence=0.0,
46
+ remaining_issues=[message],
47
+ recommendations=[
48
+ "Review agent logs for stack trace",
49
+ "Re-run with --debug to capture additional context",
50
+ ],
51
+ )
52
+
53
+ return wrapper
@@ -134,10 +134,9 @@ class FormattingAgent(SubAgent):
134
134
  [
135
135
  "uv",
136
136
  "run",
137
- "pre-commit",
138
- "run",
139
- "trailing-whitespace",
140
- "--all-files",
137
+ "python",
138
+ "-m",
139
+ "crackerjack.tools.trailing_whitespace",
141
140
  ],
142
141
  )
143
142
 
@@ -149,10 +148,9 @@ class FormattingAgent(SubAgent):
149
148
  [
150
149
  "uv",
151
150
  "run",
152
- "pre-commit",
153
- "run",
154
- "end-of-file-fixer",
155
- "--all-files",
151
+ "python",
152
+ "-m",
153
+ "crackerjack.tools.end_of_file_fixer",
156
154
  ],
157
155
  )
158
156
 
@@ -0,0 +1,9 @@
1
+ """Package for helper modules used by crackerjack agents.
2
+
3
+ This package contains supporting modules for various agent types:
4
+ - performance: Performance analysis and optimization helpers
5
+ - refactoring: Code refactoring utilities
6
+ - test_creation: Test generation helpers
7
+ """
8
+
9
+ # This file makes the directory a proper Python package
@@ -0,0 +1,22 @@
1
+ """Performance optimization helpers for the PerformanceAgent.
2
+
3
+ This module provides specialized helpers for detecting and fixing performance
4
+ anti-patterns while maintaining the AgentContext pattern.
5
+ """
6
+
7
+ from .performance_ast_analyzer import PerformanceASTAnalyzer
8
+ from .performance_pattern_detector import (
9
+ ListOpAnalyzer,
10
+ NestedLoopAnalyzer,
11
+ PerformancePatternDetector,
12
+ )
13
+ from .performance_recommender import OptimizationResult, PerformanceRecommender
14
+
15
+ __all__ = [
16
+ "PerformancePatternDetector",
17
+ "PerformanceASTAnalyzer",
18
+ "PerformanceRecommender",
19
+ "OptimizationResult",
20
+ "NestedLoopAnalyzer",
21
+ "ListOpAnalyzer",
22
+ ]
@@ -0,0 +1,357 @@
1
+ """AST analysis for performance complexity detection."""
2
+
3
+ import ast
4
+ import typing as t
5
+
6
+ from ...base import AgentContext
7
+
8
+
9
+ class PerformanceASTAnalyzer:
10
+ """Analyzes Python AST for performance-related complexity issues."""
11
+
12
+ def __init__(self, context: AgentContext) -> None:
13
+ """Initialize analyzer with agent context.
14
+
15
+ Args:
16
+ context: AgentContext for logging and operations
17
+ """
18
+ self.context = context
19
+
20
+ def extract_performance_critical_functions(
21
+ self, content: str
22
+ ) -> list[dict[str, t.Any]]:
23
+ """Extract functions likely to have performance issues.
24
+
25
+ Args:
26
+ content: File content
27
+
28
+ Returns:
29
+ List of performance-critical functions
30
+ """
31
+ functions: list[dict[str, t.Any]] = []
32
+ lines = content.split("\n")
33
+ current_function = None
34
+
35
+ for i, line in enumerate(lines):
36
+ stripped = line.strip()
37
+
38
+ if self._is_empty_or_comment_line(stripped):
39
+ if current_function:
40
+ current_function["body"] += line + "\n"
41
+ continue
42
+
43
+ indent = len(line) - len(line.lstrip())
44
+
45
+ if self._is_function_definition(stripped):
46
+ current_function = self._handle_function_definition(
47
+ current_function, functions, stripped, indent, i
48
+ )
49
+ elif current_function:
50
+ current_function = self._handle_function_body_line(
51
+ current_function, functions, line, stripped, indent, i
52
+ )
53
+
54
+ self._handle_last_function(current_function, functions, len(lines))
55
+ return functions
56
+
57
+ @staticmethod
58
+ def _is_empty_or_comment_line(stripped: str) -> bool:
59
+ """Check if line is empty or comment.
60
+
61
+ Args:
62
+ stripped: Stripped line
63
+
64
+ Returns:
65
+ True if empty or comment
66
+ """
67
+ return not stripped or stripped.startswith("#")
68
+
69
+ @staticmethod
70
+ def _is_function_definition(stripped: str) -> bool:
71
+ """Check if line is function definition.
72
+
73
+ Args:
74
+ stripped: Stripped line
75
+
76
+ Returns:
77
+ True if function definition
78
+ """
79
+ return stripped.startswith("def ") and "(" in stripped
80
+
81
+ def _handle_function_definition(
82
+ self,
83
+ current_function: dict[str, t.Any] | None,
84
+ functions: list[dict[str, t.Any]],
85
+ stripped: str,
86
+ indent: int,
87
+ line_number: int,
88
+ ) -> dict[str, t.Any]:
89
+ """Handle function definition line.
90
+
91
+ Args:
92
+ current_function: Current function being parsed
93
+ functions: List of functions
94
+ stripped: Stripped line
95
+ indent: Indentation level
96
+ line_number: Line number
97
+
98
+ Returns:
99
+ New function dict
100
+ """
101
+ if current_function and self._is_performance_critical(current_function):
102
+ self._finalize_function(current_function, functions, line_number)
103
+
104
+ func_name = stripped.split("(")[0].replace("def ", "").strip()
105
+ return {
106
+ "name": func_name,
107
+ "signature": stripped,
108
+ "start_line": line_number + 1,
109
+ "body": "",
110
+ "indent_level": indent,
111
+ }
112
+
113
+ def _handle_function_body_line(
114
+ self,
115
+ current_function: dict[str, t.Any],
116
+ functions: list[dict[str, t.Any]],
117
+ line: str,
118
+ stripped: str,
119
+ indent: int,
120
+ line_number: int,
121
+ ) -> dict[str, t.Any] | None:
122
+ """Handle line within function body.
123
+
124
+ Args:
125
+ current_function: Current function
126
+ functions: Functions list
127
+ line: Full line
128
+ stripped: Stripped line
129
+ indent: Indent level
130
+ line_number: Line number
131
+
132
+ Returns:
133
+ Updated current function or None
134
+ """
135
+ if self._is_still_in_function(current_function, indent, stripped):
136
+ current_function["body"] += line + "\n"
137
+ return current_function
138
+ else:
139
+ if self._is_performance_critical(current_function):
140
+ self._finalize_function(current_function, functions, line_number)
141
+ return None
142
+
143
+ @staticmethod
144
+ def _is_still_in_function(
145
+ current_function: dict[str, t.Any], indent: int, stripped: str
146
+ ) -> bool:
147
+ """Check if still inside function.
148
+
149
+ Args:
150
+ current_function: Current function
151
+ indent: Indent level
152
+ stripped: Stripped line
153
+
154
+ Returns:
155
+ True if still inside
156
+ """
157
+ return indent > current_function["indent_level"] or (
158
+ indent == current_function["indent_level"]
159
+ and stripped.startswith(('"', "'", "@"))
160
+ )
161
+
162
+ def _finalize_function(
163
+ self,
164
+ function: dict[str, t.Any],
165
+ functions: list[dict[str, t.Any]],
166
+ end_line: int,
167
+ ) -> None:
168
+ """Finalize function and add to results.
169
+
170
+ Args:
171
+ function: Function to finalize
172
+ functions: Functions list
173
+ end_line: End line number
174
+ """
175
+ function["end_line"] = end_line
176
+ function["body_sample"] = function["body"][:300]
177
+ function["estimated_complexity"] = self._estimate_complexity(function["body"])
178
+ functions.append(function)
179
+
180
+ def _handle_last_function(
181
+ self,
182
+ current_function: dict[str, t.Any] | None,
183
+ functions: list[dict[str, t.Any]],
184
+ total_lines: int,
185
+ ) -> None:
186
+ """Handle last function in file.
187
+
188
+ Args:
189
+ current_function: Last function
190
+ functions: Functions list
191
+ total_lines: Total lines
192
+ """
193
+ if current_function and self._is_performance_critical(current_function):
194
+ self._finalize_function(current_function, functions, total_lines)
195
+
196
+ @staticmethod
197
+ def _is_performance_critical(function_info: dict[str, t.Any]) -> bool:
198
+ """Determine if function is performance-critical.
199
+
200
+ Args:
201
+ function_info: Function info
202
+
203
+ Returns:
204
+ True if performance-critical
205
+ """
206
+ body = function_info.get("body", "")
207
+ name = function_info.get("name", "")
208
+
209
+ performance_indicators = [
210
+ "for " in body
211
+ and len([line for line in body.split("\n") if "for " in line]) > 1,
212
+ "while " in body,
213
+ body.count("for ") > 0 and len(body) > 200,
214
+ any(pattern in body for pattern in (".append(", "+=", ".extend(", "len(")),
215
+ any(
216
+ pattern in name
217
+ for pattern in (
218
+ "process",
219
+ "analyze",
220
+ "compute",
221
+ "calculate",
222
+ "optimize",
223
+ )
224
+ ),
225
+ "range(" in body and ("1000" in body or "len(" in body),
226
+ ]
227
+
228
+ return any(performance_indicators)
229
+
230
+ @staticmethod
231
+ def _estimate_complexity(body: str) -> int:
232
+ """Estimate computational complexity of function.
233
+
234
+ Args:
235
+ body: Function body
236
+
237
+ Returns:
238
+ Complexity score
239
+ """
240
+ complexity = 1
241
+
242
+ nested_for_loops = 0
243
+ for_depth = 0
244
+ lines = body.split("\n")
245
+
246
+ for line in lines:
247
+ stripped = line.strip()
248
+ if "for " in stripped:
249
+ for_depth += 1
250
+ nested_for_loops = max(nested_for_loops, for_depth)
251
+ elif (
252
+ stripped
253
+ and not stripped.startswith("#")
254
+ and len(line) - len(line.lstrip()) == 0
255
+ ):
256
+ for_depth = 0
257
+
258
+ complexity = max(complexity, nested_for_loops)
259
+
260
+ if ".sort(" in body or "sorted(" in body:
261
+ complexity += 1
262
+ if body.count("len(") > 5:
263
+ complexity += 1
264
+ if ".index(" in body or ".find(" in body:
265
+ complexity += 1
266
+
267
+ return complexity
268
+
269
+ def analyze_performance_patterns(
270
+ self, semantic_insight: t.Any, current_func: dict[str, t.Any]
271
+ ) -> dict[str, t.Any]:
272
+ """Analyze semantic patterns for performance insights.
273
+
274
+ Args:
275
+ semantic_insight: Semantic insight from analysis
276
+ current_func: Current function
277
+
278
+ Returns:
279
+ Analysis dict
280
+ """
281
+ analysis: dict[str, t.Any] = {
282
+ "issues_found": False,
283
+ "optimization_suggestion": "Consider reviewing similar implementations for consistency",
284
+ "pattern_insights": [],
285
+ }
286
+
287
+ if semantic_insight.high_confidence_matches > 0:
288
+ analysis["issues_found"] = True
289
+ analysis["pattern_insights"].append(
290
+ f"Found {semantic_insight.high_confidence_matches} highly similar implementations"
291
+ )
292
+
293
+ performance_concerns = []
294
+ for pattern in semantic_insight.related_patterns:
295
+ content = pattern.get("content", "").lower()
296
+ if any(
297
+ concern in content for concern in ("for", "while", "+=", "append")
298
+ ):
299
+ performance_concerns.append(pattern["file_path"])
300
+
301
+ if performance_concerns:
302
+ analysis["optimization_suggestion"] = (
303
+ f"Performance review needed: {len(performance_concerns)} similar functions "
304
+ f"may benefit from the same optimization approach"
305
+ )
306
+ analysis["pattern_insights"].append(
307
+ f"Similar performance patterns found in: {', '.join(list(set(performance_concerns))[:3])}"
308
+ )
309
+
310
+ return analysis
311
+
312
+ def analyze_code_metrics(self, tree: ast.AST) -> dict[str, t.Any]:
313
+ """Analyze code metrics from AST.
314
+
315
+ Args:
316
+ tree: AST tree
317
+
318
+ Returns:
319
+ Metrics dict
320
+ """
321
+ metrics: dict[str, t.Any] = {
322
+ "total_functions": 0,
323
+ "total_classes": 0,
324
+ "average_function_length": 0,
325
+ "max_nesting_depth": 0,
326
+ "high_complexity_functions": [],
327
+ }
328
+
329
+ class MetricsCollector(ast.NodeVisitor):
330
+ def __init__(self) -> None:
331
+ self.function_count = 0
332
+ self.class_count = 0
333
+ self.function_lengths: list[int] = []
334
+ self.max_depth = 0
335
+
336
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
337
+ self.function_count += 1
338
+ length = (node.end_lineno or node.lineno) - node.lineno
339
+ self.function_lengths.append(length)
340
+ self.generic_visit(node)
341
+
342
+ def visit_ClassDef(self, node: ast.ClassDef) -> None:
343
+ self.class_count += 1
344
+ self.generic_visit(node)
345
+
346
+ collector = MetricsCollector()
347
+ collector.visit(tree)
348
+
349
+ metrics["total_functions"] = collector.function_count
350
+ metrics["total_classes"] = collector.class_count
351
+
352
+ if collector.function_lengths:
353
+ metrics["average_function_length"] = sum(collector.function_lengths) / len(
354
+ collector.function_lengths
355
+ )
356
+
357
+ return metrics