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,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
|