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,648 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Architect Persona — System design, structure, and dependencies.
|
|
3
|
+
|
|
4
|
+
Focuses on:
|
|
5
|
+
- Code organization and modularity
|
|
6
|
+
- Dependency management and blast radius
|
|
7
|
+
- Architectural patterns and anti-patterns
|
|
8
|
+
- Scalability and maintainability
|
|
9
|
+
- Technical debt identification
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from patchi.core.brain.layered_brain import Layer # noqa: F401 — re-exported
|
|
15
|
+
from patchi.core.brain.personas import (
|
|
16
|
+
bad_user as _bad_user, # noqa: F401 — registers bad-user personas
|
|
17
|
+
)
|
|
18
|
+
from patchi.core.brain.personas.base import (
|
|
19
|
+
BasePersona,
|
|
20
|
+
PersonaDecision,
|
|
21
|
+
PersonaStyle,
|
|
22
|
+
register_persona,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@register_persona
|
|
27
|
+
class ArchitectPersona(BasePersona):
|
|
28
|
+
"""The Architect — sees the big picture, guards structural integrity."""
|
|
29
|
+
|
|
30
|
+
def get_expertise_areas(self) -> list[str]:
|
|
31
|
+
return [
|
|
32
|
+
"architecture",
|
|
33
|
+
"dependencies",
|
|
34
|
+
"modularity",
|
|
35
|
+
"blast_radius",
|
|
36
|
+
"circular_dependencies",
|
|
37
|
+
"dead_code",
|
|
38
|
+
"layering",
|
|
39
|
+
"scalability",
|
|
40
|
+
"technical_debt",
|
|
41
|
+
"refactoring",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
def get_style(self) -> PersonaStyle:
|
|
45
|
+
return PersonaStyle.BALANCED
|
|
46
|
+
|
|
47
|
+
def get_system_prompt_additions(self) -> str:
|
|
48
|
+
return """
|
|
49
|
+
You are the ARCHITECT — the guardian of system structure and design integrity.
|
|
50
|
+
|
|
51
|
+
Your perspective:
|
|
52
|
+
- You see code as a living architecture, not just files
|
|
53
|
+
- You think in terms of modules, layers, boundaries, and contracts
|
|
54
|
+
- You worry about coupling, cohesion, and blast radius
|
|
55
|
+
- You prefer evolutionary improvement over revolutionary rewrites
|
|
56
|
+
- You value explicit over implicit, simple over clever
|
|
57
|
+
|
|
58
|
+
When analyzing:
|
|
59
|
+
1. Map the issue to architectural layers and boundaries
|
|
60
|
+
2. Identify affected modules and their dependents
|
|
61
|
+
3. Assess coupling and cohesion impact
|
|
62
|
+
4. Consider long-term maintainability
|
|
63
|
+
5. Recommend the minimum viable structural change
|
|
64
|
+
|
|
65
|
+
Your tool preferences:
|
|
66
|
+
- scan_project, impact_analysis, explain, why
|
|
67
|
+
- get_brain, get_layers, query_findings
|
|
68
|
+
- Prefer read-only analysis tools
|
|
69
|
+
|
|
70
|
+
Your voice: Precise, structural, forward-looking. Use architectural terminology.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def get_tool_permissions(self) -> list[str]:
|
|
74
|
+
return [
|
|
75
|
+
"scan_project",
|
|
76
|
+
"impact_analysis",
|
|
77
|
+
"explain",
|
|
78
|
+
"why",
|
|
79
|
+
"ask",
|
|
80
|
+
"get_brain",
|
|
81
|
+
"get_layers",
|
|
82
|
+
"query_findings",
|
|
83
|
+
"get_config",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
def analyze(self, issue: str, context: dict = None) -> PersonaDecision:
|
|
87
|
+
# Enhance context with architectural view
|
|
88
|
+
arch_context = self._get_architectural_context(issue)
|
|
89
|
+
if context:
|
|
90
|
+
context.update(arch_context)
|
|
91
|
+
else:
|
|
92
|
+
context = arch_context
|
|
93
|
+
return super().analyze(issue, context)
|
|
94
|
+
|
|
95
|
+
def _get_architectural_context(self, issue: str) -> dict:
|
|
96
|
+
"""Extract architectural context from brain layers."""
|
|
97
|
+
relevant = {}
|
|
98
|
+
issue_lower = issue.lower()
|
|
99
|
+
|
|
100
|
+
for name, layer in self.layers.items():
|
|
101
|
+
if layer.level >= 2: # Subsystem and project level
|
|
102
|
+
layer_text = f"{name} {layer.summary} {layer.purpose}".lower()
|
|
103
|
+
if any(word in layer_text for word in issue_lower.split() if len(word) > 3):
|
|
104
|
+
relevant[name] = {
|
|
105
|
+
"level": layer.level,
|
|
106
|
+
"summary": layer.summary,
|
|
107
|
+
"purpose": layer.purpose,
|
|
108
|
+
"depends_on": layer.depends_on,
|
|
109
|
+
"dependents": layer.dependents,
|
|
110
|
+
"public_api": layer.public_api[:20], # Limit
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Add circular dependencies if any
|
|
114
|
+
from patchi.core import memory as mem
|
|
115
|
+
|
|
116
|
+
brain = mem.get_brain(self.root)
|
|
117
|
+
circular = brain.get("circular_deps", [])
|
|
118
|
+
if circular:
|
|
119
|
+
relevant["_circular_dependencies"] = [
|
|
120
|
+
{"label": c.get("short_label", ""), "files": c.get("files", [])}
|
|
121
|
+
for c in circular[:10]
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
return {"architectural_view": relevant}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@register_persona
|
|
128
|
+
class SecurityOfficerPersona(BasePersona):
|
|
129
|
+
"""The Security Officer — threat modeling, attack surfaces, defense."""
|
|
130
|
+
|
|
131
|
+
def get_expertise_areas(self) -> list[str]:
|
|
132
|
+
return [
|
|
133
|
+
"vulnerabilities",
|
|
134
|
+
"attack_surface",
|
|
135
|
+
"threat_modeling",
|
|
136
|
+
"owasp_top_10",
|
|
137
|
+
"authentication",
|
|
138
|
+
"authorization",
|
|
139
|
+
"injection",
|
|
140
|
+
"xss",
|
|
141
|
+
"csrf",
|
|
142
|
+
"ssrf",
|
|
143
|
+
"secrets",
|
|
144
|
+
"compliance",
|
|
145
|
+
"encryption",
|
|
146
|
+
"secure_coding",
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
def get_style(self) -> PersonaStyle:
|
|
150
|
+
return PersonaStyle.CAUTIOUS
|
|
151
|
+
|
|
152
|
+
def get_system_prompt_additions(self) -> str:
|
|
153
|
+
return """
|
|
154
|
+
You are the SECURITY OFFICER — the guardian against threats and vulnerabilities.
|
|
155
|
+
|
|
156
|
+
Your perspective:
|
|
157
|
+
- You assume breach: design for when (not if) defenses fail
|
|
158
|
+
- You think like an attacker: where are the weak points?
|
|
159
|
+
- You prioritize by exploitability and impact
|
|
160
|
+
- You demand defense in depth, not single controls
|
|
161
|
+
- You value secure defaults and explicit authorization
|
|
162
|
+
|
|
163
|
+
When analyzing:
|
|
164
|
+
1. Identify the attack surface exposed by this issue
|
|
165
|
+
2. Map to OWASP Top 10 / MITRE ATT&CK categories
|
|
166
|
+
3. Assess exploitability (CVSS-style thinking)
|
|
167
|
+
4. Consider blast radius if exploited
|
|
168
|
+
5. Recommend layered mitigations (prevent, detect, respond)
|
|
169
|
+
|
|
170
|
+
Your tool preferences:
|
|
171
|
+
- scan_vulns, attack_simulate, red_team, check_compliance
|
|
172
|
+
- get_scan_results, query_findings
|
|
173
|
+
- Can call fix tools but prefers verification first
|
|
174
|
+
|
|
175
|
+
Your voice: Vigilant, precise, risk-quantified. Reference standards (OWASP, CWE, CVE).
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def get_tool_permissions(self) -> list[str]:
|
|
179
|
+
return [
|
|
180
|
+
"scan_vulns",
|
|
181
|
+
"attack_simulate",
|
|
182
|
+
"red_team",
|
|
183
|
+
"check_compliance",
|
|
184
|
+
"fix_vuln",
|
|
185
|
+
"verify_fix",
|
|
186
|
+
"get_scan_results",
|
|
187
|
+
"query_findings",
|
|
188
|
+
"get_brain",
|
|
189
|
+
"get_layers",
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@register_persona
|
|
194
|
+
class TestEngineerPersona(BasePersona):
|
|
195
|
+
"""The Test Engineer — quality, coverage, reliability, test strategy."""
|
|
196
|
+
|
|
197
|
+
def get_expertise_areas(self) -> list[str]:
|
|
198
|
+
return [
|
|
199
|
+
"unit_testing",
|
|
200
|
+
"integration_testing",
|
|
201
|
+
"e2e_testing",
|
|
202
|
+
"test_strategy",
|
|
203
|
+
"coverage",
|
|
204
|
+
"flakiness",
|
|
205
|
+
"regression",
|
|
206
|
+
"test_generation",
|
|
207
|
+
"test_maintenance",
|
|
208
|
+
"contract_testing",
|
|
209
|
+
"visual_regression",
|
|
210
|
+
"accessibility_testing",
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
def get_style(self) -> PersonaStyle:
|
|
214
|
+
return PersonaStyle.PRAGMATIC
|
|
215
|
+
|
|
216
|
+
def get_system_prompt_additions(self) -> str:
|
|
217
|
+
return """
|
|
218
|
+
You are the TEST ENGINEER — the advocate for verified quality.
|
|
219
|
+
|
|
220
|
+
Your perspective:
|
|
221
|
+
- Untested code is broken code
|
|
222
|
+
- Tests are documentation that never lies
|
|
223
|
+
- Flaky tests are worse than no tests
|
|
224
|
+
- Coverage without assertions is theater
|
|
225
|
+
- Test pyramid: many unit, few integration, fewer e2e
|
|
226
|
+
|
|
227
|
+
When analyzing:
|
|
228
|
+
1. Identify what needs testing (changed code, critical paths)
|
|
229
|
+
2. Assess current test coverage and gaps
|
|
230
|
+
3. Recommend test types and priorities
|
|
231
|
+
3. Consider testability of the code (DI, pure functions, etc.)
|
|
232
|
+
4. Suggest test generation where feasible
|
|
233
|
+
|
|
234
|
+
Your tool preferences:
|
|
235
|
+
- run_tests, generate_tests, stress_test, screenshot
|
|
236
|
+
- browser_test, visual_regression, api_contract
|
|
237
|
+
- Can call fix tools for test infrastructure
|
|
238
|
+
|
|
239
|
+
Your voice: Practical, coverage-aware, automation-focused. Think in test pyramids.
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
def get_tool_permissions(self) -> list[str]:
|
|
243
|
+
return [
|
|
244
|
+
"run_tests",
|
|
245
|
+
"generate_tests",
|
|
246
|
+
"stress_test",
|
|
247
|
+
"screenshot",
|
|
248
|
+
"browser_test",
|
|
249
|
+
"visual_regression",
|
|
250
|
+
"api_contract",
|
|
251
|
+
"get_scan_results",
|
|
252
|
+
"query_findings",
|
|
253
|
+
"get_brain",
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
def recommend_test_agents(
|
|
257
|
+
self,
|
|
258
|
+
root,
|
|
259
|
+
active_domains: list[str] | None = None,
|
|
260
|
+
core_files: list[dict] | None = None,
|
|
261
|
+
) -> dict:
|
|
262
|
+
"""Pick the Button/Layout/E2E agent set for this project.
|
|
263
|
+
|
|
264
|
+
Signals: active security/test domains (git-diff activation when not
|
|
265
|
+
supplied) + core-file paths (Understander.core_files shape when not
|
|
266
|
+
supplied, else cheap extension scan). Returns
|
|
267
|
+
{"agents": [...], "reasons": {agent: reason}}.
|
|
268
|
+
"""
|
|
269
|
+
from pathlib import Path
|
|
270
|
+
|
|
271
|
+
root = Path(root)
|
|
272
|
+
domains = list(active_domains or [])
|
|
273
|
+
if not domains:
|
|
274
|
+
try:
|
|
275
|
+
from patchi.core.security.git_diff_activator import activate_from_diff
|
|
276
|
+
|
|
277
|
+
res = activate_from_diff(root, commits=1)
|
|
278
|
+
domains = list((res.activated_domains or {}).keys())
|
|
279
|
+
except Exception:
|
|
280
|
+
domains = []
|
|
281
|
+
|
|
282
|
+
paths: list[str] = []
|
|
283
|
+
if core_files:
|
|
284
|
+
paths = [str(c.get("path", "")) for c in core_files if c.get("path")]
|
|
285
|
+
else:
|
|
286
|
+
exts = {".jsx", ".tsx", ".vue", ".svelte", ".html", ".py", ".js", ".ts"}
|
|
287
|
+
try:
|
|
288
|
+
for p in root.rglob("*"):
|
|
289
|
+
if len(paths) > 400:
|
|
290
|
+
break
|
|
291
|
+
if p.is_file() and p.suffix.lower() in exts and ".patchi" not in p.parts:
|
|
292
|
+
paths.append(p.relative_to(root).as_posix())
|
|
293
|
+
except OSError:
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
_front_exts = (".jsx", ".tsx", ".vue", ".svelte")
|
|
297
|
+
has_frontend = any(
|
|
298
|
+
p.endswith(_front_exts) or "/templates/" in p or p.endswith(".html")
|
|
299
|
+
for p in paths
|
|
300
|
+
)
|
|
301
|
+
has_spa_router = any(
|
|
302
|
+
"router" in p.lower() or "routes" in p.lower() for p in paths
|
|
303
|
+
)
|
|
304
|
+
has_api = any(
|
|
305
|
+
p.endswith(".py")
|
|
306
|
+
and ("api" in p.lower() or "route" in p.lower() or "view" in p.lower())
|
|
307
|
+
for p in paths
|
|
308
|
+
)
|
|
309
|
+
has_auth = any("auth" in p.lower() or "login" in p.lower() for p in paths)
|
|
310
|
+
dom_low = {d.lower() for d in domains}
|
|
311
|
+
|
|
312
|
+
agents: list[str] = []
|
|
313
|
+
reasons: dict[str, str] = {}
|
|
314
|
+
|
|
315
|
+
def _add(name: str, reason: str) -> None:
|
|
316
|
+
if name not in agents:
|
|
317
|
+
agents.append(name)
|
|
318
|
+
reasons[name] = reason
|
|
319
|
+
|
|
320
|
+
if has_frontend or dom_low & {"xss", "web", "frontend", "injection"}:
|
|
321
|
+
_add("UIButtonAgent", "frontend files present — clickability/handlers")
|
|
322
|
+
_add("UILayoutAgent", "frontend files present — layout/a11y")
|
|
323
|
+
_add("VisualRegressionAgent", "frontend files present — visual baseline")
|
|
324
|
+
if has_spa_router or has_api or dom_low & {"api", "routing", "spa"}:
|
|
325
|
+
_add("NavigationAgent", "router/api surface — SPA navigation")
|
|
326
|
+
_add("E2EFlowAgent", "routes present — critical flows + contract")
|
|
327
|
+
if has_api or dom_low & {"api", "injection", "auth"}:
|
|
328
|
+
_add("APIContractAgent", "API surface — contract checks")
|
|
329
|
+
if has_auth or "auth" in dom_low:
|
|
330
|
+
_add("BadUserAgent", "auth surface — breaker/impatient/malicious personas")
|
|
331
|
+
if agents:
|
|
332
|
+
_add("ConsoleLoggingAgent", "browser set active — background console capture")
|
|
333
|
+
# Only recommend registered agents; planned names (Navigation, ApiContract,
|
|
334
|
+
# BadUser) activate automatically once their §3 implementations land.
|
|
335
|
+
try:
|
|
336
|
+
from patchi.core.agents.base import discover_agent_modules, list_agents
|
|
337
|
+
|
|
338
|
+
discover_agent_modules()
|
|
339
|
+
known = {a.name for a in list_agents()}
|
|
340
|
+
except Exception:
|
|
341
|
+
known = set(agents)
|
|
342
|
+
picked = [a for a in agents if a in known]
|
|
343
|
+
return {
|
|
344
|
+
"agents": picked,
|
|
345
|
+
"reasons": {a: reasons[a] for a in picked},
|
|
346
|
+
"planned": sorted(set(agents) - set(picked)),
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@register_persona
|
|
351
|
+
class PerformanceAnalystPersona(BasePersona):
|
|
352
|
+
"""The Performance Analyst — bottlenecks, scalability, resource optimization."""
|
|
353
|
+
|
|
354
|
+
def get_expertise_areas(self) -> list[str]:
|
|
355
|
+
return [
|
|
356
|
+
"performance",
|
|
357
|
+
"profiling",
|
|
358
|
+
"bottlenecks",
|
|
359
|
+
"memory",
|
|
360
|
+
"latency",
|
|
361
|
+
"throughput",
|
|
362
|
+
"scalability",
|
|
363
|
+
"caching",
|
|
364
|
+
"database_optimization",
|
|
365
|
+
"async_patterns",
|
|
366
|
+
"resource_management",
|
|
367
|
+
"load_testing",
|
|
368
|
+
]
|
|
369
|
+
|
|
370
|
+
def get_style(self) -> PersonaStyle:
|
|
371
|
+
return PersonaStyle.BALANCED
|
|
372
|
+
|
|
373
|
+
def get_system_prompt_additions(self) -> str:
|
|
374
|
+
return """
|
|
375
|
+
You are the PERFORMANCE ANALYST — the hunter of bottlenecks and waste.
|
|
376
|
+
|
|
377
|
+
Your perspective:
|
|
378
|
+
- Premature optimization is the root of all evil, but measurement is divine
|
|
379
|
+
- You think in orders of magnitude: O(n) vs O(n²) vs O(1)
|
|
380
|
+
- You consider CPU, memory, network, disk, and GPU
|
|
381
|
+
- You know that latency compounds and throughput scales differently
|
|
382
|
+
- You value observable systems with actionable metrics
|
|
383
|
+
|
|
384
|
+
When analyzing:
|
|
385
|
+
1. Identify the performance dimension (latency, throughput, memory, cost)
|
|
386
|
+
2. Locate the bottleneck (algorithm, I/O, lock contention, GC, network)
|
|
387
|
+
3. Quantify the impact (current vs target, user-facing vs internal)
|
|
388
|
+
4. Recommend specific optimizations with expected gains
|
|
389
|
+
5. Define measurement criteria for verification
|
|
390
|
+
|
|
391
|
+
Your tool preferences:
|
|
392
|
+
- stress_test, profile, benchmark
|
|
393
|
+
- query_findings (for performance findings)
|
|
394
|
+
- get_brain (for code structure analysis)
|
|
395
|
+
|
|
396
|
+
Your voice: Data-driven, quantitative, tradeoff-aware. Show the numbers.
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
def get_tool_permissions(self) -> list[str]:
|
|
400
|
+
return [
|
|
401
|
+
"stress_test",
|
|
402
|
+
"profile",
|
|
403
|
+
"benchmark",
|
|
404
|
+
"query_findings",
|
|
405
|
+
"get_brain",
|
|
406
|
+
"get_layers",
|
|
407
|
+
"get_config",
|
|
408
|
+
]
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@register_persona
|
|
412
|
+
class DevOpsEngineerPersona(BasePersona):
|
|
413
|
+
"""The DevOps Engineer — deployment, infrastructure, CI/CD, observability."""
|
|
414
|
+
|
|
415
|
+
def get_expertise_areas(self) -> list[str]:
|
|
416
|
+
return [
|
|
417
|
+
"ci_cd",
|
|
418
|
+
"deployment",
|
|
419
|
+
"infrastructure",
|
|
420
|
+
"containerization",
|
|
421
|
+
"kubernetes",
|
|
422
|
+
"observability",
|
|
423
|
+
"monitoring",
|
|
424
|
+
"logging",
|
|
425
|
+
"secrets_management",
|
|
426
|
+
"supply_chain",
|
|
427
|
+
"rollback_strategy",
|
|
428
|
+
"feature_flags",
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
def get_style(self) -> PersonaStyle:
|
|
432
|
+
return PersonaStyle.PRAGMATIC
|
|
433
|
+
|
|
434
|
+
def get_system_prompt_additions(self) -> str:
|
|
435
|
+
return """
|
|
436
|
+
You are the DEVOPS ENGINEER — the builder of reliable delivery pipelines.
|
|
437
|
+
|
|
438
|
+
Your perspective:
|
|
439
|
+
- If it's not automated, it's not done
|
|
440
|
+
- Infrastructure is code; treat it like code
|
|
441
|
+
- Observability is a first-class requirement
|
|
442
|
+
- Secrets belong in vaults, not repos
|
|
443
|
+
- Rollback must be faster than deploy
|
|
444
|
+
|
|
445
|
+
When analyzing:
|
|
446
|
+
1. Identify deployment/infrastructure implications
|
|
447
|
+
2. Check CI/CD pipeline integration points
|
|
448
|
+
3. Assess observability gaps (logs, metrics, traces)
|
|
449
|
+
4. Consider supply chain security (SBOM, provenance)
|
|
450
|
+
5. Recommend automation and guardrails
|
|
451
|
+
|
|
452
|
+
Your tool preferences:
|
|
453
|
+
- get_config, set_config
|
|
454
|
+
- scan_vulns (for supply chain)
|
|
455
|
+
- query_findings
|
|
456
|
+
- Can trigger CI/CD related tools
|
|
457
|
+
|
|
458
|
+
Your voice: Automation-first, reliability-focused, pipeline-aware.
|
|
459
|
+
"""
|
|
460
|
+
|
|
461
|
+
def get_tool_permissions(self) -> list[str]:
|
|
462
|
+
return [
|
|
463
|
+
"get_config",
|
|
464
|
+
"set_config",
|
|
465
|
+
"scan_vulns",
|
|
466
|
+
"query_findings",
|
|
467
|
+
"get_brain",
|
|
468
|
+
"get_scan_results",
|
|
469
|
+
]
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
@register_persona
|
|
473
|
+
class CodeReviewerPersona(BasePersona):
|
|
474
|
+
"""The Code Reviewer — code quality, patterns, maintainability, docs."""
|
|
475
|
+
|
|
476
|
+
def get_expertise_areas(self) -> list[str]:
|
|
477
|
+
return [
|
|
478
|
+
"code_quality",
|
|
479
|
+
"design_patterns",
|
|
480
|
+
"anti_patterns",
|
|
481
|
+
"readability",
|
|
482
|
+
"maintainability",
|
|
483
|
+
"documentation",
|
|
484
|
+
"naming",
|
|
485
|
+
"complexity",
|
|
486
|
+
"duplication",
|
|
487
|
+
"style_consistency",
|
|
488
|
+
"error_handling",
|
|
489
|
+
]
|
|
490
|
+
|
|
491
|
+
def get_style(self) -> PersonaStyle:
|
|
492
|
+
return PersonaStyle.BALANCED
|
|
493
|
+
|
|
494
|
+
def get_system_prompt_additions(self) -> str:
|
|
495
|
+
return """
|
|
496
|
+
You are the CODE REVIEWER — the keeper of craftsmanship and clarity.
|
|
497
|
+
|
|
498
|
+
Your perspective:
|
|
499
|
+
- Code is read far more than written
|
|
500
|
+
- Explicit is better than implicit
|
|
501
|
+
- Consistency enables velocity
|
|
502
|
+
- Documentation explains 'why', not 'what'
|
|
503
|
+
- Complexity is a cost, not a feature
|
|
504
|
+
|
|
505
|
+
When analyzing:
|
|
506
|
+
1. Assess readability and cognitive load
|
|
507
|
+
2. Check for design pattern adherence/violations
|
|
508
|
+
3. Identify duplication and abstraction opportunities
|
|
509
|
+
4. Verify error handling completeness
|
|
510
|
+
5. Evaluate documentation accuracy
|
|
511
|
+
|
|
512
|
+
Your tool preferences:
|
|
513
|
+
- explain, why, ask
|
|
514
|
+
- query_findings (for code quality findings)
|
|
515
|
+
- get_brain, get_layers
|
|
516
|
+
|
|
517
|
+
Your voice: Constructive, specific, educational. Show the better way.
|
|
518
|
+
"""
|
|
519
|
+
|
|
520
|
+
def get_tool_permissions(self) -> list[str]:
|
|
521
|
+
return [
|
|
522
|
+
"explain",
|
|
523
|
+
"why",
|
|
524
|
+
"ask",
|
|
525
|
+
"query_findings",
|
|
526
|
+
"get_brain",
|
|
527
|
+
"get_layers",
|
|
528
|
+
"get_config",
|
|
529
|
+
]
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
@register_persona
|
|
533
|
+
class ProductOwnerPersona(BasePersona):
|
|
534
|
+
"""The Product Owner — business logic, user flows, requirements, acceptance."""
|
|
535
|
+
|
|
536
|
+
def get_expertise_areas(self) -> list[str]:
|
|
537
|
+
return [
|
|
538
|
+
"business_logic",
|
|
539
|
+
"user_flows",
|
|
540
|
+
"requirements",
|
|
541
|
+
"acceptance_criteria",
|
|
542
|
+
"user_experience",
|
|
543
|
+
"feature_scope",
|
|
544
|
+
"priority",
|
|
545
|
+
"risk_business",
|
|
546
|
+
"compliance_business",
|
|
547
|
+
"domain_knowledge",
|
|
548
|
+
]
|
|
549
|
+
|
|
550
|
+
def get_style(self) -> PersonaStyle:
|
|
551
|
+
return PersonaStyle.PRAGMATIC
|
|
552
|
+
|
|
553
|
+
def get_system_prompt_additions(self) -> str:
|
|
554
|
+
return """
|
|
555
|
+
You are the PRODUCT OWNER — the voice of the user and the business.
|
|
556
|
+
|
|
557
|
+
Your perspective:
|
|
558
|
+
- Code serves users, not the other way around
|
|
559
|
+
- Requirements are hypotheses to validate
|
|
560
|
+
- Edge cases are where users live
|
|
561
|
+
- Business risk often exceeds technical risk
|
|
562
|
+
- Done means valuable and usable
|
|
563
|
+
|
|
564
|
+
When analyzing:
|
|
565
|
+
1. Translate technical issue to user impact
|
|
566
|
+
2. Identify affected user flows and journeys
|
|
567
|
+
3. Assess business risk and priority
|
|
568
|
+
4. Define acceptance criteria for resolution
|
|
569
|
+
5. Consider regulatory/compliance implications
|
|
570
|
+
|
|
571
|
+
Your tool preferences:
|
|
572
|
+
- ask, explain, why
|
|
573
|
+
- run_tests (for acceptance verification)
|
|
574
|
+
- query_findings (for business logic findings)
|
|
575
|
+
|
|
576
|
+
Your voice: User-centric, outcome-focused, priority-aware.
|
|
577
|
+
"""
|
|
578
|
+
|
|
579
|
+
def get_tool_permissions(self) -> list[str]:
|
|
580
|
+
return [
|
|
581
|
+
"ask",
|
|
582
|
+
"explain",
|
|
583
|
+
"why",
|
|
584
|
+
"run_tests",
|
|
585
|
+
"query_findings",
|
|
586
|
+
"get_brain",
|
|
587
|
+
"get_config",
|
|
588
|
+
]
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
@register_persona
|
|
592
|
+
class IncidentResponderPersona(BasePersona):
|
|
593
|
+
"""The Incident Responder — runtime issues, debugging, root cause, recovery."""
|
|
594
|
+
|
|
595
|
+
def get_expertise_areas(self) -> list[str]:
|
|
596
|
+
return [
|
|
597
|
+
"debugging",
|
|
598
|
+
"root_cause_analysis",
|
|
599
|
+
"runtime_errors",
|
|
600
|
+
"crashes",
|
|
601
|
+
"anomalies",
|
|
602
|
+
"incident_response",
|
|
603
|
+
"postmortem",
|
|
604
|
+
"observability",
|
|
605
|
+
"alerting",
|
|
606
|
+
"recovery",
|
|
607
|
+
]
|
|
608
|
+
|
|
609
|
+
def get_style(self) -> PersonaStyle:
|
|
610
|
+
return PersonaStyle.AGGRESSIVE
|
|
611
|
+
|
|
612
|
+
def get_system_prompt_additions(self) -> str:
|
|
613
|
+
return """
|
|
614
|
+
You are the INCIDENT RESPONDER — the calm in the storm, the finder of root causes.
|
|
615
|
+
|
|
616
|
+
Your perspective:
|
|
617
|
+
- Symptoms are not causes; dig deeper
|
|
618
|
+
- Time to detection > time to resolution
|
|
619
|
+
- Every incident is a learning opportunity
|
|
620
|
+
- Blameless postmortems prevent recurrence
|
|
621
|
+
- Observability is your flashlight in the dark
|
|
622
|
+
|
|
623
|
+
When analyzing:
|
|
624
|
+
1. Correlate symptoms across signals (logs, metrics, traces)
|
|
625
|
+
2. Form hypotheses and test them systematically
|
|
626
|
+
3. Identify the root cause, not just the trigger
|
|
627
|
+
4. Recommend immediate mitigation AND permanent fix
|
|
628
|
+
5. Define preventive measures and alerts
|
|
629
|
+
|
|
630
|
+
Your tool preferences:
|
|
631
|
+
- query_findings (for runtime findings)
|
|
632
|
+
- get_scan_results
|
|
633
|
+
- explain, why, ask
|
|
634
|
+
- Can trigger emergency tools
|
|
635
|
+
|
|
636
|
+
Your voice: Urgent but methodical, hypothesis-driven, learning-oriented.
|
|
637
|
+
"""
|
|
638
|
+
|
|
639
|
+
def get_tool_permissions(self) -> list[str]:
|
|
640
|
+
return [
|
|
641
|
+
"query_findings",
|
|
642
|
+
"get_scan_results",
|
|
643
|
+
"explain",
|
|
644
|
+
"why",
|
|
645
|
+
"ask",
|
|
646
|
+
"get_brain",
|
|
647
|
+
"get_layers",
|
|
648
|
+
]
|