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.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +30 -1
- crackerjack/__main__.py +342 -1263
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +27 -5
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
- crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
- crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +40 -12
- crackerjack/agents/base.py +1 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +49 -53
- crackerjack/agents/dry_agent.py +187 -3
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +6 -8
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/performance_agent.py +121 -1152
- crackerjack/agents/refactoring_agent.py +156 -655
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +19 -1605
- crackerjack/api.py +5 -7
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +1 -1
- crackerjack/cli/cache_handlers.py +23 -18
- crackerjack/cli/cache_handlers_enhanced.py +1 -4
- crackerjack/cli/facade.py +70 -8
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +249 -49
- crackerjack/cli/interactive.py +8 -5
- crackerjack/cli/options.py +203 -110
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +60 -24
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +256 -0
- crackerjack/config/global_lock_config.py +191 -54
- crackerjack/config/hooks.py +188 -16
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/async_workflow_orchestrator.py +79 -53
- crackerjack/core/autofix_coordinator.py +22 -9
- crackerjack/core/container.py +10 -9
- crackerjack/core/enhanced_container.py +9 -9
- crackerjack/core/performance.py +1 -1
- crackerjack/core/performance_monitor.py +5 -3
- crackerjack/core/phase_coordinator.py +1018 -634
- crackerjack/core/proactive_workflow.py +3 -3
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +167 -23
- crackerjack/core/session_coordinator.py +187 -382
- crackerjack/core/timeout_manager.py +161 -44
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +1247 -953
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/ai_templates.py +1 -1
- crackerjack/documentation/dual_output_generator.py +11 -9
- crackerjack/documentation/reference_generator.py +104 -59
- crackerjack/dynamic_config.py +52 -61
- crackerjack/errors.py +1 -1
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +2 -0
- crackerjack/executors/async_hook_executor.py +539 -77
- crackerjack/executors/cached_hook_executor.py +3 -3
- crackerjack/executors/hook_executor.py +967 -102
- crackerjack/executors/hook_lock_manager.py +31 -22
- crackerjack/executors/individual_hook_executor.py +66 -32
- crackerjack/executors/lsp_aware_hook_executor.py +136 -57
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +23 -7
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +8 -9
- crackerjack/intelligence/README.md +557 -0
- crackerjack/interactive.py +37 -10
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/async_hook_manager.py +41 -57
- crackerjack/managers/hook_manager.py +449 -79
- crackerjack/managers/publish_manager.py +81 -36
- crackerjack/managers/test_command_builder.py +290 -12
- crackerjack/managers/test_executor.py +93 -8
- crackerjack/managers/test_manager.py +1082 -75
- crackerjack/managers/test_progress.py +118 -26
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/cache.py +25 -2
- crackerjack/mcp/client_runner.py +35 -18
- crackerjack/mcp/context.py +9 -9
- crackerjack/mcp/dashboard.py +24 -8
- crackerjack/mcp/enhanced_progress_monitor.py +34 -23
- crackerjack/mcp/file_monitor.py +27 -6
- crackerjack/mcp/progress_components.py +45 -34
- crackerjack/mcp/progress_monitor.py +6 -9
- crackerjack/mcp/rate_limiter.py +11 -7
- crackerjack/mcp/server.py +2 -0
- crackerjack/mcp/server_core.py +187 -55
- crackerjack/mcp/service_watchdog.py +12 -9
- crackerjack/mcp/task_manager.py +2 -2
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +2 -0
- crackerjack/mcp/tools/core_tools.py +75 -52
- crackerjack/mcp/tools/execution_tools.py +87 -31
- crackerjack/mcp/tools/intelligence_tools.py +2 -2
- crackerjack/mcp/tools/proactive_tools.py +1 -1
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +180 -132
- crackerjack/mcp/tools/workflow_executor.py +87 -46
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/app.py +11 -1
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +27 -4
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
- crackerjack/mcp/websocket/server.py +1 -3
- crackerjack/mcp/websocket/websocket_handler.py +107 -6
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +10 -1
- crackerjack/models/config.py +639 -22
- crackerjack/models/config_adapter.py +6 -6
- crackerjack/models/protocols.py +1167 -23
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +19 -3
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/ai_agent_watchdog.py +5 -4
- crackerjack/monitoring/metrics_collector.py +4 -3
- crackerjack/monitoring/regression_prevention.py +4 -3
- crackerjack/monitoring/websocket_server.py +4 -241
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +20 -67
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +13 -6
- crackerjack/orchestration/execution_strategies.py +6 -6
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +1 -1
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/hooks.py +3 -2
- crackerjack/plugins/loader.py +3 -3
- crackerjack/plugins/managers.py +1 -1
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +8 -21
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/api_extractor.py +5 -3
- crackerjack/services/bounded_status_operations.py +45 -5
- crackerjack/services/cache.py +249 -318
- crackerjack/services/changelog_automation.py +7 -3
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +83 -39
- crackerjack/services/config_merge.py +9 -6
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +13 -26
- crackerjack/services/coverage_badge_service.py +6 -4
- crackerjack/services/coverage_ratchet.py +53 -27
- crackerjack/services/debug.py +18 -7
- crackerjack/services/dependency_analyzer.py +4 -4
- crackerjack/services/dependency_monitor.py +13 -13
- crackerjack/services/documentation_generator.py +4 -2
- crackerjack/services/documentation_service.py +62 -33
- crackerjack/services/enhanced_filesystem.py +81 -27
- crackerjack/services/enterprise_optimizer.py +1 -1
- crackerjack/services/error_pattern_analyzer.py +10 -10
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +5 -7
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +80 -109
- crackerjack/services/git.py +99 -5
- crackerjack/services/health_metrics.py +4 -6
- crackerjack/services/heatmap_generator.py +12 -3
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +101 -49
- crackerjack/services/log_manager.py +2 -2
- crackerjack/services/logging.py +120 -68
- crackerjack/services/lsp_client.py +12 -12
- crackerjack/services/memory_optimizer.py +27 -22
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
- crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
- crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
- crackerjack/services/parallel_executor.py +166 -55
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +21 -8
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
- crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
- crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
- crackerjack/services/regex_patterns.py +58 -2987
- crackerjack/services/regex_utils.py +55 -29
- crackerjack/services/secure_status_formatter.py +42 -15
- crackerjack/services/secure_subprocess.py +35 -2
- crackerjack/services/security.py +16 -8
- crackerjack/services/server_manager.py +40 -51
- crackerjack/services/smart_scheduling.py +46 -6
- crackerjack/services/status_authentication.py +3 -3
- crackerjack/services/thread_safe_status_collector.py +1 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +9 -5
- crackerjack/services/unified_config.py +43 -351
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +6 -4
- crackerjack/services/version_checker.py +14 -8
- crackerjack/services/zuban_lsp_service.py +5 -4
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/init.md +2 -12
- crackerjack/slash_commands/run.md +84 -50
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_regex_patterns.py +7 -3
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack/managers/test_manager_backup.py +0 -1075
- crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
- crackerjack/mixins/__init__.py +0 -3
- crackerjack/mixins/error_handling.py +0 -145
- crackerjack/services/config.py +0 -358
- crackerjack/ui/server_panels.py +0 -125
- crackerjack-0.37.9.dist-info/RECORD +0 -231
- /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
- /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Iterative auto-fix workflow for crackerjack.
|
|
3
|
+
|
|
4
|
+
This module implements the AutoFixWorkflow class that runs an iterative
|
|
5
|
+
loop to detect issues via pre-commit hooks, apply AI-powered fixes, and
|
|
6
|
+
verify the fixes until convergence or max iterations is reached.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import logging
|
|
11
|
+
import typing as t
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from acb import console as acb_console
|
|
16
|
+
from acb.console import Console
|
|
17
|
+
|
|
18
|
+
from crackerjack.agents.base import AgentContext, Issue, IssueType, Priority
|
|
19
|
+
from crackerjack.agents.enhanced_coordinator import EnhancedAgentCoordinator
|
|
20
|
+
from crackerjack.managers.async_hook_manager import AsyncHookManager
|
|
21
|
+
from crackerjack.models.task import HookResult
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class FixIteration:
|
|
26
|
+
"""Records data from a single iteration of the fix cycle."""
|
|
27
|
+
|
|
28
|
+
iteration_num: int
|
|
29
|
+
hooks_run: list[str]
|
|
30
|
+
issues_found: int
|
|
31
|
+
fixes_applied: int
|
|
32
|
+
fixes_successful: int
|
|
33
|
+
hooks_passing: list[str]
|
|
34
|
+
hooks_failing: list[str]
|
|
35
|
+
duration: float = 0.0
|
|
36
|
+
convergence_status: str = "incomplete"
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> dict[str, t.Any]:
|
|
39
|
+
"""Convert iteration to dictionary for serialization."""
|
|
40
|
+
return {
|
|
41
|
+
"iteration_num": self.iteration_num,
|
|
42
|
+
"hooks_run": self.hooks_run,
|
|
43
|
+
"issues_found": self.issues_found,
|
|
44
|
+
"fixes_applied": self.fixes_applied,
|
|
45
|
+
"fixes_successful": self.fixes_successful,
|
|
46
|
+
"hooks_passing": self.hooks_passing,
|
|
47
|
+
"hooks_failing": self.hooks_failing,
|
|
48
|
+
"duration": self.duration,
|
|
49
|
+
"convergence_status": self.convergence_status,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class WorkflowResult:
|
|
55
|
+
"""Results from the complete auto-fix workflow."""
|
|
56
|
+
|
|
57
|
+
success: bool
|
|
58
|
+
iterations: list[FixIteration] = field(default_factory=list)
|
|
59
|
+
total_fixes: int = 0
|
|
60
|
+
total_issues_found: int = 0
|
|
61
|
+
final_status: str = "incomplete"
|
|
62
|
+
total_duration: float = 0.0
|
|
63
|
+
convergence_achieved: bool = False
|
|
64
|
+
exit_reason: str = "unknown"
|
|
65
|
+
|
|
66
|
+
def to_dict(self) -> dict[str, t.Any]:
|
|
67
|
+
"""Convert result to dictionary for serialization."""
|
|
68
|
+
return {
|
|
69
|
+
"success": self.success,
|
|
70
|
+
"iterations": [it.to_dict() for it in self.iterations],
|
|
71
|
+
"total_fixes": self.total_fixes,
|
|
72
|
+
"total_issues_found": self.total_issues_found,
|
|
73
|
+
"final_status": self.final_status,
|
|
74
|
+
"total_duration": self.total_duration,
|
|
75
|
+
"convergence_achieved": self.convergence_achieved,
|
|
76
|
+
"exit_reason": self.exit_reason,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class AutoFixWorkflow:
|
|
81
|
+
"""Iterative auto-fix workflow with convergence detection."""
|
|
82
|
+
|
|
83
|
+
MAX_ITERATIONS = 10
|
|
84
|
+
CONVERGENCE_THRESHOLD = 0 # No new fixes needed
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
project_path: Path | None = None,
|
|
89
|
+
console: Console | None = None,
|
|
90
|
+
enable_external_agents: bool = True,
|
|
91
|
+
) -> None:
|
|
92
|
+
"""Initialize the auto-fix workflow.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
project_path: Path to project root (defaults to cwd)
|
|
96
|
+
console: Rich console for output (creates default if None)
|
|
97
|
+
enable_external_agents: Enable Claude Code external agent integration
|
|
98
|
+
"""
|
|
99
|
+
self.project_path = project_path or Path.cwd()
|
|
100
|
+
self.console = console or acb_console
|
|
101
|
+
self.logger = logging.getLogger(__name__)
|
|
102
|
+
|
|
103
|
+
# Initialize agent context
|
|
104
|
+
self.context = AgentContext(
|
|
105
|
+
project_path=self.project_path,
|
|
106
|
+
temp_dir=self.project_path / ".crackerjack" / "temp",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Initialize agent coordinator with external agent support
|
|
110
|
+
self.coordinator = EnhancedAgentCoordinator(
|
|
111
|
+
context=self.context,
|
|
112
|
+
enable_external_agents=enable_external_agents,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Initialize hook manager
|
|
116
|
+
self.hook_manager = AsyncHookManager(
|
|
117
|
+
console=self.console,
|
|
118
|
+
pkg_path=self.project_path,
|
|
119
|
+
max_concurrent=3,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
async def run(
|
|
123
|
+
self, command: str = "check", max_iterations: int | None = None
|
|
124
|
+
) -> WorkflowResult:
|
|
125
|
+
"""Run iterative auto-fix workflow.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
command: Semantic command (test, lint, check, etc.)
|
|
129
|
+
max_iterations: Max fix iterations (default: 10)
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
WorkflowResult with iteration history and final status
|
|
133
|
+
"""
|
|
134
|
+
max_iter = max_iterations or self.MAX_ITERATIONS
|
|
135
|
+
iterations: list[FixIteration] = []
|
|
136
|
+
workflow_start_time = asyncio.get_event_loop().time()
|
|
137
|
+
|
|
138
|
+
self.logger.info(
|
|
139
|
+
f"Starting auto-fix workflow: {command} (max {max_iter} iterations)"
|
|
140
|
+
)
|
|
141
|
+
self.console.print("[bold cyan]🔄 Auto-Fix Workflow Started[/bold cyan]")
|
|
142
|
+
self.console.print(
|
|
143
|
+
f"[dim]Command: {command} | Max iterations: {max_iter}[/dim]\n"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
exit_reason = "unknown"
|
|
147
|
+
all_passing = False
|
|
148
|
+
|
|
149
|
+
for i in range(1, max_iter + 1):
|
|
150
|
+
iteration_start_time = asyncio.get_event_loop().time()
|
|
151
|
+
|
|
152
|
+
self.logger.info(f"Iteration {i}/{max_iter}")
|
|
153
|
+
self.console.print(f"[bold]━━━ Iteration {i}/{max_iter} ━━━[/bold]")
|
|
154
|
+
|
|
155
|
+
# Step 1: Run hooks and collect failures
|
|
156
|
+
hook_results = await self._run_hooks(command)
|
|
157
|
+
|
|
158
|
+
# Step 2: Check for convergence (all passing)
|
|
159
|
+
if hook_results["all_passing"]:
|
|
160
|
+
all_passing = True
|
|
161
|
+
exit_reason = "convergence"
|
|
162
|
+
|
|
163
|
+
iteration_duration = (
|
|
164
|
+
asyncio.get_event_loop().time() - iteration_start_time
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
iteration = FixIteration(
|
|
168
|
+
iteration_num=i,
|
|
169
|
+
hooks_run=hook_results["hooks_run"],
|
|
170
|
+
issues_found=0,
|
|
171
|
+
fixes_applied=0,
|
|
172
|
+
fixes_successful=0,
|
|
173
|
+
hooks_passing=hook_results["passing"],
|
|
174
|
+
hooks_failing=[],
|
|
175
|
+
duration=iteration_duration,
|
|
176
|
+
convergence_status="converged",
|
|
177
|
+
)
|
|
178
|
+
iterations.append(iteration)
|
|
179
|
+
|
|
180
|
+
self.logger.info("✅ All hooks passing - convergence achieved!")
|
|
181
|
+
self.console.print(
|
|
182
|
+
"[bold green]✅ All hooks passing - convergence achieved![/bold green]\n"
|
|
183
|
+
)
|
|
184
|
+
break
|
|
185
|
+
|
|
186
|
+
# Step 3: Apply AI fixes for failures
|
|
187
|
+
fix_results = await self._apply_fixes(hook_results["failures"])
|
|
188
|
+
|
|
189
|
+
iteration_duration = asyncio.get_event_loop().time() - iteration_start_time
|
|
190
|
+
|
|
191
|
+
# Step 4: Record iteration
|
|
192
|
+
iteration = FixIteration(
|
|
193
|
+
iteration_num=i,
|
|
194
|
+
hooks_run=hook_results["hooks_run"],
|
|
195
|
+
issues_found=len(hook_results["failures"]),
|
|
196
|
+
fixes_applied=fix_results["fixes_applied"],
|
|
197
|
+
fixes_successful=fix_results["fixes_successful"],
|
|
198
|
+
hooks_passing=hook_results["passing"],
|
|
199
|
+
hooks_failing=hook_results["failing"],
|
|
200
|
+
duration=iteration_duration,
|
|
201
|
+
convergence_status="in_progress",
|
|
202
|
+
)
|
|
203
|
+
iterations.append(iteration)
|
|
204
|
+
|
|
205
|
+
self.console.print(
|
|
206
|
+
f"[dim]Issues found: {iteration.issues_found} | "
|
|
207
|
+
f"Fixes applied: {iteration.fixes_applied} | "
|
|
208
|
+
f"Successful: {iteration.fixes_successful}[/dim]\n"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Step 5: Check for convergence (no fixes possible)
|
|
212
|
+
if fix_results["fixes_applied"] == 0:
|
|
213
|
+
exit_reason = "no_progress"
|
|
214
|
+
self.logger.warning("⚠️ No fixes applied - cannot make progress")
|
|
215
|
+
self.console.print(
|
|
216
|
+
"[bold yellow]⚠️ No fixes applied - cannot make progress[/bold yellow]\n"
|
|
217
|
+
)
|
|
218
|
+
break
|
|
219
|
+
|
|
220
|
+
# Handle max iterations reached
|
|
221
|
+
if not all_passing and exit_reason == "unknown":
|
|
222
|
+
exit_reason = "max_iterations"
|
|
223
|
+
self.logger.warning(
|
|
224
|
+
f"⚠️ Max iterations ({max_iter}) reached without full convergence"
|
|
225
|
+
)
|
|
226
|
+
self.console.print(
|
|
227
|
+
f"[bold yellow]⚠️ Max iterations ({max_iter}) reached[/bold yellow]\n"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Calculate final statistics
|
|
231
|
+
total_duration = asyncio.get_event_loop().time() - workflow_start_time
|
|
232
|
+
total_fixes = sum(it.fixes_successful for it in iterations)
|
|
233
|
+
total_issues = sum(it.issues_found for it in iterations)
|
|
234
|
+
|
|
235
|
+
result = WorkflowResult(
|
|
236
|
+
success=all_passing,
|
|
237
|
+
iterations=iterations,
|
|
238
|
+
total_fixes=total_fixes,
|
|
239
|
+
total_issues_found=total_issues,
|
|
240
|
+
final_status="converged" if all_passing else "incomplete",
|
|
241
|
+
total_duration=total_duration,
|
|
242
|
+
convergence_achieved=all_passing,
|
|
243
|
+
exit_reason=exit_reason,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Print summary
|
|
247
|
+
self._print_summary(result)
|
|
248
|
+
|
|
249
|
+
return result
|
|
250
|
+
|
|
251
|
+
async def _run_hooks(self, command: str) -> dict[str, t.Any]:
|
|
252
|
+
"""Run pre-commit hooks and collect results.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
command: Semantic command (determines which hooks to run)
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Dictionary with hook results and status
|
|
259
|
+
"""
|
|
260
|
+
self.logger.debug(f"Running hooks for command: {command}")
|
|
261
|
+
|
|
262
|
+
# Choose hook strategy based on command
|
|
263
|
+
if command in ("test", "check", "all"):
|
|
264
|
+
results = await self.hook_manager.run_comprehensive_hooks_async()
|
|
265
|
+
else:
|
|
266
|
+
results = await self.hook_manager.run_fast_hooks_async()
|
|
267
|
+
|
|
268
|
+
# Parse results
|
|
269
|
+
hooks_run = [r.name for r in results]
|
|
270
|
+
passing = [r.name for r in results if r.status == "passed"]
|
|
271
|
+
failing = [r.name for r in results if r.status != "passed"]
|
|
272
|
+
all_passing = len(failing) == 0
|
|
273
|
+
|
|
274
|
+
self.logger.debug(
|
|
275
|
+
f"Hook results: {len(passing)} passing, {len(failing)} failing"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
"hooks_run": hooks_run,
|
|
280
|
+
"passing": passing,
|
|
281
|
+
"failing": failing,
|
|
282
|
+
"failures": [r for r in results if r.status != "passed"],
|
|
283
|
+
"all_passing": all_passing,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async def _apply_fixes(self, failures: list[HookResult]) -> dict[str, int]:
|
|
287
|
+
"""Apply AI fixes for all failures.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
failures: List of failed HookResults
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Dictionary with fix statistics
|
|
294
|
+
"""
|
|
295
|
+
fixes_applied = 0
|
|
296
|
+
fixes_successful = 0
|
|
297
|
+
|
|
298
|
+
self.logger.info(f"Applying fixes for {len(failures)} failures")
|
|
299
|
+
|
|
300
|
+
for failure in failures:
|
|
301
|
+
try:
|
|
302
|
+
# Convert HookResult to Issue for agent system
|
|
303
|
+
issue = self._hook_result_to_issue(failure)
|
|
304
|
+
|
|
305
|
+
self.logger.debug(f"Fixing {failure.name}: {issue.message}")
|
|
306
|
+
|
|
307
|
+
# Coordinate fix via enhanced agent coordinator
|
|
308
|
+
result = await self.coordinator.handle_issues_proactively([issue])
|
|
309
|
+
|
|
310
|
+
if result.fixes_applied:
|
|
311
|
+
fixes_applied += len(result.fixes_applied)
|
|
312
|
+
|
|
313
|
+
if result.success:
|
|
314
|
+
fixes_successful += len(result.fixes_applied)
|
|
315
|
+
self.logger.info(
|
|
316
|
+
f"✅ Successfully fixed {failure.name} ({result.confidence:.2f} confidence)"
|
|
317
|
+
)
|
|
318
|
+
else:
|
|
319
|
+
self.logger.warning(
|
|
320
|
+
f"⚠️ Partial fix for {failure.name} ({result.confidence:.2f} confidence)"
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
self.logger.debug(f"No fixes applied for {failure.name}")
|
|
324
|
+
|
|
325
|
+
except Exception as e:
|
|
326
|
+
self.logger.exception(f"Fix failed for {failure.name}: {e}")
|
|
327
|
+
self.console.print(f"[red]❌ Error fixing {failure.name}: {e}[/red]")
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
"fixes_applied": fixes_applied,
|
|
331
|
+
"fixes_successful": fixes_successful,
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
def _hook_result_to_issue(self, hook_result: HookResult) -> Issue:
|
|
335
|
+
"""Convert a HookResult to an Issue for the agent system.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
hook_result: Hook execution result
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
Issue object for agent processing
|
|
342
|
+
"""
|
|
343
|
+
# Map hook names to issue types
|
|
344
|
+
issue_type_mapping: dict[str, IssueType] = {
|
|
345
|
+
"refurb": IssueType.DRY_VIOLATION,
|
|
346
|
+
"pyright": IssueType.TYPE_ERROR,
|
|
347
|
+
"bandit": IssueType.SECURITY,
|
|
348
|
+
"ruff": IssueType.FORMATTING,
|
|
349
|
+
"pytest": IssueType.TEST_FAILURE,
|
|
350
|
+
"complexipy": IssueType.COMPLEXITY,
|
|
351
|
+
"vulture": IssueType.DEAD_CODE,
|
|
352
|
+
"creosote": IssueType.DEPENDENCY,
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
# Determine issue type from hook name
|
|
356
|
+
issue_type = IssueType.FORMATTING # Default
|
|
357
|
+
for hook_prefix, mapped_type in issue_type_mapping.items():
|
|
358
|
+
if hook_result.name.lower().startswith(hook_prefix):
|
|
359
|
+
issue_type = mapped_type
|
|
360
|
+
break
|
|
361
|
+
|
|
362
|
+
# Determine severity based on hook status
|
|
363
|
+
severity = Priority.HIGH if hook_result.status == "failed" else Priority.MEDIUM
|
|
364
|
+
|
|
365
|
+
# Create issue
|
|
366
|
+
issue = Issue(
|
|
367
|
+
id=f"{hook_result.id}_{hook_result.name}",
|
|
368
|
+
type=issue_type,
|
|
369
|
+
severity=severity,
|
|
370
|
+
message=f"Hook {hook_result.name} failed",
|
|
371
|
+
details=hook_result.issues_found or [],
|
|
372
|
+
stage=hook_result.stage,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
return issue
|
|
376
|
+
|
|
377
|
+
def _check_convergence(self, hook_results: dict[str, t.Any]) -> bool:
|
|
378
|
+
"""Determine if workflow has converged.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
hook_results: Results from _run_hooks
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
True if converged (all hooks passing)
|
|
385
|
+
"""
|
|
386
|
+
return bool(hook_results["all_passing"])
|
|
387
|
+
|
|
388
|
+
def _print_summary(self, result: WorkflowResult) -> None:
|
|
389
|
+
"""Print workflow summary to console.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
result: Final workflow result
|
|
393
|
+
"""
|
|
394
|
+
self.console.print("\n[bold cyan]━━━ Auto-Fix Summary ━━━[/bold cyan]")
|
|
395
|
+
|
|
396
|
+
# Status
|
|
397
|
+
status_color = "green" if result.success else "yellow"
|
|
398
|
+
status_icon = "✅" if result.success else "⚠️"
|
|
399
|
+
self.console.print(
|
|
400
|
+
f"{status_icon} [bold {status_color}]Status:[/bold {status_color}] {result.final_status}"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
# Statistics
|
|
404
|
+
self.console.print("📊 [bold]Statistics:[/bold]")
|
|
405
|
+
self.console.print(f" • Iterations: {len(result.iterations)}")
|
|
406
|
+
self.console.print(f" • Total issues found: {result.total_issues_found}")
|
|
407
|
+
self.console.print(f" • Total fixes applied: {result.total_fixes}")
|
|
408
|
+
self.console.print(f" • Total duration: {result.total_duration:.2f}s")
|
|
409
|
+
self.console.print(f" • Exit reason: {result.exit_reason}")
|
|
410
|
+
|
|
411
|
+
# Iteration breakdown
|
|
412
|
+
if result.iterations:
|
|
413
|
+
self.console.print("\n📋 [bold]Iteration Breakdown:[/bold]")
|
|
414
|
+
for iteration in result.iterations:
|
|
415
|
+
status_symbol = "✅" if not iteration.hooks_failing else "❌"
|
|
416
|
+
self.console.print(
|
|
417
|
+
f" {status_symbol} Iteration {iteration.iteration_num}: "
|
|
418
|
+
f"{iteration.fixes_successful}/{iteration.fixes_applied} fixes successful "
|
|
419
|
+
f"({iteration.duration:.2f}s)"
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
self.console.print()
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def create_auto_fix_workflow(
|
|
426
|
+
project_path: Path | None = None,
|
|
427
|
+
console: Console | None = None,
|
|
428
|
+
enable_external_agents: bool = True,
|
|
429
|
+
) -> AutoFixWorkflow:
|
|
430
|
+
"""Factory function to create an AutoFixWorkflow.
|
|
431
|
+
|
|
432
|
+
Args:
|
|
433
|
+
project_path: Path to project root (defaults to cwd)
|
|
434
|
+
console: Rich console for output (creates default if None)
|
|
435
|
+
enable_external_agents: Enable Claude Code external agent integration
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
Configured AutoFixWorkflow instance
|
|
439
|
+
"""
|
|
440
|
+
return AutoFixWorkflow(
|
|
441
|
+
project_path=project_path,
|
|
442
|
+
console=console,
|
|
443
|
+
enable_external_agents=enable_external_agents,
|
|
444
|
+
)
|