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,390 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from crackerjack.config.tool_commands import get_tool_command
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HookStage(Enum):
|
|
9
|
+
FAST = "fast"
|
|
10
|
+
COMPREHENSIVE = "comprehensive"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RetryPolicy(Enum):
|
|
14
|
+
NONE = "none"
|
|
15
|
+
FORMATTING_ONLY = "formatting_only"
|
|
16
|
+
ALL_HOOKS = "all_hooks"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SecurityLevel(Enum):
|
|
20
|
+
CRITICAL = "critical"
|
|
21
|
+
HIGH = "high"
|
|
22
|
+
MEDIUM = "medium"
|
|
23
|
+
LOW = "low"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class HookDefinition:
|
|
28
|
+
name: str
|
|
29
|
+
command: list[str]
|
|
30
|
+
timeout: int = 60
|
|
31
|
+
stage: HookStage = HookStage.FAST
|
|
32
|
+
description: str | None = None
|
|
33
|
+
retry_on_failure: bool = False
|
|
34
|
+
is_formatting: bool = False
|
|
35
|
+
manual_stage: bool = False
|
|
36
|
+
config_path: Path | None = None
|
|
37
|
+
security_level: SecurityLevel = SecurityLevel.MEDIUM
|
|
38
|
+
use_precommit_legacy: bool = True # Phase 8.2: Backward compatibility flag
|
|
39
|
+
accepts_file_paths: bool = False # Phase 10.4.4: Can tool process individual files?
|
|
40
|
+
_direct_cmd_cache: list[str] | None = field(default=None, init=False, repr=False)
|
|
41
|
+
|
|
42
|
+
def get_command(self) -> list[str]:
|
|
43
|
+
"""Get the command to execute this hook.
|
|
44
|
+
|
|
45
|
+
Returns the appropriate command based on use_precommit_legacy flag:
|
|
46
|
+
- If use_precommit_legacy=True: Returns pre-commit wrapper command (legacy mode)
|
|
47
|
+
- If use_precommit_legacy=False: Returns direct tool command (Phase 8+ mode)
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
List of command arguments for subprocess execution
|
|
51
|
+
"""
|
|
52
|
+
# Phase 8.2: Direct invocation mode (new behavior)
|
|
53
|
+
if not self.use_precommit_legacy:
|
|
54
|
+
if self._direct_cmd_cache is None:
|
|
55
|
+
try:
|
|
56
|
+
self._direct_cmd_cache = get_tool_command(
|
|
57
|
+
self.name, pkg_path=Path.cwd()
|
|
58
|
+
)
|
|
59
|
+
except KeyError:
|
|
60
|
+
# Fallback to pre-commit if tool not in registry
|
|
61
|
+
# This ensures graceful degradation during migration
|
|
62
|
+
self._direct_cmd_cache = None
|
|
63
|
+
if self._direct_cmd_cache is not None:
|
|
64
|
+
return self._direct_cmd_cache
|
|
65
|
+
|
|
66
|
+
# Legacy mode: Use pre-commit wrapper (Phase 1-7 behavior)
|
|
67
|
+
import shutil
|
|
68
|
+
|
|
69
|
+
pre_commit_path = None
|
|
70
|
+
current_dir = Path.cwd()
|
|
71
|
+
project_pre_commit = current_dir / ".venv" / "bin" / "pre-commit"
|
|
72
|
+
if project_pre_commit.exists():
|
|
73
|
+
pre_commit_path = str(project_pre_commit)
|
|
74
|
+
else:
|
|
75
|
+
pre_commit_path = shutil.which("pre-commit") or "pre-commit"
|
|
76
|
+
|
|
77
|
+
cmd = [pre_commit_path, "run"]
|
|
78
|
+
if self.config_path:
|
|
79
|
+
cmd.extend(["-c", str(self.config_path)])
|
|
80
|
+
if self.manual_stage:
|
|
81
|
+
cmd.extend(["--hook-stage", "manual"])
|
|
82
|
+
cmd.extend([self.name, "--all-files"])
|
|
83
|
+
return cmd
|
|
84
|
+
|
|
85
|
+
def build_command(self, files: list[Path] | None = None) -> list[str]:
|
|
86
|
+
"""Build command with optional file paths for targeted execution.
|
|
87
|
+
|
|
88
|
+
Phase 10.4.4: Enables incremental execution on specific files when supported.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
files: Optional list of file paths to process. If None, processes all files.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Command list with file paths appended if tool accepts them.
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
>>> hook = HookDefinition(
|
|
98
|
+
... name="ruff-check",
|
|
99
|
+
... command=["ruff", "check"],
|
|
100
|
+
... accepts_file_paths=True,
|
|
101
|
+
... )
|
|
102
|
+
>>> hook.build_command([Path("foo.py"), Path("bar.py")])
|
|
103
|
+
["ruff", "check", "foo.py", "bar.py"]
|
|
104
|
+
"""
|
|
105
|
+
base_cmd = self.get_command().copy()
|
|
106
|
+
|
|
107
|
+
# Append file paths if tool accepts them and files are provided
|
|
108
|
+
if files and self.accepts_file_paths:
|
|
109
|
+
base_cmd.extend([str(f) for f in files])
|
|
110
|
+
|
|
111
|
+
return base_cmd
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass
|
|
115
|
+
class HookStrategy:
|
|
116
|
+
name: str
|
|
117
|
+
hooks: list[HookDefinition]
|
|
118
|
+
timeout: int = 300
|
|
119
|
+
retry_policy: RetryPolicy = RetryPolicy.NONE
|
|
120
|
+
parallel: bool = False
|
|
121
|
+
max_workers: int = 3
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
FAST_HOOKS = [
|
|
125
|
+
HookDefinition(
|
|
126
|
+
name="validate-regex-patterns",
|
|
127
|
+
command=[],
|
|
128
|
+
is_formatting=True,
|
|
129
|
+
timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
|
|
130
|
+
retry_on_failure=True,
|
|
131
|
+
security_level=SecurityLevel.HIGH,
|
|
132
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
133
|
+
),
|
|
134
|
+
HookDefinition(
|
|
135
|
+
name="trailing-whitespace",
|
|
136
|
+
command=[],
|
|
137
|
+
is_formatting=True,
|
|
138
|
+
timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
|
|
139
|
+
retry_on_failure=True,
|
|
140
|
+
security_level=SecurityLevel.LOW,
|
|
141
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
142
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level fixer
|
|
143
|
+
),
|
|
144
|
+
HookDefinition(
|
|
145
|
+
name="end-of-file-fixer",
|
|
146
|
+
command=[],
|
|
147
|
+
is_formatting=True,
|
|
148
|
+
timeout=120, # Increased from 60 to handle larger codebases and prevent timeout issues
|
|
149
|
+
retry_on_failure=True,
|
|
150
|
+
security_level=SecurityLevel.LOW,
|
|
151
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
152
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level fixer
|
|
153
|
+
),
|
|
154
|
+
HookDefinition(
|
|
155
|
+
name="check-yaml",
|
|
156
|
+
command=[],
|
|
157
|
+
timeout=60, # Increased from 20 to reduce timeout issues with larger YAML files
|
|
158
|
+
security_level=SecurityLevel.MEDIUM,
|
|
159
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
160
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level validator
|
|
161
|
+
),
|
|
162
|
+
HookDefinition(
|
|
163
|
+
name="check-toml",
|
|
164
|
+
command=[],
|
|
165
|
+
timeout=150, # Increased from 79 to reduce timeout issues with larger TOML files
|
|
166
|
+
security_level=SecurityLevel.MEDIUM,
|
|
167
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
168
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level validator
|
|
169
|
+
),
|
|
170
|
+
HookDefinition(
|
|
171
|
+
name="check-json",
|
|
172
|
+
command=[],
|
|
173
|
+
timeout=90, # Increased from 30 to reduce timeout issues with larger JSON files
|
|
174
|
+
security_level=SecurityLevel.MEDIUM,
|
|
175
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
176
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level validator
|
|
177
|
+
),
|
|
178
|
+
HookDefinition(
|
|
179
|
+
name="check-ast",
|
|
180
|
+
command=[],
|
|
181
|
+
timeout=90, # Increased from 30 to reduce timeout issues with larger Python files
|
|
182
|
+
security_level=SecurityLevel.HIGH,
|
|
183
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
184
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level validator
|
|
185
|
+
),
|
|
186
|
+
HookDefinition(
|
|
187
|
+
name="format-json",
|
|
188
|
+
command=[],
|
|
189
|
+
is_formatting=True,
|
|
190
|
+
timeout=120, # Increased from 45 to reduce timeout issues with larger JSON files
|
|
191
|
+
retry_on_failure=True,
|
|
192
|
+
security_level=SecurityLevel.LOW,
|
|
193
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
194
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level formatter
|
|
195
|
+
),
|
|
196
|
+
HookDefinition(
|
|
197
|
+
name="check-added-large-files",
|
|
198
|
+
command=[],
|
|
199
|
+
timeout=90, # Increased from 30 to reduce timeout issues with repositories with many files
|
|
200
|
+
security_level=SecurityLevel.HIGH,
|
|
201
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
202
|
+
),
|
|
203
|
+
HookDefinition(
|
|
204
|
+
name="uv-lock",
|
|
205
|
+
command=[],
|
|
206
|
+
timeout=60, # Increased from 20 to reduce timeout issues with complex dependency trees
|
|
207
|
+
security_level=SecurityLevel.HIGH,
|
|
208
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
209
|
+
),
|
|
210
|
+
HookDefinition(
|
|
211
|
+
name="codespell",
|
|
212
|
+
command=[],
|
|
213
|
+
timeout=150, # Increased from 45 to reduce timeout issues with large codebases
|
|
214
|
+
security_level=SecurityLevel.LOW,
|
|
215
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
216
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level spell checker
|
|
217
|
+
),
|
|
218
|
+
HookDefinition(
|
|
219
|
+
name="ruff-check",
|
|
220
|
+
command=[],
|
|
221
|
+
is_formatting=True,
|
|
222
|
+
timeout=240, # Increased from 120 to reduce timeout issues with large codebases
|
|
223
|
+
retry_on_failure=True,
|
|
224
|
+
security_level=SecurityLevel.MEDIUM,
|
|
225
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
226
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level Python linter
|
|
227
|
+
),
|
|
228
|
+
HookDefinition(
|
|
229
|
+
name="ruff-format",
|
|
230
|
+
command=[],
|
|
231
|
+
is_formatting=True,
|
|
232
|
+
timeout=240, # Increased from 120 to reduce timeout issues with large codebases
|
|
233
|
+
retry_on_failure=True,
|
|
234
|
+
security_level=SecurityLevel.LOW,
|
|
235
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
236
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level Python formatter
|
|
237
|
+
),
|
|
238
|
+
HookDefinition(
|
|
239
|
+
name="mdformat",
|
|
240
|
+
command=[],
|
|
241
|
+
is_formatting=True,
|
|
242
|
+
timeout=300, # Increased from 120 to reduce timeout issues with larger markdown files
|
|
243
|
+
retry_on_failure=True,
|
|
244
|
+
security_level=SecurityLevel.LOW,
|
|
245
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
246
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level markdown formatter
|
|
247
|
+
),
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
COMPREHENSIVE_HOOKS = [
|
|
251
|
+
HookDefinition(
|
|
252
|
+
name="zuban",
|
|
253
|
+
command=[],
|
|
254
|
+
timeout=240, # Increased from 80 to reduce timeout issues with larger codebases during type checking
|
|
255
|
+
stage=HookStage.COMPREHENSIVE,
|
|
256
|
+
manual_stage=True,
|
|
257
|
+
security_level=SecurityLevel.HIGH, # Changed from CRITICAL to HIGH to allow other hooks to run
|
|
258
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
259
|
+
accepts_file_paths=True, # Phase 10.5: Allow incremental execution on changed files to avoid virtual environments
|
|
260
|
+
),
|
|
261
|
+
HookDefinition(
|
|
262
|
+
name="semgrep",
|
|
263
|
+
command=[],
|
|
264
|
+
timeout=480, # Increased from 240 to reduce timeout issues with comprehensive security scans
|
|
265
|
+
stage=HookStage.COMPREHENSIVE,
|
|
266
|
+
manual_stage=True,
|
|
267
|
+
security_level=SecurityLevel.CRITICAL,
|
|
268
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
269
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level SAST scanner
|
|
270
|
+
),
|
|
271
|
+
HookDefinition(
|
|
272
|
+
name="pyscn",
|
|
273
|
+
command=[],
|
|
274
|
+
timeout=300, # CFG analysis, clone detection, complexity metrics
|
|
275
|
+
stage=HookStage.COMPREHENSIVE,
|
|
276
|
+
manual_stage=True,
|
|
277
|
+
security_level=SecurityLevel.HIGH, # Security + quality analysis
|
|
278
|
+
use_precommit_legacy=False, # Direct invocation
|
|
279
|
+
accepts_file_paths=True, # Can scan specific Python files
|
|
280
|
+
),
|
|
281
|
+
# NOTE: Bandit replaced with Semgrep (using uvx for Python 3.13 isolation)
|
|
282
|
+
# HookDefinition(
|
|
283
|
+
# name="bandit",
|
|
284
|
+
# command=[],
|
|
285
|
+
# timeout=180, # 3 minutes for SAST scanning
|
|
286
|
+
# stage=HookStage.COMPREHENSIVE,
|
|
287
|
+
# manual_stage=True,
|
|
288
|
+
# security_level=SecurityLevel.CRITICAL,
|
|
289
|
+
# use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
290
|
+
# accepts_file_paths=True, # Phase 10.4.4: File-level SAST scanner
|
|
291
|
+
# ),
|
|
292
|
+
HookDefinition(
|
|
293
|
+
name="gitleaks",
|
|
294
|
+
command=[],
|
|
295
|
+
timeout=180, # Increased from 45 to reduce timeout issues with comprehensive security scans
|
|
296
|
+
stage=HookStage.COMPREHENSIVE,
|
|
297
|
+
manual_stage=True,
|
|
298
|
+
security_level=SecurityLevel.CRITICAL,
|
|
299
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
300
|
+
),
|
|
301
|
+
HookDefinition(
|
|
302
|
+
name="pip-audit",
|
|
303
|
+
command=[],
|
|
304
|
+
timeout=180, # Network calls to vulnerability databases
|
|
305
|
+
stage=HookStage.COMPREHENSIVE,
|
|
306
|
+
manual_stage=True,
|
|
307
|
+
security_level=SecurityLevel.CRITICAL, # CVE vulnerabilities are critical
|
|
308
|
+
use_precommit_legacy=False, # Direct invocation
|
|
309
|
+
accepts_file_paths=False, # Scans entire environment/requirements
|
|
310
|
+
),
|
|
311
|
+
HookDefinition(
|
|
312
|
+
name="skylos",
|
|
313
|
+
command=[],
|
|
314
|
+
timeout=180, # Increased from 60 to reduce timeout issues with comprehensive dead code scanning
|
|
315
|
+
stage=HookStage.COMPREHENSIVE,
|
|
316
|
+
manual_stage=True,
|
|
317
|
+
security_level=SecurityLevel.MEDIUM,
|
|
318
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
319
|
+
accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files
|
|
320
|
+
),
|
|
321
|
+
HookDefinition(
|
|
322
|
+
name="refurb",
|
|
323
|
+
command=[],
|
|
324
|
+
timeout=480, # Increased from 240 to reduce timeout issues with comprehensive refactoring analysis
|
|
325
|
+
stage=HookStage.COMPREHENSIVE,
|
|
326
|
+
manual_stage=True,
|
|
327
|
+
security_level=SecurityLevel.MEDIUM,
|
|
328
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
329
|
+
accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files (240s -> ~10s)
|
|
330
|
+
),
|
|
331
|
+
HookDefinition(
|
|
332
|
+
name="creosote",
|
|
333
|
+
command=[],
|
|
334
|
+
timeout=360, # Increased from 180 to reduce timeout issues with comprehensive dependency analysis
|
|
335
|
+
stage=HookStage.COMPREHENSIVE,
|
|
336
|
+
manual_stage=True,
|
|
337
|
+
security_level=SecurityLevel.HIGH,
|
|
338
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
339
|
+
),
|
|
340
|
+
HookDefinition(
|
|
341
|
+
name="complexipy",
|
|
342
|
+
command=[],
|
|
343
|
+
timeout=300, # Increased from 120 to reduce timeout issues with comprehensive complexity analysis
|
|
344
|
+
stage=HookStage.COMPREHENSIVE,
|
|
345
|
+
manual_stage=True,
|
|
346
|
+
security_level=SecurityLevel.MEDIUM,
|
|
347
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
348
|
+
accepts_file_paths=True, # Phase 10.5: Incremental execution on changed files
|
|
349
|
+
),
|
|
350
|
+
HookDefinition(
|
|
351
|
+
name="check-jsonschema",
|
|
352
|
+
command=[],
|
|
353
|
+
timeout=180, # Increased from 60 to reduce timeout issues with complex schema validation
|
|
354
|
+
stage=HookStage.COMPREHENSIVE,
|
|
355
|
+
manual_stage=True,
|
|
356
|
+
security_level=SecurityLevel.HIGH,
|
|
357
|
+
use_precommit_legacy=False, # Phase 8.4: Direct invocation
|
|
358
|
+
accepts_file_paths=True, # Phase 10.4.4: File-level schema validator
|
|
359
|
+
),
|
|
360
|
+
]
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
FAST_STRATEGY = HookStrategy(
|
|
364
|
+
name="fast",
|
|
365
|
+
hooks=FAST_HOOKS,
|
|
366
|
+
timeout=300, # Increased from 60 to accommodate all increased hook timeouts
|
|
367
|
+
retry_policy=RetryPolicy.FORMATTING_ONLY,
|
|
368
|
+
parallel=True, # Phase 6: Enable parallel execution for 2-3x speedup
|
|
369
|
+
max_workers=4, # Optimal concurrency for fast hooks
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
COMPREHENSIVE_STRATEGY = HookStrategy(
|
|
373
|
+
name="comprehensive",
|
|
374
|
+
hooks=COMPREHENSIVE_HOOKS,
|
|
375
|
+
timeout=1800, # Increased from 300 to accommodate all increased hook timeouts
|
|
376
|
+
retry_policy=RetryPolicy.NONE,
|
|
377
|
+
parallel=True, # Phase 6: Enable parallel execution for 2x speedup
|
|
378
|
+
max_workers=4, # Optimal concurrency for comprehensive hooks
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class HookConfigLoader:
|
|
383
|
+
@staticmethod
|
|
384
|
+
def load_strategy(name: str, _: Path | None = None) -> HookStrategy:
|
|
385
|
+
if name == "fast":
|
|
386
|
+
return FAST_STRATEGY
|
|
387
|
+
if name == "comprehensive":
|
|
388
|
+
return COMPREHENSIVE_STRATEGY
|
|
389
|
+
msg = f"Unknown hook strategy: {name}"
|
|
390
|
+
raise ValueError(msg)
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""Settings loader for ACB configuration with YAML support.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for loading ACB Settings from YAML files
|
|
4
|
+
with support for configuration layering and environment-specific overrides.
|
|
5
|
+
|
|
6
|
+
Configuration Priority (highest to lowest):
|
|
7
|
+
1. settings/local.yaml (local overrides, gitignored)
|
|
8
|
+
2. settings/crackerjack.yaml (main configuration)
|
|
9
|
+
3. Default values from Settings class
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
>>> from crackerjack.config import CrackerjackSettings
|
|
13
|
+
>>> settings = CrackerjackSettings.load()
|
|
14
|
+
>>> settings.verbose
|
|
15
|
+
False
|
|
16
|
+
|
|
17
|
+
>>> # Async loading with full ACB initialization
|
|
18
|
+
>>> settings = await CrackerjackSettings.load_async()
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
import typing as t
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import TypeVar
|
|
27
|
+
|
|
28
|
+
import yaml
|
|
29
|
+
from acb.config import Settings
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
T = TypeVar("T", bound=Settings)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _load_single_config_file(config_file: Path) -> dict[str, t.Any]:
|
|
37
|
+
"""Load a single config file and return its data."""
|
|
38
|
+
if not config_file.exists():
|
|
39
|
+
logger.debug(f"Configuration file not found: {config_file}")
|
|
40
|
+
return {}
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
with config_file.open() as f:
|
|
44
|
+
loaded_data: t.Any = yaml.safe_load(f)
|
|
45
|
+
if isinstance(loaded_data, dict):
|
|
46
|
+
logger.debug(f"Loaded configuration from {config_file}")
|
|
47
|
+
return loaded_data
|
|
48
|
+
else:
|
|
49
|
+
logger.warning(
|
|
50
|
+
f"Invalid YAML format in {config_file}: expected dict, got {type(loaded_data).__name__}"
|
|
51
|
+
)
|
|
52
|
+
return {}
|
|
53
|
+
except yaml.YAMLError as e:
|
|
54
|
+
logger.error(f"Failed to parse YAML from {config_file}: {e}")
|
|
55
|
+
return {}
|
|
56
|
+
except OSError as e:
|
|
57
|
+
logger.error(f"Failed to read {config_file}: {e}")
|
|
58
|
+
return {}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _merge_config_data(config_files: list[Path]) -> dict[str, t.Any]:
|
|
62
|
+
"""Merge data from all config files."""
|
|
63
|
+
merged_data = {}
|
|
64
|
+
for config_file in config_files:
|
|
65
|
+
file_data = _load_single_config_file(config_file)
|
|
66
|
+
merged_data.update(file_data)
|
|
67
|
+
return merged_data
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def load_settings[T: Settings](
|
|
71
|
+
settings_class: type[T],
|
|
72
|
+
settings_dir: Path | None = None,
|
|
73
|
+
) -> T:
|
|
74
|
+
"""Load settings from YAML files with layered configuration.
|
|
75
|
+
|
|
76
|
+
This function loads configuration from multiple YAML files and merges them
|
|
77
|
+
with priority-based overriding. Unknown YAML fields are silently ignored.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
settings_class: The Settings class to instantiate
|
|
81
|
+
settings_dir: Directory containing YAML files (default: ./settings)
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Initialized Settings instance with merged configuration
|
|
85
|
+
|
|
86
|
+
Configuration Priority (highest to lowest):
|
|
87
|
+
1. settings/local.yaml (local overrides, gitignored)
|
|
88
|
+
2. settings/crackerjack.yaml (main configuration)
|
|
89
|
+
3. Default values from Settings class
|
|
90
|
+
|
|
91
|
+
Example:
|
|
92
|
+
>>> class MySettings(Settings):
|
|
93
|
+
... debug: bool = False
|
|
94
|
+
... max_workers: int = 4
|
|
95
|
+
>>> settings = load_settings(MySettings)
|
|
96
|
+
>>> settings.debug
|
|
97
|
+
False
|
|
98
|
+
"""
|
|
99
|
+
if settings_dir is None:
|
|
100
|
+
settings_dir = Path.cwd() / "settings"
|
|
101
|
+
|
|
102
|
+
# Configuration files in priority order (lowest to highest)
|
|
103
|
+
config_files = [
|
|
104
|
+
settings_dir / "crackerjack.yaml",
|
|
105
|
+
settings_dir / "local.yaml",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
# Load and merge data from all config files
|
|
109
|
+
merged_data = _merge_config_data(config_files)
|
|
110
|
+
|
|
111
|
+
# Filter to only fields defined in the Settings class
|
|
112
|
+
# This prevents validation errors from unknown YAML keys
|
|
113
|
+
relevant_data = {
|
|
114
|
+
k: v for k, v in merged_data.items() if k in settings_class.model_fields
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Log filtered fields if any were excluded
|
|
118
|
+
excluded_fields = set(merged_data.keys()) - set(relevant_data.keys())
|
|
119
|
+
if excluded_fields:
|
|
120
|
+
logger.debug(
|
|
121
|
+
f"Ignored unknown configuration fields: {', '.join(sorted(excluded_fields))}"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
logger.info(
|
|
125
|
+
f"Loaded {len(relevant_data)} configuration values for {settings_class.__name__}"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Synchronous initialization (safe for module-level code)
|
|
129
|
+
return settings_class(**relevant_data)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
async def load_settings_async[T: Settings](
|
|
133
|
+
settings_class: type[T],
|
|
134
|
+
settings_dir: Path | None = None,
|
|
135
|
+
) -> T:
|
|
136
|
+
"""Load settings asynchronously with full ACB initialization.
|
|
137
|
+
|
|
138
|
+
This function provides the same configuration loading as load_settings()
|
|
139
|
+
but uses ACB's async initialization which includes secret loading and
|
|
140
|
+
other async setup operations.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
settings_class: The Settings class to instantiate
|
|
144
|
+
settings_dir: Directory containing YAML files (default: ./settings)
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Initialized Settings instance with async initialization complete
|
|
148
|
+
|
|
149
|
+
Note:
|
|
150
|
+
Use this for application runtime when async context is available.
|
|
151
|
+
For module-level initialization, use synchronous load_settings().
|
|
152
|
+
|
|
153
|
+
Example:
|
|
154
|
+
>>> settings = await load_settings_async(CrackerjackSettings)
|
|
155
|
+
>>> settings.verbose
|
|
156
|
+
False
|
|
157
|
+
"""
|
|
158
|
+
if settings_dir is None:
|
|
159
|
+
settings_dir = Path.cwd() / "settings"
|
|
160
|
+
|
|
161
|
+
# Configuration files in priority order (lowest to highest)
|
|
162
|
+
config_files = [
|
|
163
|
+
settings_dir / "crackerjack.yaml",
|
|
164
|
+
settings_dir / "local.yaml",
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
# Load and merge YAML data from all files
|
|
168
|
+
merged_data = await _load_yaml_data(config_files)
|
|
169
|
+
|
|
170
|
+
# Process the loaded data
|
|
171
|
+
relevant_data = _filter_relevant_data(merged_data, settings_class)
|
|
172
|
+
_log_filtered_fields(merged_data, relevant_data)
|
|
173
|
+
_log_load_info(settings_class, relevant_data)
|
|
174
|
+
|
|
175
|
+
# Async initialization (loads secrets, performs async setup)
|
|
176
|
+
return await settings_class.create_async(**relevant_data)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def _load_yaml_data(config_files: list[Path]) -> dict[str, t.Any]:
|
|
180
|
+
"""Load and merge YAML data from configuration files."""
|
|
181
|
+
merged_data: dict[str, t.Any] = {}
|
|
182
|
+
for config_file in config_files:
|
|
183
|
+
file_data = await _load_single_yaml_file(config_file)
|
|
184
|
+
if file_data is not None:
|
|
185
|
+
merged_data.update(file_data)
|
|
186
|
+
elif not config_file.exists():
|
|
187
|
+
logger.debug(f"Configuration file not found: {config_file}")
|
|
188
|
+
return merged_data
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
async def _load_single_yaml_file(config_file: Path) -> dict[str, t.Any] | None:
|
|
192
|
+
"""Load a single YAML file and return its content."""
|
|
193
|
+
if not config_file.exists():
|
|
194
|
+
return None
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
with config_file.open() as f:
|
|
198
|
+
loaded_data: t.Any = yaml.safe_load(f)
|
|
199
|
+
if isinstance(loaded_data, dict):
|
|
200
|
+
logger.debug(f"Loaded configuration from {config_file}")
|
|
201
|
+
return loaded_data
|
|
202
|
+
else:
|
|
203
|
+
logger.warning(
|
|
204
|
+
f"Invalid YAML format in {config_file}: expected dict, got {type(loaded_data).__name__}"
|
|
205
|
+
)
|
|
206
|
+
return {}
|
|
207
|
+
except yaml.YAMLError as e:
|
|
208
|
+
logger.error(f"Failed to parse YAML from {config_file}: {e}")
|
|
209
|
+
return None
|
|
210
|
+
except OSError as e:
|
|
211
|
+
logger.error(f"Failed to read {config_file}: {e}")
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _filter_relevant_data[T: Settings](
|
|
216
|
+
merged_data: dict[str, t.Any], settings_class: type[T]
|
|
217
|
+
) -> dict[str, t.Any]:
|
|
218
|
+
"""Filter the loaded data to only fields defined in the Settings class."""
|
|
219
|
+
return {k: v for k, v in merged_data.items() if k in settings_class.model_fields}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _log_filtered_fields(
|
|
223
|
+
merged_data: dict[str, t.Any], relevant_data: dict[str, t.Any]
|
|
224
|
+
) -> None:
|
|
225
|
+
"""Log any fields that were excluded due to not being in the settings class."""
|
|
226
|
+
excluded_fields = set(merged_data.keys()) - set(relevant_data.keys())
|
|
227
|
+
if excluded_fields:
|
|
228
|
+
logger.debug(
|
|
229
|
+
f"Ignored unknown configuration fields: {', '.join(sorted(excluded_fields))}"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _log_load_info[T: Settings](
|
|
234
|
+
settings_class: type[T], relevant_data: dict[str, t.Any]
|
|
235
|
+
) -> None:
|
|
236
|
+
"""Log information about the loaded configuration."""
|
|
237
|
+
logger.info(
|
|
238
|
+
f"Loaded {len(relevant_data)} configuration values for {settings_class.__name__} (async)"
|
|
239
|
+
)
|