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.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +96 -2
- crackerjack/__main__.py +637 -138
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +39 -0
- 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/lsp/_base.py +194 -0
- crackerjack/adapters/lsp/_client.py +358 -0
- crackerjack/adapters/lsp/_manager.py +193 -0
- crackerjack/adapters/lsp/skylos.py +283 -0
- crackerjack/adapters/lsp/zuban.py +557 -0
- 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 +66 -0
- crackerjack/agents/architect_agent.py +238 -0
- crackerjack/agents/base.py +167 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +600 -0
- crackerjack/agents/documentation_agent.py +520 -0
- crackerjack/agents/dry_agent.py +585 -0
- 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 +230 -0
- 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/import_optimization_agent.py +1181 -0
- crackerjack/agents/performance_agent.py +325 -0
- crackerjack/agents/performance_helpers.py +205 -0
- crackerjack/agents/proactive_agent.py +55 -0
- crackerjack/agents/refactoring_agent.py +511 -0
- crackerjack/agents/refactoring_helpers.py +247 -0
- crackerjack/agents/security_agent.py +793 -0
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +570 -0
- crackerjack/agents/test_specialist_agent.py +526 -0
- crackerjack/agents/tracker.py +110 -0
- crackerjack/api.py +647 -0
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/cache_handlers.py +209 -0
- crackerjack/cli/cache_handlers_enhanced.py +680 -0
- crackerjack/cli/facade.py +162 -0
- 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 +700 -0
- crackerjack/cli/interactive.py +488 -0
- crackerjack/cli/options.py +1216 -0
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/utils.py +19 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +1307 -0
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +275 -0
- crackerjack/config/global_lock_config.py +207 -0
- crackerjack/config/hooks.py +390 -0
- 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/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +738 -0
- crackerjack/core/autofix_coordinator.py +282 -0
- crackerjack/core/container.py +105 -0
- crackerjack/core/enhanced_container.py +583 -0
- crackerjack/core/file_lifecycle.py +472 -0
- crackerjack/core/performance.py +244 -0
- crackerjack/core/performance_monitor.py +357 -0
- crackerjack/core/phase_coordinator.py +1227 -0
- crackerjack/core/proactive_workflow.py +267 -0
- crackerjack/core/resource_manager.py +425 -0
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +601 -0
- crackerjack/core/session_coordinator.py +239 -0
- crackerjack/core/timeout_manager.py +563 -0
- crackerjack/core/websocket_lifecycle.py +410 -0
- 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 +2243 -0
- 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/INDEX.md +11 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +767 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +1065 -0
- crackerjack/dynamic_config.py +678 -0
- crackerjack/errors.py +378 -0
- 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 +13 -0
- crackerjack/executors/async_hook_executor.py +938 -0
- crackerjack/executors/cached_hook_executor.py +316 -0
- crackerjack/executors/hook_executor.py +1295 -0
- crackerjack/executors/hook_lock_manager.py +708 -0
- crackerjack/executors/individual_hook_executor.py +739 -0
- crackerjack/executors/lsp_aware_hook_executor.py +349 -0
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +433 -0
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +93 -0
- crackerjack/intelligence/README.md +557 -0
- crackerjack/intelligence/__init__.py +37 -0
- crackerjack/intelligence/adaptive_learning.py +693 -0
- crackerjack/intelligence/agent_orchestrator.py +485 -0
- crackerjack/intelligence/agent_registry.py +377 -0
- crackerjack/intelligence/agent_selector.py +439 -0
- crackerjack/intelligence/integration.py +250 -0
- crackerjack/interactive.py +719 -0
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +585 -0
- crackerjack/managers/publish_manager.py +631 -0
- crackerjack/managers/test_command_builder.py +391 -0
- crackerjack/managers/test_executor.py +474 -0
- crackerjack/managers/test_manager.py +1357 -0
- crackerjack/managers/test_progress.py +187 -0
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +352 -0
- crackerjack/mcp/client_runner.py +121 -0
- crackerjack/mcp/context.py +802 -0
- crackerjack/mcp/dashboard.py +657 -0
- crackerjack/mcp/enhanced_progress_monitor.py +493 -0
- crackerjack/mcp/file_monitor.py +394 -0
- crackerjack/mcp/progress_components.py +607 -0
- crackerjack/mcp/progress_monitor.py +1016 -0
- crackerjack/mcp/rate_limiter.py +336 -0
- crackerjack/mcp/server.py +24 -0
- crackerjack/mcp/server_core.py +526 -0
- crackerjack/mcp/service_watchdog.py +505 -0
- crackerjack/mcp/state.py +407 -0
- crackerjack/mcp/task_manager.py +259 -0
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +19 -0
- crackerjack/mcp/tools/core_tools.py +469 -0
- crackerjack/mcp/tools/error_analyzer.py +283 -0
- crackerjack/mcp/tools/execution_tools.py +384 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
- crackerjack/mcp/tools/intelligence_tools.py +264 -0
- crackerjack/mcp/tools/monitoring_tools.py +628 -0
- crackerjack/mcp/tools/proactive_tools.py +367 -0
- crackerjack/mcp/tools/progress_tools.py +222 -0
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +358 -0
- crackerjack/mcp/tools/workflow_executor.py +699 -0
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +54 -0
- crackerjack/mcp/websocket/endpoints.py +492 -0
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +406 -0
- 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 +21 -0
- crackerjack/mcp/websocket/server.py +174 -0
- crackerjack/mcp/websocket/websocket_handler.py +276 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +40 -0
- crackerjack/models/config.py +730 -0
- crackerjack/models/config_adapter.py +265 -0
- crackerjack/models/protocols.py +1535 -0
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/resource_protocols.py +299 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +173 -0
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +405 -0
- crackerjack/monitoring/metrics_collector.py +427 -0
- crackerjack/monitoring/regression_prevention.py +580 -0
- crackerjack/monitoring/websocket_server.py +406 -0
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +894 -0
- 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 +180 -0
- crackerjack/orchestration/execution_strategies.py +361 -0
- 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 +647 -0
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +254 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +264 -0
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/security/__init__.py +0 -0
- crackerjack/security/audit.py +197 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +9 -0
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/ai/contextual_ai_assistant.py +542 -0
- 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/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +617 -0
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +530 -0
- crackerjack/services/cache.py +369 -0
- crackerjack/services/changelog_automation.py +399 -0
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +132 -0
- crackerjack/services/config_merge.py +546 -0
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +493 -0
- crackerjack/services/coverage_badge_service.py +173 -0
- crackerjack/services/coverage_ratchet.py +381 -0
- crackerjack/services/debug.py +733 -0
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +622 -0
- crackerjack/services/documentation_generator.py +493 -0
- crackerjack/services/documentation_service.py +704 -0
- crackerjack/services/enhanced_filesystem.py +497 -0
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +149 -0
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +381 -0
- crackerjack/services/git.py +422 -0
- crackerjack/services/health_metrics.py +615 -0
- crackerjack/services/heatmap_generator.py +744 -0
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +823 -0
- crackerjack/services/input_validator.py +668 -0
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +289 -0
- crackerjack/services/logging.py +228 -0
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +414 -0
- crackerjack/services/metrics.py +587 -0
- 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/monitoring/performance_benchmarks.py +410 -0
- crackerjack/services/monitoring/performance_cache.py +388 -0
- crackerjack/services/monitoring/performance_monitor.py +569 -0
- crackerjack/services/parallel_executor.py +527 -0
- crackerjack/services/pattern_cache.py +333 -0
- crackerjack/services/pattern_detector.py +478 -0
- 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 +523 -0
- 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/quality_baseline.py +395 -0
- crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
- crackerjack/services/quality/quality_intelligence.py +949 -0
- crackerjack/services/regex_patterns.py +58 -0
- crackerjack/services/regex_utils.py +483 -0
- crackerjack/services/secure_path_utils.py +524 -0
- crackerjack/services/secure_status_formatter.py +450 -0
- crackerjack/services/secure_subprocess.py +635 -0
- crackerjack/services/security.py +239 -0
- crackerjack/services/security_logger.py +495 -0
- crackerjack/services/server_manager.py +411 -0
- crackerjack/services/smart_scheduling.py +167 -0
- crackerjack/services/status_authentication.py +460 -0
- crackerjack/services/status_security_manager.py +315 -0
- crackerjack/services/terminal_utils.py +0 -0
- crackerjack/services/thread_safe_status_collector.py +441 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +43 -0
- crackerjack/services/unified_config.py +115 -0
- crackerjack/services/validation_rate_limiter.py +220 -0
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +461 -0
- crackerjack/services/version_checker.py +223 -0
- crackerjack/services/websocket_resource_limiter.py +438 -0
- crackerjack/services/zuban_lsp_service.py +391 -0
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/__init__.py +59 -0
- crackerjack/slash_commands/init.md +112 -0
- crackerjack/slash_commands/run.md +197 -0
- crackerjack/slash_commands/status.md +127 -0
- 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_input_validator_patterns.py +236 -0
- crackerjack/tools/validate_regex_patterns.py +188 -0
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/__init__.py +1 -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.45.2.dist-info/METADATA +1678 -0
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -14
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config.yaml +0 -91
- crackerjack/.pytest_cache/.gitignore +0 -2
- crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
- crackerjack/.pytest_cache/README.md +0 -8
- crackerjack/.pytest_cache/v/cache/nodeids +0 -1
- crackerjack/.pytest_cache/v/cache/stepwise +0 -1
- crackerjack/.ruff_cache/.gitignore +0 -1
- crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
- crackerjack/crackerjack.py +0 -855
- crackerjack/pyproject.toml +0 -214
- crackerjack-0.18.2.dist-info/METADATA +0 -420
- crackerjack-0.18.2.dist-info/RECORD +0 -59
- crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
"""QA Orchestrator service for coordinating quality assurance checks.
|
|
2
|
+
|
|
3
|
+
This service coordinates multiple QA adapters, handles parallel execution,
|
|
4
|
+
caching, and result aggregation. It replaces the pre-commit hook orchestration
|
|
5
|
+
with native ACB-based quality checks.
|
|
6
|
+
|
|
7
|
+
ACB Patterns:
|
|
8
|
+
- Service implements QAOrchestratorProtocol from models.protocols
|
|
9
|
+
- Async execution throughout
|
|
10
|
+
- Proper error handling and logging
|
|
11
|
+
- Graceful degradation on adapter failures
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import contextlib
|
|
18
|
+
import hashlib
|
|
19
|
+
import typing as t
|
|
20
|
+
from datetime import datetime, timedelta
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
import yaml
|
|
24
|
+
from acb.depends import depends
|
|
25
|
+
|
|
26
|
+
from crackerjack.models.protocols import QAAdapterProtocol
|
|
27
|
+
from crackerjack.models.qa_config import QACheckConfig, QAOrchestratorConfig
|
|
28
|
+
from crackerjack.models.qa_results import QAResult, QAResultStatus
|
|
29
|
+
|
|
30
|
+
if t.TYPE_CHECKING:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class QAOrchestrator:
|
|
35
|
+
"""Orchestrates multiple QA adapters for comprehensive quality checking.
|
|
36
|
+
|
|
37
|
+
Coordinates execution of all registered QA adapters:
|
|
38
|
+
- Parallel execution with configurable concurrency
|
|
39
|
+
- Stage-based execution (fast vs comprehensive)
|
|
40
|
+
- Result caching for performance
|
|
41
|
+
- Formatter-first execution order
|
|
42
|
+
- Incremental checking support
|
|
43
|
+
|
|
44
|
+
Example:
|
|
45
|
+
```python
|
|
46
|
+
# Initialize orchestrator
|
|
47
|
+
config = QAOrchestratorConfig(
|
|
48
|
+
project_root=Path.cwd(),
|
|
49
|
+
max_parallel_checks=4,
|
|
50
|
+
enable_caching=True,
|
|
51
|
+
fail_fast=False,
|
|
52
|
+
)
|
|
53
|
+
orchestrator = QAOrchestrator(config)
|
|
54
|
+
|
|
55
|
+
# Register adapters
|
|
56
|
+
await orchestrator.register_adapter(ruff_adapter)
|
|
57
|
+
await orchestrator.register_adapter(bandit_adapter)
|
|
58
|
+
await orchestrator.register_adapter(zuban_adapter)
|
|
59
|
+
|
|
60
|
+
# Run fast stage checks
|
|
61
|
+
results = await orchestrator.run_checks(stage="fast")
|
|
62
|
+
|
|
63
|
+
# Run comprehensive checks
|
|
64
|
+
results = await orchestrator.run_checks(stage="comprehensive")
|
|
65
|
+
|
|
66
|
+
# Run all checks
|
|
67
|
+
all_results = await orchestrator.run_all_checks()
|
|
68
|
+
```
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, config: QAOrchestratorConfig) -> None:
|
|
72
|
+
"""Initialize QA orchestrator.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
config: Orchestrator configuration
|
|
76
|
+
"""
|
|
77
|
+
self.config = config
|
|
78
|
+
self._adapters: dict[str, QAAdapterProtocol] = {}
|
|
79
|
+
self._cache: dict[str, tuple[QAResult, datetime]] = {}
|
|
80
|
+
self._semaphore = asyncio.Semaphore(config.max_parallel_checks)
|
|
81
|
+
|
|
82
|
+
async def register_adapter(self, adapter: QAAdapterProtocol) -> None:
|
|
83
|
+
"""Register a QA adapter.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
adapter: QA adapter to register
|
|
87
|
+
"""
|
|
88
|
+
adapter_name = adapter.adapter_name
|
|
89
|
+
self._adapters[adapter_name] = adapter
|
|
90
|
+
|
|
91
|
+
# Initialize adapter if not already initialized
|
|
92
|
+
await adapter.init()
|
|
93
|
+
|
|
94
|
+
def get_adapter(self, name: str) -> QAAdapterProtocol | None:
|
|
95
|
+
"""Get registered adapter by name.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
name: Adapter name
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Adapter if found, None otherwise
|
|
102
|
+
"""
|
|
103
|
+
return self._adapters.get(name)
|
|
104
|
+
|
|
105
|
+
async def run_checks(
|
|
106
|
+
self,
|
|
107
|
+
stage: str = "fast",
|
|
108
|
+
files: list[Path] | None = None,
|
|
109
|
+
) -> list[QAResult]:
|
|
110
|
+
"""Run QA checks for specified stage.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
stage: Execution stage ('fast' or 'comprehensive')
|
|
114
|
+
files: Optional list of files to check
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
List of QAResult objects
|
|
118
|
+
"""
|
|
119
|
+
# Get checks for this stage
|
|
120
|
+
if stage == "fast":
|
|
121
|
+
checks = self.config.fast_checks
|
|
122
|
+
elif stage == "comprehensive":
|
|
123
|
+
checks = self.config.comprehensive_checks
|
|
124
|
+
else:
|
|
125
|
+
raise ValueError(f"Invalid stage: {stage}")
|
|
126
|
+
|
|
127
|
+
# Filter enabled checks
|
|
128
|
+
checks = [c for c in checks if c.enabled]
|
|
129
|
+
|
|
130
|
+
if not checks:
|
|
131
|
+
return []
|
|
132
|
+
|
|
133
|
+
# Sort checks: formatters first if configured
|
|
134
|
+
if self.config.run_formatters_first:
|
|
135
|
+
checks.sort(key=lambda c: (not c.is_formatter, c.check_name))
|
|
136
|
+
|
|
137
|
+
# Execute checks
|
|
138
|
+
results = await self._execute_checks(checks, files)
|
|
139
|
+
|
|
140
|
+
return results
|
|
141
|
+
|
|
142
|
+
async def run_all_checks(
|
|
143
|
+
self,
|
|
144
|
+
files: list[Path] | None = None,
|
|
145
|
+
) -> dict[str, t.Any]:
|
|
146
|
+
"""Run all registered QA checks.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
files: Optional list of files to check
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Dictionary mapping adapter names to results
|
|
153
|
+
"""
|
|
154
|
+
# Run fast stage
|
|
155
|
+
fast_results = await self.run_checks(stage="fast", files=files)
|
|
156
|
+
|
|
157
|
+
# Run comprehensive stage
|
|
158
|
+
comprehensive_results = await self.run_checks(
|
|
159
|
+
stage="comprehensive", files=files
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Aggregate results
|
|
163
|
+
all_results = fast_results + comprehensive_results
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
"fast_stage": fast_results,
|
|
167
|
+
"comprehensive_stage": comprehensive_results,
|
|
168
|
+
"all_results": all_results,
|
|
169
|
+
"summary": self._create_summary(all_results),
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
def _create_check_tasks(
|
|
173
|
+
self,
|
|
174
|
+
checks: list[QACheckConfig],
|
|
175
|
+
files: list[Path] | None,
|
|
176
|
+
) -> list[asyncio.Task]:
|
|
177
|
+
"""Create asyncio tasks for check execution."""
|
|
178
|
+
tasks = []
|
|
179
|
+
|
|
180
|
+
for check_config in checks:
|
|
181
|
+
adapter = self.get_adapter(check_config.check_name)
|
|
182
|
+
if not adapter:
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
# Create task for this check
|
|
186
|
+
task = self._execute_single_check(adapter, check_config, files)
|
|
187
|
+
tasks.append(task)
|
|
188
|
+
|
|
189
|
+
return tasks
|
|
190
|
+
|
|
191
|
+
async def _handle_fail_fast(
|
|
192
|
+
self, tasks: list[asyncio.Task]
|
|
193
|
+
) -> list[QAResult] | None:
|
|
194
|
+
"""Handle fail-fast logic if configured."""
|
|
195
|
+
if not self.config.fail_fast or not tasks:
|
|
196
|
+
return None
|
|
197
|
+
|
|
198
|
+
# Wait for first task to complete
|
|
199
|
+
done, pending = await asyncio.wait(
|
|
200
|
+
tasks[-1:], return_when=asyncio.FIRST_COMPLETED
|
|
201
|
+
)
|
|
202
|
+
result = done.pop().result()
|
|
203
|
+
if not result.is_success:
|
|
204
|
+
# Cancel remaining tasks
|
|
205
|
+
for pending_task in pending:
|
|
206
|
+
pending_task.cancel()
|
|
207
|
+
return [result]
|
|
208
|
+
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
def _filter_valid_results(self, results: list[t.Any]) -> list[QAResult]:
|
|
212
|
+
"""Filter out exceptions and convert to valid QAResult objects."""
|
|
213
|
+
valid_results = []
|
|
214
|
+
for result in results:
|
|
215
|
+
if isinstance(result, QAResult):
|
|
216
|
+
valid_results.append(result)
|
|
217
|
+
elif isinstance(result, Exception):
|
|
218
|
+
# Log error but continue
|
|
219
|
+
continue
|
|
220
|
+
return valid_results
|
|
221
|
+
|
|
222
|
+
async def _execute_checks(
|
|
223
|
+
self,
|
|
224
|
+
checks: list[QACheckConfig],
|
|
225
|
+
files: list[Path] | None,
|
|
226
|
+
) -> list[QAResult]:
|
|
227
|
+
"""Execute multiple checks in parallel.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
checks: List of check configurations
|
|
231
|
+
files: Optional files to check
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
List of QAResult objects
|
|
235
|
+
"""
|
|
236
|
+
tasks = self._create_check_tasks(checks, files)
|
|
237
|
+
|
|
238
|
+
# Handle fail fast logic if needed
|
|
239
|
+
fail_result = await self._handle_fail_fast(tasks)
|
|
240
|
+
if fail_result is not None:
|
|
241
|
+
return fail_result
|
|
242
|
+
|
|
243
|
+
# Execute all tasks
|
|
244
|
+
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
245
|
+
|
|
246
|
+
# Filter out exceptions and convert to QAResult
|
|
247
|
+
return self._filter_valid_results(results)
|
|
248
|
+
|
|
249
|
+
async def _execute_single_check(
|
|
250
|
+
self,
|
|
251
|
+
adapter: QAAdapterProtocol,
|
|
252
|
+
config: QACheckConfig,
|
|
253
|
+
files: list[Path] | None,
|
|
254
|
+
) -> QAResult:
|
|
255
|
+
"""Execute a single check with caching and semaphore control.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
adapter: QA adapter to execute
|
|
259
|
+
config: Check configuration
|
|
260
|
+
files: Optional files to check
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
QAResult
|
|
264
|
+
"""
|
|
265
|
+
# Generate cache key
|
|
266
|
+
cache_key = self._generate_cache_key(adapter, config, files)
|
|
267
|
+
|
|
268
|
+
# Check cache if enabled
|
|
269
|
+
if self.config.enable_caching:
|
|
270
|
+
cached_result = self._get_cached_result(cache_key)
|
|
271
|
+
if cached_result:
|
|
272
|
+
return cached_result
|
|
273
|
+
|
|
274
|
+
# Acquire semaphore for parallel execution control
|
|
275
|
+
async with self._semaphore:
|
|
276
|
+
try:
|
|
277
|
+
# Execute check
|
|
278
|
+
result = await adapter.check(files=files, config=config)
|
|
279
|
+
|
|
280
|
+
# Cache result if enabled
|
|
281
|
+
if self.config.enable_caching:
|
|
282
|
+
self._cache_result(cache_key, result)
|
|
283
|
+
|
|
284
|
+
# Retry on failure if configured
|
|
285
|
+
if not result.is_success and config.retry_on_failure:
|
|
286
|
+
result = await adapter.check(files=files, config=config)
|
|
287
|
+
|
|
288
|
+
return result
|
|
289
|
+
|
|
290
|
+
except Exception as e:
|
|
291
|
+
# Return error result
|
|
292
|
+
return QAResult(
|
|
293
|
+
check_id=config.check_id,
|
|
294
|
+
check_name=adapter.adapter_name,
|
|
295
|
+
check_type=config.check_type,
|
|
296
|
+
status=QAResultStatus.ERROR,
|
|
297
|
+
message=f"Check failed: {e}",
|
|
298
|
+
details=str(e),
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
def _generate_cache_key(
|
|
302
|
+
self,
|
|
303
|
+
adapter: QAAdapterProtocol,
|
|
304
|
+
config: QACheckConfig,
|
|
305
|
+
files: list[Path] | None,
|
|
306
|
+
) -> str:
|
|
307
|
+
"""Generate cache key for check execution.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
adapter: QA adapter
|
|
311
|
+
config: Check configuration
|
|
312
|
+
files: Files to check
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Cache key string
|
|
316
|
+
"""
|
|
317
|
+
key_parts = [
|
|
318
|
+
adapter.adapter_name,
|
|
319
|
+
str(config.check_id),
|
|
320
|
+
str(sorted([str(f) for f in files]) if files else "all"),
|
|
321
|
+
]
|
|
322
|
+
|
|
323
|
+
key_string = "|".join(key_parts)
|
|
324
|
+
return hashlib.sha256(key_string.encode()).hexdigest()[:16]
|
|
325
|
+
|
|
326
|
+
def _get_cached_result(self, cache_key: str) -> QAResult | None:
|
|
327
|
+
"""Get cached result if valid.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
cache_key: Cache key
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
Cached QAResult or None
|
|
334
|
+
"""
|
|
335
|
+
if cache_key not in self._cache:
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
result, timestamp = self._cache[cache_key]
|
|
339
|
+
|
|
340
|
+
# Check if cache is still valid (1 hour TTL)
|
|
341
|
+
if datetime.now() - timestamp > timedelta(hours=1):
|
|
342
|
+
del self._cache[cache_key]
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
return result
|
|
346
|
+
|
|
347
|
+
def _cache_result(self, cache_key: str, result: QAResult) -> None:
|
|
348
|
+
"""Cache check result.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
cache_key: Cache key
|
|
352
|
+
result: QAResult to cache
|
|
353
|
+
"""
|
|
354
|
+
self._cache[cache_key] = (result, datetime.now())
|
|
355
|
+
|
|
356
|
+
def _create_summary(self, results: list[QAResult]) -> dict[str, t.Any]:
|
|
357
|
+
"""Create summary statistics from results.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
results: List of QAResult objects
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Summary dictionary
|
|
364
|
+
"""
|
|
365
|
+
total_checks = len(results)
|
|
366
|
+
success_count = sum(1 for r in results if r.is_success)
|
|
367
|
+
failure_count = sum(1 for r in results if r.status == QAResultStatus.FAILURE)
|
|
368
|
+
error_count = sum(1 for r in results if r.status == QAResultStatus.ERROR)
|
|
369
|
+
warning_count = sum(1 for r in results if r.status == QAResultStatus.WARNING)
|
|
370
|
+
|
|
371
|
+
total_issues = sum(r.issues_found for r in results)
|
|
372
|
+
total_fixed = sum(r.issues_fixed for r in results)
|
|
373
|
+
total_execution_time = sum(r.execution_time_ms for r in results)
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
"total_checks": total_checks,
|
|
377
|
+
"success": success_count,
|
|
378
|
+
"failures": failure_count,
|
|
379
|
+
"errors": error_count,
|
|
380
|
+
"warnings": warning_count,
|
|
381
|
+
"total_issues_found": total_issues,
|
|
382
|
+
"total_issues_fixed": total_fixed,
|
|
383
|
+
"total_execution_time_ms": total_execution_time,
|
|
384
|
+
"pass_rate": success_count / total_checks if total_checks > 0 else 0.0,
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@classmethod
|
|
388
|
+
async def from_yaml_config(
|
|
389
|
+
cls,
|
|
390
|
+
config_path: Path,
|
|
391
|
+
project_root: Path | None = None,
|
|
392
|
+
) -> QAOrchestrator:
|
|
393
|
+
"""Create orchestrator from YAML configuration.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
config_path: Path to YAML configuration file
|
|
397
|
+
project_root: Optional project root override
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
Configured QAOrchestrator instance
|
|
401
|
+
|
|
402
|
+
Example YAML:
|
|
403
|
+
```yaml
|
|
404
|
+
project_root: .
|
|
405
|
+
max_parallel_checks: 4
|
|
406
|
+
enable_caching: true
|
|
407
|
+
fail_fast: false
|
|
408
|
+
run_formatters_first: true
|
|
409
|
+
|
|
410
|
+
checks:
|
|
411
|
+
- check_name: ruff-lint
|
|
412
|
+
check_type: lint
|
|
413
|
+
enabled: true
|
|
414
|
+
stage: fast
|
|
415
|
+
settings:
|
|
416
|
+
mode: check
|
|
417
|
+
fix_enabled: false
|
|
418
|
+
|
|
419
|
+
- check_name: ruff-format
|
|
420
|
+
check_type: format
|
|
421
|
+
enabled: true
|
|
422
|
+
stage: fast
|
|
423
|
+
settings:
|
|
424
|
+
mode: format
|
|
425
|
+
fix_enabled: false
|
|
426
|
+
|
|
427
|
+
- check_name: bandit
|
|
428
|
+
check_type: security
|
|
429
|
+
enabled: true
|
|
430
|
+
stage: comprehensive
|
|
431
|
+
```
|
|
432
|
+
"""
|
|
433
|
+
if not config_path.exists():
|
|
434
|
+
raise FileNotFoundError(f"Config file not found: {config_path}")
|
|
435
|
+
|
|
436
|
+
# Load YAML configuration
|
|
437
|
+
with config_path.open() as f:
|
|
438
|
+
config_data = yaml.safe_load(f)
|
|
439
|
+
|
|
440
|
+
# Create orchestrator config
|
|
441
|
+
if project_root is None:
|
|
442
|
+
project_root = Path(config_data.get("project_root", "."))
|
|
443
|
+
|
|
444
|
+
config = QAOrchestratorConfig(
|
|
445
|
+
project_root=project_root,
|
|
446
|
+
max_parallel_checks=config_data.get("max_parallel_checks", 4),
|
|
447
|
+
enable_caching=config_data.get("enable_caching", True),
|
|
448
|
+
fail_fast=config_data.get("fail_fast", False),
|
|
449
|
+
run_formatters_first=config_data.get("run_formatters_first", True),
|
|
450
|
+
enable_incremental=config_data.get("enable_incremental", True),
|
|
451
|
+
verbose=config_data.get("verbose", False),
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# Create orchestrator
|
|
455
|
+
orchestrator = cls(config)
|
|
456
|
+
|
|
457
|
+
# Load and register adapters based on configuration
|
|
458
|
+
# This would be implemented to dynamically load adapters
|
|
459
|
+
# based on the YAML configuration
|
|
460
|
+
|
|
461
|
+
return orchestrator
|
|
462
|
+
|
|
463
|
+
async def health_check(self) -> dict[str, t.Any]:
|
|
464
|
+
"""Check health of orchestrator and all adapters.
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
Health status dictionary
|
|
468
|
+
"""
|
|
469
|
+
adapter_health = {}
|
|
470
|
+
|
|
471
|
+
for name, adapter in self._adapters.items():
|
|
472
|
+
try:
|
|
473
|
+
health = await adapter.health_check()
|
|
474
|
+
adapter_health[name] = health
|
|
475
|
+
except Exception as e:
|
|
476
|
+
adapter_health[name] = {
|
|
477
|
+
"status": "error",
|
|
478
|
+
"error": str(e),
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return {
|
|
482
|
+
"orchestrator_status": "healthy",
|
|
483
|
+
"registered_adapters": len(self._adapters),
|
|
484
|
+
"cache_entries": len(self._cache),
|
|
485
|
+
"adapters": adapter_health,
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
# Register orchestrator with ACB dependency injection
|
|
490
|
+
with contextlib.suppress(Exception):
|
|
491
|
+
depends.set(QAOrchestrator)
|