patchi 0.7.5__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.
- patchi/__init__.py +1 -0
- patchi/__main__.py +13 -0
- patchi/cli/__init__.py +0 -0
- patchi/cli/command_families.py +235 -0
- patchi/cli/commands/__init__.py +0 -0
- patchi/cli/commands/access_cmd.py +65 -0
- patchi/cli/commands/agent_stats_cmd.py +273 -0
- patchi/cli/commands/agents_cmd.py +187 -0
- patchi/cli/commands/ai_cmd.py +308 -0
- patchi/cli/commands/assure_cmd.py +538 -0
- patchi/cli/commands/audit_cmd.py +286 -0
- patchi/cli/commands/auto_cmd.py +110 -0
- patchi/cli/commands/blame_cmd.py +53 -0
- patchi/cli/commands/chains_cmd.py +327 -0
- patchi/cli/commands/charter_cmd.py +173 -0
- patchi/cli/commands/chat_cmd.py +597 -0
- patchi/cli/commands/check_cmd.py +232 -0
- patchi/cli/commands/cleanup_cmd.py +328 -0
- patchi/cli/commands/cockpit_cmd.py +208 -0
- patchi/cli/commands/commands_cmd.py +160 -0
- patchi/cli/commands/cross_repo_cmd.py +113 -0
- patchi/cli/commands/deps_cmd.py +110 -0
- patchi/cli/commands/dev_check_cmd.py +342 -0
- patchi/cli/commands/dev_cmd.py +445 -0
- patchi/cli/commands/doctor_cmd.py +457 -0
- patchi/cli/commands/findings_cmd.py +187 -0
- patchi/cli/commands/fix_cmd.py +648 -0
- patchi/cli/commands/fix_review_cmd.py +273 -0
- patchi/cli/commands/heatmap_cmd.py +62 -0
- patchi/cli/commands/help_cmd.py +159 -0
- patchi/cli/commands/hosted_cmd.py +980 -0
- patchi/cli/commands/init.py +456 -0
- patchi/cli/commands/key_cmd.py +571 -0
- patchi/cli/commands/learn_cmd.py +140 -0
- patchi/cli/commands/link_cmd.py +104 -0
- patchi/cli/commands/log_cmd.py +57 -0
- patchi/cli/commands/memory_cmd.py +215 -0
- patchi/cli/commands/model_cmd.py +207 -0
- patchi/cli/commands/notify_cmd.py +213 -0
- patchi/cli/commands/notify_prompts.py +29 -0
- patchi/cli/commands/patch_cmd.py +231 -0
- patchi/cli/commands/plan_cmd.py +128 -0
- patchi/cli/commands/plugins_cmd.py +307 -0
- patchi/cli/commands/queue_cmd.py +152 -0
- patchi/cli/commands/quick_cmd.py +159 -0
- patchi/cli/commands/ready_cmd.py +292 -0
- patchi/cli/commands/report_cmd.py +416 -0
- patchi/cli/commands/restrict_cmd.py +127 -0
- patchi/cli/commands/review_cmd.py +225 -0
- patchi/cli/commands/rules_cmd.py +233 -0
- patchi/cli/commands/scan_cmd.py +1908 -0
- patchi/cli/commands/settings_cmd.py +45 -0
- patchi/cli/commands/status_cmd.py +679 -0
- patchi/cli/commands/test_cmd.py +1052 -0
- patchi/cli/commands/trend_cmd.py +296 -0
- patchi/cli/commands/undo_cmd.py +235 -0
- patchi/cli/commands/update_cmd.py +345 -0
- patchi/cli/commands/verify_cmd.py +56 -0
- patchi/cli/commands/vr_cmd.py +440 -0
- patchi/cli/commands/watch_cmd.py +304 -0
- patchi/cli/commands/web_cmd.py +114 -0
- patchi/cli/console.py +101 -0
- patchi/cli/display/__init__.py +1 -0
- patchi/cli/display/live_audit.py +269 -0
- patchi/cli/display/live_progress.py +169 -0
- patchi/cli/framework.py +241 -0
- patchi/cli/logo.py +128 -0
- patchi/cli/main.py +222 -0
- patchi/cli/registry.py +1171 -0
- patchi/cli/style.py +68 -0
- patchi/cli/themes.py +187 -0
- patchi/cli/ux.py +444 -0
- patchi/core/__init__.py +0 -0
- patchi/core/agents/__init__.py +0 -0
- patchi/core/agents/api_fuzzer_agent.py +141 -0
- patchi/core/agents/attack_agent.py +242 -0
- patchi/core/agents/base.py +1012 -0
- patchi/core/agents/bug_predictor_agent.py +58 -0
- patchi/core/agents/build_tool_validator.py +150 -0
- patchi/core/agents/cache.py +192 -0
- patchi/core/agents/chaos_agent.py +133 -0
- patchi/core/agents/cicd_generator.py +240 -0
- patchi/core/agents/comment_scanner.py +280 -0
- patchi/core/agents/console_logging_agent.py +156 -0
- patchi/core/agents/coordinator.py +858 -0
- patchi/core/agents/core_scanner.py +269 -0
- patchi/core/agents/coverage_prioritizer.py +181 -0
- patchi/core/agents/dead_code_hygiene.py +296 -0
- patchi/core/agents/dead_code_scanner.py +692 -0
- patchi/core/agents/dependency_scanner.py +725 -0
- patchi/core/agents/doc_claim_agent.py +573 -0
- patchi/core/agents/duplicate_scanner.py +568 -0
- patchi/core/agents/env_scanner.py +410 -0
- patchi/core/agents/feature_flag_agent.py +89 -0
- patchi/core/agents/frontend_framework_agent.py +133 -0
- patchi/core/agents/goroutine_agent.py +82 -0
- patchi/core/agents/governor.py +1972 -0
- patchi/core/agents/i18n_agent.py +95 -0
- patchi/core/agents/license_compliance.py +247 -0
- patchi/core/agents/linking_agent.py +251 -0
- patchi/core/agents/memory_profiler_agent.py +102 -0
- patchi/core/agents/modernization_agent.py +84 -0
- patchi/core/agents/mutation_agent.py +174 -0
- patchi/core/agents/nl_query_agent.py +74 -0
- patchi/core/agents/promise_rejection_agent.py +100 -0
- patchi/core/agents/refactoring_agent.py +286 -0
- patchi/core/agents/resource_leak_agent.py +91 -0
- patchi/core/agents/route_graph_scanner.py +951 -0
- patchi/core/agents/run_agent.py +106 -0
- patchi/core/agents/rust_unwrap_agent.py +100 -0
- patchi/core/agents/sbom_generator.py +284 -0
- patchi/core/agents/scanners.py +67 -0
- patchi/core/agents/side/__init__.py +1 -0
- patchi/core/agents/side/build_agent.py +65 -0
- patchi/core/agents/side/format_agent.py +50 -0
- patchi/core/agents/side/install_agent.py +63 -0
- patchi/core/agents/side_file_scanner.py +549 -0
- patchi/core/agents/snapshot_drift_detector.py +146 -0
- patchi/core/agents/spa_route_inventory.py +203 -0
- patchi/core/agents/test_scanner.py +442 -0
- patchi/core/agents/tool_health.py +109 -0
- patchi/core/agents/tool_runner.py +162 -0
- patchi/core/agents/type_scanner.py +168 -0
- patchi/core/agents/ui_scanner.py +558 -0
- patchi/core/ai/__init__.py +20 -0
- patchi/core/ai/agent_audit.py +153 -0
- patchi/core/ai/agent_profiler.py +277 -0
- patchi/core/ai/client.py +499 -0
- patchi/core/ai/cost_tracker.py +107 -0
- patchi/core/ai/model_router.py +318 -0
- patchi/core/ai/orchestrator.py +625 -0
- patchi/core/ai/prompts.py +681 -0
- patchi/core/ai/smart.py +302 -0
- patchi/core/ai/tool_executor.py +24 -0
- patchi/core/ai/tools/__init__.py +10 -0
- patchi/core/ai/tools/executor.py +621 -0
- patchi/core/ai/tools/realize.py +1160 -0
- patchi/core/ai/tools/registry.py +1577 -0
- patchi/core/assurance/__init__.py +33 -0
- patchi/core/assurance/builder.py +211 -0
- patchi/core/assurance/graph.py +342 -0
- patchi/core/assurance/invariants.py +168 -0
- patchi/core/atomic.py +61 -0
- patchi/core/attackers/__init__.py +17 -0
- patchi/core/attackers/api_abuse.py +89 -0
- patchi/core/attackers/auth_bypass.py +73 -0
- patchi/core/attackers/base.py +91 -0
- patchi/core/attackers/business_logic.py +88 -0
- patchi/core/attackers/planner.py +108 -0
- patchi/core/attackers/priv_escalation.py +88 -0
- patchi/core/attackers/recon.py +87 -0
- patchi/core/brain/__init__.py +0 -0
- patchi/core/brain/ast_utils/__init__.py +81 -0
- patchi/core/brain/ast_utils/assignments.py +219 -0
- patchi/core/brain/ast_utils/calls.py +139 -0
- patchi/core/brain/ast_utils/config.py +132 -0
- patchi/core/brain/ast_utils/control_flow.py +74 -0
- patchi/core/brain/ast_utils/dead_symbols.py +205 -0
- patchi/core/brain/ast_utils/decorators.py +108 -0
- patchi/core/brain/ast_utils/helpers.py +144 -0
- patchi/core/brain/ast_utils/imports.py +169 -0
- patchi/core/brain/ast_utils/scan.py +143 -0
- patchi/core/brain/ast_utils/taint.py +310 -0
- patchi/core/brain/audit.py +379 -0
- patchi/core/brain/baseline.py +195 -0
- patchi/core/brain/blast_radius.py +312 -0
- patchi/core/brain/body_tags.py +144 -0
- patchi/core/brain/brain.py +1161 -0
- patchi/core/brain/brain_context.py +393 -0
- patchi/core/brain/brain_watcher.py +340 -0
- patchi/core/brain/charter.py +473 -0
- patchi/core/brain/classifier.py +214 -0
- patchi/core/brain/cockpit.py +350 -0
- patchi/core/brain/code_query.py +710 -0
- patchi/core/brain/contract.py +889 -0
- patchi/core/brain/contract_diff.py +155 -0
- patchi/core/brain/council.py +800 -0
- patchi/core/brain/cross_repo.py +104 -0
- patchi/core/brain/dead_code_tools.py +157 -0
- patchi/core/brain/doc_validator.py +197 -0
- patchi/core/brain/domain_activator.py +2183 -0
- patchi/core/brain/enriched_context.py +220 -0
- patchi/core/brain/file_corpus.py +220 -0
- patchi/core/brain/framework.py +953 -0
- patchi/core/brain/freshness.py +273 -0
- patchi/core/brain/git_aware.py +206 -0
- patchi/core/brain/heatmap.py +104 -0
- patchi/core/brain/ignore_parser.py +153 -0
- patchi/core/brain/import_graph.py +486 -0
- patchi/core/brain/languages.py +397 -0
- patchi/core/brain/layered_brain.py +419 -0
- patchi/core/brain/learning.py +229 -0
- patchi/core/brain/orphaned_endpoints.py +313 -0
- patchi/core/brain/personas/__init__.py +648 -0
- patchi/core/brain/personas/bad_user.py +165 -0
- patchi/core/brain/personas/base.py +349 -0
- patchi/core/brain/proactive.py +807 -0
- patchi/core/brain/project_context.py +121 -0
- patchi/core/brain/project_reader.py +521 -0
- patchi/core/brain/reasoning.py +269 -0
- patchi/core/brain/route_detector/__init__.py +15 -0
- patchi/core/brain/route_detector/base.py +31 -0
- patchi/core/brain/route_detector/csharp.py +209 -0
- patchi/core/brain/route_detector/file_based.py +81 -0
- patchi/core/brain/route_detector/go.py +152 -0
- patchi/core/brain/route_detector/java.py +195 -0
- patchi/core/brain/route_detector/javascript.py +197 -0
- patchi/core/brain/route_detector/php.py +158 -0
- patchi/core/brain/route_detector/python.py +193 -0
- patchi/core/brain/route_detector/registry.py +25 -0
- patchi/core/brain/route_detector/ruby.py +134 -0
- patchi/core/brain/route_detector/rust.py +216 -0
- patchi/core/brain/route_detector/swift.py +118 -0
- patchi/core/brain/route_mapper.py +265 -0
- patchi/core/brain/scanner.py +2136 -0
- patchi/core/brain/secrets.py +280 -0
- patchi/core/brain/symbol_graph.py +1955 -0
- patchi/core/brain/team.py +28 -0
- patchi/core/brain/trace_log.py +132 -0
- patchi/core/brain/type_checker/__init__.py +65 -0
- patchi/core/brain/type_checker/base.py +60 -0
- patchi/core/brain/type_checker/csharp.py +59 -0
- patchi/core/brain/type_checker/dart.py +59 -0
- patchi/core/brain/type_checker/go.py +81 -0
- patchi/core/brain/type_checker/java.py +75 -0
- patchi/core/brain/type_checker/kotlin.py +75 -0
- patchi/core/brain/type_checker/php.py +88 -0
- patchi/core/brain/type_checker/python.py +87 -0
- patchi/core/brain/type_checker/rust.py +81 -0
- patchi/core/brain/type_checker/swift.py +59 -0
- patchi/core/brain/type_checker/typescript.py +298 -0
- patchi/core/brain/understander.py +130 -0
- patchi/core/brain/verify.py +379 -0
- patchi/core/campaigns/__init__.py +14 -0
- patchi/core/campaigns/base.py +62 -0
- patchi/core/campaigns/data_flow_abuse.py +153 -0
- patchi/core/campaigns/orchestrator.py +140 -0
- patchi/core/campaigns/state_transitions.py +178 -0
- patchi/core/ci_bundle.py +104 -0
- patchi/core/config.py +311 -0
- patchi/core/constants.py +245 -0
- patchi/core/debug/__init__.py +25 -0
- patchi/core/debug/adapters/__init__.py +11 -0
- patchi/core/debug/adapters/codelldb.py +379 -0
- patchi/core/debug/adapters/node.py +222 -0
- patchi/core/debug/adapters/powershell.py +210 -0
- patchi/core/debug/adapters/python.py +244 -0
- patchi/core/debug/capture.py +210 -0
- patchi/core/debug/dap_client.py +268 -0
- patchi/core/detector/__init__.py +0 -0
- patchi/core/detector/audit.py +194 -0
- patchi/core/detector/bus.py +226 -0
- patchi/core/detector/dispatcher.py +275 -0
- patchi/core/detector/event.py +254 -0
- patchi/core/detector/sigma_engine.py +378 -0
- patchi/core/detector/triage.py +289 -0
- patchi/core/export/sarif.py +113 -0
- patchi/core/fix/__init__.py +17 -0
- patchi/core/fix/applier.py +574 -0
- patchi/core/fix/base.py +510 -0
- patchi/core/fix/code_fixer.py +169 -0
- patchi/core/fix/dead_code_remover.py +131 -0
- patchi/core/fix/fix_agents.py +775 -0
- patchi/core/fix/patch.py +444 -0
- patchi/core/fix/risk_gate.py +383 -0
- patchi/core/fix/security_fixer.py +93 -0
- patchi/core/fix/verify_loop.py +204 -0
- patchi/core/fuzz/__init__.py +8 -0
- patchi/core/fuzz/corpus.py +137 -0
- patchi/core/fuzz/input_fuzzer.py +256 -0
- patchi/core/fuzz/sequence_fuzzer.py +162 -0
- patchi/core/fuzz/state_fuzzer.py +236 -0
- patchi/core/health.py +407 -0
- patchi/core/hosted/__init__.py +1 -0
- patchi/core/hosted/anomaly.py +298 -0
- patchi/core/hosted/audit_log.py +102 -0
- patchi/core/hosted/compliance_report.py +148 -0
- patchi/core/hosted/ip_reputation.py +169 -0
- patchi/core/hosted/log_parsers.py +251 -0
- patchi/core/hosted/tokens.py +127 -0
- patchi/core/hosted/watchlist.py +164 -0
- patchi/core/hosted/webhooks.py +156 -0
- patchi/core/memory.py +437 -0
- patchi/core/notifications/__init__.py +18 -0
- patchi/core/notifications/channels.py +192 -0
- patchi/core/notifications/digest.py +141 -0
- patchi/core/notifications/escalation.py +158 -0
- patchi/core/notifications/notifier.py +182 -0
- patchi/core/notifications/quiet_hours.py +69 -0
- patchi/core/plugins/__init__.py +48 -0
- patchi/core/plugins/analyzer.py +326 -0
- patchi/core/plugins/analyzers/__init__.py +6 -0
- patchi/core/plugins/analyzers/dead_code_analyzer.py +120 -0
- patchi/core/plugins/analyzers/secret_scanner.py +158 -0
- patchi/core/plugins/analyzers/todo_scanner.py +115 -0
- patchi/core/plugins/registry.py +335 -0
- patchi/core/queue.py +375 -0
- patchi/core/reliability/__init__.py +13 -0
- patchi/core/reliability/chaos.py +163 -0
- patchi/core/reliability/fault_injector.py +172 -0
- patchi/core/reliability/idempotency.py +128 -0
- patchi/core/reliability/recovery.py +147 -0
- patchi/core/runtime/__init__.py +5 -0
- patchi/core/runtime/tracer.py +230 -0
- patchi/core/scan_bus.py +156 -0
- patchi/core/security/__init__.py +1 -0
- patchi/core/security/ai_validator.py +462 -0
- patchi/core/security/app_mapper.py +216 -0
- patchi/core/security/app_profile.py +464 -0
- patchi/core/security/attack_feedback.py +141 -0
- patchi/core/security/attack_scenarios/__init__.py +1 -0
- patchi/core/security/attack_tree.py +176 -0
- patchi/core/security/auth_audit_agent.py +344 -0
- patchi/core/security/authz_agent.py +602 -0
- patchi/core/security/auto_fix_proactive.py +620 -0
- patchi/core/security/auto_fixer.py +660 -0
- patchi/core/security/auto_ticket.py +53 -0
- patchi/core/security/bandit_agent.py +152 -0
- patchi/core/security/blast_radius.py +226 -0
- patchi/core/security/browser_tester.py +333 -0
- patchi/core/security/business_logic_agent.py +263 -0
- patchi/core/security/catch_block_auditor.py +395 -0
- patchi/core/security/cdn_cache_agent.py +357 -0
- patchi/core/security/chain_analyzer.py +321 -0
- patchi/core/security/chain_to_assurance.py +168 -0
- patchi/core/security/charter.py +510 -0
- patchi/core/security/cloud_waf_detector.py +295 -0
- patchi/core/security/codeql_agent.py +233 -0
- patchi/core/security/compliance_agent.py +348 -0
- patchi/core/security/confidence_gate.py +423 -0
- patchi/core/security/container_scanner.py +282 -0
- patchi/core/security/crypto_agent.py +378 -0
- patchi/core/security/cve_monitor.py +262 -0
- patchi/core/security/dast_agent.py +865 -0
- patchi/core/security/defectdojo.py +238 -0
- patchi/core/security/defenders/__init__.py +75 -0
- patchi/core/security/defenders/auth_middleware.py +115 -0
- patchi/core/security/defenders/base.py +97 -0
- patchi/core/security/defenders/block_ip.py +71 -0
- patchi/core/security/defenders/block_ws_origin.py +36 -0
- patchi/core/security/defenders/crypto_fix.py +118 -0
- patchi/core/security/defenders/enforce_rate_limit.py +108 -0
- patchi/core/security/defenders/fix_code.py +93 -0
- patchi/core/security/defenders/invalidate_session.py +40 -0
- patchi/core/security/defenders/patch_config.py +70 -0
- patchi/core/security/defenders/rotate_secret.py +54 -0
- patchi/core/security/defenders/suspend_account.py +41 -0
- patchi/core/security/defenders/update_dependency.py +160 -0
- patchi/core/security/defense_layer.py +217 -0
- patchi/core/security/dependency_vulnerability_agent.py +616 -0
- patchi/core/security/detection_pipeline.py +289 -0
- patchi/core/security/dns_security_agent.py +497 -0
- patchi/core/security/domain_activator_v2.py +913 -0
- patchi/core/security/domain_loader.py +1004 -0
- patchi/core/security/domains/__init__.py +0 -0
- patchi/core/security/email_authentication_agent.py +417 -0
- patchi/core/security/env_var_validator.py +304 -0
- patchi/core/security/evidence.py +100 -0
- patchi/core/security/falco_runtime_agent.py +387 -0
- patchi/core/security/fix-playbooks/__init__.py +0 -0
- patchi/core/security/gated_finding.py +85 -0
- patchi/core/security/git_diff_activator.py +367 -0
- patchi/core/security/governance.py +208 -0
- patchi/core/security/gradual_gate.py +34 -0
- patchi/core/security/history.py +315 -0
- patchi/core/security/iac_scanner.py +250 -0
- patchi/core/security/ignore_expiry.py +111 -0
- patchi/core/security/ignore_learner.py +416 -0
- patchi/core/security/injection_agent.py +319 -0
- patchi/core/security/insecure_randomness_agent.py +288 -0
- patchi/core/security/intent_analyzer.py +326 -0
- patchi/core/security/jwt_agent.py +453 -0
- patchi/core/security/kubernetes_agent.py +638 -0
- patchi/core/security/layer2_orchestrator.py +341 -0
- patchi/core/security/llm_security_agent.py +252 -0
- patchi/core/security/misconfig_agent.py +600 -0
- patchi/core/security/mobile_security_agent.py +474 -0
- patchi/core/security/network_agent.py +376 -0
- patchi/core/security/noise_filter.py +274 -0
- patchi/core/security/orchestrator.py +313 -0
- patchi/core/security/pattern_context.py +125 -0
- patchi/core/security/pattern_loader.py +101 -0
- patchi/core/security/pentest/__init__.py +4 -0
- patchi/core/security/pentest/base.py +58 -0
- patchi/core/security/pentest/dalfox_adapter.py +40 -0
- patchi/core/security/pentest/ffuf_adapter.py +48 -0
- patchi/core/security/pentest/nuclei_adapter.py +50 -0
- patchi/core/security/pentest/registry.py +80 -0
- patchi/core/security/pentest/shannon_adapter.py +107 -0
- patchi/core/security/pentest/sqlmap_adapter.py +56 -0
- patchi/core/security/pentest/zap_adapter.py +52 -0
- patchi/core/security/plan_auditor.py +276 -0
- patchi/core/security/policy_engine.py +272 -0
- patchi/core/security/prechecks.py +172 -0
- patchi/core/security/precommit_hook.py +247 -0
- patchi/core/security/privacy_agent.py +361 -0
- patchi/core/security/push_notification_agent.py +417 -0
- patchi/core/security/pysa_agent.py +143 -0
- patchi/core/security/reasoning.py +442 -0
- patchi/core/security/red_team_agent.py +184 -0
- patchi/core/security/red_team_engine.py +1142 -0
- patchi/core/security/remediation.py +360 -0
- patchi/core/security/request_interceptor.py +294 -0
- patchi/core/security/runtime_validator.py +245 -0
- patchi/core/security/saml_sso_agent.py +401 -0
- patchi/core/security/sast_agent.py +213 -0
- patchi/core/security/sast_gate.py +95 -0
- patchi/core/security/scheduler.py +287 -0
- patchi/core/security/secrets_runtime_agent.py +476 -0
- patchi/core/security/security_agents.py +175 -0
- patchi/core/security/security_config.py +551 -0
- patchi/core/security/security_probe.py +762 -0
- patchi/core/security/security_taint.py +1005 -0
- patchi/core/security/sensitive_data_agent.py +271 -0
- patchi/core/security/service_mesh_agent.py +412 -0
- patchi/core/security/session_management_agent.py +245 -0
- patchi/core/security/ssrf_agent.py +422 -0
- patchi/core/security/supply_chain.py +449 -0
- patchi/core/security/threat_model_generator.py +378 -0
- patchi/core/security/threat_model_updater.py +196 -0
- patchi/core/security/tool_adapters.py +135 -0
- patchi/core/security/tool_verify.py +173 -0
- patchi/core/security/websocket_security_agent.py +188 -0
- patchi/core/snapshot.py +242 -0
- patchi/core/tenant.py +386 -0
- patchi/core/testing/__init__.py +17 -0
- patchi/core/testing/_browser.py +147 -0
- patchi/core/testing/ads_agent.py +141 -0
- patchi/core/testing/api_contract_agent.py +450 -0
- patchi/core/testing/app_discovery_agent.py +641 -0
- patchi/core/testing/app_launcher.py +184 -0
- patchi/core/testing/browser_test_agent.py +516 -0
- patchi/core/testing/e2e_flow_agent.py +354 -0
- patchi/core/testing/flake_detector_agent.py +292 -0
- patchi/core/testing/gate.py +31 -0
- patchi/core/testing/live_test_runner.py +304 -0
- patchi/core/testing/live_v2/__init__.py +1 -0
- patchi/core/testing/live_v2/browser_pool.py +349 -0
- patchi/core/testing/live_v2/browser_test_runner.py +313 -0
- patchi/core/testing/live_v2/runner.py +626 -0
- patchi/core/testing/live_v2/screenshot_manager.py +474 -0
- patchi/core/testing/live_v2/stress_orchestrator.py +523 -0
- patchi/core/testing/live_v2/video_recorder.py +303 -0
- patchi/core/testing/regression_agent.py +302 -0
- patchi/core/testing/security_test_agent.py +253 -0
- patchi/core/testing/stress_test_agent.py +203 -0
- patchi/core/testing/test_agents.py +50 -0
- patchi/core/testing/test_config.py +194 -0
- patchi/core/testing/ui_accessibility_agent.py +324 -0
- patchi/core/testing/ui_button_agent.py +294 -0
- patchi/core/testing/ui_layout_agent.py +330 -0
- patchi/core/testing/unit_test_agent.py +1149 -0
- patchi/core/testing/visual_regression_agent.py +260 -0
- patchi/web/__init__.py +1 -0
- patchi/web/api/__init__.py +1 -0
- patchi/web/api/brain_map.py +114 -0
- patchi/web/api/charts.py +47 -0
- patchi/web/api/chat.py +224 -0
- patchi/web/api/cicd.py +576 -0
- patchi/web/api/dast_evidence.py +49 -0
- patchi/web/api/dev_check.py +320 -0
- patchi/web/api/fix.py +134 -0
- patchi/web/api/guard.py +65 -0
- patchi/web/api/hosted.py +128 -0
- patchi/web/api/hosted_v2.py +234 -0
- patchi/web/api/live_testing.py +699 -0
- patchi/web/api/scan.py +582 -0
- patchi/web/api/smart.py +111 -0
- patchi/web/api/tenant.py +117 -0
- patchi/web/api/tools.py +85 -0
- patchi/web/api_legacy.py +2401 -0
- patchi/web/app.py +310 -0
- patchi/web/events.py +483 -0
- patchi/web/routes/__init__.py +1 -0
- patchi/web/routes/assurance.py +541 -0
- patchi/web/routes/brain.py +36 -0
- patchi/web/routes/charter.py +227 -0
- patchi/web/routes/chat.py +23 -0
- patchi/web/routes/dashboard.py +558 -0
- patchi/web/routes/dashboard_v2.py +402 -0
- patchi/web/routes/findings.py +330 -0
- patchi/web/routes/guard.py +35 -0
- patchi/web/routes/history.py +126 -0
- patchi/web/routes/landing.py +52 -0
- patchi/web/routes/live_testing.py +24 -0
- patchi/web/routes/review.py +57 -0
- patchi/web/routes/self_improvement.py +110 -0
- patchi/web/routes/settings.py +49 -0
- patchi/web/routes/tokens.py +29 -0
- patchi/web/spawn.py +139 -0
- patchi/web/ws.py +141 -0
- patchi-0.7.5.dist-info/METADATA +315 -0
- patchi-0.7.5.dist-info/RECORD +496 -0
- patchi-0.7.5.dist-info/WHEEL +5 -0
- patchi-0.7.5.dist-info/licenses/LICENSE +60 -0
- patchi-0.7.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Language registry for Patchi's Brain scanner.
|
|
3
|
+
|
|
4
|
+
Manages tree-sitter parsers for all supported languages.
|
|
5
|
+
Parsers are expensive to create — build once, reuse always.
|
|
6
|
+
|
|
7
|
+
Every language with a tree-sitter grammar gets AST-level parsing.
|
|
8
|
+
Languages without tree-sitter grammars (JSON, YAML) use stdlib/heuristic
|
|
9
|
+
parsing. All other languages use tree-sitter AST."""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from tree_sitter import Tree
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from tree_sitter import Parser
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ── Language enum ──────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Lang(StrEnum):
|
|
28
|
+
PYTHON = "python"
|
|
29
|
+
JAVASCRIPT = "javascript"
|
|
30
|
+
TYPESCRIPT = "typescript"
|
|
31
|
+
HTML = "html"
|
|
32
|
+
CSS = "css"
|
|
33
|
+
JSON = "json"
|
|
34
|
+
SQL = "sql"
|
|
35
|
+
BASH = "bash"
|
|
36
|
+
YAML = "yaml"
|
|
37
|
+
PHP = "php"
|
|
38
|
+
JAVA = "java"
|
|
39
|
+
C_SHARP = "c_sharp"
|
|
40
|
+
RUBY = "ruby"
|
|
41
|
+
GO = "go"
|
|
42
|
+
RUST = "rust"
|
|
43
|
+
CPP = "cpp"
|
|
44
|
+
C = "c"
|
|
45
|
+
SCALA = "scala"
|
|
46
|
+
KOTLIN = "kotlin"
|
|
47
|
+
SWIFT = "swift"
|
|
48
|
+
DART = "dart"
|
|
49
|
+
SVELTE = "svelte"
|
|
50
|
+
UNKNOWN = "unknown"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ── Extension → Language map ───────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
EXTENSION_MAP: dict[str, Lang] = {
|
|
56
|
+
".py": Lang.PYTHON,
|
|
57
|
+
".pyw": Lang.PYTHON,
|
|
58
|
+
".js": Lang.JAVASCRIPT,
|
|
59
|
+
".mjs": Lang.JAVASCRIPT,
|
|
60
|
+
".cjs": Lang.JAVASCRIPT,
|
|
61
|
+
".jsx": Lang.JAVASCRIPT,
|
|
62
|
+
".ts": Lang.TYPESCRIPT,
|
|
63
|
+
".tsx": Lang.TYPESCRIPT,
|
|
64
|
+
".mts": Lang.TYPESCRIPT,
|
|
65
|
+
".html": Lang.HTML,
|
|
66
|
+
".htm": Lang.HTML,
|
|
67
|
+
".jinja": Lang.HTML,
|
|
68
|
+
".jinja2": Lang.HTML,
|
|
69
|
+
".j2": Lang.HTML,
|
|
70
|
+
".css": Lang.CSS,
|
|
71
|
+
".scss": Lang.CSS,
|
|
72
|
+
".sass": Lang.CSS,
|
|
73
|
+
".json": Lang.JSON,
|
|
74
|
+
".jsonc": Lang.JSON,
|
|
75
|
+
".sql": Lang.SQL,
|
|
76
|
+
".sh": Lang.BASH,
|
|
77
|
+
".bash": Lang.BASH,
|
|
78
|
+
".zsh": Lang.BASH,
|
|
79
|
+
".yml": Lang.YAML,
|
|
80
|
+
".yaml": Lang.YAML,
|
|
81
|
+
".php": Lang.PHP,
|
|
82
|
+
".php3": Lang.PHP,
|
|
83
|
+
".php4": Lang.PHP,
|
|
84
|
+
".php5": Lang.PHP,
|
|
85
|
+
".phtml": Lang.PHP,
|
|
86
|
+
".java": Lang.JAVA,
|
|
87
|
+
".cs": Lang.C_SHARP,
|
|
88
|
+
".rb": Lang.RUBY,
|
|
89
|
+
".go": Lang.GO,
|
|
90
|
+
".rs": Lang.RUST,
|
|
91
|
+
".cpp": Lang.CPP,
|
|
92
|
+
".cxx": Lang.CPP,
|
|
93
|
+
".cc": Lang.CPP,
|
|
94
|
+
".c": Lang.C,
|
|
95
|
+
".h": Lang.C,
|
|
96
|
+
".hpp": Lang.CPP,
|
|
97
|
+
".scala": Lang.SCALA,
|
|
98
|
+
".kt": Lang.KOTLIN,
|
|
99
|
+
".kts": Lang.KOTLIN,
|
|
100
|
+
".swift": Lang.SWIFT,
|
|
101
|
+
".dart": Lang.DART,
|
|
102
|
+
".svelte": Lang.SVELTE,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Languages where tree-sitter gives us real AST parsing
|
|
106
|
+
TREE_SITTER_LANGS = {
|
|
107
|
+
Lang.PYTHON,
|
|
108
|
+
Lang.JAVASCRIPT,
|
|
109
|
+
Lang.TYPESCRIPT,
|
|
110
|
+
Lang.RUST,
|
|
111
|
+
Lang.SVELTE,
|
|
112
|
+
Lang.JAVA,
|
|
113
|
+
Lang.GO,
|
|
114
|
+
Lang.C,
|
|
115
|
+
Lang.CPP,
|
|
116
|
+
Lang.SWIFT,
|
|
117
|
+
Lang.RUBY,
|
|
118
|
+
Lang.PHP,
|
|
119
|
+
Lang.C_SHARP,
|
|
120
|
+
Lang.KOTLIN,
|
|
121
|
+
Lang.DART,
|
|
122
|
+
Lang.BASH,
|
|
123
|
+
Lang.CSS,
|
|
124
|
+
Lang.SQL,
|
|
125
|
+
Lang.HTML,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Config-style files detected by filename (not extension)
|
|
129
|
+
FILENAME_LANG_MAP: dict[str, Lang] = {
|
|
130
|
+
"Makefile": Lang.BASH,
|
|
131
|
+
".bashrc": Lang.BASH,
|
|
132
|
+
".zshrc": Lang.BASH,
|
|
133
|
+
".env": Lang.BASH,
|
|
134
|
+
".htaccess": Lang.PHP,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def detect_language(path: Path) -> Lang:
|
|
139
|
+
"""Detect language from file path (extension first, filename fallback)."""
|
|
140
|
+
by_name = FILENAME_LANG_MAP.get(path.name)
|
|
141
|
+
if by_name:
|
|
142
|
+
return by_name
|
|
143
|
+
return EXTENSION_MAP.get(path.suffix.lower(), Lang.UNKNOWN)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ── Parser registry ────────────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
_parsers: dict[Lang, Parser] = {}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def get_parser(lang: Lang) -> Parser | None:
|
|
152
|
+
"""
|
|
153
|
+
Return a cached tree-sitter Parser for the given language.
|
|
154
|
+
Returns None for languages handled by regex (not tree-sitter).
|
|
155
|
+
"""
|
|
156
|
+
if lang not in TREE_SITTER_LANGS:
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
if lang not in _parsers:
|
|
160
|
+
try:
|
|
161
|
+
_parsers[lang] = _build_parser(lang)
|
|
162
|
+
except (ImportError, ModuleNotFoundError):
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
return _parsers[lang]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _build_parser(lang: Lang) -> Parser:
|
|
169
|
+
from tree_sitter import Language, Parser
|
|
170
|
+
|
|
171
|
+
if lang == Lang.PYTHON:
|
|
172
|
+
import tree_sitter_python as tspy
|
|
173
|
+
|
|
174
|
+
return Parser(Language(tspy.language()))
|
|
175
|
+
|
|
176
|
+
if lang == Lang.JAVASCRIPT:
|
|
177
|
+
import tree_sitter_javascript as tsjs
|
|
178
|
+
|
|
179
|
+
return Parser(Language(tsjs.language()))
|
|
180
|
+
|
|
181
|
+
if lang == Lang.TYPESCRIPT:
|
|
182
|
+
import tree_sitter_typescript as tsts
|
|
183
|
+
|
|
184
|
+
return Parser(Language(tsts.language_typescript()))
|
|
185
|
+
|
|
186
|
+
if lang == Lang.RUST:
|
|
187
|
+
import tree_sitter_rust as tsrs
|
|
188
|
+
|
|
189
|
+
return Parser(Language(tsrs.language()))
|
|
190
|
+
|
|
191
|
+
if lang == Lang.SVELTE:
|
|
192
|
+
import tree_sitter_svelte as tssv
|
|
193
|
+
|
|
194
|
+
return Parser(Language(tssv.language()))
|
|
195
|
+
|
|
196
|
+
if lang == Lang.JAVA:
|
|
197
|
+
import tree_sitter_java as tsjava
|
|
198
|
+
|
|
199
|
+
return Parser(Language(tsjava.language()))
|
|
200
|
+
|
|
201
|
+
if lang == Lang.GO:
|
|
202
|
+
import tree_sitter_go as tsgo
|
|
203
|
+
|
|
204
|
+
return Parser(Language(tsgo.language()))
|
|
205
|
+
|
|
206
|
+
if lang == Lang.C:
|
|
207
|
+
import tree_sitter_c as tsc
|
|
208
|
+
|
|
209
|
+
return Parser(Language(tsc.language()))
|
|
210
|
+
|
|
211
|
+
if lang == Lang.CPP:
|
|
212
|
+
import tree_sitter_cpp as tscpp
|
|
213
|
+
|
|
214
|
+
return Parser(Language(tscpp.language()))
|
|
215
|
+
|
|
216
|
+
if lang == Lang.SWIFT:
|
|
217
|
+
import tree_sitter_swift as tssw
|
|
218
|
+
|
|
219
|
+
return Parser(Language(tssw.language()))
|
|
220
|
+
|
|
221
|
+
if lang == Lang.RUBY:
|
|
222
|
+
import tree_sitter_ruby as tsrb
|
|
223
|
+
|
|
224
|
+
return Parser(Language(tsrb.language()))
|
|
225
|
+
|
|
226
|
+
if lang == Lang.PHP:
|
|
227
|
+
import tree_sitter_php as tsphp
|
|
228
|
+
|
|
229
|
+
return Parser(Language(tsphp.language_php()))
|
|
230
|
+
|
|
231
|
+
if lang == Lang.C_SHARP:
|
|
232
|
+
import tree_sitter_c_sharp as tscs
|
|
233
|
+
|
|
234
|
+
return Parser(Language(tscs.language()))
|
|
235
|
+
|
|
236
|
+
if lang == Lang.KOTLIN:
|
|
237
|
+
import tree_sitter_kotlin as tskt
|
|
238
|
+
|
|
239
|
+
return Parser(Language(tskt.language()))
|
|
240
|
+
|
|
241
|
+
if lang == Lang.DART:
|
|
242
|
+
import tree_sitter_dart as tsdart
|
|
243
|
+
|
|
244
|
+
return Parser(Language(tsdart.language()))
|
|
245
|
+
|
|
246
|
+
if lang == Lang.BASH:
|
|
247
|
+
import tree_sitter_bash as tsbash
|
|
248
|
+
|
|
249
|
+
return Parser(Language(tsbash.language()))
|
|
250
|
+
|
|
251
|
+
if lang == Lang.CSS:
|
|
252
|
+
import tree_sitter_css as tscss
|
|
253
|
+
|
|
254
|
+
return Parser(Language(tscss.language()))
|
|
255
|
+
|
|
256
|
+
if lang == Lang.SQL:
|
|
257
|
+
import tree_sitter_sql as tssql
|
|
258
|
+
|
|
259
|
+
return Parser(Language(tssql.language()))
|
|
260
|
+
|
|
261
|
+
if lang == Lang.HTML:
|
|
262
|
+
import tree_sitter_html as tshtml
|
|
263
|
+
|
|
264
|
+
return Parser(Language(tshtml.language()))
|
|
265
|
+
|
|
266
|
+
raise ValueError(f"No tree-sitter grammar for {lang}")
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# ── Parse-once tree cache ────────────────────────────────────────────────────
|
|
270
|
+
# tree-sitter Trees are expensive to build and are NOT pickleable (they hold
|
|
271
|
+
# C pointers), so this cache is strictly per-process. Its job: during one run,
|
|
272
|
+
# every agent that parses the same file content gets the SAME tree instead of
|
|
273
|
+
# re-parsing it — the "single-pass scan" for the tree-sitter agents. In the
|
|
274
|
+
# process-pool mode each worker warms its own cache; the cache only dedupes
|
|
275
|
+
# WITHIN a worker, which is the correct trade-off (cross-process Trees are
|
|
276
|
+
# impossible by design).
|
|
277
|
+
#
|
|
278
|
+
# The cache key is the content hash, not the path: agents may hold different
|
|
279
|
+
# relative path spellings (os vs posix) for the same file, but content is
|
|
280
|
+
# unambiguous. Reading a file and parsing it is O(bytes); hashing is the
|
|
281
|
+
# cheaper half, so a hash-first design wins whenever two agents parse the
|
|
282
|
+
# same file — which is the entire scanner group during a run.
|
|
283
|
+
|
|
284
|
+
_CACHE_LIMIT = 512 # max cached trees; bounded so long sweeps don't balloon
|
|
285
|
+
|
|
286
|
+
_source_tree_cache: dict[tuple[str, str], Tree] = {} # (lang, sha256) -> Tree
|
|
287
|
+
_cache_hits = 0
|
|
288
|
+
_cache_misses = 0
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def parse_source(lang: Lang, source: str | bytes) -> Tree | None:
|
|
292
|
+
"""Parse `source` with the cached tree-sitter parser for `lang`.
|
|
293
|
+
|
|
294
|
+
Returns the SAME tree object for identical (lang, content) pairs within
|
|
295
|
+
this process — agents in one run stop re-parsing shared files. Returns
|
|
296
|
+
None for languages without a tree-sitter grammar (regex/stdio fallback
|
|
297
|
+
languages) or when parsing fails.
|
|
298
|
+
"""
|
|
299
|
+
if lang not in TREE_SITTER_LANGS:
|
|
300
|
+
return None
|
|
301
|
+
|
|
302
|
+
if isinstance(source, str):
|
|
303
|
+
source = source.encode("utf-8")
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
import hashlib
|
|
307
|
+
|
|
308
|
+
key = (lang.value, hashlib.sha256(source).hexdigest())
|
|
309
|
+
except Exception:
|
|
310
|
+
return None
|
|
311
|
+
|
|
312
|
+
global _cache_hits, _cache_misses
|
|
313
|
+
cached = _source_tree_cache.get(key)
|
|
314
|
+
if cached is not None:
|
|
315
|
+
_cache_hits += 1
|
|
316
|
+
return cached
|
|
317
|
+
|
|
318
|
+
parser = get_parser(lang)
|
|
319
|
+
if parser is None:
|
|
320
|
+
return None
|
|
321
|
+
|
|
322
|
+
try:
|
|
323
|
+
tree = parser.parse(source)
|
|
324
|
+
except Exception:
|
|
325
|
+
return None
|
|
326
|
+
|
|
327
|
+
_cache_misses += 1
|
|
328
|
+
if len(_source_tree_cache) >= _CACHE_LIMIT:
|
|
329
|
+
# Bound memory: drop the oldest 25% of cached trees (dict preserves
|
|
330
|
+
# insertion order), keeping the hot tail for the rest of the run.
|
|
331
|
+
for old_key in list(_source_tree_cache)[: _CACHE_LIMIT // 4]:
|
|
332
|
+
_source_tree_cache.pop(old_key, None)
|
|
333
|
+
_source_tree_cache[key] = tree
|
|
334
|
+
return tree
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def parse_stats() -> dict[str, int]:
|
|
338
|
+
"""Return cache hit/miss counters (observability for the single-pass gate)."""
|
|
339
|
+
return {
|
|
340
|
+
"hits": _cache_hits,
|
|
341
|
+
"misses": _cache_misses,
|
|
342
|
+
"cached_trees": len(_source_tree_cache),
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def clear_source_tree_cache() -> int:
|
|
347
|
+
"""Drop all cached trees; returns how many were evicted.
|
|
348
|
+
|
|
349
|
+
Used between runs and at process-pool worker startup so a long-lived
|
|
350
|
+
process never serves stale trees (same content hash always reparses to
|
|
351
|
+
the same tree, but keeping memory tight matters on big repos).
|
|
352
|
+
"""
|
|
353
|
+
global _cache_hits, _cache_misses
|
|
354
|
+
n = len(_source_tree_cache)
|
|
355
|
+
_source_tree_cache.clear()
|
|
356
|
+
_cache_hits = 0
|
|
357
|
+
_cache_misses = 0
|
|
358
|
+
return n
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
# ── Ignore dirs (shared with scanner + freshness) ─────────────────────────────
|
|
362
|
+
|
|
363
|
+
MINIFIED_SUFFIXES = (".min.js", ".min.mjs", ".min.css", ".bundle.js", ".map")
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def is_minified_asset(name: str) -> bool:
|
|
367
|
+
"""True for minified/bundled/source-map assets.
|
|
368
|
+
|
|
369
|
+
These are typically single-line giants (e.g. a 900 KB one-line
|
|
370
|
+
three.min.js). Python's re module holds the GIL for the whole match on a
|
|
371
|
+
single line, so scanning them freezes the dashboard event loop mid-scan.
|
|
372
|
+
"""
|
|
373
|
+
return name.lower().endswith(MINIFIED_SUFFIXES)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
DEFAULT_IGNORE_DIRS = {
|
|
377
|
+
"node_modules",
|
|
378
|
+
".git",
|
|
379
|
+
"__pycache__",
|
|
380
|
+
".patchi",
|
|
381
|
+
".venv",
|
|
382
|
+
"venv",
|
|
383
|
+
"env",
|
|
384
|
+
".env",
|
|
385
|
+
"dist",
|
|
386
|
+
"build",
|
|
387
|
+
".next",
|
|
388
|
+
".nuxt",
|
|
389
|
+
".svelte-kit",
|
|
390
|
+
"coverage",
|
|
391
|
+
".coverage",
|
|
392
|
+
"htmlcov",
|
|
393
|
+
".pytest_cache",
|
|
394
|
+
".mypy_cache",
|
|
395
|
+
".ruff_cache",
|
|
396
|
+
"target",
|
|
397
|
+
}
|