crackerjack 0.18.2__py3-none-any.whl → 0.45.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +96 -2
- crackerjack/__main__.py +637 -138
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +39 -0
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/lsp/_base.py +194 -0
- crackerjack/adapters/lsp/_client.py +358 -0
- crackerjack/adapters/lsp/_manager.py +193 -0
- crackerjack/adapters/lsp/skylos.py +283 -0
- crackerjack/adapters/lsp/zuban.py +557 -0
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +66 -0
- crackerjack/agents/architect_agent.py +238 -0
- crackerjack/agents/base.py +167 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +600 -0
- crackerjack/agents/documentation_agent.py +520 -0
- crackerjack/agents/dry_agent.py +585 -0
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +230 -0
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/import_optimization_agent.py +1181 -0
- crackerjack/agents/performance_agent.py +325 -0
- crackerjack/agents/performance_helpers.py +205 -0
- crackerjack/agents/proactive_agent.py +55 -0
- crackerjack/agents/refactoring_agent.py +511 -0
- crackerjack/agents/refactoring_helpers.py +247 -0
- crackerjack/agents/security_agent.py +793 -0
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +570 -0
- crackerjack/agents/test_specialist_agent.py +526 -0
- crackerjack/agents/tracker.py +110 -0
- crackerjack/api.py +647 -0
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +24 -0
- crackerjack/cli/cache_handlers.py +209 -0
- crackerjack/cli/cache_handlers_enhanced.py +680 -0
- crackerjack/cli/facade.py +162 -0
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +700 -0
- crackerjack/cli/interactive.py +488 -0
- crackerjack/cli/options.py +1216 -0
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/utils.py +19 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +1307 -0
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +275 -0
- crackerjack/config/global_lock_config.py +207 -0
- crackerjack/config/hooks.py +390 -0
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/__init__.py +0 -0
- crackerjack/core/async_workflow_orchestrator.py +738 -0
- crackerjack/core/autofix_coordinator.py +282 -0
- crackerjack/core/container.py +105 -0
- crackerjack/core/enhanced_container.py +583 -0
- crackerjack/core/file_lifecycle.py +472 -0
- crackerjack/core/performance.py +244 -0
- crackerjack/core/performance_monitor.py +357 -0
- crackerjack/core/phase_coordinator.py +1227 -0
- crackerjack/core/proactive_workflow.py +267 -0
- crackerjack/core/resource_manager.py +425 -0
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +601 -0
- crackerjack/core/session_coordinator.py +239 -0
- crackerjack/core/timeout_manager.py +563 -0
- crackerjack/core/websocket_lifecycle.py +410 -0
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +2243 -0
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/INDEX.md +11 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +767 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +1065 -0
- crackerjack/dynamic_config.py +678 -0
- crackerjack/errors.py +378 -0
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +13 -0
- crackerjack/executors/async_hook_executor.py +938 -0
- crackerjack/executors/cached_hook_executor.py +316 -0
- crackerjack/executors/hook_executor.py +1295 -0
- crackerjack/executors/hook_lock_manager.py +708 -0
- crackerjack/executors/individual_hook_executor.py +739 -0
- crackerjack/executors/lsp_aware_hook_executor.py +349 -0
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +433 -0
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +93 -0
- crackerjack/intelligence/README.md +557 -0
- crackerjack/intelligence/__init__.py +37 -0
- crackerjack/intelligence/adaptive_learning.py +693 -0
- crackerjack/intelligence/agent_orchestrator.py +485 -0
- crackerjack/intelligence/agent_registry.py +377 -0
- crackerjack/intelligence/agent_selector.py +439 -0
- crackerjack/intelligence/integration.py +250 -0
- crackerjack/interactive.py +719 -0
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/__init__.py +11 -0
- crackerjack/managers/async_hook_manager.py +135 -0
- crackerjack/managers/hook_manager.py +585 -0
- crackerjack/managers/publish_manager.py +631 -0
- crackerjack/managers/test_command_builder.py +391 -0
- crackerjack/managers/test_executor.py +474 -0
- crackerjack/managers/test_manager.py +1357 -0
- crackerjack/managers/test_progress.py +187 -0
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/__init__.py +0 -0
- crackerjack/mcp/cache.py +352 -0
- crackerjack/mcp/client_runner.py +121 -0
- crackerjack/mcp/context.py +802 -0
- crackerjack/mcp/dashboard.py +657 -0
- crackerjack/mcp/enhanced_progress_monitor.py +493 -0
- crackerjack/mcp/file_monitor.py +394 -0
- crackerjack/mcp/progress_components.py +607 -0
- crackerjack/mcp/progress_monitor.py +1016 -0
- crackerjack/mcp/rate_limiter.py +336 -0
- crackerjack/mcp/server.py +24 -0
- crackerjack/mcp/server_core.py +526 -0
- crackerjack/mcp/service_watchdog.py +505 -0
- crackerjack/mcp/state.py +407 -0
- crackerjack/mcp/task_manager.py +259 -0
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +19 -0
- crackerjack/mcp/tools/core_tools.py +469 -0
- crackerjack/mcp/tools/error_analyzer.py +283 -0
- crackerjack/mcp/tools/execution_tools.py +384 -0
- crackerjack/mcp/tools/intelligence_tool_registry.py +46 -0
- crackerjack/mcp/tools/intelligence_tools.py +264 -0
- crackerjack/mcp/tools/monitoring_tools.py +628 -0
- crackerjack/mcp/tools/proactive_tools.py +367 -0
- crackerjack/mcp/tools/progress_tools.py +222 -0
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +358 -0
- crackerjack/mcp/tools/workflow_executor.py +699 -0
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/__init__.py +14 -0
- crackerjack/mcp/websocket/app.py +54 -0
- crackerjack/mcp/websocket/endpoints.py +492 -0
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +406 -0
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +21 -0
- crackerjack/mcp/websocket/server.py +174 -0
- crackerjack/mcp/websocket/websocket_handler.py +276 -0
- crackerjack/mcp/websocket_server.py +10 -0
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +40 -0
- crackerjack/models/config.py +730 -0
- crackerjack/models/config_adapter.py +265 -0
- crackerjack/models/protocols.py +1535 -0
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/resource_protocols.py +299 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +173 -0
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +405 -0
- crackerjack/monitoring/metrics_collector.py +427 -0
- crackerjack/monitoring/regression_prevention.py +580 -0
- crackerjack/monitoring/websocket_server.py +406 -0
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +894 -0
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +180 -0
- crackerjack/orchestration/execution_strategies.py +361 -0
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +647 -0
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/__init__.py +15 -0
- crackerjack/plugins/base.py +200 -0
- crackerjack/plugins/hooks.py +254 -0
- crackerjack/plugins/loader.py +335 -0
- crackerjack/plugins/managers.py +264 -0
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/security/__init__.py +0 -0
- crackerjack/security/audit.py +197 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +9 -0
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/ai/contextual_ai_assistant.py +542 -0
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +617 -0
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +530 -0
- crackerjack/services/cache.py +369 -0
- crackerjack/services/changelog_automation.py +399 -0
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +132 -0
- crackerjack/services/config_merge.py +546 -0
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +493 -0
- crackerjack/services/coverage_badge_service.py +173 -0
- crackerjack/services/coverage_ratchet.py +381 -0
- crackerjack/services/debug.py +733 -0
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +622 -0
- crackerjack/services/documentation_generator.py +493 -0
- crackerjack/services/documentation_service.py +704 -0
- crackerjack/services/enhanced_filesystem.py +497 -0
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +149 -0
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +381 -0
- crackerjack/services/git.py +422 -0
- crackerjack/services/health_metrics.py +615 -0
- crackerjack/services/heatmap_generator.py +744 -0
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +823 -0
- crackerjack/services/input_validator.py +668 -0
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +289 -0
- crackerjack/services/logging.py +228 -0
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +414 -0
- crackerjack/services/metrics.py +587 -0
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/monitoring/performance_benchmarks.py +410 -0
- crackerjack/services/monitoring/performance_cache.py +388 -0
- crackerjack/services/monitoring/performance_monitor.py +569 -0
- crackerjack/services/parallel_executor.py +527 -0
- crackerjack/services/pattern_cache.py +333 -0
- crackerjack/services/pattern_detector.py +478 -0
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +523 -0
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/quality/quality_baseline.py +395 -0
- crackerjack/services/quality/quality_baseline_enhanced.py +649 -0
- crackerjack/services/quality/quality_intelligence.py +949 -0
- crackerjack/services/regex_patterns.py +58 -0
- crackerjack/services/regex_utils.py +483 -0
- crackerjack/services/secure_path_utils.py +524 -0
- crackerjack/services/secure_status_formatter.py +450 -0
- crackerjack/services/secure_subprocess.py +635 -0
- crackerjack/services/security.py +239 -0
- crackerjack/services/security_logger.py +495 -0
- crackerjack/services/server_manager.py +411 -0
- crackerjack/services/smart_scheduling.py +167 -0
- crackerjack/services/status_authentication.py +460 -0
- crackerjack/services/status_security_manager.py +315 -0
- crackerjack/services/terminal_utils.py +0 -0
- crackerjack/services/thread_safe_status_collector.py +441 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +43 -0
- crackerjack/services/unified_config.py +115 -0
- crackerjack/services/validation_rate_limiter.py +220 -0
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +461 -0
- crackerjack/services/version_checker.py +223 -0
- crackerjack/services/websocket_resource_limiter.py +438 -0
- crackerjack/services/zuban_lsp_service.py +391 -0
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/__init__.py +59 -0
- crackerjack/slash_commands/init.md +112 -0
- crackerjack/slash_commands/run.md +197 -0
- crackerjack/slash_commands/status.md +127 -0
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_input_validator_patterns.py +236 -0
- crackerjack/tools/validate_regex_patterns.py +188 -0
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/__init__.py +1 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- crackerjack-0.45.2.dist-info/METADATA +1678 -0
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack-0.45.2.dist-info/entry_points.txt +2 -0
- crackerjack/.gitignore +0 -14
- crackerjack/.libcst.codemod.yaml +0 -18
- crackerjack/.pdm.toml +0 -1
- crackerjack/.pre-commit-config.yaml +0 -91
- crackerjack/.pytest_cache/.gitignore +0 -2
- crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
- crackerjack/.pytest_cache/README.md +0 -8
- crackerjack/.pytest_cache/v/cache/nodeids +0 -1
- crackerjack/.pytest_cache/v/cache/stepwise +0 -1
- crackerjack/.ruff_cache/.gitignore +0 -1
- crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
- crackerjack/crackerjack.py +0 -855
- crackerjack/pyproject.toml +0 -214
- crackerjack-0.18.2.dist-info/METADATA +0 -420
- crackerjack-0.18.2.dist-info/RECORD +0 -59
- crackerjack-0.18.2.dist-info/entry_points.txt +0 -4
- {crackerjack-0.18.2.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
import typing as t
|
|
2
|
+
from contextlib import suppress
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from acb.console import Console
|
|
6
|
+
from acb.depends import depends
|
|
7
|
+
|
|
8
|
+
from crackerjack.config import CrackerjackSettings
|
|
9
|
+
from crackerjack.config.hooks import HookConfigLoader
|
|
10
|
+
from crackerjack.executors.hook_executor import HookExecutor
|
|
11
|
+
from crackerjack.executors.lsp_aware_hook_executor import LSPAwareHookExecutor
|
|
12
|
+
from crackerjack.executors.progress_hook_executor import ProgressHookExecutor
|
|
13
|
+
from crackerjack.models.task import HookResult
|
|
14
|
+
|
|
15
|
+
if t.TYPE_CHECKING:
|
|
16
|
+
from crackerjack.orchestration.hook_orchestrator import HookOrchestratorAdapter
|
|
17
|
+
|
|
18
|
+
|
|
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
|
+
|
|
158
|
+
def __init__(
|
|
159
|
+
self,
|
|
160
|
+
pkg_path: Path,
|
|
161
|
+
verbose: bool = False,
|
|
162
|
+
quiet: bool = False,
|
|
163
|
+
debug: bool = False,
|
|
164
|
+
enable_lsp_optimization: bool = False,
|
|
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
|
|
174
|
+
) -> None:
|
|
175
|
+
self.pkg_path = pkg_path
|
|
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)
|
|
183
|
+
|
|
184
|
+
# Use LSP-aware executor if optimization is enabled
|
|
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
|
+
)
|
|
195
|
+
|
|
196
|
+
self.config_loader = HookConfigLoader()
|
|
197
|
+
self._config_path: Path | None = None
|
|
198
|
+
self.lsp_optimization_enabled = enable_lsp_optimization
|
|
199
|
+
self.tool_proxy_enabled = enable_tool_proxy
|
|
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
|
+
|
|
212
|
+
def set_config_path(self, config_path: Path) -> None:
|
|
213
|
+
self._config_path = config_path
|
|
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
|
+
|
|
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)
|
|
313
|
+
strategy = self.config_loader.load_strategy("fast")
|
|
314
|
+
|
|
315
|
+
if self._config_path:
|
|
316
|
+
for hook in strategy.hooks:
|
|
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
|
+
)
|
|
325
|
+
execution_result = self.executor.execute_strategy(strategy)
|
|
326
|
+
return execution_result.results
|
|
327
|
+
|
|
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)
|
|
350
|
+
strategy = self.config_loader.load_strategy("comprehensive")
|
|
351
|
+
|
|
352
|
+
if self._config_path:
|
|
353
|
+
for hook in strategy.hooks:
|
|
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
|
+
)
|
|
362
|
+
execution_result = self.executor.execute_strategy(strategy)
|
|
363
|
+
return execution_result.results
|
|
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
|
+
|
|
375
|
+
def run_hooks(self) -> list[HookResult]:
|
|
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
|
|
383
|
+
|
|
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
|
|
389
|
+
|
|
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())
|
|
396
|
+
|
|
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
|
|
401
|
+
|
|
402
|
+
def configure_lsp_optimization(self, enable: bool) -> None:
|
|
403
|
+
"""Enable or disable LSP optimization by switching executors."""
|
|
404
|
+
if enable == self.lsp_optimization_enabled:
|
|
405
|
+
return # Already in the correct state
|
|
406
|
+
|
|
407
|
+
# Switch executor based on the enable flag
|
|
408
|
+
if enable:
|
|
409
|
+
self.executor = LSPAwareHookExecutor( # type: ignore[assignment]
|
|
410
|
+
self.console,
|
|
411
|
+
self.pkg_path,
|
|
412
|
+
verbose=getattr(self.executor, "verbose", False),
|
|
413
|
+
quiet=getattr(self.executor, "quiet", True),
|
|
414
|
+
use_tool_proxy=self.tool_proxy_enabled,
|
|
415
|
+
)
|
|
416
|
+
else:
|
|
417
|
+
self.executor = HookExecutor( # type: ignore[assignment]
|
|
418
|
+
self.console,
|
|
419
|
+
self.pkg_path,
|
|
420
|
+
verbose=getattr(self.executor, "verbose", False),
|
|
421
|
+
quiet=getattr(self.executor, "quiet", True),
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
self.lsp_optimization_enabled = enable
|
|
425
|
+
|
|
426
|
+
# Restore config path if it was set[t.Any]
|
|
427
|
+
if self._config_path:
|
|
428
|
+
# Config path is set[t.Any] at the manager level, not executor level
|
|
429
|
+
pass
|
|
430
|
+
|
|
431
|
+
def configure_tool_proxy(self, enable: bool) -> None:
|
|
432
|
+
"""Enable or disable tool proxy resilience."""
|
|
433
|
+
if enable == self.tool_proxy_enabled:
|
|
434
|
+
return # Already in the correct state
|
|
435
|
+
|
|
436
|
+
self.tool_proxy_enabled = enable
|
|
437
|
+
|
|
438
|
+
# If using LSP-aware executor, recreate it with new tool proxy setting
|
|
439
|
+
if isinstance(self.executor, LSPAwareHookExecutor):
|
|
440
|
+
self.executor = LSPAwareHookExecutor(
|
|
441
|
+
self.console,
|
|
442
|
+
self.pkg_path,
|
|
443
|
+
verbose=getattr(self.executor, "verbose", False),
|
|
444
|
+
quiet=getattr(self.executor, "quiet", True),
|
|
445
|
+
use_tool_proxy=enable,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Restore config path if it was set[t.Any]
|
|
449
|
+
if self._config_path:
|
|
450
|
+
pass # Config path handled at manager level
|
|
451
|
+
|
|
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
|
|
500
|
+
|
|
501
|
+
def get_hook_ids(self) -> list[str]:
|
|
502
|
+
fast_strategy = self.config_loader.load_strategy("fast")
|
|
503
|
+
comprehensive_strategy = self.config_loader.load_strategy("comprehensive")
|
|
504
|
+
|
|
505
|
+
all_hooks = fast_strategy.hooks + comprehensive_strategy.hooks
|
|
506
|
+
return [hook.name for hook in all_hooks]
|
|
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
|
+
|
|
520
|
+
def install_hooks(self) -> bool:
|
|
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
|
|
530
|
+
|
|
531
|
+
def update_hooks(self) -> bool:
|
|
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
|
|
541
|
+
|
|
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
|
+
"""
|
|
557
|
+
if not results:
|
|
558
|
+
return {
|
|
559
|
+
"total": 0,
|
|
560
|
+
"passed": 0,
|
|
561
|
+
"failed": 0,
|
|
562
|
+
"errors": 0,
|
|
563
|
+
"total_duration": 0,
|
|
564
|
+
"success_rate": 0,
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
passed = sum(1 for r in results if r.status == "passed")
|
|
568
|
+
failed = sum(1 for r in results if r.status == "failed")
|
|
569
|
+
errors = sum(1 for r in results if r.status in ("timeout", "error"))
|
|
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
|
+
)
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
"total": len(results),
|
|
580
|
+
"passed": passed,
|
|
581
|
+
"failed": failed,
|
|
582
|
+
"errors": errors,
|
|
583
|
+
"total_duration": total_duration,
|
|
584
|
+
"success_rate": (passed / len(results)) * 100 if results else 0,
|
|
585
|
+
}
|