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,198 @@
|
|
|
1
|
+
"""Remove trailing whitespace from files.
|
|
2
|
+
|
|
3
|
+
This tool is a native Python implementation replacing pre-commit's
|
|
4
|
+
trailing-whitespace hook. It scans files for lines with trailing whitespace
|
|
5
|
+
and automatically removes it.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python -m crackerjack.tools.trailing_whitespace [files...]
|
|
9
|
+
|
|
10
|
+
Exit Codes:
|
|
11
|
+
0: No trailing whitespace found (or successfully fixed)
|
|
12
|
+
1: Trailing whitespace found and fixed (files modified)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from ._git_utils import get_files_by_extension
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def has_trailing_whitespace(line: str) -> bool:
|
|
25
|
+
"""Check if a line has trailing whitespace.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
line: Line to check (should include newline if present)
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
True if line has trailing whitespace before newline
|
|
32
|
+
"""
|
|
33
|
+
# Remove trailing newline for checking
|
|
34
|
+
line_stripped = line.rstrip("\n\r")
|
|
35
|
+
# Check if there's whitespace at the end
|
|
36
|
+
return line_stripped != line_stripped.rstrip()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def fix_trailing_whitespace(file_path: Path) -> bool:
|
|
40
|
+
"""Remove trailing whitespace from a file.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
file_path: Path to file to process
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
True if file was modified, False if no changes needed
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
# Read file content
|
|
50
|
+
content = file_path.read_text(encoding="utf-8")
|
|
51
|
+
lines = content.splitlines(keepends=True)
|
|
52
|
+
|
|
53
|
+
# Process lines
|
|
54
|
+
modified = False
|
|
55
|
+
new_lines = []
|
|
56
|
+
for line in lines:
|
|
57
|
+
if has_trailing_whitespace(line):
|
|
58
|
+
# Remove trailing whitespace but preserve newline
|
|
59
|
+
stripped = line.rstrip()
|
|
60
|
+
if line.endswith("\n"):
|
|
61
|
+
stripped += "\n"
|
|
62
|
+
elif line.endswith("\r\n"):
|
|
63
|
+
stripped += "\r\n"
|
|
64
|
+
new_lines.append(stripped)
|
|
65
|
+
modified = True
|
|
66
|
+
else:
|
|
67
|
+
new_lines.append(line)
|
|
68
|
+
|
|
69
|
+
# Write back if modified
|
|
70
|
+
if modified:
|
|
71
|
+
file_path.write_text("".join(new_lines), encoding="utf-8")
|
|
72
|
+
print(f"Fixed trailing whitespace: {file_path}") # noqa: T201
|
|
73
|
+
|
|
74
|
+
return modified
|
|
75
|
+
|
|
76
|
+
except UnicodeDecodeError:
|
|
77
|
+
# Skip binary files
|
|
78
|
+
return False
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(f"Error processing {file_path}: {e}", file=sys.stderr) # noqa: T201
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _collect_files_to_check(args: argparse.Namespace) -> list[Path]:
|
|
85
|
+
"""Collect files to check for trailing whitespace.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
args: Parsed command-line arguments
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
List of file paths to process
|
|
92
|
+
"""
|
|
93
|
+
# Default to all git-tracked files if none specified
|
|
94
|
+
if not args.files:
|
|
95
|
+
# Get all tracked text files (respects .gitignore via git ls-files)
|
|
96
|
+
files = get_files_by_extension(
|
|
97
|
+
[".py", ".md", ".txt", ".yaml", ".yml", ".toml", ".json"]
|
|
98
|
+
)
|
|
99
|
+
if not files:
|
|
100
|
+
# Fallback to Python files if not in git repo
|
|
101
|
+
files = list(Path.cwd().rglob("*.py"))
|
|
102
|
+
else:
|
|
103
|
+
files = args.files
|
|
104
|
+
|
|
105
|
+
# Filter to existing files only
|
|
106
|
+
return [f for f in files if f.is_file()]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _process_files_in_check_mode(files: list[Path]) -> int:
|
|
110
|
+
"""Process files in check-only mode.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
files: List of file paths to check
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Count of files with trailing whitespace
|
|
117
|
+
"""
|
|
118
|
+
modified_count = 0
|
|
119
|
+
for file_path in files:
|
|
120
|
+
content = file_path.read_text(encoding="utf-8")
|
|
121
|
+
lines = content.splitlines(keepends=True)
|
|
122
|
+
if any(has_trailing_whitespace(line) for line in lines):
|
|
123
|
+
print(f"Trailing whitespace found: {file_path}") # noqa: T201
|
|
124
|
+
modified_count += 1
|
|
125
|
+
return modified_count
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _process_files_in_fix_mode(files: list[Path]) -> int:
|
|
129
|
+
"""Process files in fix mode.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
files: List of file paths to fix
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Count of files modified
|
|
136
|
+
"""
|
|
137
|
+
modified_count = 0
|
|
138
|
+
for file_path in files:
|
|
139
|
+
if fix_trailing_whitespace(file_path):
|
|
140
|
+
modified_count += 1
|
|
141
|
+
return modified_count
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def main(argv: list[str] | None = None) -> int:
|
|
145
|
+
"""Main entry point for trailing-whitespace tool.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
argv: Command-line arguments (defaults to sys.argv[1:])
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Exit code: 0 if no files modified, 1 if files were modified
|
|
152
|
+
"""
|
|
153
|
+
parser = argparse.ArgumentParser(
|
|
154
|
+
description="Remove trailing whitespace from files"
|
|
155
|
+
)
|
|
156
|
+
parser.add_argument(
|
|
157
|
+
"files",
|
|
158
|
+
nargs="*",
|
|
159
|
+
type=Path,
|
|
160
|
+
help="Files to check (default: all Python files in current directory)",
|
|
161
|
+
)
|
|
162
|
+
parser.add_argument(
|
|
163
|
+
"--check",
|
|
164
|
+
action="store_true",
|
|
165
|
+
help="Check only, don't modify files",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
args = parser.parse_args(argv)
|
|
169
|
+
|
|
170
|
+
files = _collect_files_to_check(args)
|
|
171
|
+
|
|
172
|
+
if not files:
|
|
173
|
+
print("No files to check") # noqa: T201
|
|
174
|
+
return 0
|
|
175
|
+
|
|
176
|
+
# Process files based on mode
|
|
177
|
+
if args.check:
|
|
178
|
+
modified_count = _process_files_in_check_mode(files)
|
|
179
|
+
else:
|
|
180
|
+
modified_count = _process_files_in_fix_mode(files)
|
|
181
|
+
|
|
182
|
+
# Return appropriate exit code
|
|
183
|
+
if modified_count > 0:
|
|
184
|
+
if args.check:
|
|
185
|
+
print(f"\n{modified_count} file(s) with trailing whitespace") # noqa: T201
|
|
186
|
+
else:
|
|
187
|
+
print(f"\nFixed {modified_count} file(s)") # noqa: T201
|
|
188
|
+
# Align with pre-commit semantics so HookExecutor treats this as pass
|
|
189
|
+
# when a formatter modifies files but exits with code 1.
|
|
190
|
+
print("files were modified by this hook") # noqa: T201
|
|
191
|
+
return 1
|
|
192
|
+
|
|
193
|
+
print("No trailing whitespace found") # noqa: T201
|
|
194
|
+
return 0
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
if __name__ == "__main__":
|
|
198
|
+
sys.exit(main())
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
5
|
+
|
|
6
|
+
from crackerjack.services.input_validator import SecureInputValidator
|
|
7
|
+
from crackerjack.services.regex_patterns import SAFE_PATTERNS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_sql_injection_patterns() -> bool:
|
|
11
|
+
print("Testing SQL injection patterns...")
|
|
12
|
+
|
|
13
|
+
test_cases = [
|
|
14
|
+
("SELECT * FROM users", True, "Basic SELECT"),
|
|
15
|
+
("UNION SELECT password FROM admin", True, "UNION injection"),
|
|
16
|
+
("'; DROP TABLE users; --", True, "SQL comment injection"),
|
|
17
|
+
("' OR 1=1--", True, "Boolean injection"),
|
|
18
|
+
("xp_cmdshell('dir')", True, "SQL Server specific"),
|
|
19
|
+
("sp_executesql @sql", True, "SQL Server procedure"),
|
|
20
|
+
("user selected item", False, "Legitimate text with 'select'"),
|
|
21
|
+
("button execution", False, "Legitimate text with 'execution'"),
|
|
22
|
+
("team membership", False, "Legitimate text without SQL keywords"),
|
|
23
|
+
("normal text", False, "Normal text"),
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
patterns = [
|
|
27
|
+
"validate_sql_injection_patterns",
|
|
28
|
+
"validate_sql_comment_patterns",
|
|
29
|
+
"validate_sql_boolean_injection",
|
|
30
|
+
"validate_sql_server_specific",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
for text, should_detect, description in test_cases:
|
|
34
|
+
detected = False
|
|
35
|
+
for pattern_name in patterns:
|
|
36
|
+
if SAFE_PATTERNS[pattern_name].test(text):
|
|
37
|
+
detected = True
|
|
38
|
+
break
|
|
39
|
+
|
|
40
|
+
status = "✅" if detected == should_detect else "❌"
|
|
41
|
+
print(
|
|
42
|
+
f" {status} {description}: '{text}' -> {'BLOCKED' if detected else 'ALLOWED'}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if detected != should_detect:
|
|
46
|
+
print(f" Expected: {'BLOCKED' if should_detect else 'ALLOWED'}")
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
print("✅ All SQL injection pattern tests passed!")
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_code_injection_patterns() -> bool:
|
|
54
|
+
print("\nTesting code injection patterns...")
|
|
55
|
+
|
|
56
|
+
test_cases = [
|
|
57
|
+
("eval(user_input)", True, "eval() execution"),
|
|
58
|
+
("exec(malicious_code)", True, "exec() execution"),
|
|
59
|
+
("__import__('os')", True, "Dynamic import"),
|
|
60
|
+
("getattr(obj, 'dangerous')", True, "Dynamic attribute access"),
|
|
61
|
+
("subprocess.run(cmd)", True, "System command"),
|
|
62
|
+
("os.system('rm -rf')", True, "OS system call"),
|
|
63
|
+
("compile(code, 'string', 'exec')", True, "Code compilation"),
|
|
64
|
+
("evaluate the results", False, "Legitimate text with 'eval'"),
|
|
65
|
+
("execute the plan", False, "Legitimate text with 'execute'"),
|
|
66
|
+
("import statement", False, "Normal import discussion"),
|
|
67
|
+
("compiled successfully", False, "Normal compilation discussion"),
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
patterns = [
|
|
71
|
+
"validate_code_eval_injection",
|
|
72
|
+
"validate_code_dynamic_access",
|
|
73
|
+
"validate_code_system_commands",
|
|
74
|
+
"validate_code_compilation",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
for text, should_detect, description in test_cases:
|
|
78
|
+
detected = False
|
|
79
|
+
for pattern_name in patterns:
|
|
80
|
+
if SAFE_PATTERNS[pattern_name].test(text):
|
|
81
|
+
detected = True
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
status = "✅" if detected == should_detect else "❌"
|
|
85
|
+
print(
|
|
86
|
+
f" {status} {description}: '{text}' -> {'BLOCKED' if detected else 'ALLOWED'}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if detected != should_detect:
|
|
90
|
+
print(f" Expected: {'BLOCKED' if should_detect else 'ALLOWED'}")
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
print("✅ All code injection pattern tests passed!")
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_job_id_validation() -> bool:
|
|
98
|
+
print("\nTesting job ID validation...")
|
|
99
|
+
|
|
100
|
+
test_cases = [
|
|
101
|
+
("valid_job-123", True, "Standard job ID"),
|
|
102
|
+
("another-valid_job", True, "Hyphen and underscore"),
|
|
103
|
+
("JOB123", True, "Uppercase"),
|
|
104
|
+
("job_456", True, "Underscore only"),
|
|
105
|
+
("job-789", True, "Hyphen only"),
|
|
106
|
+
("complex_job-id_123", True, "Complex valid ID"),
|
|
107
|
+
("job with spaces", False, "Contains spaces"),
|
|
108
|
+
("job@invalid", False, "Contains @ symbol"),
|
|
109
|
+
("job.invalid", False, "Contains dot"),
|
|
110
|
+
("job/invalid", False, "Contains slash"),
|
|
111
|
+
("job=invalid", False, "Contains equals"),
|
|
112
|
+
("job$invalid", False, "Contains dollar"),
|
|
113
|
+
("", False, "Empty string"),
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
pattern = SAFE_PATTERNS["validate_job_id_format"]
|
|
117
|
+
|
|
118
|
+
for job_id, should_be_valid, description in test_cases:
|
|
119
|
+
is_valid = pattern.test(job_id)
|
|
120
|
+
status = "✅" if is_valid == should_be_valid else "❌"
|
|
121
|
+
print(
|
|
122
|
+
f" {status} {description}: '{job_id}' -> {'VALID' if is_valid else 'INVALID'}"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if is_valid != should_be_valid:
|
|
126
|
+
print(f" Expected: {'VALID' if should_be_valid else 'INVALID'}")
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
print("✅ All job ID validation tests passed!")
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_env_var_validation() -> bool:
|
|
134
|
+
print("\nTesting environment variable name validation...")
|
|
135
|
+
|
|
136
|
+
test_cases = [
|
|
137
|
+
("VALID_VAR", True, "Standard env var"),
|
|
138
|
+
("_PRIVATE_VAR", True, "Starting with underscore"),
|
|
139
|
+
("API_KEY_123", True, "With numbers"),
|
|
140
|
+
("DATABASE_URL", True, "Typical env var"),
|
|
141
|
+
("MAX_RETRIES", True, "Another typical var"),
|
|
142
|
+
("lowercase_var", False, "Contains lowercase"),
|
|
143
|
+
("123_INVALID", False, "Starts with number"),
|
|
144
|
+
("INVALID-VAR", False, "Contains hyphen"),
|
|
145
|
+
("INVALID.VAR", False, "Contains dot"),
|
|
146
|
+
("INVALID VAR", False, "Contains space"),
|
|
147
|
+
("INVALID@VAR", False, "Contains @ symbol"),
|
|
148
|
+
("", False, "Empty string"),
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
pattern = SAFE_PATTERNS["validate_env_var_name_format"]
|
|
152
|
+
|
|
153
|
+
for env_var, should_be_valid, description in test_cases:
|
|
154
|
+
is_valid = pattern.test(env_var)
|
|
155
|
+
status = "✅" if is_valid == should_be_valid else "❌"
|
|
156
|
+
print(
|
|
157
|
+
f" {status} {description}: '{env_var}' -> {'VALID' if is_valid else 'INVALID'}"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if is_valid != should_be_valid:
|
|
161
|
+
print(f" Expected: {'VALID' if should_be_valid else 'INVALID'}")
|
|
162
|
+
return False
|
|
163
|
+
|
|
164
|
+
print("✅ All environment variable validation tests passed!")
|
|
165
|
+
return True
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def test_integration_with_validator() -> bool:
|
|
169
|
+
print("\nTesting integration with SecureInputValidator...")
|
|
170
|
+
|
|
171
|
+
validator = SecureInputValidator()
|
|
172
|
+
|
|
173
|
+
result = validator.sanitizer.sanitize_string("'; DROP TABLE users; --")
|
|
174
|
+
if result.valid:
|
|
175
|
+
print("❌ SQL injection should have been detected")
|
|
176
|
+
return False
|
|
177
|
+
print("✅ SQL injection properly detected and blocked")
|
|
178
|
+
|
|
179
|
+
result = validator.validate_job_id("valid_job-123")
|
|
180
|
+
if not result.valid:
|
|
181
|
+
print("❌ Valid job ID should have been accepted")
|
|
182
|
+
return False
|
|
183
|
+
print("✅ Valid job ID properly accepted")
|
|
184
|
+
|
|
185
|
+
result = validator.validate_job_id("invalid job with spaces")
|
|
186
|
+
if result.valid:
|
|
187
|
+
print("❌ Invalid job ID should have been rejected")
|
|
188
|
+
return False
|
|
189
|
+
print("✅ Invalid job ID properly rejected")
|
|
190
|
+
|
|
191
|
+
result = validator.validate_environment_var("VALID_VAR", "some_value")
|
|
192
|
+
if not result.valid:
|
|
193
|
+
print("❌ Valid env var should have been accepted")
|
|
194
|
+
return False
|
|
195
|
+
print("✅ Valid environment variable properly accepted")
|
|
196
|
+
|
|
197
|
+
result = validator.validate_environment_var("invalid_var", "some_value")
|
|
198
|
+
if result.valid:
|
|
199
|
+
print("❌ Invalid env var should have been rejected")
|
|
200
|
+
return False
|
|
201
|
+
print("✅ Invalid environment variable properly rejected")
|
|
202
|
+
|
|
203
|
+
print("✅ All integration tests passed!")
|
|
204
|
+
return True
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main() -> int:
|
|
208
|
+
print("🔒 Validating Input Validator Security Patterns")
|
|
209
|
+
print("=" * 50)
|
|
210
|
+
|
|
211
|
+
tests = [
|
|
212
|
+
test_sql_injection_patterns,
|
|
213
|
+
test_code_injection_patterns,
|
|
214
|
+
test_job_id_validation,
|
|
215
|
+
test_env_var_validation,
|
|
216
|
+
test_integration_with_validator,
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
all_passed = True
|
|
220
|
+
for test_func in tests:
|
|
221
|
+
if not test_func():
|
|
222
|
+
all_passed = False
|
|
223
|
+
|
|
224
|
+
print("\n" + "=" * 50)
|
|
225
|
+
if all_passed:
|
|
226
|
+
print("✅ ALL SECURITY VALIDATION TESTS PASSED!")
|
|
227
|
+
print("🔒 Input validation is properly secured with SAFE_PATTERNS")
|
|
228
|
+
return 0
|
|
229
|
+
else:
|
|
230
|
+
print("❌ SOME TESTS FAILED!")
|
|
231
|
+
print("🚨 Security issues detected - review failed tests")
|
|
232
|
+
return 1
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
if __name__ == "__main__":
|
|
236
|
+
sys.exit(main())
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import re
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
REGEX_IMPORTS = {
|
|
7
|
+
"re",
|
|
8
|
+
"regex",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
REGEX_FUNCTIONS = {
|
|
12
|
+
"re.sub",
|
|
13
|
+
"re.search",
|
|
14
|
+
"re.match",
|
|
15
|
+
"re.findall",
|
|
16
|
+
"re.split",
|
|
17
|
+
"re.compile",
|
|
18
|
+
"regex.sub",
|
|
19
|
+
"regex.search",
|
|
20
|
+
"regex.match",
|
|
21
|
+
"regex.findall",
|
|
22
|
+
"regex.split",
|
|
23
|
+
"regex.compile",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
ALLOWED_PATTERNS = {
|
|
28
|
+
r"re\.escape\(",
|
|
29
|
+
r"re\.compile\(r?['\"]\\\\[wd]",
|
|
30
|
+
r"# REGEX OK: ",
|
|
31
|
+
r"crackerjack/services/regex_patterns\.py$",
|
|
32
|
+
r"tools/validate_regex_patterns_standalone\.py$",
|
|
33
|
+
r"crackerjack/tools/validate_regex_patterns\.py$",
|
|
34
|
+
r"tests/test_.*\.py$",
|
|
35
|
+
r"crackerjack/services/secure_subprocess\.py$",
|
|
36
|
+
r"crackerjack/mcp/tools/core_tools\.py$",
|
|
37
|
+
r"crackerjack/intelligence/agent_selector\.py$",
|
|
38
|
+
r"crackerjack/managers/test_.*\.py$",
|
|
39
|
+
r"crackerjack/core/async_workflow_orchestrator\.py$",
|
|
40
|
+
r"crackerjack/core/workflow_orchestrator\.py$",
|
|
41
|
+
r"crackerjack/agents/.*\.py$",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
FORBIDDEN_REPLACEMENT_PATTERNS = [
|
|
45
|
+
r"\\g\s+<\s*\d+\s*>", # Only match when there are spaces before <
|
|
46
|
+
r"\\g<\s+\d+>", # Spaces after opening <
|
|
47
|
+
r"\\g<\d+\s+>", # Spaces before closing >
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class RegexVisitor(ast.NodeVisitor):
|
|
52
|
+
def __init__(self, file_path: Path) -> None:
|
|
53
|
+
self.file_path = file_path
|
|
54
|
+
self.issues: list[tuple[int, str]] = []
|
|
55
|
+
self.has_regex_import = False
|
|
56
|
+
self.allowed_file = any(
|
|
57
|
+
re.search(pattern, str(file_path)) for pattern in ALLOWED_PATTERNS
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def visit_Import(self, node: ast.Import) -> None:
|
|
61
|
+
for alias in node.names:
|
|
62
|
+
if alias.name in REGEX_IMPORTS:
|
|
63
|
+
self.has_regex_import = True
|
|
64
|
+
self.generic_visit(node)
|
|
65
|
+
|
|
66
|
+
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
|
67
|
+
if node.module in REGEX_IMPORTS:
|
|
68
|
+
self.has_regex_import = True
|
|
69
|
+
self.generic_visit(node)
|
|
70
|
+
|
|
71
|
+
def visit_Call(self, node: ast.Call) -> None:
|
|
72
|
+
if self.allowed_file:
|
|
73
|
+
self.generic_visit(node)
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
func_name = self._get_function_name(node.func)
|
|
77
|
+
|
|
78
|
+
if func_name in REGEX_FUNCTIONS:
|
|
79
|
+
for arg in node.args:
|
|
80
|
+
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
|
|
81
|
+
self._check_replacement_syntax(arg.value, node.lineno)
|
|
82
|
+
|
|
83
|
+
if not self._is_exempted_line(node.lineno):
|
|
84
|
+
self.issues.append(
|
|
85
|
+
(
|
|
86
|
+
node.lineno,
|
|
87
|
+
f"Raw regex usage detected: {func_name}(). "
|
|
88
|
+
f"Use validated patterns from crackerjack.services.regex_patterns instead.",
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
self.generic_visit(node)
|
|
93
|
+
|
|
94
|
+
def _get_function_name(self, func_node: ast.AST) -> str:
|
|
95
|
+
if isinstance(func_node, ast.Name):
|
|
96
|
+
return func_node.id
|
|
97
|
+
elif isinstance(func_node, ast.Attribute):
|
|
98
|
+
if isinstance(func_node.value, ast.Name):
|
|
99
|
+
return f"{func_node.value.id}.{func_node.attr}"
|
|
100
|
+
return func_node.attr
|
|
101
|
+
return ""
|
|
102
|
+
|
|
103
|
+
def _check_replacement_syntax(self, replacement: str, line_no: int) -> None:
|
|
104
|
+
for pattern in FORBIDDEN_REPLACEMENT_PATTERNS:
|
|
105
|
+
if re.search(pattern, replacement):
|
|
106
|
+
self.issues.append(
|
|
107
|
+
(
|
|
108
|
+
line_no,
|
|
109
|
+
f"CRITICAL: Bad replacement syntax detected: '{replacement}'. "
|
|
110
|
+
f"Use \\g<1> not \\g<1>",
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def _is_exempted_line(self, line_no: int) -> bool:
|
|
115
|
+
from contextlib import suppress
|
|
116
|
+
|
|
117
|
+
with suppress(OSError, UnicodeDecodeError):
|
|
118
|
+
with self.file_path.open(encoding="utf-8") as f:
|
|
119
|
+
lines = f.readlines()
|
|
120
|
+
# Check current line and next 5 lines for exemption comments
|
|
121
|
+
# This handles multi-line statements
|
|
122
|
+
for offset in range(6): # Check lines: current, +1, +2, +3, +4, +5
|
|
123
|
+
check_line = line_no - 1 + offset
|
|
124
|
+
if check_line < len(lines):
|
|
125
|
+
line = lines[check_line]
|
|
126
|
+
if "# REGEX OK:" in line or "# regex ok:" in line.lower():
|
|
127
|
+
return True
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def validate_file(file_path: Path) -> list[tuple[int, str]]:
|
|
132
|
+
try:
|
|
133
|
+
content = file_path.read_text(encoding="utf-8")
|
|
134
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
135
|
+
return [(1, f"Error reading file: {e}")]
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
tree = ast.parse(content, filename=str(file_path))
|
|
139
|
+
except SyntaxError as e:
|
|
140
|
+
return [(e.lineno or 1, f"Syntax error: {e}")]
|
|
141
|
+
|
|
142
|
+
visitor = RegexVisitor(file_path)
|
|
143
|
+
visitor.visit(tree)
|
|
144
|
+
return visitor.issues
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def main(file_paths: list[str]) -> int:
|
|
148
|
+
if not file_paths:
|
|
149
|
+
print("✅ No Python files to validate")
|
|
150
|
+
return 0
|
|
151
|
+
|
|
152
|
+
exit_code = 0
|
|
153
|
+
|
|
154
|
+
for file_path_str in file_paths:
|
|
155
|
+
file_path = Path(file_path_str)
|
|
156
|
+
|
|
157
|
+
if file_path.suffix != ".py":
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
if not file_path.exists():
|
|
161
|
+
continue
|
|
162
|
+
|
|
163
|
+
issues = validate_file(file_path)
|
|
164
|
+
|
|
165
|
+
if issues:
|
|
166
|
+
exit_code = 1
|
|
167
|
+
print(f"\n❌ {file_path}: ")
|
|
168
|
+
for line_no, message in issues:
|
|
169
|
+
print(f" Line {line_no}: {message}")
|
|
170
|
+
|
|
171
|
+
if exit_code == 0:
|
|
172
|
+
print("✅ All regex patterns validated successfully!")
|
|
173
|
+
else:
|
|
174
|
+
print("\n" + "=" * 70)
|
|
175
|
+
print("REGEX VALIDATION FAILED")
|
|
176
|
+
print("=" * 70)
|
|
177
|
+
print("To fix these issues: ")
|
|
178
|
+
print("1. Use patterns from crackerjack.services.regex_patterns")
|
|
179
|
+
print("2. Add new patterns to SAFE_PATTERNS with comprehensive tests")
|
|
180
|
+
print("3. Use '# REGEX OK: reason' comment for legitimate exceptions")
|
|
181
|
+
print("4. Fix \\g<1> replacement syntax (no spaces)")
|
|
182
|
+
print("=" * 70)
|
|
183
|
+
|
|
184
|
+
return exit_code
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if __name__ == "__main__":
|
|
188
|
+
sys.exit(main(sys.argv[1:]))
|
crackerjack/ui/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
> Crackerjack Docs: [Main](<../../README.md>) | [Crackerjack Package](<../README.md>) | [UI](<./README.md>)
|
|
2
|
+
|
|
3
|
+
# UI
|
|
4
|
+
|
|
5
|
+
User interface components and templates.
|
|
6
|
+
|
|
7
|
+
## Related
|
|
8
|
+
|
|
9
|
+
- [Crackerjack Package](<../README.md>) - Parent package
|
|
10
|
+
- [UI Templates](<./templates/README.md>) - Template files for UI components
|
|
11
|
+
- [MCP](<../mcp/README.md>) - MCP progress monitor UI
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""UI components for Crackerjack."""
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Utilities for rendering the monitoring dashboard UI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
_TEMPLATE_DIR = Path(__file__).with_suffix("").parent / "templates"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _load_asset(filename: str) -> str:
|
|
12
|
+
path = _TEMPLATE_DIR / filename
|
|
13
|
+
if not path.exists():
|
|
14
|
+
msg = f"Dashboard asset not found: {filename}"
|
|
15
|
+
raise FileNotFoundError(msg)
|
|
16
|
+
return path.read_text(encoding="utf-8")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@lru_cache(maxsize=1)
|
|
20
|
+
def render_monitoring_dashboard() -> str:
|
|
21
|
+
"""Render the monitoring dashboard HTML using cached assets."""
|
|
22
|
+
html_template = _load_asset("monitoring_dashboard.html")
|
|
23
|
+
css_styles = _load_asset("monitoring_dashboard.css")
|
|
24
|
+
javascript_code = _load_asset("monitoring_dashboard.js")
|
|
25
|
+
return html_template.format(
|
|
26
|
+
css_styles=css_styles,
|
|
27
|
+
javascript_code=javascript_code,
|
|
28
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
> Crackerjack Docs: [Main](<../../../README.md>) | [Crackerjack Package](<../../README.md>) | [UI](<../README.md>) | [Templates](<./README.md>)
|
|
2
|
+
|
|
3
|
+
# UI Templates
|
|
4
|
+
|
|
5
|
+
Templates used by UI components.
|
|
6
|
+
|
|
7
|
+
## Related
|
|
8
|
+
|
|
9
|
+
- [UI](<../README.md>) - Parent UI package
|
|
10
|
+
- [Crackerjack Package](<../../README.md>) - Root package
|
|
11
|
+
- [Data](<../../data/README.md>) - Static data and assets
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from crackerjack.config import get_console_width
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def separator(char: str = "-", width: int | None = None) -> str:
|
|
7
|
+
"""Return a horizontal separator string.
|
|
8
|
+
|
|
9
|
+
- char: the character to repeat (default '-')
|
|
10
|
+
- width: explicit width; if None, uses configured console width
|
|
11
|
+
"""
|
|
12
|
+
w = width if isinstance(width, int) and width > 0 else get_console_width()
|
|
13
|
+
return char * w
|