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,325 @@
1
+ import time
2
+ import typing as t
3
+ from pathlib import Path
4
+
5
+ from .base import (
6
+ AgentContext,
7
+ FixResult,
8
+ Issue,
9
+ IssueType,
10
+ SubAgent,
11
+ agent_registry,
12
+ )
13
+ from .helpers.performance.performance_ast_analyzer import PerformanceASTAnalyzer
14
+ from .helpers.performance.performance_pattern_detector import PerformancePatternDetector
15
+ from .helpers.performance.performance_recommender import PerformanceRecommender
16
+ from .semantic_helpers import (
17
+ SemanticInsight,
18
+ create_semantic_enhancer,
19
+ get_session_enhanced_recommendations,
20
+ )
21
+
22
+
23
+ class PerformanceAgent(SubAgent):
24
+ """Agent for detecting and fixing performance issues.
25
+
26
+ Enhanced with semantic context to detect performance patterns across
27
+ the codebase and find similar bottlenecks that may not be immediately visible.
28
+ """
29
+
30
+ def __init__(self, context: AgentContext) -> None:
31
+ super().__init__(context)
32
+ self.semantic_enhancer = create_semantic_enhancer(context.project_path)
33
+ self.semantic_insights: dict[str, SemanticInsight] = {}
34
+ self.performance_metrics: dict[str, t.Any] = {}
35
+
36
+ # Initialize helper modules
37
+ self._pattern_detector = PerformancePatternDetector(context)
38
+ self._ast_analyzer = PerformanceASTAnalyzer(context)
39
+ self._recommender = PerformanceRecommender(context)
40
+
41
+ def get_supported_types(self) -> set[IssueType]:
42
+ return {IssueType.PERFORMANCE}
43
+
44
+ async def can_handle(self, issue: Issue) -> float:
45
+ if issue.type != IssueType.PERFORMANCE:
46
+ return 0.0
47
+
48
+ confidence = 0.85
49
+ message_lower = issue.message.lower()
50
+
51
+ if any(
52
+ pattern in message_lower
53
+ for pattern in (
54
+ "nested loop",
55
+ "o(n²)",
56
+ "string concatenation",
57
+ "list[t.Any] concatenation",
58
+ "inefficient",
59
+ "complexity",
60
+ )
61
+ ):
62
+ confidence = 0.9
63
+
64
+ return confidence
65
+
66
+ async def analyze_and_fix(self, issue: Issue) -> FixResult:
67
+ self.log(f"Analyzing performance issue: {issue.message}")
68
+ start_time = time.time()
69
+
70
+ validation_result = self._validate_performance_issue(issue)
71
+ if validation_result:
72
+ return validation_result
73
+
74
+ if issue.file_path is None:
75
+ return FixResult(
76
+ success=False,
77
+ confidence=0.0,
78
+ remaining_issues=["No file path provided for performance issue"],
79
+ )
80
+
81
+ file_path = Path(issue.file_path)
82
+
83
+ try:
84
+ result = await self._process_performance_optimization(file_path)
85
+
86
+ analysis_time = time.time() - start_time
87
+ self.performance_metrics[str(file_path)] = {
88
+ "analysis_duration": analysis_time,
89
+ "optimizations_applied": result.fixes_applied,
90
+ "timestamp": time.time(),
91
+ }
92
+
93
+ if result.success and result.fixes_applied:
94
+ stats_summary = self._generate_optimization_summary()
95
+ result.recommendations = result.recommendations + [stats_summary]
96
+
97
+ return result
98
+ except Exception as e:
99
+ return self._create_performance_error_result(e)
100
+
101
+ @staticmethod
102
+ def _validate_performance_issue(issue: Issue) -> FixResult | None:
103
+ if not issue.file_path:
104
+ return FixResult(
105
+ success=False,
106
+ confidence=0.0,
107
+ remaining_issues=["No file path specified for performance issue"],
108
+ )
109
+
110
+ file_path = Path(issue.file_path)
111
+ if not file_path.exists():
112
+ return FixResult(
113
+ success=False,
114
+ confidence=0.0,
115
+ remaining_issues=[f"File not found: {file_path}"],
116
+ )
117
+
118
+ return None
119
+
120
+ async def _process_performance_optimization(self, file_path: Path) -> FixResult:
121
+ content = self.context.get_file_content(file_path)
122
+ if not content:
123
+ return FixResult(
124
+ success=False,
125
+ confidence=0.0,
126
+ remaining_issues=[f"Could not read file: {file_path}"],
127
+ )
128
+
129
+ # Detect traditional performance issues using helper
130
+ performance_issues = self._pattern_detector.detect_performance_issues(
131
+ content, file_path
132
+ )
133
+
134
+ # Enhance with semantic performance pattern detection
135
+ semantic_issues = await self._detect_semantic_performance_issues(
136
+ content, file_path
137
+ )
138
+ performance_issues.extend(semantic_issues)
139
+
140
+ if not performance_issues:
141
+ return FixResult(
142
+ success=True,
143
+ confidence=0.7,
144
+ recommendations=["No performance issues detected"],
145
+ )
146
+
147
+ return await self._apply_and_save_optimizations(
148
+ file_path,
149
+ content,
150
+ performance_issues,
151
+ )
152
+
153
+ async def _apply_and_save_optimizations(
154
+ self,
155
+ file_path: Path,
156
+ content: str,
157
+ issues: list[dict[str, t.Any]],
158
+ ) -> FixResult:
159
+ # Delegate to recommender helper
160
+ optimized_content = self._recommender.apply_performance_optimizations(
161
+ content, issues
162
+ )
163
+
164
+ if optimized_content == content:
165
+ return self._create_no_optimization_result()
166
+
167
+ success = self.context.write_file_content(file_path, optimized_content)
168
+ if not success:
169
+ return FixResult(
170
+ success=False,
171
+ confidence=0.0,
172
+ remaining_issues=[f"Failed to write optimized file: {file_path}"],
173
+ )
174
+
175
+ # Get summary from recommender
176
+ stats_summary = self._recommender.generate_optimization_summary()
177
+
178
+ return FixResult(
179
+ success=True,
180
+ confidence=0.8,
181
+ fixes_applied=[
182
+ f"Optimized {len(issues)} performance issues",
183
+ "Applied algorithmic improvements",
184
+ stats_summary,
185
+ ],
186
+ files_modified=[str(file_path)],
187
+ recommendations=await self._generate_enhanced_recommendations(issues),
188
+ )
189
+
190
+ @staticmethod
191
+ def _create_no_optimization_result() -> FixResult:
192
+ return FixResult(
193
+ success=False,
194
+ confidence=0.6,
195
+ remaining_issues=["Could not automatically optimize performance"],
196
+ recommendations=[
197
+ "Manual optimization required",
198
+ "Consider algorithm complexity improvements",
199
+ "Review data structure choices",
200
+ "Profile code execution for bottlenecks",
201
+ ],
202
+ )
203
+
204
+ @staticmethod
205
+ def _create_performance_error_result(error: Exception) -> FixResult:
206
+ return FixResult(
207
+ success=False,
208
+ confidence=0.0,
209
+ remaining_issues=[f"Error processing file: {error}"],
210
+ )
211
+
212
+ async def _detect_semantic_performance_issues(
213
+ self, content: str, file_path: Path
214
+ ) -> list[dict[str, t.Any]]:
215
+ """Detect performance issues using semantic analysis of similar code patterns."""
216
+ issues = []
217
+
218
+ try:
219
+ # Delegate to AST analyzer helper
220
+ critical_functions = (
221
+ self._ast_analyzer.extract_performance_critical_functions(content)
222
+ )
223
+
224
+ for func in critical_functions:
225
+ if (
226
+ func["estimated_complexity"] > 2
227
+ ): # Focus on potentially complex functions
228
+ # Search for similar performance patterns
229
+ insight = await self.semantic_enhancer.find_similar_patterns(
230
+ f"performance {func['signature']} {func['body_sample']}",
231
+ current_file=file_path,
232
+ min_similarity=0.6,
233
+ max_results=8,
234
+ )
235
+
236
+ if insight.total_matches > 1:
237
+ # Delegate analysis to AST analyzer helper
238
+ analysis = self._ast_analyzer.analyze_performance_patterns(
239
+ insight, func
240
+ )
241
+ if analysis["issues_found"]:
242
+ issues.append(
243
+ {
244
+ "type": "semantic_performance_pattern",
245
+ "function": func,
246
+ "similar_patterns": insight.related_patterns,
247
+ "performance_analysis": analysis,
248
+ "confidence_score": insight.high_confidence_matches
249
+ / max(insight.total_matches, 1),
250
+ "suggestion": analysis["optimization_suggestion"],
251
+ }
252
+ )
253
+
254
+ # Store insight for recommendation enhancement
255
+ self.semantic_insights[func["name"]] = insight
256
+
257
+ except Exception as e:
258
+ self.log(f"Warning: Semantic performance analysis failed: {e}")
259
+
260
+ return issues
261
+
262
+ def _generate_optimization_summary(self) -> str:
263
+ """Generate a summary of optimization results."""
264
+ total_files = len(self.performance_metrics)
265
+ total_optimizations = sum(
266
+ metrics.get("optimizations_applied", 0)
267
+ for metrics in self.performance_metrics.values()
268
+ )
269
+
270
+ total_time = sum(
271
+ metrics.get("analysis_duration", 0)
272
+ for metrics in self.performance_metrics.values()
273
+ )
274
+
275
+ return (
276
+ f"Performance optimization summary: "
277
+ f"{total_optimizations} optimizations applied across {total_files} files "
278
+ f"in {total_time:.2f}s total"
279
+ )
280
+
281
+ async def _generate_enhanced_recommendations(
282
+ self, issues: list[dict[str, t.Any]]
283
+ ) -> list[str]:
284
+ """Generate enhanced recommendations including semantic insights."""
285
+ recommendations = ["Test performance improvements with benchmarks"]
286
+
287
+ # Add semantic insights
288
+ semantic_issues = [
289
+ issue for issue in issues if issue["type"] == "semantic_performance_pattern"
290
+ ]
291
+ if semantic_issues:
292
+ recommendations.append(
293
+ f"Semantic analysis found {len(semantic_issues)} similar performance patterns "
294
+ "across codebase - consider applying optimizations consistently"
295
+ )
296
+
297
+ # Store insights for session continuity
298
+ for issue in semantic_issues:
299
+ if "semantic_insight" in issue:
300
+ await self.semantic_enhancer.store_insight_to_session(
301
+ issue["semantic_insight"], "PerformanceAgent"
302
+ )
303
+
304
+ # Enhance with session-stored insights
305
+ recommendations = await get_session_enhanced_recommendations(
306
+ recommendations, "PerformanceAgent", self.context.project_path
307
+ )
308
+
309
+ # Add insights from stored semantic analysis
310
+ for func_name, insight in self.semantic_insights.items():
311
+ if insight.high_confidence_matches > 0:
312
+ enhanced_recs = self.semantic_enhancer.enhance_recommendations(
313
+ [], # Start with empty list to get just semantic recommendations
314
+ insight,
315
+ )
316
+ recommendations.extend(enhanced_recs)
317
+
318
+ # Log semantic context for debugging
319
+ summary = self.semantic_enhancer.get_semantic_context_summary(insight)
320
+ self.log(f"Performance semantic context for {func_name}: {summary}")
321
+
322
+ return recommendations
323
+
324
+
325
+ agent_registry.register(PerformanceAgent)
@@ -0,0 +1,205 @@
1
+ import ast
2
+ import typing as t
3
+ from dataclasses import dataclass
4
+
5
+
6
+ @dataclass
7
+ class OptimizationResult:
8
+ lines: list[str]
9
+ modified: bool
10
+ optimization_description: str | None = None
11
+
12
+
13
+ class EnhancedNestedLoopAnalyzer(ast.NodeVisitor):
14
+ def __init__(self) -> None:
15
+ self.loop_stack: list[tuple[str, ast.AST, int]] = []
16
+ self.nested_loops: list[dict[str, t.Any]] = []
17
+ self.complexity_hotspots: list[dict[str, t.Any]] = []
18
+
19
+ def visit_For(self, node: ast.For) -> None:
20
+ self._process_loop_node(node, "nested_for_loop")
21
+
22
+ def visit_While(self, node: ast.While) -> None:
23
+ self._process_loop_node(node, "nested_while_loop")
24
+
25
+ def _process_loop_node(self, node: ast.For | ast.While, loop_type: str) -> None:
26
+ current_depth = len(self.loop_stack) + 1
27
+ self.loop_stack.append((loop_type.split("_")[1], node, current_depth))
28
+
29
+ if current_depth > 1:
30
+ loop_info = self._create_loop_info(node, loop_type, current_depth)
31
+ self.nested_loops.append(loop_info)
32
+ self._check_complexity_hotspot(loop_info, current_depth)
33
+
34
+ self.generic_visit(node)
35
+ self.loop_stack.pop()
36
+
37
+ def _create_loop_info(
38
+ self, node: ast.For | ast.While, loop_type: str, current_depth: int
39
+ ) -> dict[str, t.Any]:
40
+ loop_info: dict[str, t.Any] = {
41
+ "line_number": node.lineno,
42
+ "type": loop_type,
43
+ "depth": current_depth,
44
+ "complexity": f"O(n^{current_depth})",
45
+ "complexity_factor": self._calculate_complexity_factor(current_depth),
46
+ "priority": self._get_optimization_priority(current_depth),
47
+ "node": node,
48
+ }
49
+
50
+ if isinstance(node, ast.For):
51
+ loop_info["iterable"] = self._extract_iterable_info(node)
52
+
53
+ return loop_info
54
+
55
+ def _check_complexity_hotspot(
56
+ self, loop_info: dict[str, t.Any], current_depth: int
57
+ ) -> None:
58
+ if current_depth >= 3:
59
+ self.complexity_hotspots.append(
60
+ loop_info
61
+ | {
62
+ "severity": "high",
63
+ "suggestion": "Critical: Consider algorithmic improvements (memoization, caching, different data structures)",
64
+ }
65
+ )
66
+
67
+ def _calculate_complexity_factor(self, depth: int) -> int:
68
+ return depth**2
69
+
70
+ def _get_optimization_priority(self, depth: int) -> str:
71
+ if depth >= 4:
72
+ return "critical"
73
+ elif depth == 3:
74
+ return "high"
75
+ elif depth == 2:
76
+ return "medium"
77
+ return "low"
78
+
79
+ def _extract_iterable_info(self, node: ast.For) -> dict[str, t.Any]:
80
+ iterable_info = {"type": "unknown", "name": None}
81
+
82
+ if isinstance(node.iter, ast.Name):
83
+ iterable_info = {"type": "variable", "name": node.iter.id}
84
+ elif isinstance(node.iter, ast.Call) and isinstance(node.iter.func, ast.Name):
85
+ iterable_info = {
86
+ "type": "function_call",
87
+ "name": node.iter.func.id,
88
+ }
89
+ if node.iter.func.id == "range":
90
+ iterable_info["optimization_hint"] = (
91
+ "Consider list[t.Any] comprehension or vectorization"
92
+ )
93
+
94
+ return iterable_info
95
+
96
+
97
+ class EnhancedListOpAnalyzer(ast.NodeVisitor):
98
+ def __init__(self) -> None:
99
+ self.in_loop = False
100
+ self.loop_depth = 0
101
+ self.list_ops: list[dict[str, t.Any]] = []
102
+ self.current_loop_node: ast.For | ast.While | None = None
103
+
104
+ def visit_For(self, node: ast.For) -> None:
105
+ self._enter_loop_context(node)
106
+ self.generic_visit(node)
107
+ self._exit_loop_context()
108
+
109
+ def visit_While(self, node: ast.While) -> None:
110
+ self._enter_loop_context(node)
111
+ self.generic_visit(node)
112
+ self._exit_loop_context()
113
+
114
+ def visit_AugAssign(self, node: ast.AugAssign) -> None:
115
+ if self._should_analyze_aug_assign(node):
116
+ self._analyze_aug_assign_node(node)
117
+ self.generic_visit(node)
118
+
119
+ def _enter_loop_context(self, node: ast.For | ast.While) -> None:
120
+ self._old_state = (self.in_loop, self.loop_depth, self.current_loop_node)
121
+ self.in_loop = True
122
+ self.loop_depth += 1
123
+ self.current_loop_node = node
124
+
125
+ def _exit_loop_context(self) -> None:
126
+ self.in_loop, self.loop_depth, self.current_loop_node = self._old_state
127
+
128
+ def _should_analyze_aug_assign(self, node: ast.AugAssign) -> bool:
129
+ return self.in_loop and isinstance(node.op, ast.Add)
130
+
131
+ def _analyze_aug_assign_node(self, node: ast.AugAssign) -> None:
132
+ impact_factor = self._calculate_performance_impact()
133
+
134
+ if isinstance(node.value, ast.List):
135
+ self._handle_list_concat(node, impact_factor)
136
+ elif isinstance(node.value, ast.Name):
137
+ self._handle_variable_concat(node, impact_factor)
138
+
139
+ def _handle_list_concat(self, node: ast.AugAssign, impact_factor: int) -> None:
140
+ assert isinstance(node.value, ast.List)
141
+ list_size = len(node.value.elts)
142
+
143
+ self.list_ops.append(
144
+ {
145
+ "line_number": node.lineno,
146
+ "type": "list_concat_in_loop",
147
+ "pattern": f"list[t.Any] += [{list_size} items]",
148
+ "loop_depth": self.loop_depth,
149
+ "impact_factor": impact_factor,
150
+ "optimization": "append" if list_size == 1 else "extend",
151
+ "performance_gain": f"{impact_factor * 2}x"
152
+ if list_size > 1
153
+ else "2-3x",
154
+ }
155
+ )
156
+
157
+ def _handle_variable_concat(self, node: ast.AugAssign, impact_factor: int) -> None:
158
+ var_name = getattr(node.value, "id", "unknown")
159
+ self.list_ops.append(
160
+ {
161
+ "line_number": node.lineno,
162
+ "type": "list_concat_variable",
163
+ "pattern": f"list[t.Any] += {var_name}",
164
+ "loop_depth": self.loop_depth,
165
+ "impact_factor": impact_factor,
166
+ "optimization": "extend",
167
+ "performance_gain": f"{impact_factor * 3}x",
168
+ }
169
+ )
170
+
171
+ def _calculate_performance_impact(self) -> int:
172
+ base_impact = 2
173
+
174
+ if self.loop_depth > 1:
175
+ base_impact *= self.loop_depth**2
176
+
177
+ if self._is_hot_loop():
178
+ base_impact *= 5
179
+
180
+ return min(base_impact, 50)
181
+
182
+ def _is_hot_loop(self) -> bool:
183
+ if not (self.current_loop_node and isinstance(self.current_loop_node, ast.For)):
184
+ return False
185
+
186
+ return self._has_large_range_iterator()
187
+
188
+ def _has_large_range_iterator(self) -> bool:
189
+ if not isinstance(self.current_loop_node, ast.For):
190
+ return False
191
+
192
+ iter_node = self.current_loop_node.iter
193
+ if not (
194
+ isinstance(iter_node, ast.Call)
195
+ and isinstance(iter_node.func, ast.Name)
196
+ and iter_node.func.id == "range"
197
+ ):
198
+ return False
199
+
200
+ args = iter_node.args
201
+ if not (args and isinstance(args[0], ast.Constant)):
202
+ return False
203
+
204
+ value = args[0].value
205
+ return isinstance(value, int | float) and value > 100
@@ -0,0 +1,55 @@
1
+ import typing as t
2
+ from abc import abstractmethod
3
+
4
+ from .base import AgentContext, FixResult, Issue, SubAgent
5
+
6
+
7
+ class ProactiveAgent(SubAgent):
8
+ def __init__(self, context: AgentContext) -> None:
9
+ super().__init__(context)
10
+ self._planning_cache: dict[str, dict[str, t.Any]] = {}
11
+ self._pattern_cache: dict[str, t.Any] = {}
12
+
13
+ @abstractmethod
14
+ async def plan_before_action(self, issue: Issue) -> dict[str, t.Any]:
15
+ pass
16
+
17
+ async def analyze_and_fix_proactively(self, issue: Issue) -> FixResult:
18
+ cache_key = self._get_planning_cache_key(issue)
19
+ if cache_key in self._planning_cache:
20
+ plan = self._planning_cache[cache_key]
21
+ self.log(f"Using cached plan for {cache_key}")
22
+ else:
23
+ plan = await self.plan_before_action(issue)
24
+ self._planning_cache[cache_key] = plan
25
+ self.log(f"Created new plan for {cache_key}")
26
+
27
+ result = await self._execute_with_plan(issue, plan)
28
+
29
+ if result.success and result.confidence >= 0.8:
30
+ self._cache_successful_pattern(issue, plan, result)
31
+
32
+ return result
33
+
34
+ async def _execute_with_plan(
35
+ self, issue: Issue, plan: dict[str, t.Any]
36
+ ) -> FixResult:
37
+ return await self.analyze_and_fix(issue)
38
+
39
+ def _get_planning_cache_key(self, issue: Issue) -> str:
40
+ return f"{issue.type.value}: {issue.file_path}: {issue.line_number}"
41
+
42
+ def _cache_successful_pattern(
43
+ self, issue: Issue, plan: dict[str, t.Any], result: FixResult
44
+ ) -> None:
45
+ pattern_key = f"{issue.type.value}_{plan.get('strategy', 'default')}"
46
+ self._pattern_cache[pattern_key] = {
47
+ "plan": plan,
48
+ "confidence": result.confidence,
49
+ "files_modified": result.files_modified,
50
+ "fixes_applied": result.fixes_applied,
51
+ }
52
+ self.log(f"Cached successful pattern: {pattern_key}")
53
+
54
+ def get_cached_patterns(self) -> dict[str, t.Any]:
55
+ return self._pattern_cache.copy()