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
patchi/cli/logo.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logo draw sequence for Patchi CLI.
|
|
3
|
+
|
|
4
|
+
Big, bold green ASCII art wordmark "PATCHI" with letter-by-letter animation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.style import Style
|
|
12
|
+
from rich.text import Text
|
|
13
|
+
|
|
14
|
+
from patchi.core.constants import PATCHI_VERSION
|
|
15
|
+
|
|
16
|
+
GREEN = "#4ADE80"
|
|
17
|
+
GREEN_DIM = "#22C55E"
|
|
18
|
+
VERSION_COLOR = "#7A6A5A"
|
|
19
|
+
|
|
20
|
+
# Big block-letter Unicode box-drawing art for PATCHI (6 lines tall)
|
|
21
|
+
_FULL_ART = [
|
|
22
|
+
"██████╗ █████╗ ████████╗ ██████╗██╗ ██╗██╗",
|
|
23
|
+
"██╔══██╗██╔══██╗╚══██╔══╝██╔════╝██║ ██║██║",
|
|
24
|
+
"██████╔╝███████║ ██║ ██║ ███████║██║",
|
|
25
|
+
"██╔═══╝ ██╔══██║ ██║ ██║ ██╔══██║██║",
|
|
26
|
+
"██║ ██║ ██║ ██║ ╚██████╗██║ ██║██║",
|
|
27
|
+
"╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# Each letter's column span in the art (start, end)
|
|
31
|
+
_LETTER_COLS = {
|
|
32
|
+
"P": (0, 11),
|
|
33
|
+
"A": (11, 17),
|
|
34
|
+
"T": (17, 28),
|
|
35
|
+
"C": (28, 39),
|
|
36
|
+
"H": (39, 50),
|
|
37
|
+
"I": (50, 57),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_ANIM_FRAMES = [
|
|
41
|
+
(150, "P"),
|
|
42
|
+
(300, "PA"),
|
|
43
|
+
(450, "PAT"),
|
|
44
|
+
(600, "PATC"),
|
|
45
|
+
(750, "PATCH"),
|
|
46
|
+
(900, "PATCHI"),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def draw(console: Console | None = None, skip: bool = False) -> None:
|
|
51
|
+
"""Run the logo draw sequence."""
|
|
52
|
+
if skip:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
con = console or Console(stderr=False, highlight=False)
|
|
56
|
+
is_tty = sys.stdout.isatty() or (
|
|
57
|
+
con.file is not None and hasattr(con.file, "isatty") and con.file.isatty()
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if not is_tty:
|
|
61
|
+
_print_final(con)
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
start = time.monotonic()
|
|
65
|
+
current_lines = 0
|
|
66
|
+
|
|
67
|
+
def erase_frame(n_lines: int) -> None:
|
|
68
|
+
if n_lines <= 0:
|
|
69
|
+
return
|
|
70
|
+
for _ in range(n_lines):
|
|
71
|
+
con.file.write("\033[F\033[2K")
|
|
72
|
+
con.file.flush()
|
|
73
|
+
|
|
74
|
+
def print_art(text: str) -> int:
|
|
75
|
+
t = Text()
|
|
76
|
+
t.append(text, style=Style(color=GREEN, bold=True))
|
|
77
|
+
con.print(t, end="\n")
|
|
78
|
+
return text.count("\n") + 1
|
|
79
|
+
|
|
80
|
+
for target_ms, word in _ANIM_FRAMES:
|
|
81
|
+
target_s = target_ms / 1000.0
|
|
82
|
+
elapsed = time.monotonic() - start
|
|
83
|
+
wait = target_s - elapsed
|
|
84
|
+
if wait > 0:
|
|
85
|
+
time.sleep(wait)
|
|
86
|
+
|
|
87
|
+
erase_frame(current_lines)
|
|
88
|
+
art_text = build_partial_art(word)
|
|
89
|
+
current_lines = print_art(art_text)
|
|
90
|
+
|
|
91
|
+
time.sleep(0.3)
|
|
92
|
+
|
|
93
|
+
erase_frame(current_lines)
|
|
94
|
+
art_text = build_partial_art("PATCHI")
|
|
95
|
+
t = Text()
|
|
96
|
+
t.append(art_text + "\n", style=Style(color=GREEN, bold=True))
|
|
97
|
+
t.append(
|
|
98
|
+
f" v{PATCHI_VERSION} An immune system for your apps.\n",
|
|
99
|
+
style=Style(color=VERSION_COLOR),
|
|
100
|
+
)
|
|
101
|
+
con.print(t)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _print_final(con: Console) -> None:
|
|
105
|
+
"""Non-interactive fallback - print full art in one shot."""
|
|
106
|
+
art_text = build_partial_art("PATCHI")
|
|
107
|
+
t = Text()
|
|
108
|
+
t.append(art_text + "\n", style=Style(color=GREEN, bold=True))
|
|
109
|
+
t.append(
|
|
110
|
+
f" v{PATCHI_VERSION} An immune system for your apps.\n",
|
|
111
|
+
style=Style(color=VERSION_COLOR),
|
|
112
|
+
)
|
|
113
|
+
con.print(t)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def build_partial_art(partial_word: str) -> str:
|
|
117
|
+
"""Build the ASCII art showing only the letters typed so far."""
|
|
118
|
+
if not partial_word:
|
|
119
|
+
return ""
|
|
120
|
+
max_col = max(_LETTER_COLS[ch][1] for ch in partial_word if ch in _LETTER_COLS)
|
|
121
|
+
lines = []
|
|
122
|
+
for art_line in _FULL_ART:
|
|
123
|
+
lines.append(art_line[:max_col].rstrip())
|
|
124
|
+
return "\n".join(lines)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
draw()
|
patchi/cli/main.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from patchi import __version__
|
|
6
|
+
from patchi.cli.console import con
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Patchi CLI — main entry point.
|
|
10
|
+
|
|
11
|
+
Argparse wiring + dispatch are fully registry-driven (§3 Command Unification):
|
|
12
|
+
parser subparsers are built from patchi.cli.registry.COMMANDS and every
|
|
13
|
+
command resolves through it — there is no elif dispatch ladder left. Lazy
|
|
14
|
+
imports happen inside the registry framework (dotted "module:handler" paths),
|
|
15
|
+
so cold start stays fast regardless of how many commands are registered.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ── Lazy imports (only load what's needed for the called command) ──────────────
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
_log = logging.getLogger("patchi.cli.main")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _cmd_status():
|
|
26
|
+
from patchi.cli.commands.status_cmd import run
|
|
27
|
+
|
|
28
|
+
return run
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ── Upcoming stub ──────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _coming_soon(command: str, phase: str) -> None:
|
|
35
|
+
con.print(
|
|
36
|
+
f"[dim]{command}[/dim] [yellow]→[/yellow] "
|
|
37
|
+
f"[dim]Coming in {phase}. Not yet available in this build.[/dim]"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ── Parser setup ───────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
45
|
+
parser = argparse.ArgumentParser(
|
|
46
|
+
prog="patchi",
|
|
47
|
+
description="An intelligent agent that scans, fixes, secures, and guards your app.",
|
|
48
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
49
|
+
epilog="Short alias: p | Docs: patchi.dev",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
parser.add_argument("--version", action="version", version=f"Patchi v{__version__}")
|
|
53
|
+
parser.add_argument("--no-logo", action="store_true", help="Skip logo draw sequence (for CI)")
|
|
54
|
+
parser.add_argument("--json", action="store_true", help="Output as JSON instead of rich format")
|
|
55
|
+
parser.add_argument("--quiet", action="store_true", help="Errors only")
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--verbose", action="store_true", help="Show agent reasoning and full detail"
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview actions without executing")
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"--theme",
|
|
62
|
+
default=None,
|
|
63
|
+
choices=("dark", "light", "mono", "highcontrast"),
|
|
64
|
+
help="CLI color palette (default: value from settings, or dark)",
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"--no-color", action="store_true", help="Disable color output (same as NO_COLOR env)"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
sub = parser.add_subparsers(dest="command", metavar="<command>")
|
|
71
|
+
|
|
72
|
+
# ── registry-driven commands (§3 Command Unification) ──────────────────────
|
|
73
|
+
# Every `p <command>` is declared in patchi.cli.registry.COMMANDS and built
|
|
74
|
+
# here — the legacy argparse blocks and the elif dispatch ladder are gone,
|
|
75
|
+
# so the parser and the router can never drift apart.
|
|
76
|
+
from patchi.cli.framework import register_commands
|
|
77
|
+
from patchi.cli.registry import COMMANDS
|
|
78
|
+
|
|
79
|
+
register_commands(sub, COMMANDS)
|
|
80
|
+
return parser
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ── Router ─────────────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _load_patchi_env() -> None:
|
|
87
|
+
"""
|
|
88
|
+
Load .patchi/.env into os.environ (non-destructive — never overwrites shell env).
|
|
89
|
+
Called on every CLI invocation before any command runs.
|
|
90
|
+
"""
|
|
91
|
+
import os
|
|
92
|
+
|
|
93
|
+
from patchi.core.config import find_project_root
|
|
94
|
+
|
|
95
|
+
root = find_project_root()
|
|
96
|
+
if root is None:
|
|
97
|
+
return
|
|
98
|
+
env_file = root / ".patchi" / ".env"
|
|
99
|
+
keys_file = root / ".patchi" / "keys.json"
|
|
100
|
+
|
|
101
|
+
# Load .env file if it exists
|
|
102
|
+
if env_file.exists():
|
|
103
|
+
try:
|
|
104
|
+
for line in env_file.read_text(encoding="utf-8").splitlines():
|
|
105
|
+
line = line.strip()
|
|
106
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
107
|
+
continue
|
|
108
|
+
key, _, value = line.partition("=")
|
|
109
|
+
key = key.strip()
|
|
110
|
+
if key and key not in os.environ:
|
|
111
|
+
os.environ[key] = value.strip()
|
|
112
|
+
except OSError:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
# Load JSON keys file if it exists
|
|
116
|
+
if keys_file.exists():
|
|
117
|
+
try:
|
|
118
|
+
import json
|
|
119
|
+
import os
|
|
120
|
+
|
|
121
|
+
data = json.loads(keys_file.read_text(encoding="utf-8"))
|
|
122
|
+
for k, v in data.items():
|
|
123
|
+
if k and k not in os.environ:
|
|
124
|
+
os.environ[k] = str(v)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
_log.warning("_load_patchi_env failed: %s", e)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def main() -> None:
|
|
130
|
+
# Force UTF-8 encoding on Windows to support Unicode characters (✓, etc.)
|
|
131
|
+
import os
|
|
132
|
+
|
|
133
|
+
os.environ.setdefault("PYTHONIOENCODING", "utf-8")
|
|
134
|
+
if sys.stdout.encoding != "utf-8":
|
|
135
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
136
|
+
if sys.stderr.encoding != "utf-8":
|
|
137
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
138
|
+
|
|
139
|
+
parser = _build_parser()
|
|
140
|
+
args = parser.parse_args()
|
|
141
|
+
|
|
142
|
+
getattr(args, "no_logo", False)
|
|
143
|
+
|
|
144
|
+
# Apply the CLI theme before ANY command output happens, so every command
|
|
145
|
+
# (including the "no command -> show status" default path below) is
|
|
146
|
+
# themed consistently with zero per-command wiring.
|
|
147
|
+
from patchi.cli.console import configure_theme
|
|
148
|
+
|
|
149
|
+
configure_theme(
|
|
150
|
+
explicit=getattr(args, "theme", None),
|
|
151
|
+
no_color_flag=getattr(args, "no_color", False),
|
|
152
|
+
json_mode=getattr(args, "json", False),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Auto-load .patchi/.env into os.environ on every command invocation.
|
|
156
|
+
# Keys are only set if not already present — never overwrite shell env.
|
|
157
|
+
_load_patchi_env()
|
|
158
|
+
|
|
159
|
+
# No command → show status if project exists, else show help
|
|
160
|
+
if not args.command:
|
|
161
|
+
from patchi.core.config import find_project_root
|
|
162
|
+
|
|
163
|
+
if find_project_root():
|
|
164
|
+
_cmd_status()(root=None)
|
|
165
|
+
else:
|
|
166
|
+
parser.print_help()
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
cmd = args.command
|
|
170
|
+
|
|
171
|
+
# Auto-update check (background, weekly)
|
|
172
|
+
import threading
|
|
173
|
+
|
|
174
|
+
from patchi.cli.commands.update_cmd import auto_check_background
|
|
175
|
+
|
|
176
|
+
threading.Thread(target=auto_check_background, daemon=True).start()
|
|
177
|
+
|
|
178
|
+
# Onboarding check (M-01): if project exists but onboarding not complete,
|
|
179
|
+
# and the user didn't explicitly run `init`, prompt them to run it.
|
|
180
|
+
if cmd != "init":
|
|
181
|
+
try:
|
|
182
|
+
from patchi.core.config import find_project_root, load
|
|
183
|
+
|
|
184
|
+
r = find_project_root()
|
|
185
|
+
if r:
|
|
186
|
+
conf = load(r)
|
|
187
|
+
if not conf.get("onboarding_complete", False):
|
|
188
|
+
con.print()
|
|
189
|
+
con.print("[bold #C8621A]Welcome to Patchi![/bold #C8621A]")
|
|
190
|
+
con.print("[dim]It looks like you haven't completed setup yet.[/dim]")
|
|
191
|
+
con.print("[dim]Run [bold]p init[/bold] to configure your project.[/dim]")
|
|
192
|
+
con.print()
|
|
193
|
+
sys.stdout.flush()
|
|
194
|
+
except Exception as e:
|
|
195
|
+
_log.warning("main failed: %s", e)
|
|
196
|
+
|
|
197
|
+
# ── registry-driven dispatch (§3 Command Unification) ──────────────────────
|
|
198
|
+
# The registry IS the router: every subparser resolves through COMMANDS, so
|
|
199
|
+
# there is no fall-through ladder anymore.
|
|
200
|
+
from patchi.cli.framework import dispatch as _registry_dispatch
|
|
201
|
+
from patchi.cli.registry import COMMANDS as _REGISTRY_COMMANDS
|
|
202
|
+
|
|
203
|
+
_result, _handled = _registry_dispatch(_REGISTRY_COMMANDS, args)
|
|
204
|
+
|
|
205
|
+
# After command dispatch, show update notification if available
|
|
206
|
+
if cmd and cmd != "update":
|
|
207
|
+
from patchi.cli.commands.update_cmd import print_update_available_if_needed
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
print_update_available_if_needed()
|
|
211
|
+
except Exception as e:
|
|
212
|
+
_log.warning("main failed: %s", e)
|
|
213
|
+
|
|
214
|
+
if _handled:
|
|
215
|
+
return _result
|
|
216
|
+
|
|
217
|
+
parser.print_help()
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
if __name__ == "__main__":
|
|
222
|
+
sys.exit(main() or 0)
|