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,320 @@
1
+ """Pydantic models to replace dataclasses in the Crackerjack codebase."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class CleaningConfig(BaseModel):
9
+ clean: bool = True
10
+ update_docs: bool = False
11
+ force_update_docs: bool = False
12
+ compress_docs: bool = False
13
+ auto_compress_docs: bool = False
14
+ targets: list[str] = Field(
15
+ default_factory=list
16
+ ) # Changed Path to str for validation
17
+
18
+ @classmethod
19
+ def from_settings(cls, settings: Any) -> "CleaningConfig":
20
+ return cls(
21
+ clean=getattr(settings, "clean", True),
22
+ update_docs=getattr(settings, "update_docs", False),
23
+ force_update_docs=getattr(settings, "force_update_docs", False),
24
+ compress_docs=getattr(settings, "compress_docs", False),
25
+ auto_compress_docs=getattr(settings, "auto_compress_docs", False),
26
+ targets=[str(p) for p in getattr(settings, "targets", [])],
27
+ )
28
+
29
+
30
+ class HookConfig(BaseModel):
31
+ skip_hooks: bool = False
32
+ update_precommit: bool = False
33
+ experimental_hooks: bool = False
34
+ enable_pyrefly: bool = False
35
+ enable_ty: bool = False
36
+ enable_lsp_optimization: bool = False
37
+
38
+ @classmethod
39
+ def from_settings(cls, settings: Any) -> "HookConfig":
40
+ return cls(
41
+ skip_hooks=getattr(settings, "skip_hooks", False),
42
+ update_precommit=getattr(settings, "update_precommit", False),
43
+ experimental_hooks=getattr(settings, "experimental_hooks", False),
44
+ enable_pyrefly=getattr(settings, "enable_pyrefly", False),
45
+ enable_ty=getattr(settings, "enable_ty", False),
46
+ enable_lsp_optimization=getattr(settings, "enable_lsp_optimization", False),
47
+ )
48
+
49
+
50
+ class TestConfig(BaseModel):
51
+ test: bool = False
52
+ benchmark: bool = False
53
+ benchmark_regression: bool = False
54
+ benchmark_regression_threshold: float = 0.1
55
+ test_workers: int = 0
56
+ test_timeout: int = 0
57
+
58
+ @classmethod
59
+ def from_settings(cls, settings: Any) -> "TestConfig":
60
+ return cls(
61
+ test=getattr(settings, "test", False),
62
+ benchmark=getattr(settings, "benchmark", False),
63
+ benchmark_regression=getattr(settings, "benchmark_regression", False),
64
+ benchmark_regression_threshold=getattr(
65
+ settings,
66
+ "benchmark_regression_threshold",
67
+ 0.1,
68
+ ),
69
+ test_workers=getattr(settings, "test_workers", 0),
70
+ test_timeout=getattr(settings, "test_timeout", 0),
71
+ )
72
+
73
+
74
+ class PublishConfig(BaseModel):
75
+ publish: str | None = None
76
+ bump: str | None = None
77
+ all: str | None = None
78
+ cleanup_pypi: bool = False
79
+ keep_releases: int = 10
80
+ no_git_tags: bool = False
81
+ skip_version_check: bool = False
82
+
83
+ @classmethod
84
+ def from_settings(cls, settings: Any) -> "PublishConfig":
85
+ return cls(
86
+ publish=getattr(settings, "publish", None),
87
+ bump=getattr(settings, "bump", None),
88
+ all=getattr(settings, "all", None),
89
+ cleanup_pypi=getattr(settings, "cleanup_pypi", False),
90
+ keep_releases=getattr(settings, "keep_releases", 10),
91
+ no_git_tags=getattr(settings, "no_git_tags", False),
92
+ skip_version_check=getattr(settings, "skip_version_check", False),
93
+ )
94
+
95
+
96
+ class GitConfig(BaseModel):
97
+ commit: bool = False
98
+ create_pr: bool = False
99
+
100
+ @classmethod
101
+ def from_settings(cls, settings: Any) -> "GitConfig":
102
+ return cls(
103
+ commit=getattr(settings, "commit", False),
104
+ create_pr=getattr(settings, "create_pr", False),
105
+ )
106
+
107
+
108
+ class AIConfig(BaseModel):
109
+ ai_agent: bool = False
110
+ autofix: bool = True
111
+ ai_agent_autofix: bool = False
112
+ start_mcp_server: bool = False
113
+ max_iterations: int = 5
114
+
115
+ @classmethod
116
+ def from_settings(cls, settings: Any) -> "AIConfig":
117
+ return cls(
118
+ ai_agent=getattr(settings, "ai_agent", False),
119
+ autofix=getattr(settings, "autofix", True),
120
+ ai_agent_autofix=getattr(settings, "ai_agent_autofix", False),
121
+ start_mcp_server=getattr(settings, "start_mcp_server", False),
122
+ max_iterations=getattr(settings, "max_iterations", 5),
123
+ )
124
+
125
+
126
+ class ExecutionConfig(BaseModel):
127
+ interactive: bool = True
128
+ verbose: bool = False
129
+ async_mode: bool = False
130
+ no_config_updates: bool = False
131
+ dry_run: bool = False
132
+
133
+ @classmethod
134
+ def from_settings(cls, settings: Any) -> "ExecutionConfig":
135
+ return cls(
136
+ interactive=getattr(settings, "interactive", True),
137
+ verbose=getattr(settings, "verbose", False),
138
+ async_mode=getattr(settings, "async_mode", False),
139
+ no_config_updates=getattr(settings, "no_config_updates", False),
140
+ dry_run=getattr(settings, "dry_run", False),
141
+ )
142
+
143
+
144
+ class ProgressConfig(BaseModel):
145
+ track_progress: bool = False
146
+ resume_from: str | None = None
147
+ progress_file: str | None = None
148
+
149
+ @classmethod
150
+ def from_settings(cls, settings: Any) -> "ProgressConfig":
151
+ return cls(
152
+ track_progress=getattr(settings, "enabled", False),
153
+ resume_from=getattr(settings, "resume_from", None),
154
+ progress_file=getattr(settings, "progress_file", None),
155
+ )
156
+
157
+
158
+ class CleanupConfig(BaseModel):
159
+ auto_cleanup: bool = True
160
+ keep_debug_logs: int = 5
161
+ keep_coverage_files: int = 10
162
+
163
+ @classmethod
164
+ def from_settings(cls, settings: Any) -> "CleanupConfig":
165
+ return cls(
166
+ auto_cleanup=getattr(settings, "auto_cleanup", True),
167
+ keep_debug_logs=getattr(settings, "keep_debug_logs", 5),
168
+ keep_coverage_files=getattr(settings, "keep_coverage_files", 10),
169
+ )
170
+
171
+
172
+ class AdvancedConfig(BaseModel):
173
+ enabled: bool = False
174
+ license_key: str | None = None
175
+ organization: str | None = None
176
+
177
+ @classmethod
178
+ def from_settings(cls, settings: Any) -> "AdvancedConfig":
179
+ return cls(
180
+ enabled=getattr(settings, "enabled", False),
181
+ license_key=getattr(settings, "license_key", None),
182
+ organization=getattr(settings, "organization", None),
183
+ )
184
+
185
+
186
+ class MCPServerConfig(BaseModel):
187
+ http_port: int = 8676
188
+ http_host: str = "127.0.0.1"
189
+ websocket_port: int = 8675
190
+ http_enabled: bool = False
191
+
192
+ @classmethod
193
+ def from_settings(cls, settings: Any) -> "MCPServerConfig":
194
+ return cls(
195
+ http_port=getattr(settings, "http_port", 8676),
196
+ http_host=getattr(settings, "http_host", "127.0.0.1"),
197
+ websocket_port=getattr(settings, "websocket_port", 8675),
198
+ http_enabled=getattr(settings, "http_enabled", False),
199
+ )
200
+
201
+
202
+ class ZubanLSPConfig(BaseModel):
203
+ enabled: bool = True
204
+ auto_start: bool = True
205
+ port: int = 8677
206
+ mode: str = "stdio"
207
+ timeout: int = 30
208
+
209
+ @classmethod
210
+ def from_settings(cls, settings: Any) -> "ZubanLSPConfig":
211
+ return cls(
212
+ enabled=getattr(settings, "enabled", True),
213
+ auto_start=getattr(settings, "auto_start", True),
214
+ port=getattr(settings, "port", 8677),
215
+ mode=getattr(settings, "mode", "stdio"),
216
+ timeout=getattr(settings, "timeout", 30),
217
+ )
218
+
219
+
220
+ class WorkflowOptions(BaseModel):
221
+ cleaning: CleaningConfig = Field(default_factory=CleaningConfig)
222
+ hooks: HookConfig = Field(default_factory=HookConfig)
223
+ testing: TestConfig = Field(default_factory=TestConfig)
224
+ publishing: PublishConfig = Field(default_factory=PublishConfig)
225
+ git: GitConfig = Field(default_factory=GitConfig)
226
+ ai: AIConfig = Field(default_factory=AIConfig)
227
+ execution: ExecutionConfig = Field(default_factory=ExecutionConfig)
228
+ progress: ProgressConfig = Field(default_factory=ProgressConfig)
229
+ cleanup: CleanupConfig = Field(default_factory=CleanupConfig)
230
+ advanced: AdvancedConfig = Field(default_factory=AdvancedConfig)
231
+ mcp_server: MCPServerConfig = Field(default_factory=MCPServerConfig)
232
+ zuban_lsp: ZubanLSPConfig = Field(default_factory=ZubanLSPConfig)
233
+
234
+ # Simple properties that map to nested config values
235
+ @property
236
+ def clean(self) -> bool:
237
+ return self.cleaning.clean
238
+
239
+ @clean.setter
240
+ def clean(self, value: bool) -> None:
241
+ self.cleaning.clean = value
242
+
243
+ @property
244
+ def test(self) -> bool:
245
+ return self.testing.test
246
+
247
+ @test.setter
248
+ def test(self, value: bool) -> None:
249
+ self.testing.test = value
250
+
251
+ @property
252
+ def publish(self) -> str | None:
253
+ return self.publishing.publish
254
+
255
+ @publish.setter
256
+ def publish(self, value: str | None) -> None:
257
+ self.publishing.publish = value
258
+
259
+ @property
260
+ def commit(self) -> bool:
261
+ return self.git.commit
262
+
263
+ @commit.setter
264
+ def commit(self, value: bool) -> None:
265
+ self.git.commit = value
266
+
267
+ @classmethod
268
+ def from_settings(cls, settings: Any) -> "WorkflowOptions":
269
+ # Simplified implementation for demonstration
270
+ return cls(
271
+ cleaning=CleaningConfig.from_settings(getattr(settings, "cleaning", {})),
272
+ hooks=HookConfig.from_settings(getattr(settings, "hooks", {})),
273
+ testing=TestConfig.from_settings(getattr(settings, "testing", {})),
274
+ publishing=PublishConfig.from_settings(getattr(settings, "publishing", {})),
275
+ git=GitConfig.from_settings(getattr(settings, "git", {})),
276
+ ai=AIConfig.from_settings(getattr(settings, "ai", {})),
277
+ execution=ExecutionConfig.from_settings(getattr(settings, "execution", {})),
278
+ progress=ProgressConfig.from_settings(getattr(settings, "progress", {})),
279
+ cleanup=CleanupConfig.from_settings(getattr(settings, "cleanup", {})),
280
+ advanced=AdvancedConfig.from_settings(getattr(settings, "advanced", {})),
281
+ mcp_server=MCPServerConfig.from_settings(
282
+ getattr(settings, "mcp_server", {})
283
+ ),
284
+ zuban_lsp=ZubanLSPConfig.from_settings(getattr(settings, "zuban_lsp", {})),
285
+ )
286
+
287
+ def to_dict(self) -> dict[str, Any]:
288
+ return self.model_dump()
289
+
290
+
291
+ # Results models
292
+ class ExecutionResult(BaseModel):
293
+ operation_id: str
294
+ success: bool
295
+ duration_seconds: float
296
+ output: str = ""
297
+ error: str = ""
298
+ exit_code: int = 0
299
+ metadata: dict[str, Any] = Field(default_factory=dict)
300
+
301
+
302
+ class ParallelExecutionResult(BaseModel):
303
+ group_name: str
304
+ total_operations: int
305
+ successful_operations: int
306
+ failed_operations: int
307
+ total_duration_seconds: float
308
+ results: list[ExecutionResult]
309
+
310
+ @property
311
+ def success_rate(self) -> float:
312
+ return (
313
+ self.successful_operations / self.total_operations
314
+ if self.total_operations > 0
315
+ else 0.0
316
+ )
317
+
318
+ @property
319
+ def overall_success(self) -> bool:
320
+ return self.failed_operations == 0
@@ -0,0 +1,145 @@
1
+ """Configuration models for ACB Quality Assurance framework."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+ from uuid import UUID
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ from crackerjack.models.qa_results import QACheckType
12
+
13
+
14
+ class QACheckConfig(BaseModel):
15
+ """Configuration for a single quality assurance check.
16
+
17
+ This model defines how a QA check should be executed, including
18
+ file patterns, exclusions, timeouts, and check-specific settings.
19
+ """
20
+
21
+ check_id: UUID = Field(
22
+ ...,
23
+ description="Unique identifier for this check",
24
+ )
25
+ check_name: str = Field(
26
+ ...,
27
+ description="Human-readable name (e.g., 'ruff-format', 'pyright')",
28
+ )
29
+ check_type: QACheckType = Field(
30
+ ...,
31
+ description="Category of the check (lint, format, type_check, etc.)",
32
+ )
33
+ enabled: bool = Field(
34
+ default=True,
35
+ description="Whether this check is enabled",
36
+ )
37
+ file_patterns: list[str] = Field(
38
+ default_factory=list,
39
+ description="Glob patterns for files to check",
40
+ )
41
+ exclude_patterns: list[str] = Field(
42
+ default_factory=list,
43
+ description="Glob patterns for files to exclude",
44
+ )
45
+ timeout_seconds: int = Field(
46
+ default=300, # 5 minutes default
47
+ gt=0, # Must be positive
48
+ description="Maximum execution time in seconds",
49
+ )
50
+ retry_on_failure: bool = Field(
51
+ default=False,
52
+ description="Whether to retry if the check fails",
53
+ )
54
+ is_formatter: bool = Field(
55
+ default=False,
56
+ description="Whether this check modifies files",
57
+ )
58
+ parallel_safe: bool = Field(
59
+ default=True,
60
+ description="Whether this check can run in parallel with others",
61
+ )
62
+ stage: str = Field(
63
+ default="fast",
64
+ description="Execution stage: 'fast' or 'comprehensive'",
65
+ )
66
+ settings: dict[str, Any] = Field(
67
+ default_factory=dict,
68
+ description="Check-specific configuration settings",
69
+ )
70
+
71
+ @property
72
+ def is_fast_stage(self) -> bool:
73
+ """Check if this is a fast stage check."""
74
+ return self.stage == "fast"
75
+
76
+ @property
77
+ def is_comprehensive_stage(self) -> bool:
78
+ """Check if this is a comprehensive stage check."""
79
+ return self.stage == "comprehensive"
80
+
81
+
82
+ class QAOrchestratorConfig(BaseModel):
83
+ """Configuration for the quality assurance orchestrator.
84
+
85
+ This model defines global settings for QA execution, including
86
+ parallelization, caching, and execution order.
87
+ """
88
+
89
+ project_root: Path = Field(
90
+ ...,
91
+ description="Root directory of the project being checked",
92
+ )
93
+ max_parallel_checks: int = Field(
94
+ default=4,
95
+ gt=0, # Must be positive
96
+ description="Maximum number of checks to run in parallel",
97
+ )
98
+ enable_caching: bool = Field(
99
+ default=True,
100
+ description="Whether to cache check results",
101
+ )
102
+ cache_directory: Path | None = Field(
103
+ default=None,
104
+ description="Directory for caching results (None = use default)",
105
+ )
106
+ fail_fast: bool = Field(
107
+ default=False,
108
+ description="Stop execution on first failure",
109
+ )
110
+ run_formatters_first: bool = Field(
111
+ default=True,
112
+ description="Run formatter checks before other checks",
113
+ )
114
+ enable_incremental: bool = Field(
115
+ default=True,
116
+ description="Only check modified files when possible",
117
+ )
118
+ verbose: bool = Field(
119
+ default=False,
120
+ description="Enable verbose output",
121
+ )
122
+ checks: list[QACheckConfig] = Field(
123
+ default_factory=list,
124
+ description="List of QA checks to execute",
125
+ )
126
+
127
+ @property
128
+ def fast_checks(self) -> list[QACheckConfig]:
129
+ """Get all fast stage checks."""
130
+ return [check for check in self.checks if check.is_fast_stage]
131
+
132
+ @property
133
+ def comprehensive_checks(self) -> list[QACheckConfig]:
134
+ """Get all comprehensive stage checks."""
135
+ return [check for check in self.checks if check.is_comprehensive_stage]
136
+
137
+ @property
138
+ def formatter_checks(self) -> list[QACheckConfig]:
139
+ """Get all formatter checks."""
140
+ return [check for check in self.checks if check.is_formatter]
141
+
142
+ @property
143
+ def enabled_checks(self) -> list[QACheckConfig]:
144
+ """Get all enabled checks."""
145
+ return [check for check in self.checks if check.enabled]
@@ -0,0 +1,134 @@
1
+ """Result models for ACB Quality Assurance framework."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from enum import Enum
7
+ from pathlib import Path
8
+ from typing import Any
9
+ from uuid import UUID
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class QAResultStatus(str, Enum):
15
+ """Status of a quality assurance check result."""
16
+
17
+ SUCCESS = "success"
18
+ FAILURE = "failure"
19
+ WARNING = "warning"
20
+ SKIPPED = "skipped"
21
+ ERROR = "error"
22
+
23
+
24
+ class QACheckType(str, Enum):
25
+ """Type of quality assurance check."""
26
+
27
+ LINT = "lint"
28
+ FORMAT = "format"
29
+ TYPE = "type" # Type checking (pyright, mypy, zuban)
30
+ SECURITY = "security" # Secret leak prevention (gitleaks)
31
+ SAST = "sast" # Static Application Security Testing (bandit, semgrep, pyscn)
32
+ COMPLEXITY = "complexity" # Code complexity analysis
33
+ REFACTOR = "refactor"
34
+ TEST = "test"
35
+
36
+
37
+ class QAResult(BaseModel):
38
+ """Result of a quality assurance check execution.
39
+
40
+ This model represents the outcome of running a single QA check,
41
+ including timing information, file changes, and detailed messages.
42
+ """
43
+
44
+ check_id: UUID = Field(
45
+ ...,
46
+ description="Unique identifier for the check that produced this result",
47
+ )
48
+ check_name: str = Field(
49
+ ...,
50
+ description="Human-readable name of the check (e.g., 'ruff-format', 'pyright')",
51
+ )
52
+ check_type: QACheckType = Field(
53
+ ...,
54
+ description="Category of the check (lint, format, type_check, etc.)",
55
+ )
56
+ status: QAResultStatus = Field(
57
+ ...,
58
+ description="Outcome status of the check",
59
+ )
60
+ message: str = Field(
61
+ default="",
62
+ description="Summary message describing the result",
63
+ )
64
+ details: str = Field(
65
+ default="",
66
+ description="Detailed output from the check (stdout/stderr)",
67
+ )
68
+ files_checked: list[Path] = Field(
69
+ default_factory=list,
70
+ description="List of files that were checked",
71
+ )
72
+ files_modified: list[Path] = Field(
73
+ default_factory=list,
74
+ description="List of files modified by the check (for formatters)",
75
+ )
76
+ issues_found: int = Field(
77
+ default=0,
78
+ description="Number of issues found (errors, warnings, style violations)",
79
+ )
80
+ issues_fixed: int = Field(
81
+ default=0,
82
+ description="Number of issues automatically fixed",
83
+ )
84
+ execution_time_ms: float = Field(
85
+ default=0.0,
86
+ description="Execution time in milliseconds",
87
+ )
88
+ timestamp: datetime = Field(
89
+ default_factory=datetime.now,
90
+ description="When the check was executed",
91
+ )
92
+ metadata: dict[str, Any] = Field(
93
+ default_factory=dict,
94
+ description="Additional check-specific metadata",
95
+ )
96
+
97
+ @property
98
+ def is_success(self) -> bool:
99
+ """Check if the result indicates success.
100
+
101
+ Warnings are considered successful - they indicate potential issues
102
+ but don't fail the quality check.
103
+ """
104
+ return self.status in (QAResultStatus.SUCCESS, QAResultStatus.WARNING)
105
+
106
+ @property
107
+ def is_failure(self) -> bool:
108
+ """Check if the result indicates failure."""
109
+ return self.status == QAResultStatus.FAILURE
110
+
111
+ @property
112
+ def is_warning(self) -> bool:
113
+ """Check if the result indicates a warning."""
114
+ return self.status == QAResultStatus.WARNING
115
+
116
+ @property
117
+ def has_issues(self) -> bool:
118
+ """Check if any issues were found."""
119
+ return self.issues_found > 0
120
+
121
+ def to_summary(self) -> str:
122
+ """Generate a human-readable summary of the result."""
123
+ summary_parts = [f"{self.check_name}: {self.status.value}"]
124
+
125
+ if self.issues_found > 0:
126
+ summary_parts.append(f"{self.issues_found} issues found")
127
+
128
+ if self.issues_fixed > 0:
129
+ summary_parts.append(f"{self.issues_fixed} fixed")
130
+
131
+ if self.execution_time_ms > 0:
132
+ summary_parts.append(f"({self.execution_time_ms:.0f}ms)")
133
+
134
+ return " | ".join(summary_parts)
@@ -0,0 +1,35 @@
1
+ import typing as t
2
+ from dataclasses import dataclass, field
3
+
4
+
5
+ @dataclass
6
+ class ExecutionResult:
7
+ operation_id: str
8
+ success: bool
9
+ duration_seconds: float
10
+ output: str = ""
11
+ error: str = ""
12
+ exit_code: int = 0
13
+ metadata: dict[str, t.Any] = field(default_factory=dict[str, t.Any])
14
+
15
+
16
+ @dataclass
17
+ class ParallelExecutionResult:
18
+ group_name: str
19
+ total_operations: int
20
+ successful_operations: int
21
+ failed_operations: int
22
+ total_duration_seconds: float
23
+ results: list[ExecutionResult]
24
+
25
+ @property
26
+ def success_rate(self) -> float:
27
+ return (
28
+ self.successful_operations / self.total_operations
29
+ if self.total_operations > 0
30
+ else 0.0
31
+ )
32
+
33
+ @property
34
+ def overall_success(self) -> bool:
35
+ return self.failed_operations == 0