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
|
@@ -1,81 +1,403 @@
|
|
|
1
|
-
import subprocess
|
|
2
1
|
import typing as t
|
|
2
|
+
from contextlib import suppress
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from acb.console import Console
|
|
6
|
+
from acb.depends import depends
|
|
6
7
|
|
|
8
|
+
from crackerjack.config import CrackerjackSettings
|
|
7
9
|
from crackerjack.config.hooks import HookConfigLoader
|
|
8
10
|
from crackerjack.executors.hook_executor import HookExecutor
|
|
9
11
|
from crackerjack.executors.lsp_aware_hook_executor import LSPAwareHookExecutor
|
|
12
|
+
from crackerjack.executors.progress_hook_executor import ProgressHookExecutor
|
|
10
13
|
from crackerjack.models.task import HookResult
|
|
11
14
|
|
|
15
|
+
if t.TYPE_CHECKING:
|
|
16
|
+
from crackerjack.orchestration.hook_orchestrator import HookOrchestratorAdapter
|
|
17
|
+
|
|
12
18
|
|
|
13
19
|
class HookManagerImpl:
|
|
20
|
+
executor: HookExecutor | LSPAwareHookExecutor | ProgressHookExecutor
|
|
21
|
+
|
|
22
|
+
def _setup_git_service(self, use_incremental: bool, pkg_path: Path):
|
|
23
|
+
"""Setup GitService for incremental execution."""
|
|
24
|
+
from crackerjack.services.git import GitService
|
|
25
|
+
|
|
26
|
+
git_service = None
|
|
27
|
+
if use_incremental:
|
|
28
|
+
git_service = GitService(self.console, pkg_path)
|
|
29
|
+
return git_service
|
|
30
|
+
|
|
31
|
+
def _setup_executor(
|
|
32
|
+
self,
|
|
33
|
+
pkg_path: Path,
|
|
34
|
+
verbose: bool,
|
|
35
|
+
quiet: bool,
|
|
36
|
+
debug: bool,
|
|
37
|
+
enable_lsp_optimization: bool,
|
|
38
|
+
enable_tool_proxy: bool,
|
|
39
|
+
use_incremental: bool,
|
|
40
|
+
git_service: t.Any,
|
|
41
|
+
):
|
|
42
|
+
"""Setup the appropriate executor based on configuration."""
|
|
43
|
+
if enable_lsp_optimization:
|
|
44
|
+
self.executor = LSPAwareHookExecutor(
|
|
45
|
+
self.console,
|
|
46
|
+
pkg_path,
|
|
47
|
+
verbose,
|
|
48
|
+
quiet,
|
|
49
|
+
debug,
|
|
50
|
+
use_tool_proxy=enable_tool_proxy,
|
|
51
|
+
use_incremental=use_incremental,
|
|
52
|
+
git_service=git_service,
|
|
53
|
+
)
|
|
54
|
+
else:
|
|
55
|
+
# Use HookExecutor - match what tests expect
|
|
56
|
+
# Pass only the expected positional arguments for test compatibility
|
|
57
|
+
self.executor = HookExecutor( # type: ignore[assignment]
|
|
58
|
+
self.console,
|
|
59
|
+
pkg_path,
|
|
60
|
+
verbose,
|
|
61
|
+
quiet,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def _load_from_project_config(
|
|
65
|
+
self,
|
|
66
|
+
config_path: Path,
|
|
67
|
+
enable_orchestration: bool | None,
|
|
68
|
+
orchestration_mode: str | None,
|
|
69
|
+
) -> None:
|
|
70
|
+
"""Load orchestration config from project .crackerjack.yaml file."""
|
|
71
|
+
from crackerjack.orchestration.config import OrchestrationConfig
|
|
72
|
+
|
|
73
|
+
loaded_config = OrchestrationConfig.load(config_path)
|
|
74
|
+
self._orchestration_config: t.Any = loaded_config # Can be either OrchestrationConfig or HookOrchestratorSettings
|
|
75
|
+
# Extract orchestration settings with param override
|
|
76
|
+
self.orchestration_enabled = (
|
|
77
|
+
enable_orchestration
|
|
78
|
+
if enable_orchestration is not None
|
|
79
|
+
else loaded_config.enable_orchestration
|
|
80
|
+
)
|
|
81
|
+
self.orchestration_mode = (
|
|
82
|
+
orchestration_mode
|
|
83
|
+
if orchestration_mode is not None
|
|
84
|
+
else loaded_config.orchestration_mode
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def _create_default_orchestration_config(
|
|
88
|
+
self,
|
|
89
|
+
enable_orchestration: bool | None,
|
|
90
|
+
orchestration_mode: str | None,
|
|
91
|
+
enable_caching: bool,
|
|
92
|
+
cache_backend: str,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Create default orchestration config from constructor params."""
|
|
95
|
+
from crackerjack.orchestration.hook_orchestrator import (
|
|
96
|
+
HookOrchestratorSettings,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
self._orchestration_config = HookOrchestratorSettings(
|
|
100
|
+
enable_caching=enable_caching,
|
|
101
|
+
cache_backend=cache_backend,
|
|
102
|
+
)
|
|
103
|
+
# Default to enabled unless explicitly disabled
|
|
104
|
+
# Fallback chain: explicit param -> DI settings -> True (application default)
|
|
105
|
+
self.orchestration_enabled = (
|
|
106
|
+
bool(enable_orchestration)
|
|
107
|
+
if enable_orchestration is not None
|
|
108
|
+
else getattr(self._settings, "enable_orchestration", True)
|
|
109
|
+
)
|
|
110
|
+
self.orchestration_mode = (
|
|
111
|
+
orchestration_mode
|
|
112
|
+
if orchestration_mode is not None
|
|
113
|
+
else (self._settings.orchestration_mode or "acb")
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def _load_orchestration_config(
|
|
117
|
+
self,
|
|
118
|
+
pkg_path: Path,
|
|
119
|
+
orchestration_config: t.Any,
|
|
120
|
+
enable_orchestration: bool | None,
|
|
121
|
+
orchestration_mode: str | None,
|
|
122
|
+
enable_caching: bool,
|
|
123
|
+
cache_backend: str,
|
|
124
|
+
):
|
|
125
|
+
"""Load orchestration configuration with priority."""
|
|
126
|
+
# Get settings from ACB dependency injection
|
|
127
|
+
self._settings = depends.get_sync(CrackerjackSettings)
|
|
128
|
+
|
|
129
|
+
# Load orchestration config with priority:
|
|
130
|
+
# 1. Explicit orchestration_config param (highest - for testing)
|
|
131
|
+
# 2. Project .crackerjack.yaml file (middle - for project-specific settings)
|
|
132
|
+
# 3. Create from constructor params + DI settings (lowest - for defaults)
|
|
133
|
+
if orchestration_config:
|
|
134
|
+
# Explicit config object provided - use its values directly
|
|
135
|
+
# Legacy parameters (enable_orchestration, orchestration_mode) are ignored
|
|
136
|
+
# when an explicit config object is provided
|
|
137
|
+
self._orchestration_config = orchestration_config
|
|
138
|
+
self.orchestration_enabled = getattr(
|
|
139
|
+
orchestration_config, "enable_orchestration", False
|
|
140
|
+
)
|
|
141
|
+
self.orchestration_mode = getattr(
|
|
142
|
+
orchestration_config, "orchestration_mode", "acb"
|
|
143
|
+
)
|
|
144
|
+
else:
|
|
145
|
+
config_path = pkg_path / ".crackerjack.yaml"
|
|
146
|
+
if config_path.exists():
|
|
147
|
+
self._load_from_project_config(
|
|
148
|
+
config_path, enable_orchestration, orchestration_mode
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
self._create_default_orchestration_config(
|
|
152
|
+
enable_orchestration,
|
|
153
|
+
orchestration_mode,
|
|
154
|
+
enable_caching,
|
|
155
|
+
cache_backend,
|
|
156
|
+
)
|
|
157
|
+
|
|
14
158
|
def __init__(
|
|
15
159
|
self,
|
|
16
|
-
console: Console,
|
|
17
160
|
pkg_path: Path,
|
|
18
161
|
verbose: bool = False,
|
|
19
162
|
quiet: bool = False,
|
|
163
|
+
debug: bool = False,
|
|
20
164
|
enable_lsp_optimization: bool = False,
|
|
21
165
|
enable_tool_proxy: bool = True,
|
|
166
|
+
use_incremental: bool = False,
|
|
167
|
+
# Legacy parameters kept for backward compatibility (deprecated)
|
|
168
|
+
orchestration_config: t.Any = None,
|
|
169
|
+
enable_orchestration: bool | None = None,
|
|
170
|
+
orchestration_mode: str | None = None,
|
|
171
|
+
enable_caching: bool = True,
|
|
172
|
+
cache_backend: str = "memory",
|
|
173
|
+
console: t.Any = None, # Accept console parameter for DI
|
|
22
174
|
) -> None:
|
|
23
|
-
self.console = console
|
|
24
175
|
self.pkg_path = pkg_path
|
|
25
|
-
self.
|
|
176
|
+
self.debug = debug
|
|
177
|
+
|
|
178
|
+
# Use provided console or get from DI
|
|
179
|
+
self.console = console or depends.get_sync(Console)
|
|
180
|
+
|
|
181
|
+
# Get GitService for incremental execution
|
|
182
|
+
git_service = self._setup_git_service(use_incremental, pkg_path)
|
|
26
183
|
|
|
27
184
|
# Use LSP-aware executor if optimization is enabled
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
185
|
+
self._setup_executor(
|
|
186
|
+
pkg_path,
|
|
187
|
+
verbose,
|
|
188
|
+
quiet,
|
|
189
|
+
debug,
|
|
190
|
+
enable_lsp_optimization,
|
|
191
|
+
enable_tool_proxy,
|
|
192
|
+
use_incremental,
|
|
193
|
+
git_service,
|
|
194
|
+
)
|
|
34
195
|
|
|
35
196
|
self.config_loader = HookConfigLoader()
|
|
36
197
|
self._config_path: Path | None = None
|
|
37
198
|
self.lsp_optimization_enabled = enable_lsp_optimization
|
|
38
199
|
self.tool_proxy_enabled = enable_tool_proxy
|
|
39
200
|
|
|
201
|
+
self._load_orchestration_config(
|
|
202
|
+
pkg_path,
|
|
203
|
+
orchestration_config,
|
|
204
|
+
enable_orchestration,
|
|
205
|
+
orchestration_mode,
|
|
206
|
+
enable_caching,
|
|
207
|
+
cache_backend,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
self._orchestrator: HookOrchestratorAdapter | None = None
|
|
211
|
+
|
|
40
212
|
def set_config_path(self, config_path: Path) -> None:
|
|
41
213
|
self._config_path = config_path
|
|
42
214
|
|
|
215
|
+
async def _init_orchestrator(self) -> None:
|
|
216
|
+
"""Initialize orchestrator if not already initialized."""
|
|
217
|
+
if self._orchestrator is not None:
|
|
218
|
+
return # Already initialized
|
|
219
|
+
|
|
220
|
+
from crackerjack.orchestration.hook_orchestrator import (
|
|
221
|
+
HookOrchestratorAdapter,
|
|
222
|
+
HookOrchestratorSettings,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Create orchestrator settings from orchestration config
|
|
226
|
+
# Handle both OrchestrationConfig (uses orchestration_mode) and
|
|
227
|
+
# HookOrchestratorSettings (uses execution_mode)
|
|
228
|
+
execution_mode = getattr(
|
|
229
|
+
self._orchestration_config,
|
|
230
|
+
"execution_mode",
|
|
231
|
+
getattr(self._orchestration_config, "orchestration_mode", "acb"),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
orchestrator_settings = HookOrchestratorSettings(
|
|
235
|
+
execution_mode=execution_mode,
|
|
236
|
+
enable_caching=self._orchestration_config.enable_caching,
|
|
237
|
+
cache_backend=self._orchestration_config.cache_backend,
|
|
238
|
+
max_parallel_hooks=self._orchestration_config.max_parallel_hooks,
|
|
239
|
+
enable_adaptive_execution=getattr(
|
|
240
|
+
self._orchestration_config, "enable_adaptive_execution", True
|
|
241
|
+
),
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
self._orchestrator = HookOrchestratorAdapter(
|
|
245
|
+
settings=orchestrator_settings,
|
|
246
|
+
hook_executor=self.executor, # Provide executor for legacy mode fallback
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
await self._orchestrator.init()
|
|
250
|
+
|
|
251
|
+
async def _run_fast_hooks_orchestrated(self) -> list[HookResult]:
|
|
252
|
+
"""Run fast hooks using orchestrator (async path)."""
|
|
253
|
+
await self._init_orchestrator()
|
|
254
|
+
assert self._orchestrator is not None
|
|
255
|
+
|
|
256
|
+
strategy = self.config_loader.load_strategy("fast")
|
|
257
|
+
|
|
258
|
+
if self._config_path:
|
|
259
|
+
for hook in strategy.hooks:
|
|
260
|
+
hook.config_path = self._config_path
|
|
261
|
+
|
|
262
|
+
# Check for progress callback from PhaseCoordinator
|
|
263
|
+
getattr(self, "_progress_callback", None)
|
|
264
|
+
|
|
265
|
+
return await self._orchestrator.execute_strategy(
|
|
266
|
+
strategy,
|
|
267
|
+
progress_callback=getattr(self, "_progress_callback", None),
|
|
268
|
+
progress_start_callback=getattr(self, "_progress_start_callback", None),
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
async def _run_comprehensive_hooks_orchestrated(self) -> list[HookResult]:
|
|
272
|
+
"""Run comprehensive hooks using orchestrator (async path)."""
|
|
273
|
+
await self._init_orchestrator()
|
|
274
|
+
assert self._orchestrator is not None
|
|
275
|
+
|
|
276
|
+
strategy = self.config_loader.load_strategy("comprehensive")
|
|
277
|
+
|
|
278
|
+
if self._config_path:
|
|
279
|
+
for hook in strategy.hooks:
|
|
280
|
+
hook.config_path = self._config_path
|
|
281
|
+
|
|
282
|
+
# Check for progress callback from PhaseCoordinator
|
|
283
|
+
getattr(self, "_progress_callback", None)
|
|
284
|
+
|
|
285
|
+
return await self._orchestrator.execute_strategy(
|
|
286
|
+
strategy,
|
|
287
|
+
progress_callback=getattr(self, "_progress_callback", None),
|
|
288
|
+
progress_start_callback=getattr(self, "_progress_start_callback", None),
|
|
289
|
+
)
|
|
290
|
+
|
|
43
291
|
def run_fast_hooks(self) -> list[HookResult]:
|
|
292
|
+
# Use orchestrator if enabled (Phase 3+)
|
|
293
|
+
if self.orchestration_enabled:
|
|
294
|
+
import asyncio
|
|
295
|
+
|
|
296
|
+
# Check if we're already in an event loop (e.g., during testing)
|
|
297
|
+
try:
|
|
298
|
+
asyncio.get_running_loop()
|
|
299
|
+
# We're in an event loop, run in thread
|
|
300
|
+
import concurrent.futures
|
|
301
|
+
|
|
302
|
+
# Let executor show progress - orchestrator doesn't display progress
|
|
303
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
304
|
+
future = executor.submit(
|
|
305
|
+
asyncio.run, self._run_fast_hooks_orchestrated()
|
|
306
|
+
)
|
|
307
|
+
return future.result()
|
|
308
|
+
except RuntimeError:
|
|
309
|
+
# No event loop running, safe to use asyncio.run()
|
|
310
|
+
return asyncio.run(self._run_fast_hooks_orchestrated())
|
|
311
|
+
|
|
312
|
+
# Legacy executor path (Phase 1-2)
|
|
44
313
|
strategy = self.config_loader.load_strategy("fast")
|
|
45
314
|
|
|
46
315
|
if self._config_path:
|
|
47
316
|
for hook in strategy.hooks:
|
|
48
317
|
hook.config_path = self._config_path
|
|
318
|
+
# Wire progress callbacks for legacy executor path so ticks update
|
|
319
|
+
with suppress(Exception):
|
|
320
|
+
self.executor.set_progress_callbacks(
|
|
321
|
+
started_cb=getattr(self, "_progress_start_callback", None),
|
|
322
|
+
completed_cb=getattr(self, "_progress_callback", None),
|
|
323
|
+
total=len(strategy.hooks),
|
|
324
|
+
)
|
|
49
325
|
execution_result = self.executor.execute_strategy(strategy)
|
|
50
326
|
return execution_result.results
|
|
51
327
|
|
|
52
328
|
def run_comprehensive_hooks(self) -> list[HookResult]:
|
|
329
|
+
# Use orchestrator if enabled (Phase 3+)
|
|
330
|
+
if self.orchestration_enabled:
|
|
331
|
+
import asyncio
|
|
332
|
+
|
|
333
|
+
# Check if we're already in an event loop (e.g., during testing)
|
|
334
|
+
try:
|
|
335
|
+
asyncio.get_running_loop()
|
|
336
|
+
# We're in an event loop, run in thread
|
|
337
|
+
import concurrent.futures
|
|
338
|
+
|
|
339
|
+
# Let executor show progress - orchestrator doesn't display progress
|
|
340
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
341
|
+
future = executor.submit(
|
|
342
|
+
asyncio.run, self._run_comprehensive_hooks_orchestrated()
|
|
343
|
+
)
|
|
344
|
+
return future.result()
|
|
345
|
+
except RuntimeError:
|
|
346
|
+
# No event loop running, safe to use asyncio.run()
|
|
347
|
+
return asyncio.run(self._run_comprehensive_hooks_orchestrated())
|
|
348
|
+
|
|
349
|
+
# Legacy executor path (Phase 1-2)
|
|
53
350
|
strategy = self.config_loader.load_strategy("comprehensive")
|
|
54
351
|
|
|
55
352
|
if self._config_path:
|
|
56
353
|
for hook in strategy.hooks:
|
|
57
354
|
hook.config_path = self._config_path
|
|
355
|
+
# Wire progress callbacks for legacy executor path so ticks update
|
|
356
|
+
with suppress(Exception):
|
|
357
|
+
self.executor.set_progress_callbacks(
|
|
358
|
+
started_cb=getattr(self, "_progress_start_callback", None),
|
|
359
|
+
completed_cb=getattr(self, "_progress_callback", None),
|
|
360
|
+
total=len(strategy.hooks),
|
|
361
|
+
)
|
|
58
362
|
execution_result = self.executor.execute_strategy(strategy)
|
|
59
363
|
return execution_result.results
|
|
60
364
|
|
|
365
|
+
async def _run_hooks_parallel(self) -> list[HookResult]:
|
|
366
|
+
"""Run fast and comprehensive strategies in parallel (async helper)."""
|
|
367
|
+
import asyncio
|
|
368
|
+
|
|
369
|
+
fast_task = self._run_fast_hooks_orchestrated()
|
|
370
|
+
comp_task = self._run_comprehensive_hooks_orchestrated()
|
|
371
|
+
|
|
372
|
+
fast_results, comp_results = await asyncio.gather(fast_task, comp_task)
|
|
373
|
+
return fast_results + comp_results
|
|
374
|
+
|
|
61
375
|
def run_hooks(self) -> list[HookResult]:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
376
|
+
# Phase 5-7: Enable strategy-level parallelism when orchestration is enabled
|
|
377
|
+
# Use config's enable_strategy_parallelism setting (defaults to True if not set)
|
|
378
|
+
enable_parallelism = getattr(
|
|
379
|
+
self._orchestration_config, "enable_strategy_parallelism", True
|
|
380
|
+
)
|
|
381
|
+
if self.orchestration_enabled and enable_parallelism:
|
|
382
|
+
import asyncio
|
|
65
383
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"executor_type": type(self.executor).__name__,
|
|
72
|
-
}
|
|
384
|
+
# Check if we're already in an event loop (e.g., during testing)
|
|
385
|
+
try:
|
|
386
|
+
asyncio.get_running_loop()
|
|
387
|
+
# We're in an event loop, use nest_asyncio or run in thread
|
|
388
|
+
import concurrent.futures
|
|
73
389
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
390
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
391
|
+
future = executor.submit(asyncio.run, self._run_hooks_parallel())
|
|
392
|
+
return future.result()
|
|
393
|
+
except RuntimeError:
|
|
394
|
+
# No event loop running, safe to use asyncio.run()
|
|
395
|
+
return asyncio.run(self._run_hooks_parallel())
|
|
77
396
|
|
|
78
|
-
|
|
397
|
+
# Legacy path: Sequential execution (backward compatibility)
|
|
398
|
+
fast_results = self.run_fast_hooks()
|
|
399
|
+
comprehensive_results = self.run_comprehensive_hooks()
|
|
400
|
+
return fast_results + comprehensive_results
|
|
79
401
|
|
|
80
402
|
def configure_lsp_optimization(self, enable: bool) -> None:
|
|
81
403
|
"""Enable or disable LSP optimization by switching executors."""
|
|
@@ -84,7 +406,7 @@ class HookManagerImpl:
|
|
|
84
406
|
|
|
85
407
|
# Switch executor based on the enable flag
|
|
86
408
|
if enable:
|
|
87
|
-
self.executor = LSPAwareHookExecutor(
|
|
409
|
+
self.executor = LSPAwareHookExecutor( # type: ignore[assignment]
|
|
88
410
|
self.console,
|
|
89
411
|
self.pkg_path,
|
|
90
412
|
verbose=getattr(self.executor, "verbose", False),
|
|
@@ -92,7 +414,7 @@ class HookManagerImpl:
|
|
|
92
414
|
use_tool_proxy=self.tool_proxy_enabled,
|
|
93
415
|
)
|
|
94
416
|
else:
|
|
95
|
-
self.executor = HookExecutor(
|
|
417
|
+
self.executor = HookExecutor( # type: ignore[assignment]
|
|
96
418
|
self.console,
|
|
97
419
|
self.pkg_path,
|
|
98
420
|
verbose=getattr(self.executor, "verbose", False),
|
|
@@ -127,18 +449,54 @@ class HookManagerImpl:
|
|
|
127
449
|
if self._config_path:
|
|
128
450
|
pass # Config path handled at manager level
|
|
129
451
|
|
|
130
|
-
def
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
452
|
+
async def get_orchestration_stats(self) -> dict[str, t.Any] | None:
|
|
453
|
+
"""Get orchestration statistics if orchestrator is initialized.
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
Dictionary with orchestration stats, or None if orchestration disabled
|
|
457
|
+
"""
|
|
458
|
+
if not self.orchestration_enabled or self._orchestrator is None:
|
|
459
|
+
return None
|
|
460
|
+
|
|
461
|
+
return await self._orchestrator.get_cache_stats()
|
|
462
|
+
|
|
463
|
+
def get_execution_info(self) -> dict[str, t.Any]:
|
|
464
|
+
"""Get information about current execution mode and capabilities."""
|
|
465
|
+
info = {
|
|
466
|
+
"lsp_optimization_enabled": self.lsp_optimization_enabled,
|
|
467
|
+
"tool_proxy_enabled": self.tool_proxy_enabled,
|
|
468
|
+
"executor_type": type(self.executor).__name__,
|
|
469
|
+
# Use instance properties which may override settings via constructor params
|
|
470
|
+
"orchestration_enabled": self.orchestration_enabled,
|
|
471
|
+
"orchestration_mode": (
|
|
472
|
+
self.orchestration_mode if self.orchestration_enabled else None
|
|
473
|
+
),
|
|
474
|
+
"caching_enabled": (
|
|
475
|
+
self._orchestration_config.enable_caching
|
|
476
|
+
if self.orchestration_enabled
|
|
477
|
+
else False
|
|
478
|
+
),
|
|
479
|
+
"cache_backend": (
|
|
480
|
+
self._orchestration_config.cache_backend
|
|
481
|
+
if self.orchestration_enabled
|
|
482
|
+
else None
|
|
483
|
+
),
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
# Get LSP-specific info if available
|
|
487
|
+
if hasattr(self.executor, "get_execution_mode_summary"):
|
|
488
|
+
info.update(self.executor.get_execution_mode_summary())
|
|
489
|
+
|
|
490
|
+
return info
|
|
491
|
+
|
|
492
|
+
@staticmethod
|
|
493
|
+
def validate_hooks_config() -> bool:
|
|
494
|
+
"""Validate hooks configuration.
|
|
495
|
+
|
|
496
|
+
Phase 8.5: This method is deprecated. Direct tool invocation doesn't require
|
|
497
|
+
pre-commit config validation. Always returns True for backward compatibility.
|
|
498
|
+
"""
|
|
499
|
+
return True
|
|
142
500
|
|
|
143
501
|
def get_hook_ids(self) -> list[str]:
|
|
144
502
|
fast_strategy = self.config_loader.load_strategy("fast")
|
|
@@ -147,49 +505,55 @@ class HookManagerImpl:
|
|
|
147
505
|
all_hooks = fast_strategy.hooks + comprehensive_strategy.hooks
|
|
148
506
|
return [hook.name for hook in all_hooks]
|
|
149
507
|
|
|
508
|
+
def get_hook_count(self, suite_name: str) -> int:
|
|
509
|
+
"""Get the number of hooks in a specific suite.
|
|
510
|
+
|
|
511
|
+
Args:
|
|
512
|
+
suite_name: Name of the suite ('fast' or 'comprehensive')
|
|
513
|
+
|
|
514
|
+
Returns:
|
|
515
|
+
Number of hooks in the suite
|
|
516
|
+
"""
|
|
517
|
+
strategy = self.config_loader.load_strategy(suite_name)
|
|
518
|
+
return len(strategy.hooks)
|
|
519
|
+
|
|
150
520
|
def install_hooks(self) -> bool:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if result.returncode == 0:
|
|
161
|
-
self.console.print("[green]✅[/ green] Pre-commit hooks installed")
|
|
162
|
-
return True
|
|
163
|
-
self.console.print(
|
|
164
|
-
f"[red]❌[/ red] Failed to install hooks: {result.stderr}",
|
|
165
|
-
)
|
|
166
|
-
return False
|
|
167
|
-
except Exception as e:
|
|
168
|
-
self.console.print(f"[red]❌[/ red] Error installing hooks: {e}")
|
|
169
|
-
return False
|
|
521
|
+
"""Install git hooks.
|
|
522
|
+
|
|
523
|
+
Phase 8.5: This method is deprecated. Direct tool invocation doesn't require
|
|
524
|
+
pre-commit hook installation. Returns True with informational message.
|
|
525
|
+
"""
|
|
526
|
+
self.console.print(
|
|
527
|
+
"[yellow]ℹ️[/yellow] Hook installation not required with direct invocation"
|
|
528
|
+
)
|
|
529
|
+
return True
|
|
170
530
|
|
|
171
531
|
def update_hooks(self) -> bool:
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if result.returncode == 0:
|
|
182
|
-
self.console.print("[green]✅[/ green] Pre-commit hooks updated")
|
|
183
|
-
return True
|
|
184
|
-
self.console.print(
|
|
185
|
-
f"[red]❌[/ red] Failed to update hooks: {result.stderr}",
|
|
186
|
-
)
|
|
187
|
-
return False
|
|
188
|
-
except Exception as e:
|
|
189
|
-
self.console.print(f"[red]❌[/ red] Error updating hooks: {e}")
|
|
190
|
-
return False
|
|
532
|
+
"""Update hooks to latest versions.
|
|
533
|
+
|
|
534
|
+
Phase 8.5: This method is deprecated. Direct tool invocation uses UV for
|
|
535
|
+
dependency management. Returns True with informational message.
|
|
536
|
+
"""
|
|
537
|
+
self.console.print(
|
|
538
|
+
"[yellow]ℹ️[/yellow] Hook updates managed via UV dependency resolution"
|
|
539
|
+
)
|
|
540
|
+
return True
|
|
191
541
|
|
|
192
|
-
|
|
542
|
+
@staticmethod
|
|
543
|
+
def get_hook_summary(
|
|
544
|
+
results: list[HookResult], elapsed_time: float | None = None
|
|
545
|
+
) -> dict[str, t.Any]:
|
|
546
|
+
"""Calculate summary statistics for hook execution results.
|
|
547
|
+
|
|
548
|
+
Args:
|
|
549
|
+
results: List of hook execution results
|
|
550
|
+
elapsed_time: Optional wall-clock elapsed time in seconds.
|
|
551
|
+
If provided, used as total_duration (critical for parallel execution).
|
|
552
|
+
If None, falls back to sum of individual durations (sequential mode).
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
Dictionary with execution statistics
|
|
556
|
+
"""
|
|
193
557
|
if not results:
|
|
194
558
|
return {
|
|
195
559
|
"total": 0,
|
|
@@ -203,7 +567,13 @@ class HookManagerImpl:
|
|
|
203
567
|
passed = sum(1 for r in results if r.status == "passed")
|
|
204
568
|
failed = sum(1 for r in results if r.status == "failed")
|
|
205
569
|
errors = sum(1 for r in results if r.status in ("timeout", "error"))
|
|
206
|
-
|
|
570
|
+
|
|
571
|
+
# Use wall-clock time if provided (parallel execution), else sum durations (sequential)
|
|
572
|
+
total_duration = (
|
|
573
|
+
elapsed_time
|
|
574
|
+
if elapsed_time is not None
|
|
575
|
+
else sum(r.duration for r in results)
|
|
576
|
+
)
|
|
207
577
|
|
|
208
578
|
return {
|
|
209
579
|
"total": len(results),
|