crackerjack 0.37.9__py3-none-any.whl → 0.45.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +30 -1
- crackerjack/__main__.py +342 -1263
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +27 -5
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
- crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
- crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +40 -12
- crackerjack/agents/base.py +1 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +49 -53
- crackerjack/agents/dry_agent.py +187 -3
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +6 -8
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/performance_agent.py +121 -1152
- crackerjack/agents/refactoring_agent.py +156 -655
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +19 -1605
- crackerjack/api.py +5 -7
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +1 -1
- crackerjack/cli/cache_handlers.py +23 -18
- crackerjack/cli/cache_handlers_enhanced.py +1 -4
- crackerjack/cli/facade.py +70 -8
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +249 -49
- crackerjack/cli/interactive.py +8 -5
- crackerjack/cli/options.py +203 -110
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +60 -24
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +256 -0
- crackerjack/config/global_lock_config.py +191 -54
- crackerjack/config/hooks.py +188 -16
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/async_workflow_orchestrator.py +79 -53
- crackerjack/core/autofix_coordinator.py +22 -9
- crackerjack/core/container.py +10 -9
- crackerjack/core/enhanced_container.py +9 -9
- crackerjack/core/performance.py +1 -1
- crackerjack/core/performance_monitor.py +5 -3
- crackerjack/core/phase_coordinator.py +1018 -634
- crackerjack/core/proactive_workflow.py +3 -3
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +167 -23
- crackerjack/core/session_coordinator.py +187 -382
- crackerjack/core/timeout_manager.py +161 -44
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +1247 -953
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/ai_templates.py +1 -1
- crackerjack/documentation/dual_output_generator.py +11 -9
- crackerjack/documentation/reference_generator.py +104 -59
- crackerjack/dynamic_config.py +52 -61
- crackerjack/errors.py +1 -1
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +2 -0
- crackerjack/executors/async_hook_executor.py +539 -77
- crackerjack/executors/cached_hook_executor.py +3 -3
- crackerjack/executors/hook_executor.py +967 -102
- crackerjack/executors/hook_lock_manager.py +31 -22
- crackerjack/executors/individual_hook_executor.py +66 -32
- crackerjack/executors/lsp_aware_hook_executor.py +136 -57
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +23 -7
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +8 -9
- crackerjack/intelligence/README.md +557 -0
- crackerjack/interactive.py +37 -10
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/async_hook_manager.py +41 -57
- crackerjack/managers/hook_manager.py +449 -79
- crackerjack/managers/publish_manager.py +81 -36
- crackerjack/managers/test_command_builder.py +290 -12
- crackerjack/managers/test_executor.py +93 -8
- crackerjack/managers/test_manager.py +1082 -75
- crackerjack/managers/test_progress.py +118 -26
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/cache.py +25 -2
- crackerjack/mcp/client_runner.py +35 -18
- crackerjack/mcp/context.py +9 -9
- crackerjack/mcp/dashboard.py +24 -8
- crackerjack/mcp/enhanced_progress_monitor.py +34 -23
- crackerjack/mcp/file_monitor.py +27 -6
- crackerjack/mcp/progress_components.py +45 -34
- crackerjack/mcp/progress_monitor.py +6 -9
- crackerjack/mcp/rate_limiter.py +11 -7
- crackerjack/mcp/server.py +2 -0
- crackerjack/mcp/server_core.py +187 -55
- crackerjack/mcp/service_watchdog.py +12 -9
- crackerjack/mcp/task_manager.py +2 -2
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +2 -0
- crackerjack/mcp/tools/core_tools.py +75 -52
- crackerjack/mcp/tools/execution_tools.py +87 -31
- crackerjack/mcp/tools/intelligence_tools.py +2 -2
- crackerjack/mcp/tools/proactive_tools.py +1 -1
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +180 -132
- crackerjack/mcp/tools/workflow_executor.py +87 -46
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/app.py +11 -1
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +27 -4
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
- crackerjack/mcp/websocket/server.py +1 -3
- crackerjack/mcp/websocket/websocket_handler.py +107 -6
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +10 -1
- crackerjack/models/config.py +639 -22
- crackerjack/models/config_adapter.py +6 -6
- crackerjack/models/protocols.py +1167 -23
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +19 -3
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/ai_agent_watchdog.py +5 -4
- crackerjack/monitoring/metrics_collector.py +4 -3
- crackerjack/monitoring/regression_prevention.py +4 -3
- crackerjack/monitoring/websocket_server.py +4 -241
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +20 -67
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +13 -6
- crackerjack/orchestration/execution_strategies.py +6 -6
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +1 -1
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/hooks.py +3 -2
- crackerjack/plugins/loader.py +3 -3
- crackerjack/plugins/managers.py +1 -1
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +8 -21
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/api_extractor.py +5 -3
- crackerjack/services/bounded_status_operations.py +45 -5
- crackerjack/services/cache.py +249 -318
- crackerjack/services/changelog_automation.py +7 -3
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +83 -39
- crackerjack/services/config_merge.py +9 -6
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +13 -26
- crackerjack/services/coverage_badge_service.py +6 -4
- crackerjack/services/coverage_ratchet.py +53 -27
- crackerjack/services/debug.py +18 -7
- crackerjack/services/dependency_analyzer.py +4 -4
- crackerjack/services/dependency_monitor.py +13 -13
- crackerjack/services/documentation_generator.py +4 -2
- crackerjack/services/documentation_service.py +62 -33
- crackerjack/services/enhanced_filesystem.py +81 -27
- crackerjack/services/enterprise_optimizer.py +1 -1
- crackerjack/services/error_pattern_analyzer.py +10 -10
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +5 -7
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +80 -109
- crackerjack/services/git.py +99 -5
- crackerjack/services/health_metrics.py +4 -6
- crackerjack/services/heatmap_generator.py +12 -3
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +101 -49
- crackerjack/services/log_manager.py +2 -2
- crackerjack/services/logging.py +120 -68
- crackerjack/services/lsp_client.py +12 -12
- crackerjack/services/memory_optimizer.py +27 -22
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
- crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
- crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
- crackerjack/services/parallel_executor.py +166 -55
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +21 -8
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
- crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
- crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
- crackerjack/services/regex_patterns.py +58 -2987
- crackerjack/services/regex_utils.py +55 -29
- crackerjack/services/secure_status_formatter.py +42 -15
- crackerjack/services/secure_subprocess.py +35 -2
- crackerjack/services/security.py +16 -8
- crackerjack/services/server_manager.py +40 -51
- crackerjack/services/smart_scheduling.py +46 -6
- crackerjack/services/status_authentication.py +3 -3
- crackerjack/services/thread_safe_status_collector.py +1 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +9 -5
- crackerjack/services/unified_config.py +43 -351
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +6 -4
- crackerjack/services/version_checker.py +14 -8
- crackerjack/services/zuban_lsp_service.py +5 -4
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/init.md +2 -12
- crackerjack/slash_commands/run.md +84 -50
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_regex_patterns.py +7 -3
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack/managers/test_manager_backup.py +0 -1075
- crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
- crackerjack/mixins/__init__.py +0 -3
- crackerjack/mixins/error_handling.py +0 -145
- crackerjack/services/config.py +0 -358
- crackerjack/ui/server_panels.py +0 -125
- crackerjack-0.37.9.dist-info/RECORD +0 -231
- /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
- /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sqlite3
|
|
3
|
+
import threading
|
|
4
|
+
import typing as t
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from datetime import date, datetime
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MetricsCollector:
|
|
12
|
+
def __init__(self, db_path: Path | None = None) -> None:
|
|
13
|
+
if db_path is None:
|
|
14
|
+
db_dir = Path.home() / ".cache" / "crackerjack"
|
|
15
|
+
db_dir.mkdir(parents=True, exist_ok=True)
|
|
16
|
+
db_path = db_dir / "metrics.db"
|
|
17
|
+
|
|
18
|
+
self.db_path = db_path
|
|
19
|
+
self._lock = threading.Lock()
|
|
20
|
+
self._init_database()
|
|
21
|
+
|
|
22
|
+
def _init_database(self) -> None:
|
|
23
|
+
with self._get_connection() as conn:
|
|
24
|
+
conn.executescript("""
|
|
25
|
+
-- Jobs table
|
|
26
|
+
CREATE TABLE IF NOT EXISTS jobs (
|
|
27
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
28
|
+
job_id TEXT UNIQUE NOT NULL,
|
|
29
|
+
start_time TIMESTAMP NOT NULL,
|
|
30
|
+
end_time TIMESTAMP,
|
|
31
|
+
status TEXT NOT NULL, -- 'running', 'success', 'failed', 'cancelled'
|
|
32
|
+
iterations INTEGER DEFAULT 0,
|
|
33
|
+
ai_agent BOOLEAN DEFAULT 0,
|
|
34
|
+
error_message TEXT,
|
|
35
|
+
metadata TEXT -- JSON field for additional data
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
-- Errors table
|
|
39
|
+
CREATE TABLE IF NOT EXISTS errors (
|
|
40
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
41
|
+
job_id TEXT,
|
|
42
|
+
timestamp TIMESTAMP NOT NULL,
|
|
43
|
+
error_type TEXT NOT NULL, -- 'hook', 'test', 'lint', 'type_check', etc.
|
|
44
|
+
error_category TEXT, -- 'ruff', 'pyright', 'pytest', etc.
|
|
45
|
+
error_message TEXT,
|
|
46
|
+
file_path TEXT,
|
|
47
|
+
line_number INTEGER,
|
|
48
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
-- Hook executions table
|
|
52
|
+
CREATE TABLE IF NOT EXISTS hook_executions (
|
|
53
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
54
|
+
job_id TEXT,
|
|
55
|
+
timestamp TIMESTAMP NOT NULL,
|
|
56
|
+
hook_name TEXT NOT NULL,
|
|
57
|
+
hook_type TEXT, -- 'fast', 'comprehensive'
|
|
58
|
+
execution_time_ms INTEGER,
|
|
59
|
+
status TEXT, -- 'success', 'failed', 'skipped'
|
|
60
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
-- Test executions table
|
|
64
|
+
CREATE TABLE IF NOT EXISTS test_executions (
|
|
65
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
66
|
+
job_id TEXT,
|
|
67
|
+
timestamp TIMESTAMP NOT NULL,
|
|
68
|
+
total_tests INTEGER,
|
|
69
|
+
passed INTEGER,
|
|
70
|
+
failed INTEGER,
|
|
71
|
+
skipped INTEGER,
|
|
72
|
+
execution_time_ms INTEGER,
|
|
73
|
+
coverage_percent REAL,
|
|
74
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
-- Orchestration executions table (NEW)
|
|
78
|
+
CREATE TABLE IF NOT EXISTS orchestration_executions (
|
|
79
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
80
|
+
job_id TEXT,
|
|
81
|
+
timestamp TIMESTAMP NOT NULL,
|
|
82
|
+
execution_strategy TEXT NOT NULL, -- 'batch', 'individual', 'adaptive', 'selective'
|
|
83
|
+
progress_level TEXT NOT NULL, -- 'basic', 'detailed', 'granular', 'streaming'
|
|
84
|
+
ai_mode TEXT NOT NULL, -- 'single-agent', 'multi-agent', 'coordinator'
|
|
85
|
+
iteration_count INTEGER DEFAULT 1,
|
|
86
|
+
strategy_switches INTEGER DEFAULT 0, -- How many times strategy changed
|
|
87
|
+
correlation_insights TEXT, -- JSON of correlation analysis results
|
|
88
|
+
total_execution_time_ms INTEGER,
|
|
89
|
+
hooks_execution_time_ms INTEGER,
|
|
90
|
+
tests_execution_time_ms INTEGER,
|
|
91
|
+
ai_analysis_time_ms INTEGER,
|
|
92
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
-- Strategy decisions table (NEW)
|
|
96
|
+
CREATE TABLE IF NOT EXISTS strategy_decisions (
|
|
97
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
98
|
+
job_id TEXT,
|
|
99
|
+
iteration INTEGER,
|
|
100
|
+
timestamp TIMESTAMP NOT NULL,
|
|
101
|
+
previous_strategy TEXT,
|
|
102
|
+
selected_strategy TEXT NOT NULL,
|
|
103
|
+
decision_reason TEXT, -- Why this strategy was chosen
|
|
104
|
+
context_data TEXT, -- JSON of execution context
|
|
105
|
+
effectiveness_score REAL, -- How well the strategy worked (0 - 1)
|
|
106
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
-- Individual test executions table (NEW - more granular than test_executions)
|
|
110
|
+
CREATE TABLE IF NOT EXISTS individual_test_executions (
|
|
111
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
112
|
+
job_id TEXT,
|
|
113
|
+
timestamp TIMESTAMP NOT NULL,
|
|
114
|
+
test_id TEXT NOT NULL, -- Full test identifier
|
|
115
|
+
test_file TEXT NOT NULL,
|
|
116
|
+
test_class TEXT,
|
|
117
|
+
test_method TEXT,
|
|
118
|
+
status TEXT NOT NULL, -- 'passed', 'failed', 'skipped', 'error'
|
|
119
|
+
execution_time_ms INTEGER,
|
|
120
|
+
error_message TEXT,
|
|
121
|
+
error_traceback TEXT,
|
|
122
|
+
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
-- Daily summary table (for quick stats)
|
|
126
|
+
CREATE TABLE IF NOT EXISTS daily_summary (
|
|
127
|
+
date DATE PRIMARY KEY,
|
|
128
|
+
total_jobs INTEGER DEFAULT 0,
|
|
129
|
+
successful_jobs INTEGER DEFAULT 0,
|
|
130
|
+
failed_jobs INTEGER DEFAULT 0,
|
|
131
|
+
total_errors INTEGER DEFAULT 0,
|
|
132
|
+
hook_errors INTEGER DEFAULT 0,
|
|
133
|
+
test_errors INTEGER DEFAULT 0,
|
|
134
|
+
lint_errors INTEGER DEFAULT 0,
|
|
135
|
+
type_errors INTEGER DEFAULT 0,
|
|
136
|
+
avg_job_duration_ms INTEGER,
|
|
137
|
+
total_ai_fixes INTEGER DEFAULT 0,
|
|
138
|
+
orchestrated_jobs INTEGER DEFAULT 0, -- NEW
|
|
139
|
+
avg_orchestration_iterations REAL DEFAULT 0, -- NEW
|
|
140
|
+
most_effective_strategy TEXT -- NEW
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
--Create indexes for performance
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_start_time ON jobs(start_time);
|
|
145
|
+
CREATE INDEX IF NOT EXISTS idx_errors_job_id ON errors(job_id);
|
|
146
|
+
CREATE INDEX IF NOT EXISTS idx_errors_type ON errors(error_type);
|
|
147
|
+
CREATE INDEX IF NOT EXISTS idx_hooks_job_id ON hook_executions(job_id);
|
|
148
|
+
CREATE INDEX IF NOT EXISTS idx_tests_job_id ON test_executions(job_id);
|
|
149
|
+
CREATE INDEX IF NOT EXISTS idx_orchestration_job_id ON orchestration_executions(job_id);
|
|
150
|
+
CREATE INDEX IF NOT EXISTS idx_strategy_decisions_job_id ON strategy_decisions(job_id);
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_individual_tests_job_id ON individual_test_executions(job_id);
|
|
152
|
+
CREATE INDEX IF NOT EXISTS idx_strategy_decisions_strategy ON strategy_decisions(selected_strategy);
|
|
153
|
+
""")
|
|
154
|
+
|
|
155
|
+
@contextmanager
|
|
156
|
+
def _get_connection(self) -> t.Iterator[sqlite3.Connection]:
|
|
157
|
+
conn = sqlite3.connect(str(self.db_path))
|
|
158
|
+
conn.row_factory = sqlite3.Row
|
|
159
|
+
try:
|
|
160
|
+
yield conn
|
|
161
|
+
conn.commit()
|
|
162
|
+
except Exception:
|
|
163
|
+
conn.rollback()
|
|
164
|
+
raise
|
|
165
|
+
finally:
|
|
166
|
+
conn.close()
|
|
167
|
+
|
|
168
|
+
def start_job(
|
|
169
|
+
self,
|
|
170
|
+
job_id: str,
|
|
171
|
+
ai_agent: bool = False,
|
|
172
|
+
metadata: dict[str, Any] | None = None,
|
|
173
|
+
) -> None:
|
|
174
|
+
with self._lock, self._get_connection() as conn:
|
|
175
|
+
conn.execute(
|
|
176
|
+
"""
|
|
177
|
+
INSERT INTO jobs (job_id, start_time, status, ai_agent, metadata)
|
|
178
|
+
VALUES (?, ?, 'running', ?, ?)
|
|
179
|
+
""",
|
|
180
|
+
(job_id, datetime.now(), ai_agent, json.dumps(metadata or {})),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def end_job(
|
|
184
|
+
self,
|
|
185
|
+
job_id: str,
|
|
186
|
+
status: str,
|
|
187
|
+
iterations: int = 0,
|
|
188
|
+
error_message: str | None = None,
|
|
189
|
+
) -> None:
|
|
190
|
+
with self._lock, self._get_connection() as conn:
|
|
191
|
+
conn.execute(
|
|
192
|
+
"""
|
|
193
|
+
UPDATE jobs
|
|
194
|
+
SET end_time=?, status=?, iterations=?, error_message=?
|
|
195
|
+
WHERE job_id=?
|
|
196
|
+
""",
|
|
197
|
+
(datetime.now(), status, iterations, error_message, job_id),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
self._update_daily_summary(conn, datetime.now().date())
|
|
201
|
+
|
|
202
|
+
def record_error(
|
|
203
|
+
self,
|
|
204
|
+
job_id: str,
|
|
205
|
+
error_type: str,
|
|
206
|
+
error_category: str,
|
|
207
|
+
error_message: str,
|
|
208
|
+
file_path: str | None = None,
|
|
209
|
+
line_number: int | None = None,
|
|
210
|
+
) -> None:
|
|
211
|
+
with self._lock, self._get_connection() as conn:
|
|
212
|
+
conn.execute(
|
|
213
|
+
"""
|
|
214
|
+
INSERT INTO errors (job_id, timestamp, error_type, error_category,
|
|
215
|
+
error_message, file_path, line_number)
|
|
216
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
217
|
+
""",
|
|
218
|
+
(
|
|
219
|
+
job_id,
|
|
220
|
+
datetime.now(),
|
|
221
|
+
error_type,
|
|
222
|
+
error_category,
|
|
223
|
+
error_message,
|
|
224
|
+
file_path,
|
|
225
|
+
line_number,
|
|
226
|
+
),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
def record_hook_execution(
|
|
230
|
+
self,
|
|
231
|
+
job_id: str,
|
|
232
|
+
hook_name: str,
|
|
233
|
+
hook_type: str,
|
|
234
|
+
execution_time_ms: int,
|
|
235
|
+
status: str,
|
|
236
|
+
) -> None:
|
|
237
|
+
with self._lock, self._get_connection() as conn:
|
|
238
|
+
conn.execute(
|
|
239
|
+
"""
|
|
240
|
+
INSERT INTO hook_executions (job_id, timestamp, hook_name,
|
|
241
|
+
hook_type, execution_time_ms, status)
|
|
242
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
243
|
+
""",
|
|
244
|
+
(
|
|
245
|
+
job_id,
|
|
246
|
+
datetime.now(),
|
|
247
|
+
hook_name,
|
|
248
|
+
hook_type,
|
|
249
|
+
execution_time_ms,
|
|
250
|
+
status,
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def record_test_execution(
|
|
255
|
+
self,
|
|
256
|
+
job_id: str,
|
|
257
|
+
total_tests: int,
|
|
258
|
+
passed: int,
|
|
259
|
+
failed: int,
|
|
260
|
+
skipped: int,
|
|
261
|
+
execution_time_ms: int,
|
|
262
|
+
coverage_percent: float | None = None,
|
|
263
|
+
) -> None:
|
|
264
|
+
with self._lock, self._get_connection() as conn:
|
|
265
|
+
conn.execute(
|
|
266
|
+
"""
|
|
267
|
+
INSERT INTO test_executions (job_id, timestamp, total_tests,
|
|
268
|
+
passed, failed, skipped,
|
|
269
|
+
execution_time_ms, coverage_percent)
|
|
270
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
271
|
+
""",
|
|
272
|
+
(
|
|
273
|
+
job_id,
|
|
274
|
+
datetime.now(),
|
|
275
|
+
total_tests,
|
|
276
|
+
passed,
|
|
277
|
+
failed,
|
|
278
|
+
skipped,
|
|
279
|
+
execution_time_ms,
|
|
280
|
+
coverage_percent,
|
|
281
|
+
),
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def record_orchestration_execution(
|
|
285
|
+
self,
|
|
286
|
+
job_id: str,
|
|
287
|
+
execution_strategy: str,
|
|
288
|
+
progress_level: str,
|
|
289
|
+
ai_mode: str,
|
|
290
|
+
iteration_count: int,
|
|
291
|
+
strategy_switches: int,
|
|
292
|
+
correlation_insights: dict[str, Any],
|
|
293
|
+
total_execution_time_ms: int,
|
|
294
|
+
hooks_execution_time_ms: int,
|
|
295
|
+
tests_execution_time_ms: int,
|
|
296
|
+
ai_analysis_time_ms: int,
|
|
297
|
+
) -> None:
|
|
298
|
+
with self._lock, self._get_connection() as conn:
|
|
299
|
+
conn.execute(
|
|
300
|
+
"""
|
|
301
|
+
INSERT INTO orchestration_executions
|
|
302
|
+
(job_id, timestamp, execution_strategy, progress_level, ai_mode,
|
|
303
|
+
iteration_count, strategy_switches, correlation_insights,
|
|
304
|
+
total_execution_time_ms, hooks_execution_time_ms,
|
|
305
|
+
tests_execution_time_ms, ai_analysis_time_ms)
|
|
306
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
307
|
+
""",
|
|
308
|
+
(
|
|
309
|
+
job_id,
|
|
310
|
+
datetime.now(),
|
|
311
|
+
execution_strategy,
|
|
312
|
+
progress_level,
|
|
313
|
+
ai_mode,
|
|
314
|
+
iteration_count,
|
|
315
|
+
strategy_switches,
|
|
316
|
+
json.dumps(correlation_insights),
|
|
317
|
+
total_execution_time_ms,
|
|
318
|
+
hooks_execution_time_ms,
|
|
319
|
+
tests_execution_time_ms,
|
|
320
|
+
ai_analysis_time_ms,
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def record_strategy_decision(
|
|
325
|
+
self,
|
|
326
|
+
job_id: str,
|
|
327
|
+
iteration: int,
|
|
328
|
+
previous_strategy: str | None,
|
|
329
|
+
selected_strategy: str,
|
|
330
|
+
decision_reason: str,
|
|
331
|
+
context_data: dict[str, Any],
|
|
332
|
+
effectiveness_score: float | None = None,
|
|
333
|
+
) -> None:
|
|
334
|
+
with self._lock, self._get_connection() as conn:
|
|
335
|
+
conn.execute(
|
|
336
|
+
"""
|
|
337
|
+
INSERT INTO strategy_decisions
|
|
338
|
+
(job_id, iteration, timestamp, previous_strategy, selected_strategy,
|
|
339
|
+
decision_reason, context_data, effectiveness_score)
|
|
340
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
341
|
+
""",
|
|
342
|
+
(
|
|
343
|
+
job_id,
|
|
344
|
+
iteration,
|
|
345
|
+
datetime.now(),
|
|
346
|
+
previous_strategy,
|
|
347
|
+
selected_strategy,
|
|
348
|
+
decision_reason,
|
|
349
|
+
json.dumps(context_data),
|
|
350
|
+
effectiveness_score,
|
|
351
|
+
),
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
def record_individual_test(
|
|
355
|
+
self,
|
|
356
|
+
job_id: str,
|
|
357
|
+
test_id: str,
|
|
358
|
+
test_file: str,
|
|
359
|
+
test_class: str | None,
|
|
360
|
+
test_method: str | None,
|
|
361
|
+
status: str,
|
|
362
|
+
execution_time_ms: int | None,
|
|
363
|
+
error_message: str | None = None,
|
|
364
|
+
error_traceback: str | None = None,
|
|
365
|
+
) -> None:
|
|
366
|
+
with self._lock, self._get_connection() as conn:
|
|
367
|
+
conn.execute(
|
|
368
|
+
"""
|
|
369
|
+
INSERT INTO individual_test_executions
|
|
370
|
+
(job_id, timestamp, test_id, test_file, test_class, test_method,
|
|
371
|
+
status, execution_time_ms, error_message, error_traceback)
|
|
372
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
373
|
+
""",
|
|
374
|
+
(
|
|
375
|
+
job_id,
|
|
376
|
+
datetime.now(),
|
|
377
|
+
test_id,
|
|
378
|
+
test_file,
|
|
379
|
+
test_class,
|
|
380
|
+
test_method,
|
|
381
|
+
status,
|
|
382
|
+
execution_time_ms,
|
|
383
|
+
error_message,
|
|
384
|
+
error_traceback,
|
|
385
|
+
),
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
def get_orchestration_stats(self) -> dict[str, Any]:
|
|
389
|
+
with self._get_connection() as conn:
|
|
390
|
+
strategy_stats = conn.execute("""
|
|
391
|
+
SELECT
|
|
392
|
+
selected_strategy,
|
|
393
|
+
COUNT(*) as usage_count,
|
|
394
|
+
AVG(effectiveness_score) as avg_effectiveness,
|
|
395
|
+
AVG(
|
|
396
|
+
SELECT iteration_count
|
|
397
|
+
FROM orchestration_executions o
|
|
398
|
+
WHERE o.job_id=sd.job_id
|
|
399
|
+
) as avg_iterations_needed
|
|
400
|
+
FROM strategy_decisions sd
|
|
401
|
+
WHERE effectiveness_score IS NOT NULL
|
|
402
|
+
GROUP BY selected_strategy
|
|
403
|
+
ORDER BY avg_effectiveness DESC, usage_count DESC
|
|
404
|
+
""").fetchall()
|
|
405
|
+
|
|
406
|
+
correlation_patterns = conn.execute("""
|
|
407
|
+
SELECT
|
|
408
|
+
json_extract(correlation_insights, '$.problematic_hooks') as problematic_hooks,
|
|
409
|
+
COUNT(*) as frequency
|
|
410
|
+
FROM orchestration_executions
|
|
411
|
+
WHERE correlation_insights != 'null'
|
|
412
|
+
AND correlation_insights != '{}'
|
|
413
|
+
GROUP BY problematic_hooks
|
|
414
|
+
ORDER BY frequency DESC
|
|
415
|
+
LIMIT 10
|
|
416
|
+
""").fetchall()
|
|
417
|
+
|
|
418
|
+
performance_stats = conn.execute("""
|
|
419
|
+
SELECT
|
|
420
|
+
execution_strategy,
|
|
421
|
+
COUNT(*) as executions,
|
|
422
|
+
AVG(total_execution_time_ms) as avg_total_time,
|
|
423
|
+
AVG(hooks_execution_time_ms) as avg_hooks_time,
|
|
424
|
+
AVG(tests_execution_time_ms) as avg_tests_time,
|
|
425
|
+
AVG(ai_analysis_time_ms) as avg_ai_time,
|
|
426
|
+
AVG(iteration_count) as avg_iterations
|
|
427
|
+
FROM orchestration_executions
|
|
428
|
+
GROUP BY execution_strategy
|
|
429
|
+
""").fetchall()
|
|
430
|
+
|
|
431
|
+
test_failure_patterns = conn.execute("""
|
|
432
|
+
SELECT
|
|
433
|
+
test_file,
|
|
434
|
+
test_class,
|
|
435
|
+
test_method,
|
|
436
|
+
COUNT(*) as failure_count,
|
|
437
|
+
AVG(execution_time_ms) as avg_execution_time
|
|
438
|
+
FROM individual_test_executions
|
|
439
|
+
WHERE status='failed'
|
|
440
|
+
GROUP BY test_file, test_class, test_method
|
|
441
|
+
ORDER BY failure_count DESC
|
|
442
|
+
LIMIT 15
|
|
443
|
+
""").fetchall()
|
|
444
|
+
|
|
445
|
+
return {
|
|
446
|
+
"strategy_effectiveness": [
|
|
447
|
+
dict[str, t.Any](row) for row in strategy_stats
|
|
448
|
+
],
|
|
449
|
+
"correlation_patterns": [
|
|
450
|
+
dict[str, t.Any](row) for row in correlation_patterns
|
|
451
|
+
],
|
|
452
|
+
"performance_by_strategy": [
|
|
453
|
+
dict[str, t.Any](row) for row in performance_stats
|
|
454
|
+
],
|
|
455
|
+
"test_failure_patterns": [
|
|
456
|
+
dict[str, t.Any](row) for row in test_failure_patterns
|
|
457
|
+
],
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
def _update_daily_summary(
|
|
461
|
+
self,
|
|
462
|
+
conn: sqlite3.Connection,
|
|
463
|
+
date: date,
|
|
464
|
+
) -> None:
|
|
465
|
+
job_stats = conn.execute(
|
|
466
|
+
"""
|
|
467
|
+
SELECT
|
|
468
|
+
COUNT(*) as total_jobs,
|
|
469
|
+
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as successful_jobs,
|
|
470
|
+
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as failed_jobs,
|
|
471
|
+
AVG(CASE
|
|
472
|
+
WHEN end_time IS NOT NULL
|
|
473
|
+
THEN (julianday(end_time)-julianday(start_time)) * 86400000
|
|
474
|
+
ELSE NULL
|
|
475
|
+
END) as avg_duration_ms,
|
|
476
|
+
SUM(CASE WHEN ai_agent=1 AND status='success' THEN 1 ELSE 0 END) as ai_fixes
|
|
477
|
+
FROM jobs
|
|
478
|
+
WHERE DATE(start_time) = ?
|
|
479
|
+
""",
|
|
480
|
+
(date,),
|
|
481
|
+
).fetchone()
|
|
482
|
+
|
|
483
|
+
error_stats = conn.execute(
|
|
484
|
+
"""
|
|
485
|
+
SELECT
|
|
486
|
+
COUNT(*) as total_errors,
|
|
487
|
+
SUM(CASE WHEN error_type='hook' THEN 1 ELSE 0 END) as hook_errors,
|
|
488
|
+
SUM(CASE WHEN error_type='test' THEN 1 ELSE 0 END) as test_errors,
|
|
489
|
+
SUM(CASE WHEN error_type='lint' THEN 1 ELSE 0 END) as lint_errors,
|
|
490
|
+
SUM(CASE WHEN error_type='type_check' THEN 1 ELSE 0 END) as type_errors
|
|
491
|
+
FROM errors
|
|
492
|
+
WHERE DATE(timestamp) = ?
|
|
493
|
+
""",
|
|
494
|
+
(date,),
|
|
495
|
+
).fetchone()
|
|
496
|
+
|
|
497
|
+
orchestration_stats = conn.execute(
|
|
498
|
+
"""
|
|
499
|
+
SELECT
|
|
500
|
+
COUNT(*) as orchestrated_jobs,
|
|
501
|
+
AVG(iteration_count) as avg_iterations,
|
|
502
|
+
(SELECT selected_strategy
|
|
503
|
+
FROM strategy_decisions sd2
|
|
504
|
+
WHERE DATE(sd2.timestamp) = ?
|
|
505
|
+
GROUP BY selected_strategy
|
|
506
|
+
ORDER BY COUNT(*) DESC
|
|
507
|
+
LIMIT 1) as most_effective_strategy
|
|
508
|
+
FROM orchestration_executions
|
|
509
|
+
WHERE DATE(timestamp) = ?
|
|
510
|
+
""",
|
|
511
|
+
(date, date),
|
|
512
|
+
).fetchone()
|
|
513
|
+
|
|
514
|
+
conn.execute(
|
|
515
|
+
"""
|
|
516
|
+
INSERT OR REPLACE INTO daily_summary
|
|
517
|
+
(date, total_jobs, successful_jobs, failed_jobs, total_errors,
|
|
518
|
+
hook_errors, test_errors, lint_errors, type_errors,
|
|
519
|
+
avg_job_duration_ms, total_ai_fixes, orchestrated_jobs,
|
|
520
|
+
avg_orchestration_iterations, most_effective_strategy)
|
|
521
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
522
|
+
""",
|
|
523
|
+
(
|
|
524
|
+
date,
|
|
525
|
+
job_stats["total_jobs"] or 0,
|
|
526
|
+
job_stats["successful_jobs"] or 0,
|
|
527
|
+
job_stats["failed_jobs"] or 0,
|
|
528
|
+
error_stats["total_errors"] or 0,
|
|
529
|
+
error_stats["hook_errors"] or 0,
|
|
530
|
+
error_stats["test_errors"] or 0,
|
|
531
|
+
error_stats["lint_errors"] or 0,
|
|
532
|
+
error_stats["type_errors"] or 0,
|
|
533
|
+
int(job_stats["avg_duration_ms"] or 0),
|
|
534
|
+
job_stats["ai_fixes"] or 0,
|
|
535
|
+
orchestration_stats["orchestrated_jobs"] or 0,
|
|
536
|
+
float(orchestration_stats["avg_iterations"] or 0),
|
|
537
|
+
orchestration_stats["most_effective_strategy"],
|
|
538
|
+
),
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
def get_all_time_stats(self) -> dict[str, Any]:
|
|
542
|
+
with self._get_connection() as conn:
|
|
543
|
+
job_stats = conn.execute("""
|
|
544
|
+
SELECT
|
|
545
|
+
COUNT(*) as total_jobs,
|
|
546
|
+
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as successful_jobs,
|
|
547
|
+
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as failed_jobs,
|
|
548
|
+
SUM(CASE WHEN ai_agent=1 THEN 1 ELSE 0 END) as ai_agent_jobs,
|
|
549
|
+
AVG(iterations) as avg_iterations
|
|
550
|
+
FROM jobs
|
|
551
|
+
""").fetchone()
|
|
552
|
+
|
|
553
|
+
error_stats = conn.execute("""
|
|
554
|
+
SELECT error_type, COUNT( * ) as count
|
|
555
|
+
FROM errors
|
|
556
|
+
GROUP BY error_type
|
|
557
|
+
""").fetchall()
|
|
558
|
+
|
|
559
|
+
common_errors = conn.execute("""
|
|
560
|
+
SELECT error_category, error_message, COUNT( * ) as count
|
|
561
|
+
FROM errors
|
|
562
|
+
GROUP BY error_category, error_message
|
|
563
|
+
ORDER BY count DESC
|
|
564
|
+
LIMIT 10
|
|
565
|
+
""").fetchall()
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
"total_jobs": job_stats["total_jobs"] or 0,
|
|
569
|
+
"successful_jobs": job_stats["successful_jobs"] or 0,
|
|
570
|
+
"failed_jobs": job_stats["failed_jobs"] or 0,
|
|
571
|
+
"ai_agent_jobs": job_stats["ai_agent_jobs"] or 0,
|
|
572
|
+
"avg_iterations": float(job_stats["avg_iterations"] or 0),
|
|
573
|
+
"error_breakdown": {
|
|
574
|
+
row["error_type"]: row["count"] for row in error_stats
|
|
575
|
+
},
|
|
576
|
+
"common_errors": [dict[str, t.Any](row) for row in common_errors],
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
_metrics_collector: MetricsCollector | None = None
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
def get_metrics_collector() -> MetricsCollector:
|
|
584
|
+
global _metrics_collector
|
|
585
|
+
if _metrics_collector is None:
|
|
586
|
+
_metrics_collector = MetricsCollector()
|
|
587
|
+
return _metrics_collector
|