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,141 @@
|
|
|
1
|
+
"""REST API endpoints for dependency analysis.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for dependency graph visualization,
|
|
4
|
+
metrics, clustering, and analysis triggers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI, HTTPException
|
|
10
|
+
from fastapi.responses import JSONResponse
|
|
11
|
+
|
|
12
|
+
from crackerjack.services.dependency_analyzer import (
|
|
13
|
+
DependencyAnalyzer,
|
|
14
|
+
DependencyGraph,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from ..filters import _apply_graph_filters
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_dependency_api_endpoints(
|
|
21
|
+
app: FastAPI, dependency_analyzer: DependencyAnalyzer
|
|
22
|
+
) -> None:
|
|
23
|
+
"""Register dependency-related REST API endpoints."""
|
|
24
|
+
|
|
25
|
+
@app.get("/api/dependencies/graph")
|
|
26
|
+
async def get_dependency_graph(
|
|
27
|
+
filter_type: str = None,
|
|
28
|
+
max_nodes: int = 1000,
|
|
29
|
+
include_external: bool = False,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Get dependency graph data."""
|
|
32
|
+
return await _handle_dependency_graph_request(
|
|
33
|
+
dependency_analyzer, filter_type, max_nodes, include_external
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@app.get("/api/dependencies/metrics")
|
|
37
|
+
async def get_dependency_metrics() -> None:
|
|
38
|
+
"""Get dependency graph metrics."""
|
|
39
|
+
return await _handle_dependency_metrics_request(dependency_analyzer)
|
|
40
|
+
|
|
41
|
+
@app.get("/api/dependencies/clusters")
|
|
42
|
+
async def get_dependency_clusters() -> None:
|
|
43
|
+
"""Get dependency graph clusters."""
|
|
44
|
+
return await _handle_dependency_clusters_request(dependency_analyzer)
|
|
45
|
+
|
|
46
|
+
@app.post("/api/dependencies/analyze")
|
|
47
|
+
async def trigger_dependency_analysis(request: dict) -> None:
|
|
48
|
+
"""Trigger fresh dependency analysis."""
|
|
49
|
+
return await _handle_dependency_analysis_request(dependency_analyzer, request)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def _handle_dependency_graph_request(
|
|
53
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
54
|
+
filter_type: str | None,
|
|
55
|
+
max_nodes: int,
|
|
56
|
+
include_external: bool,
|
|
57
|
+
) -> JSONResponse:
|
|
58
|
+
"""Handle dependency graph API request."""
|
|
59
|
+
try:
|
|
60
|
+
graph = dependency_analyzer.analyze_project()
|
|
61
|
+
|
|
62
|
+
# Apply filters if requested
|
|
63
|
+
if filter_type or max_nodes < len(graph.nodes):
|
|
64
|
+
filters = {
|
|
65
|
+
"type": filter_type,
|
|
66
|
+
"max_nodes": max_nodes,
|
|
67
|
+
"include_external": include_external,
|
|
68
|
+
}
|
|
69
|
+
graph = await _apply_graph_filters(graph, filters)
|
|
70
|
+
|
|
71
|
+
return JSONResponse(
|
|
72
|
+
{
|
|
73
|
+
"status": "success",
|
|
74
|
+
"data": graph.to_dict(),
|
|
75
|
+
"timestamp": datetime.now().isoformat(),
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def _handle_dependency_metrics_request(
|
|
83
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
84
|
+
) -> JSONResponse:
|
|
85
|
+
"""Handle dependency metrics API request."""
|
|
86
|
+
try:
|
|
87
|
+
graph = dependency_analyzer.analyze_project()
|
|
88
|
+
|
|
89
|
+
return JSONResponse(
|
|
90
|
+
{
|
|
91
|
+
"status": "success",
|
|
92
|
+
"data": graph.metrics,
|
|
93
|
+
"timestamp": datetime.now().isoformat(),
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
async def _handle_dependency_clusters_request(
|
|
101
|
+
dependency_analyzer: DependencyAnalyzer,
|
|
102
|
+
) -> JSONResponse:
|
|
103
|
+
"""Handle dependency clusters API request."""
|
|
104
|
+
try:
|
|
105
|
+
graph = dependency_analyzer.analyze_project()
|
|
106
|
+
|
|
107
|
+
return JSONResponse(
|
|
108
|
+
{
|
|
109
|
+
"status": "success",
|
|
110
|
+
"data": graph.clusters,
|
|
111
|
+
"timestamp": datetime.now().isoformat(),
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def _handle_dependency_analysis_request(
|
|
119
|
+
dependency_analyzer: DependencyAnalyzer, request: dict
|
|
120
|
+
) -> JSONResponse:
|
|
121
|
+
"""Handle dependency analysis trigger API request."""
|
|
122
|
+
try:
|
|
123
|
+
# Reset analyzer for fresh analysis
|
|
124
|
+
dependency_analyzer.dependency_graph = DependencyGraph()
|
|
125
|
+
graph = dependency_analyzer.analyze_project()
|
|
126
|
+
|
|
127
|
+
return JSONResponse(
|
|
128
|
+
{
|
|
129
|
+
"status": "success",
|
|
130
|
+
"message": "Dependency analysis completed",
|
|
131
|
+
"data": {
|
|
132
|
+
"nodes": len(graph.nodes),
|
|
133
|
+
"edges": len(graph.edges),
|
|
134
|
+
"clusters": len(graph.clusters),
|
|
135
|
+
"metrics": graph.metrics,
|
|
136
|
+
},
|
|
137
|
+
"timestamp": datetime.now().isoformat(),
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""REST API endpoints for error heatmap analysis.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for file-based, temporal, and
|
|
4
|
+
function-based error heatmap visualization and pattern analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI, HTTPException
|
|
10
|
+
from fastapi.responses import JSONResponse
|
|
11
|
+
|
|
12
|
+
from crackerjack.services.cache import CrackerjackCache
|
|
13
|
+
from crackerjack.services.monitoring.error_pattern_analyzer import (
|
|
14
|
+
ErrorPatternAnalyzer,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def register_heatmap_api_endpoints(
|
|
19
|
+
app: FastAPI, error_analyzer: ErrorPatternAnalyzer, cache: CrackerjackCache
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Register heatmap-related REST API endpoints."""
|
|
22
|
+
|
|
23
|
+
@app.get("/api/heatmap/file_errors")
|
|
24
|
+
async def get_file_error_heatmap() -> None:
|
|
25
|
+
"""Get error heat map by file."""
|
|
26
|
+
return await _handle_file_error_heatmap_request(error_analyzer)
|
|
27
|
+
|
|
28
|
+
@app.get("/api/heatmap/temporal_errors")
|
|
29
|
+
async def get_temporal_error_heatmap(time_buckets: int = 24) -> None:
|
|
30
|
+
"""Get error heat map over time."""
|
|
31
|
+
return await _handle_temporal_error_heatmap_request(
|
|
32
|
+
error_analyzer, time_buckets
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@app.get("/api/heatmap/function_errors")
|
|
36
|
+
async def get_function_error_heatmap() -> None:
|
|
37
|
+
"""Get error heat map by function."""
|
|
38
|
+
return await _handle_function_error_heatmap_request(error_analyzer)
|
|
39
|
+
|
|
40
|
+
@app.get("/api/error_patterns")
|
|
41
|
+
async def get_error_patterns(
|
|
42
|
+
days: int = 30, min_occurrences: int = 2, severity: str | None = None
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Get analyzed error patterns."""
|
|
45
|
+
return await _handle_error_patterns_request(
|
|
46
|
+
error_analyzer, days, min_occurrences, severity
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@app.post("/api/trigger_error_analysis")
|
|
50
|
+
async def trigger_error_analysis(request: dict) -> None:
|
|
51
|
+
"""Trigger fresh error pattern analysis."""
|
|
52
|
+
return await _handle_trigger_error_analysis_request(
|
|
53
|
+
error_analyzer, cache, request
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def _handle_file_error_heatmap_request(
|
|
58
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
59
|
+
) -> JSONResponse:
|
|
60
|
+
"""Handle file error heatmap API request."""
|
|
61
|
+
try:
|
|
62
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
63
|
+
heatmap = error_analyzer.generate_file_error_heatmap()
|
|
64
|
+
return JSONResponse(heatmap.to_dict())
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
async def _handle_temporal_error_heatmap_request(
|
|
70
|
+
error_analyzer: ErrorPatternAnalyzer, time_buckets: int
|
|
71
|
+
) -> JSONResponse:
|
|
72
|
+
"""Handle temporal error heatmap API request."""
|
|
73
|
+
try:
|
|
74
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
75
|
+
heatmap = error_analyzer.generate_temporal_heatmap(time_buckets=time_buckets)
|
|
76
|
+
return JSONResponse(heatmap.to_dict())
|
|
77
|
+
except Exception as e:
|
|
78
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def _handle_function_error_heatmap_request(
|
|
82
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
83
|
+
) -> JSONResponse:
|
|
84
|
+
"""Handle function error heatmap API request."""
|
|
85
|
+
try:
|
|
86
|
+
error_analyzer.analyze_error_patterns(days=30)
|
|
87
|
+
heatmap = error_analyzer.generate_function_error_heatmap()
|
|
88
|
+
return JSONResponse(heatmap.to_dict())
|
|
89
|
+
except Exception as e:
|
|
90
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def _handle_error_patterns_request(
|
|
94
|
+
error_analyzer: ErrorPatternAnalyzer,
|
|
95
|
+
days: int,
|
|
96
|
+
min_occurrences: int,
|
|
97
|
+
severity: str | None,
|
|
98
|
+
) -> JSONResponse:
|
|
99
|
+
"""Handle error patterns API request."""
|
|
100
|
+
try:
|
|
101
|
+
patterns = error_analyzer.analyze_error_patterns(
|
|
102
|
+
days=days, min_occurrences=min_occurrences
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Filter by severity if specified
|
|
106
|
+
if severity:
|
|
107
|
+
patterns = [p for p in patterns if p.severity == severity]
|
|
108
|
+
|
|
109
|
+
return JSONResponse(
|
|
110
|
+
{
|
|
111
|
+
"patterns": [pattern.to_dict() for pattern in patterns],
|
|
112
|
+
"total_count": len(patterns),
|
|
113
|
+
"analysis_period_days": days,
|
|
114
|
+
"generated_at": datetime.now().isoformat(),
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def _handle_trigger_error_analysis_request(
|
|
122
|
+
error_analyzer: ErrorPatternAnalyzer, cache: CrackerjackCache, request: dict
|
|
123
|
+
) -> JSONResponse:
|
|
124
|
+
"""Handle trigger error analysis API request."""
|
|
125
|
+
try:
|
|
126
|
+
days = request.get("days", 30)
|
|
127
|
+
min_occurrences = request.get("min_occurrences", 2)
|
|
128
|
+
|
|
129
|
+
# Perform fresh analysis
|
|
130
|
+
patterns = error_analyzer.analyze_error_patterns(
|
|
131
|
+
days=days, min_occurrences=min_occurrences
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Store results in cache
|
|
135
|
+
cache_key = f"error_patterns_{days}d"
|
|
136
|
+
cache.set(cache_key, [p.to_dict() for p in patterns], ttl_seconds=1800)
|
|
137
|
+
|
|
138
|
+
severity_breakdown = {
|
|
139
|
+
severity: len([p for p in patterns if p.severity == severity])
|
|
140
|
+
for severity in ("low", "medium", "high", "critical")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return JSONResponse(
|
|
144
|
+
{
|
|
145
|
+
"status": "success",
|
|
146
|
+
"message": "Error pattern analysis completed",
|
|
147
|
+
"patterns_found": len(patterns),
|
|
148
|
+
"analysis_period_days": days,
|
|
149
|
+
"severity_breakdown": severity_breakdown,
|
|
150
|
+
"generated_at": datetime.now().isoformat(),
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
except Exception as e:
|
|
154
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""REST API endpoints for quality intelligence features.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for anomaly detection, predictions,
|
|
4
|
+
insights, and pattern analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import typing as t
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from fastapi import FastAPI, HTTPException
|
|
11
|
+
from fastapi.responses import JSONResponse
|
|
12
|
+
|
|
13
|
+
from crackerjack.services.quality.quality_intelligence import (
|
|
14
|
+
QualityIntelligenceService,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def register_intelligence_api_endpoints(
|
|
19
|
+
app: FastAPI, intelligence_service: QualityIntelligenceService
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Register intelligence-related REST API endpoints."""
|
|
22
|
+
|
|
23
|
+
@app.get("/api/intelligence/anomalies")
|
|
24
|
+
async def get_anomalies(days: int = 7, metrics: str = None) -> None:
|
|
25
|
+
"""Get anomaly detection results."""
|
|
26
|
+
return await _handle_anomalies_request(intelligence_service, days, metrics)
|
|
27
|
+
|
|
28
|
+
@app.get("/api/intelligence/predictions/{metric}")
|
|
29
|
+
async def get_metric_prediction(metric: str, horizon_days: int = 7) -> None:
|
|
30
|
+
"""Get prediction for a specific metric."""
|
|
31
|
+
return await _handle_metric_prediction_request(
|
|
32
|
+
intelligence_service, metric, horizon_days
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@app.get("/api/intelligence/insights")
|
|
36
|
+
async def get_quality_insights(days: int = 30) -> None:
|
|
37
|
+
"""Get comprehensive quality insights."""
|
|
38
|
+
return await _handle_quality_insights_request(intelligence_service, days)
|
|
39
|
+
|
|
40
|
+
@app.get("/api/intelligence/patterns")
|
|
41
|
+
async def get_pattern_analysis(days: int = 30) -> None:
|
|
42
|
+
"""Get pattern recognition analysis."""
|
|
43
|
+
return await _handle_pattern_analysis_request(intelligence_service, days)
|
|
44
|
+
|
|
45
|
+
@app.post("/api/intelligence/analyze")
|
|
46
|
+
async def run_comprehensive_analysis(request: dict) -> None:
|
|
47
|
+
"""Run comprehensive intelligence analysis."""
|
|
48
|
+
return await _handle_comprehensive_analysis_request(
|
|
49
|
+
intelligence_service, request
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def _handle_anomalies_request(
|
|
54
|
+
intelligence_service: QualityIntelligenceService, days: int, metrics: str | None
|
|
55
|
+
) -> JSONResponse:
|
|
56
|
+
"""Handle anomalies API request."""
|
|
57
|
+
try:
|
|
58
|
+
if days > 365:
|
|
59
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
60
|
+
|
|
61
|
+
metrics_list = metrics.split(",") if metrics else None
|
|
62
|
+
anomalies = intelligence_service.detect_anomalies(
|
|
63
|
+
days=days, metrics=metrics_list
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return JSONResponse(
|
|
67
|
+
{
|
|
68
|
+
"status": "success",
|
|
69
|
+
"data": [anomaly.to_dict() for anomaly in anomalies],
|
|
70
|
+
"timestamp": datetime.now().isoformat(),
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
except Exception as e:
|
|
74
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
async def _handle_metric_prediction_request(
|
|
78
|
+
intelligence_service: QualityIntelligenceService, metric: str, horizon_days: int
|
|
79
|
+
) -> JSONResponse:
|
|
80
|
+
"""Handle metric prediction API request."""
|
|
81
|
+
try:
|
|
82
|
+
if horizon_days > 30:
|
|
83
|
+
raise HTTPException(status_code=400, detail="Horizon too far in the future")
|
|
84
|
+
|
|
85
|
+
all_predictions = intelligence_service.generate_advanced_predictions(
|
|
86
|
+
horizon_days
|
|
87
|
+
)
|
|
88
|
+
prediction = next((p for p in all_predictions if p.metric_name == metric), None)
|
|
89
|
+
if not prediction:
|
|
90
|
+
raise HTTPException(status_code=404, detail="Prediction not available")
|
|
91
|
+
|
|
92
|
+
return JSONResponse(
|
|
93
|
+
{
|
|
94
|
+
"status": "success",
|
|
95
|
+
"data": prediction.to_dict(),
|
|
96
|
+
"timestamp": datetime.now().isoformat(),
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
except Exception as e:
|
|
100
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
async def _handle_quality_insights_request(
|
|
104
|
+
intelligence_service: QualityIntelligenceService, days: int
|
|
105
|
+
) -> JSONResponse:
|
|
106
|
+
"""Handle quality insights API request."""
|
|
107
|
+
try:
|
|
108
|
+
if days > 365:
|
|
109
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
110
|
+
|
|
111
|
+
insights = intelligence_service.generate_comprehensive_insights(days=days)
|
|
112
|
+
|
|
113
|
+
return JSONResponse(
|
|
114
|
+
{
|
|
115
|
+
"status": "success",
|
|
116
|
+
"data": insights.to_dict(),
|
|
117
|
+
"timestamp": datetime.now().isoformat(),
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
async def _handle_pattern_analysis_request(
|
|
125
|
+
intelligence_service: QualityIntelligenceService, days: int
|
|
126
|
+
) -> JSONResponse:
|
|
127
|
+
"""Handle pattern analysis API request."""
|
|
128
|
+
try:
|
|
129
|
+
if days > 365:
|
|
130
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
131
|
+
|
|
132
|
+
patterns = intelligence_service.identify_patterns(days=days)
|
|
133
|
+
|
|
134
|
+
return JSONResponse(
|
|
135
|
+
{
|
|
136
|
+
"status": "success",
|
|
137
|
+
"data": patterns,
|
|
138
|
+
"timestamp": datetime.now().isoformat(),
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
except Exception as e:
|
|
142
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
async def _handle_comprehensive_analysis_request(
|
|
146
|
+
intelligence_service: QualityIntelligenceService, request: dict
|
|
147
|
+
) -> JSONResponse:
|
|
148
|
+
"""Handle comprehensive analysis API request."""
|
|
149
|
+
try:
|
|
150
|
+
days = request.get("days", 30)
|
|
151
|
+
|
|
152
|
+
if days > 365:
|
|
153
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
154
|
+
|
|
155
|
+
results = await _build_comprehensive_analysis_results(
|
|
156
|
+
intelligence_service, request, days
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return JSONResponse(
|
|
160
|
+
{
|
|
161
|
+
"status": "success",
|
|
162
|
+
"data": results,
|
|
163
|
+
"timestamp": datetime.now().isoformat(),
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
async def _build_comprehensive_analysis_results(
|
|
171
|
+
intelligence_service: QualityIntelligenceService, request: dict, days: int
|
|
172
|
+
) -> dict[str, t.Any]:
|
|
173
|
+
"""Build comprehensive analysis results based on request parameters."""
|
|
174
|
+
results = {}
|
|
175
|
+
|
|
176
|
+
if request.get("include_anomalies", True):
|
|
177
|
+
results["anomalies"] = [
|
|
178
|
+
anomaly.to_dict()
|
|
179
|
+
for anomaly in intelligence_service.detect_anomalies(days=days)
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
if request.get("include_predictions", True):
|
|
183
|
+
insights = intelligence_service.generate_comprehensive_insights(days=days)
|
|
184
|
+
results["insights"] = insights.to_dict()
|
|
185
|
+
|
|
186
|
+
# Generate specific predictions
|
|
187
|
+
predictions = {}
|
|
188
|
+
for metric in ("quality_score", "test_coverage", "hook_duration"):
|
|
189
|
+
pred = intelligence_service.generate_advanced_predictions(
|
|
190
|
+
metric, horizon_days=7
|
|
191
|
+
)
|
|
192
|
+
if pred:
|
|
193
|
+
predictions[metric] = pred.to_dict()
|
|
194
|
+
results["predictions"] = predictions
|
|
195
|
+
|
|
196
|
+
if request.get("include_patterns", True):
|
|
197
|
+
results["patterns"] = intelligence_service.identify_patterns(days=days)
|
|
198
|
+
|
|
199
|
+
return results
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""REST API endpoints for metrics and quality analysis.
|
|
2
|
+
|
|
3
|
+
This module provides HTTP endpoints for metrics summaries, quality trends,
|
|
4
|
+
alert configuration, and data export.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import csv
|
|
9
|
+
import typing as t
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from io import StringIO
|
|
12
|
+
|
|
13
|
+
from fastapi import FastAPI, HTTPException
|
|
14
|
+
from fastapi.responses import JSONResponse, Response
|
|
15
|
+
|
|
16
|
+
from crackerjack.services.quality.quality_baseline_enhanced import (
|
|
17
|
+
EnhancedQualityBaselineService,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from ..metrics import get_monitoring_current_metrics
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def register_metrics_api_endpoints(
|
|
24
|
+
app: FastAPI, job_manager: t.Any, quality_service: EnhancedQualityBaselineService
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Register metrics-related REST API endpoints."""
|
|
27
|
+
|
|
28
|
+
@app.get("/api/metrics/summary")
|
|
29
|
+
async def get_metrics_summary() -> None:
|
|
30
|
+
"""Get current system summary."""
|
|
31
|
+
try:
|
|
32
|
+
current_metrics = await get_monitoring_current_metrics(
|
|
33
|
+
quality_service, job_manager
|
|
34
|
+
)
|
|
35
|
+
return JSONResponse(
|
|
36
|
+
{
|
|
37
|
+
"status": "success",
|
|
38
|
+
"data": current_metrics.to_dict(),
|
|
39
|
+
"timestamp": datetime.now().isoformat(),
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
44
|
+
|
|
45
|
+
@app.get("/api/trends/quality")
|
|
46
|
+
async def get_quality_trends(days: int = 30) -> None:
|
|
47
|
+
"""Get quality trend analysis."""
|
|
48
|
+
return await _handle_quality_trends_request(quality_service, days)
|
|
49
|
+
|
|
50
|
+
@app.get("/api/alerts/configure")
|
|
51
|
+
async def get_alert_configuration() -> None:
|
|
52
|
+
"""Get current alert configuration."""
|
|
53
|
+
return await _handle_get_alert_configuration(quality_service)
|
|
54
|
+
|
|
55
|
+
@app.post("/api/alerts/configure")
|
|
56
|
+
async def update_alert_configuration(config: dict) -> None:
|
|
57
|
+
"""Update alert configuration."""
|
|
58
|
+
return await _handle_update_alert_configuration(quality_service, config)
|
|
59
|
+
|
|
60
|
+
@app.get("/api/export/data")
|
|
61
|
+
async def export_data(days: int = 30, format: str = "json") -> None:
|
|
62
|
+
"""Export historical data for external analysis."""
|
|
63
|
+
return await _handle_export_data_request(quality_service, days, format)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async def _handle_quality_trends_request(
|
|
67
|
+
quality_service: EnhancedQualityBaselineService, days: int
|
|
68
|
+
) -> JSONResponse:
|
|
69
|
+
"""Handle quality trends API request."""
|
|
70
|
+
try:
|
|
71
|
+
if days > 365:
|
|
72
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
73
|
+
|
|
74
|
+
trends = await asyncio.to_thread(
|
|
75
|
+
quality_service.analyze_quality_trend,
|
|
76
|
+
days,
|
|
77
|
+
)
|
|
78
|
+
return JSONResponse(
|
|
79
|
+
{
|
|
80
|
+
"status": "success",
|
|
81
|
+
"data": trends.to_dict(),
|
|
82
|
+
"timestamp": datetime.now().isoformat(),
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
except Exception as e:
|
|
86
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
async def _handle_get_alert_configuration(
|
|
90
|
+
quality_service: EnhancedQualityBaselineService,
|
|
91
|
+
) -> JSONResponse:
|
|
92
|
+
"""Handle get alert configuration API request."""
|
|
93
|
+
try:
|
|
94
|
+
config = quality_service.get_alert_thresholds()
|
|
95
|
+
return JSONResponse(
|
|
96
|
+
{
|
|
97
|
+
"status": "success",
|
|
98
|
+
"data": config,
|
|
99
|
+
"timestamp": datetime.now().isoformat(),
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
async def _handle_update_alert_configuration(
|
|
107
|
+
quality_service: EnhancedQualityBaselineService, config: dict
|
|
108
|
+
) -> JSONResponse:
|
|
109
|
+
"""Handle update alert configuration API request."""
|
|
110
|
+
try:
|
|
111
|
+
# Update individual thresholds
|
|
112
|
+
for metric, threshold in config.items():
|
|
113
|
+
quality_service.set_alert_threshold(metric, threshold)
|
|
114
|
+
return JSONResponse(
|
|
115
|
+
{
|
|
116
|
+
"status": "success",
|
|
117
|
+
"message": "Alert configuration updated",
|
|
118
|
+
"timestamp": datetime.now().isoformat(),
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
async def _handle_export_data_request(
|
|
126
|
+
quality_service: EnhancedQualityBaselineService, days: int, format_type: str
|
|
127
|
+
) -> JSONResponse | t.Any:
|
|
128
|
+
"""Handle export data API request."""
|
|
129
|
+
try:
|
|
130
|
+
if days > 365:
|
|
131
|
+
raise HTTPException(status_code=400, detail="Days parameter too large")
|
|
132
|
+
|
|
133
|
+
if format_type not in ("json", "csv"):
|
|
134
|
+
raise HTTPException(
|
|
135
|
+
status_code=400, detail="Format must be 'json' or 'csv'"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
historical_baselines = await quality_service.aget_recent_baselines(limit=days)
|
|
139
|
+
|
|
140
|
+
if format_type == "csv":
|
|
141
|
+
return _export_csv_data(historical_baselines, days)
|
|
142
|
+
else:
|
|
143
|
+
data = [baseline.to_dict() for baseline in historical_baselines]
|
|
144
|
+
return JSONResponse(
|
|
145
|
+
{
|
|
146
|
+
"status": "success",
|
|
147
|
+
"data": data,
|
|
148
|
+
"timestamp": datetime.now().isoformat(),
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
except Exception as e:
|
|
152
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _export_csv_data(historical_baselines: list[t.Any], days: int) -> t.Any:
|
|
156
|
+
"""Export data in CSV format."""
|
|
157
|
+
output = StringIO()
|
|
158
|
+
writer = csv.writer(output)
|
|
159
|
+
|
|
160
|
+
# Write header
|
|
161
|
+
writer.writerow(
|
|
162
|
+
[
|
|
163
|
+
"timestamp",
|
|
164
|
+
"git_hash",
|
|
165
|
+
"quality_score",
|
|
166
|
+
"coverage_percent",
|
|
167
|
+
"test_count",
|
|
168
|
+
"test_pass_rate",
|
|
169
|
+
"hook_failures",
|
|
170
|
+
"complexity_violations",
|
|
171
|
+
"security_issues",
|
|
172
|
+
"type_errors",
|
|
173
|
+
"linting_issues",
|
|
174
|
+
]
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Write data
|
|
178
|
+
for baseline in historical_baselines:
|
|
179
|
+
writer.writerow(
|
|
180
|
+
[
|
|
181
|
+
baseline.timestamp.isoformat(),
|
|
182
|
+
baseline.git_hash,
|
|
183
|
+
baseline.quality_score,
|
|
184
|
+
baseline.coverage_percent,
|
|
185
|
+
baseline.test_count,
|
|
186
|
+
baseline.test_pass_rate,
|
|
187
|
+
baseline.hook_failures,
|
|
188
|
+
baseline.complexity_violations,
|
|
189
|
+
baseline.security_issues,
|
|
190
|
+
baseline.type_errors,
|
|
191
|
+
baseline.linting_issues,
|
|
192
|
+
]
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return Response(
|
|
196
|
+
content=output.getvalue(),
|
|
197
|
+
media_type="text/csv",
|
|
198
|
+
headers={
|
|
199
|
+
"Content-Disposition": (
|
|
200
|
+
f"attachment; filename=crackerjack_metrics_{days}d.csv"
|
|
201
|
+
)
|
|
202
|
+
},
|
|
203
|
+
)
|