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.
Files changed (496) hide show
  1. patchi/__init__.py +1 -0
  2. patchi/__main__.py +13 -0
  3. patchi/cli/__init__.py +0 -0
  4. patchi/cli/command_families.py +235 -0
  5. patchi/cli/commands/__init__.py +0 -0
  6. patchi/cli/commands/access_cmd.py +65 -0
  7. patchi/cli/commands/agent_stats_cmd.py +273 -0
  8. patchi/cli/commands/agents_cmd.py +187 -0
  9. patchi/cli/commands/ai_cmd.py +308 -0
  10. patchi/cli/commands/assure_cmd.py +538 -0
  11. patchi/cli/commands/audit_cmd.py +286 -0
  12. patchi/cli/commands/auto_cmd.py +110 -0
  13. patchi/cli/commands/blame_cmd.py +53 -0
  14. patchi/cli/commands/chains_cmd.py +327 -0
  15. patchi/cli/commands/charter_cmd.py +173 -0
  16. patchi/cli/commands/chat_cmd.py +597 -0
  17. patchi/cli/commands/check_cmd.py +232 -0
  18. patchi/cli/commands/cleanup_cmd.py +328 -0
  19. patchi/cli/commands/cockpit_cmd.py +208 -0
  20. patchi/cli/commands/commands_cmd.py +160 -0
  21. patchi/cli/commands/cross_repo_cmd.py +113 -0
  22. patchi/cli/commands/deps_cmd.py +110 -0
  23. patchi/cli/commands/dev_check_cmd.py +342 -0
  24. patchi/cli/commands/dev_cmd.py +445 -0
  25. patchi/cli/commands/doctor_cmd.py +457 -0
  26. patchi/cli/commands/findings_cmd.py +187 -0
  27. patchi/cli/commands/fix_cmd.py +648 -0
  28. patchi/cli/commands/fix_review_cmd.py +273 -0
  29. patchi/cli/commands/heatmap_cmd.py +62 -0
  30. patchi/cli/commands/help_cmd.py +159 -0
  31. patchi/cli/commands/hosted_cmd.py +980 -0
  32. patchi/cli/commands/init.py +456 -0
  33. patchi/cli/commands/key_cmd.py +571 -0
  34. patchi/cli/commands/learn_cmd.py +140 -0
  35. patchi/cli/commands/link_cmd.py +104 -0
  36. patchi/cli/commands/log_cmd.py +57 -0
  37. patchi/cli/commands/memory_cmd.py +215 -0
  38. patchi/cli/commands/model_cmd.py +207 -0
  39. patchi/cli/commands/notify_cmd.py +213 -0
  40. patchi/cli/commands/notify_prompts.py +29 -0
  41. patchi/cli/commands/patch_cmd.py +231 -0
  42. patchi/cli/commands/plan_cmd.py +128 -0
  43. patchi/cli/commands/plugins_cmd.py +307 -0
  44. patchi/cli/commands/queue_cmd.py +152 -0
  45. patchi/cli/commands/quick_cmd.py +159 -0
  46. patchi/cli/commands/ready_cmd.py +292 -0
  47. patchi/cli/commands/report_cmd.py +416 -0
  48. patchi/cli/commands/restrict_cmd.py +127 -0
  49. patchi/cli/commands/review_cmd.py +225 -0
  50. patchi/cli/commands/rules_cmd.py +233 -0
  51. patchi/cli/commands/scan_cmd.py +1908 -0
  52. patchi/cli/commands/settings_cmd.py +45 -0
  53. patchi/cli/commands/status_cmd.py +679 -0
  54. patchi/cli/commands/test_cmd.py +1052 -0
  55. patchi/cli/commands/trend_cmd.py +296 -0
  56. patchi/cli/commands/undo_cmd.py +235 -0
  57. patchi/cli/commands/update_cmd.py +345 -0
  58. patchi/cli/commands/verify_cmd.py +56 -0
  59. patchi/cli/commands/vr_cmd.py +440 -0
  60. patchi/cli/commands/watch_cmd.py +304 -0
  61. patchi/cli/commands/web_cmd.py +114 -0
  62. patchi/cli/console.py +101 -0
  63. patchi/cli/display/__init__.py +1 -0
  64. patchi/cli/display/live_audit.py +269 -0
  65. patchi/cli/display/live_progress.py +169 -0
  66. patchi/cli/framework.py +241 -0
  67. patchi/cli/logo.py +128 -0
  68. patchi/cli/main.py +222 -0
  69. patchi/cli/registry.py +1171 -0
  70. patchi/cli/style.py +68 -0
  71. patchi/cli/themes.py +187 -0
  72. patchi/cli/ux.py +444 -0
  73. patchi/core/__init__.py +0 -0
  74. patchi/core/agents/__init__.py +0 -0
  75. patchi/core/agents/api_fuzzer_agent.py +141 -0
  76. patchi/core/agents/attack_agent.py +242 -0
  77. patchi/core/agents/base.py +1012 -0
  78. patchi/core/agents/bug_predictor_agent.py +58 -0
  79. patchi/core/agents/build_tool_validator.py +150 -0
  80. patchi/core/agents/cache.py +192 -0
  81. patchi/core/agents/chaos_agent.py +133 -0
  82. patchi/core/agents/cicd_generator.py +240 -0
  83. patchi/core/agents/comment_scanner.py +280 -0
  84. patchi/core/agents/console_logging_agent.py +156 -0
  85. patchi/core/agents/coordinator.py +858 -0
  86. patchi/core/agents/core_scanner.py +269 -0
  87. patchi/core/agents/coverage_prioritizer.py +181 -0
  88. patchi/core/agents/dead_code_hygiene.py +296 -0
  89. patchi/core/agents/dead_code_scanner.py +692 -0
  90. patchi/core/agents/dependency_scanner.py +725 -0
  91. patchi/core/agents/doc_claim_agent.py +573 -0
  92. patchi/core/agents/duplicate_scanner.py +568 -0
  93. patchi/core/agents/env_scanner.py +410 -0
  94. patchi/core/agents/feature_flag_agent.py +89 -0
  95. patchi/core/agents/frontend_framework_agent.py +133 -0
  96. patchi/core/agents/goroutine_agent.py +82 -0
  97. patchi/core/agents/governor.py +1972 -0
  98. patchi/core/agents/i18n_agent.py +95 -0
  99. patchi/core/agents/license_compliance.py +247 -0
  100. patchi/core/agents/linking_agent.py +251 -0
  101. patchi/core/agents/memory_profiler_agent.py +102 -0
  102. patchi/core/agents/modernization_agent.py +84 -0
  103. patchi/core/agents/mutation_agent.py +174 -0
  104. patchi/core/agents/nl_query_agent.py +74 -0
  105. patchi/core/agents/promise_rejection_agent.py +100 -0
  106. patchi/core/agents/refactoring_agent.py +286 -0
  107. patchi/core/agents/resource_leak_agent.py +91 -0
  108. patchi/core/agents/route_graph_scanner.py +951 -0
  109. patchi/core/agents/run_agent.py +106 -0
  110. patchi/core/agents/rust_unwrap_agent.py +100 -0
  111. patchi/core/agents/sbom_generator.py +284 -0
  112. patchi/core/agents/scanners.py +67 -0
  113. patchi/core/agents/side/__init__.py +1 -0
  114. patchi/core/agents/side/build_agent.py +65 -0
  115. patchi/core/agents/side/format_agent.py +50 -0
  116. patchi/core/agents/side/install_agent.py +63 -0
  117. patchi/core/agents/side_file_scanner.py +549 -0
  118. patchi/core/agents/snapshot_drift_detector.py +146 -0
  119. patchi/core/agents/spa_route_inventory.py +203 -0
  120. patchi/core/agents/test_scanner.py +442 -0
  121. patchi/core/agents/tool_health.py +109 -0
  122. patchi/core/agents/tool_runner.py +162 -0
  123. patchi/core/agents/type_scanner.py +168 -0
  124. patchi/core/agents/ui_scanner.py +558 -0
  125. patchi/core/ai/__init__.py +20 -0
  126. patchi/core/ai/agent_audit.py +153 -0
  127. patchi/core/ai/agent_profiler.py +277 -0
  128. patchi/core/ai/client.py +499 -0
  129. patchi/core/ai/cost_tracker.py +107 -0
  130. patchi/core/ai/model_router.py +318 -0
  131. patchi/core/ai/orchestrator.py +625 -0
  132. patchi/core/ai/prompts.py +681 -0
  133. patchi/core/ai/smart.py +302 -0
  134. patchi/core/ai/tool_executor.py +24 -0
  135. patchi/core/ai/tools/__init__.py +10 -0
  136. patchi/core/ai/tools/executor.py +621 -0
  137. patchi/core/ai/tools/realize.py +1160 -0
  138. patchi/core/ai/tools/registry.py +1577 -0
  139. patchi/core/assurance/__init__.py +33 -0
  140. patchi/core/assurance/builder.py +211 -0
  141. patchi/core/assurance/graph.py +342 -0
  142. patchi/core/assurance/invariants.py +168 -0
  143. patchi/core/atomic.py +61 -0
  144. patchi/core/attackers/__init__.py +17 -0
  145. patchi/core/attackers/api_abuse.py +89 -0
  146. patchi/core/attackers/auth_bypass.py +73 -0
  147. patchi/core/attackers/base.py +91 -0
  148. patchi/core/attackers/business_logic.py +88 -0
  149. patchi/core/attackers/planner.py +108 -0
  150. patchi/core/attackers/priv_escalation.py +88 -0
  151. patchi/core/attackers/recon.py +87 -0
  152. patchi/core/brain/__init__.py +0 -0
  153. patchi/core/brain/ast_utils/__init__.py +81 -0
  154. patchi/core/brain/ast_utils/assignments.py +219 -0
  155. patchi/core/brain/ast_utils/calls.py +139 -0
  156. patchi/core/brain/ast_utils/config.py +132 -0
  157. patchi/core/brain/ast_utils/control_flow.py +74 -0
  158. patchi/core/brain/ast_utils/dead_symbols.py +205 -0
  159. patchi/core/brain/ast_utils/decorators.py +108 -0
  160. patchi/core/brain/ast_utils/helpers.py +144 -0
  161. patchi/core/brain/ast_utils/imports.py +169 -0
  162. patchi/core/brain/ast_utils/scan.py +143 -0
  163. patchi/core/brain/ast_utils/taint.py +310 -0
  164. patchi/core/brain/audit.py +379 -0
  165. patchi/core/brain/baseline.py +195 -0
  166. patchi/core/brain/blast_radius.py +312 -0
  167. patchi/core/brain/body_tags.py +144 -0
  168. patchi/core/brain/brain.py +1161 -0
  169. patchi/core/brain/brain_context.py +393 -0
  170. patchi/core/brain/brain_watcher.py +340 -0
  171. patchi/core/brain/charter.py +473 -0
  172. patchi/core/brain/classifier.py +214 -0
  173. patchi/core/brain/cockpit.py +350 -0
  174. patchi/core/brain/code_query.py +710 -0
  175. patchi/core/brain/contract.py +889 -0
  176. patchi/core/brain/contract_diff.py +155 -0
  177. patchi/core/brain/council.py +800 -0
  178. patchi/core/brain/cross_repo.py +104 -0
  179. patchi/core/brain/dead_code_tools.py +157 -0
  180. patchi/core/brain/doc_validator.py +197 -0
  181. patchi/core/brain/domain_activator.py +2183 -0
  182. patchi/core/brain/enriched_context.py +220 -0
  183. patchi/core/brain/file_corpus.py +220 -0
  184. patchi/core/brain/framework.py +953 -0
  185. patchi/core/brain/freshness.py +273 -0
  186. patchi/core/brain/git_aware.py +206 -0
  187. patchi/core/brain/heatmap.py +104 -0
  188. patchi/core/brain/ignore_parser.py +153 -0
  189. patchi/core/brain/import_graph.py +486 -0
  190. patchi/core/brain/languages.py +397 -0
  191. patchi/core/brain/layered_brain.py +419 -0
  192. patchi/core/brain/learning.py +229 -0
  193. patchi/core/brain/orphaned_endpoints.py +313 -0
  194. patchi/core/brain/personas/__init__.py +648 -0
  195. patchi/core/brain/personas/bad_user.py +165 -0
  196. patchi/core/brain/personas/base.py +349 -0
  197. patchi/core/brain/proactive.py +807 -0
  198. patchi/core/brain/project_context.py +121 -0
  199. patchi/core/brain/project_reader.py +521 -0
  200. patchi/core/brain/reasoning.py +269 -0
  201. patchi/core/brain/route_detector/__init__.py +15 -0
  202. patchi/core/brain/route_detector/base.py +31 -0
  203. patchi/core/brain/route_detector/csharp.py +209 -0
  204. patchi/core/brain/route_detector/file_based.py +81 -0
  205. patchi/core/brain/route_detector/go.py +152 -0
  206. patchi/core/brain/route_detector/java.py +195 -0
  207. patchi/core/brain/route_detector/javascript.py +197 -0
  208. patchi/core/brain/route_detector/php.py +158 -0
  209. patchi/core/brain/route_detector/python.py +193 -0
  210. patchi/core/brain/route_detector/registry.py +25 -0
  211. patchi/core/brain/route_detector/ruby.py +134 -0
  212. patchi/core/brain/route_detector/rust.py +216 -0
  213. patchi/core/brain/route_detector/swift.py +118 -0
  214. patchi/core/brain/route_mapper.py +265 -0
  215. patchi/core/brain/scanner.py +2136 -0
  216. patchi/core/brain/secrets.py +280 -0
  217. patchi/core/brain/symbol_graph.py +1955 -0
  218. patchi/core/brain/team.py +28 -0
  219. patchi/core/brain/trace_log.py +132 -0
  220. patchi/core/brain/type_checker/__init__.py +65 -0
  221. patchi/core/brain/type_checker/base.py +60 -0
  222. patchi/core/brain/type_checker/csharp.py +59 -0
  223. patchi/core/brain/type_checker/dart.py +59 -0
  224. patchi/core/brain/type_checker/go.py +81 -0
  225. patchi/core/brain/type_checker/java.py +75 -0
  226. patchi/core/brain/type_checker/kotlin.py +75 -0
  227. patchi/core/brain/type_checker/php.py +88 -0
  228. patchi/core/brain/type_checker/python.py +87 -0
  229. patchi/core/brain/type_checker/rust.py +81 -0
  230. patchi/core/brain/type_checker/swift.py +59 -0
  231. patchi/core/brain/type_checker/typescript.py +298 -0
  232. patchi/core/brain/understander.py +130 -0
  233. patchi/core/brain/verify.py +379 -0
  234. patchi/core/campaigns/__init__.py +14 -0
  235. patchi/core/campaigns/base.py +62 -0
  236. patchi/core/campaigns/data_flow_abuse.py +153 -0
  237. patchi/core/campaigns/orchestrator.py +140 -0
  238. patchi/core/campaigns/state_transitions.py +178 -0
  239. patchi/core/ci_bundle.py +104 -0
  240. patchi/core/config.py +311 -0
  241. patchi/core/constants.py +245 -0
  242. patchi/core/debug/__init__.py +25 -0
  243. patchi/core/debug/adapters/__init__.py +11 -0
  244. patchi/core/debug/adapters/codelldb.py +379 -0
  245. patchi/core/debug/adapters/node.py +222 -0
  246. patchi/core/debug/adapters/powershell.py +210 -0
  247. patchi/core/debug/adapters/python.py +244 -0
  248. patchi/core/debug/capture.py +210 -0
  249. patchi/core/debug/dap_client.py +268 -0
  250. patchi/core/detector/__init__.py +0 -0
  251. patchi/core/detector/audit.py +194 -0
  252. patchi/core/detector/bus.py +226 -0
  253. patchi/core/detector/dispatcher.py +275 -0
  254. patchi/core/detector/event.py +254 -0
  255. patchi/core/detector/sigma_engine.py +378 -0
  256. patchi/core/detector/triage.py +289 -0
  257. patchi/core/export/sarif.py +113 -0
  258. patchi/core/fix/__init__.py +17 -0
  259. patchi/core/fix/applier.py +574 -0
  260. patchi/core/fix/base.py +510 -0
  261. patchi/core/fix/code_fixer.py +169 -0
  262. patchi/core/fix/dead_code_remover.py +131 -0
  263. patchi/core/fix/fix_agents.py +775 -0
  264. patchi/core/fix/patch.py +444 -0
  265. patchi/core/fix/risk_gate.py +383 -0
  266. patchi/core/fix/security_fixer.py +93 -0
  267. patchi/core/fix/verify_loop.py +204 -0
  268. patchi/core/fuzz/__init__.py +8 -0
  269. patchi/core/fuzz/corpus.py +137 -0
  270. patchi/core/fuzz/input_fuzzer.py +256 -0
  271. patchi/core/fuzz/sequence_fuzzer.py +162 -0
  272. patchi/core/fuzz/state_fuzzer.py +236 -0
  273. patchi/core/health.py +407 -0
  274. patchi/core/hosted/__init__.py +1 -0
  275. patchi/core/hosted/anomaly.py +298 -0
  276. patchi/core/hosted/audit_log.py +102 -0
  277. patchi/core/hosted/compliance_report.py +148 -0
  278. patchi/core/hosted/ip_reputation.py +169 -0
  279. patchi/core/hosted/log_parsers.py +251 -0
  280. patchi/core/hosted/tokens.py +127 -0
  281. patchi/core/hosted/watchlist.py +164 -0
  282. patchi/core/hosted/webhooks.py +156 -0
  283. patchi/core/memory.py +437 -0
  284. patchi/core/notifications/__init__.py +18 -0
  285. patchi/core/notifications/channels.py +192 -0
  286. patchi/core/notifications/digest.py +141 -0
  287. patchi/core/notifications/escalation.py +158 -0
  288. patchi/core/notifications/notifier.py +182 -0
  289. patchi/core/notifications/quiet_hours.py +69 -0
  290. patchi/core/plugins/__init__.py +48 -0
  291. patchi/core/plugins/analyzer.py +326 -0
  292. patchi/core/plugins/analyzers/__init__.py +6 -0
  293. patchi/core/plugins/analyzers/dead_code_analyzer.py +120 -0
  294. patchi/core/plugins/analyzers/secret_scanner.py +158 -0
  295. patchi/core/plugins/analyzers/todo_scanner.py +115 -0
  296. patchi/core/plugins/registry.py +335 -0
  297. patchi/core/queue.py +375 -0
  298. patchi/core/reliability/__init__.py +13 -0
  299. patchi/core/reliability/chaos.py +163 -0
  300. patchi/core/reliability/fault_injector.py +172 -0
  301. patchi/core/reliability/idempotency.py +128 -0
  302. patchi/core/reliability/recovery.py +147 -0
  303. patchi/core/runtime/__init__.py +5 -0
  304. patchi/core/runtime/tracer.py +230 -0
  305. patchi/core/scan_bus.py +156 -0
  306. patchi/core/security/__init__.py +1 -0
  307. patchi/core/security/ai_validator.py +462 -0
  308. patchi/core/security/app_mapper.py +216 -0
  309. patchi/core/security/app_profile.py +464 -0
  310. patchi/core/security/attack_feedback.py +141 -0
  311. patchi/core/security/attack_scenarios/__init__.py +1 -0
  312. patchi/core/security/attack_tree.py +176 -0
  313. patchi/core/security/auth_audit_agent.py +344 -0
  314. patchi/core/security/authz_agent.py +602 -0
  315. patchi/core/security/auto_fix_proactive.py +620 -0
  316. patchi/core/security/auto_fixer.py +660 -0
  317. patchi/core/security/auto_ticket.py +53 -0
  318. patchi/core/security/bandit_agent.py +152 -0
  319. patchi/core/security/blast_radius.py +226 -0
  320. patchi/core/security/browser_tester.py +333 -0
  321. patchi/core/security/business_logic_agent.py +263 -0
  322. patchi/core/security/catch_block_auditor.py +395 -0
  323. patchi/core/security/cdn_cache_agent.py +357 -0
  324. patchi/core/security/chain_analyzer.py +321 -0
  325. patchi/core/security/chain_to_assurance.py +168 -0
  326. patchi/core/security/charter.py +510 -0
  327. patchi/core/security/cloud_waf_detector.py +295 -0
  328. patchi/core/security/codeql_agent.py +233 -0
  329. patchi/core/security/compliance_agent.py +348 -0
  330. patchi/core/security/confidence_gate.py +423 -0
  331. patchi/core/security/container_scanner.py +282 -0
  332. patchi/core/security/crypto_agent.py +378 -0
  333. patchi/core/security/cve_monitor.py +262 -0
  334. patchi/core/security/dast_agent.py +865 -0
  335. patchi/core/security/defectdojo.py +238 -0
  336. patchi/core/security/defenders/__init__.py +75 -0
  337. patchi/core/security/defenders/auth_middleware.py +115 -0
  338. patchi/core/security/defenders/base.py +97 -0
  339. patchi/core/security/defenders/block_ip.py +71 -0
  340. patchi/core/security/defenders/block_ws_origin.py +36 -0
  341. patchi/core/security/defenders/crypto_fix.py +118 -0
  342. patchi/core/security/defenders/enforce_rate_limit.py +108 -0
  343. patchi/core/security/defenders/fix_code.py +93 -0
  344. patchi/core/security/defenders/invalidate_session.py +40 -0
  345. patchi/core/security/defenders/patch_config.py +70 -0
  346. patchi/core/security/defenders/rotate_secret.py +54 -0
  347. patchi/core/security/defenders/suspend_account.py +41 -0
  348. patchi/core/security/defenders/update_dependency.py +160 -0
  349. patchi/core/security/defense_layer.py +217 -0
  350. patchi/core/security/dependency_vulnerability_agent.py +616 -0
  351. patchi/core/security/detection_pipeline.py +289 -0
  352. patchi/core/security/dns_security_agent.py +497 -0
  353. patchi/core/security/domain_activator_v2.py +913 -0
  354. patchi/core/security/domain_loader.py +1004 -0
  355. patchi/core/security/domains/__init__.py +0 -0
  356. patchi/core/security/email_authentication_agent.py +417 -0
  357. patchi/core/security/env_var_validator.py +304 -0
  358. patchi/core/security/evidence.py +100 -0
  359. patchi/core/security/falco_runtime_agent.py +387 -0
  360. patchi/core/security/fix-playbooks/__init__.py +0 -0
  361. patchi/core/security/gated_finding.py +85 -0
  362. patchi/core/security/git_diff_activator.py +367 -0
  363. patchi/core/security/governance.py +208 -0
  364. patchi/core/security/gradual_gate.py +34 -0
  365. patchi/core/security/history.py +315 -0
  366. patchi/core/security/iac_scanner.py +250 -0
  367. patchi/core/security/ignore_expiry.py +111 -0
  368. patchi/core/security/ignore_learner.py +416 -0
  369. patchi/core/security/injection_agent.py +319 -0
  370. patchi/core/security/insecure_randomness_agent.py +288 -0
  371. patchi/core/security/intent_analyzer.py +326 -0
  372. patchi/core/security/jwt_agent.py +453 -0
  373. patchi/core/security/kubernetes_agent.py +638 -0
  374. patchi/core/security/layer2_orchestrator.py +341 -0
  375. patchi/core/security/llm_security_agent.py +252 -0
  376. patchi/core/security/misconfig_agent.py +600 -0
  377. patchi/core/security/mobile_security_agent.py +474 -0
  378. patchi/core/security/network_agent.py +376 -0
  379. patchi/core/security/noise_filter.py +274 -0
  380. patchi/core/security/orchestrator.py +313 -0
  381. patchi/core/security/pattern_context.py +125 -0
  382. patchi/core/security/pattern_loader.py +101 -0
  383. patchi/core/security/pentest/__init__.py +4 -0
  384. patchi/core/security/pentest/base.py +58 -0
  385. patchi/core/security/pentest/dalfox_adapter.py +40 -0
  386. patchi/core/security/pentest/ffuf_adapter.py +48 -0
  387. patchi/core/security/pentest/nuclei_adapter.py +50 -0
  388. patchi/core/security/pentest/registry.py +80 -0
  389. patchi/core/security/pentest/shannon_adapter.py +107 -0
  390. patchi/core/security/pentest/sqlmap_adapter.py +56 -0
  391. patchi/core/security/pentest/zap_adapter.py +52 -0
  392. patchi/core/security/plan_auditor.py +276 -0
  393. patchi/core/security/policy_engine.py +272 -0
  394. patchi/core/security/prechecks.py +172 -0
  395. patchi/core/security/precommit_hook.py +247 -0
  396. patchi/core/security/privacy_agent.py +361 -0
  397. patchi/core/security/push_notification_agent.py +417 -0
  398. patchi/core/security/pysa_agent.py +143 -0
  399. patchi/core/security/reasoning.py +442 -0
  400. patchi/core/security/red_team_agent.py +184 -0
  401. patchi/core/security/red_team_engine.py +1142 -0
  402. patchi/core/security/remediation.py +360 -0
  403. patchi/core/security/request_interceptor.py +294 -0
  404. patchi/core/security/runtime_validator.py +245 -0
  405. patchi/core/security/saml_sso_agent.py +401 -0
  406. patchi/core/security/sast_agent.py +213 -0
  407. patchi/core/security/sast_gate.py +95 -0
  408. patchi/core/security/scheduler.py +287 -0
  409. patchi/core/security/secrets_runtime_agent.py +476 -0
  410. patchi/core/security/security_agents.py +175 -0
  411. patchi/core/security/security_config.py +551 -0
  412. patchi/core/security/security_probe.py +762 -0
  413. patchi/core/security/security_taint.py +1005 -0
  414. patchi/core/security/sensitive_data_agent.py +271 -0
  415. patchi/core/security/service_mesh_agent.py +412 -0
  416. patchi/core/security/session_management_agent.py +245 -0
  417. patchi/core/security/ssrf_agent.py +422 -0
  418. patchi/core/security/supply_chain.py +449 -0
  419. patchi/core/security/threat_model_generator.py +378 -0
  420. patchi/core/security/threat_model_updater.py +196 -0
  421. patchi/core/security/tool_adapters.py +135 -0
  422. patchi/core/security/tool_verify.py +173 -0
  423. patchi/core/security/websocket_security_agent.py +188 -0
  424. patchi/core/snapshot.py +242 -0
  425. patchi/core/tenant.py +386 -0
  426. patchi/core/testing/__init__.py +17 -0
  427. patchi/core/testing/_browser.py +147 -0
  428. patchi/core/testing/ads_agent.py +141 -0
  429. patchi/core/testing/api_contract_agent.py +450 -0
  430. patchi/core/testing/app_discovery_agent.py +641 -0
  431. patchi/core/testing/app_launcher.py +184 -0
  432. patchi/core/testing/browser_test_agent.py +516 -0
  433. patchi/core/testing/e2e_flow_agent.py +354 -0
  434. patchi/core/testing/flake_detector_agent.py +292 -0
  435. patchi/core/testing/gate.py +31 -0
  436. patchi/core/testing/live_test_runner.py +304 -0
  437. patchi/core/testing/live_v2/__init__.py +1 -0
  438. patchi/core/testing/live_v2/browser_pool.py +349 -0
  439. patchi/core/testing/live_v2/browser_test_runner.py +313 -0
  440. patchi/core/testing/live_v2/runner.py +626 -0
  441. patchi/core/testing/live_v2/screenshot_manager.py +474 -0
  442. patchi/core/testing/live_v2/stress_orchestrator.py +523 -0
  443. patchi/core/testing/live_v2/video_recorder.py +303 -0
  444. patchi/core/testing/regression_agent.py +302 -0
  445. patchi/core/testing/security_test_agent.py +253 -0
  446. patchi/core/testing/stress_test_agent.py +203 -0
  447. patchi/core/testing/test_agents.py +50 -0
  448. patchi/core/testing/test_config.py +194 -0
  449. patchi/core/testing/ui_accessibility_agent.py +324 -0
  450. patchi/core/testing/ui_button_agent.py +294 -0
  451. patchi/core/testing/ui_layout_agent.py +330 -0
  452. patchi/core/testing/unit_test_agent.py +1149 -0
  453. patchi/core/testing/visual_regression_agent.py +260 -0
  454. patchi/web/__init__.py +1 -0
  455. patchi/web/api/__init__.py +1 -0
  456. patchi/web/api/brain_map.py +114 -0
  457. patchi/web/api/charts.py +47 -0
  458. patchi/web/api/chat.py +224 -0
  459. patchi/web/api/cicd.py +576 -0
  460. patchi/web/api/dast_evidence.py +49 -0
  461. patchi/web/api/dev_check.py +320 -0
  462. patchi/web/api/fix.py +134 -0
  463. patchi/web/api/guard.py +65 -0
  464. patchi/web/api/hosted.py +128 -0
  465. patchi/web/api/hosted_v2.py +234 -0
  466. patchi/web/api/live_testing.py +699 -0
  467. patchi/web/api/scan.py +582 -0
  468. patchi/web/api/smart.py +111 -0
  469. patchi/web/api/tenant.py +117 -0
  470. patchi/web/api/tools.py +85 -0
  471. patchi/web/api_legacy.py +2401 -0
  472. patchi/web/app.py +310 -0
  473. patchi/web/events.py +483 -0
  474. patchi/web/routes/__init__.py +1 -0
  475. patchi/web/routes/assurance.py +541 -0
  476. patchi/web/routes/brain.py +36 -0
  477. patchi/web/routes/charter.py +227 -0
  478. patchi/web/routes/chat.py +23 -0
  479. patchi/web/routes/dashboard.py +558 -0
  480. patchi/web/routes/dashboard_v2.py +402 -0
  481. patchi/web/routes/findings.py +330 -0
  482. patchi/web/routes/guard.py +35 -0
  483. patchi/web/routes/history.py +126 -0
  484. patchi/web/routes/landing.py +52 -0
  485. patchi/web/routes/live_testing.py +24 -0
  486. patchi/web/routes/review.py +57 -0
  487. patchi/web/routes/self_improvement.py +110 -0
  488. patchi/web/routes/settings.py +49 -0
  489. patchi/web/routes/tokens.py +29 -0
  490. patchi/web/spawn.py +139 -0
  491. patchi/web/ws.py +141 -0
  492. patchi-0.7.5.dist-info/METADATA +315 -0
  493. patchi-0.7.5.dist-info/RECORD +496 -0
  494. patchi-0.7.5.dist-info/WHEEL +5 -0
  495. patchi-0.7.5.dist-info/licenses/LICENSE +60 -0
  496. patchi-0.7.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,153 @@
1
+ """
2
+ Agent audit harness.
3
+
4
+ Scans every registered agent (security, test, fix, scanner, guard) for the
5
+ defects called out in AUDIT_STUBS_PLACEHOLDERS_WRONG_LOGIC.md and the user's
6
+ "audit each agent and improve them" request:
7
+
8
+ * raises ``NotImplementedError``
9
+ * returns placeholder text ("initiated", "placeholder", "TODO", "not implemented")
10
+ * uses the OLD single-arg ``_run(self, inp)`` signature instead of the
11
+ mutation style ``_run(self, inp, result)``
12
+
13
+ It does NOT auto-mutate agents (too risky to rewrite 50+ classes blindly); it
14
+ returns a structured, machine-readable report so the issues can be tracked and
15
+ fixed deliberately. Run it with ``python -m patchi.core.ai.agent_audit``.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import inspect
21
+ import logging
22
+ from dataclasses import dataclass, field
23
+ from pathlib import Path
24
+ from typing import Any
25
+
26
+ _log = logging.getLogger("patchi.ai.agent_audit")
27
+
28
+ _STUB_MARKERS = (
29
+ "not implemented",
30
+ "notimplemented",
31
+ "placeholder",
32
+ "todo",
33
+ "fixme",
34
+ "initiated",
35
+ "coming soon",
36
+ "stub",
37
+ )
38
+
39
+
40
+ @dataclass
41
+ class AuditIssue:
42
+ agent: str
43
+ group: str
44
+ issue: str
45
+ severity: str # "high" | "medium" | "low"
46
+ evidence: str = ""
47
+
48
+
49
+ @dataclass
50
+ class AuditReport:
51
+ total_agents: int = 0
52
+ groups_scanned: list[str] = field(default_factory=list)
53
+ issues: list[AuditIssue] = field(default_factory=list)
54
+
55
+ @property
56
+ def by_severity(self) -> dict[str, int]:
57
+ out = {"high": 0, "medium": 0, "low": 0}
58
+ for i in self.issues:
59
+ out[i.severity] = out.get(i.severity, 0) + 1
60
+ return out
61
+
62
+ def to_dict(self) -> dict:
63
+ return {
64
+ "total_agents": self.total_agents,
65
+ "groups_scanned": self.groups_scanned,
66
+ "issue_count": len(self.issues),
67
+ "by_severity": self.by_severity,
68
+ "issues": [vars(i) for i in self.issues],
69
+ }
70
+
71
+
72
+ def _all_groups():
73
+ from patchi.core.agents.base import AgentGroup
74
+
75
+ return list(AgentGroup)
76
+
77
+
78
+ def audit(root: Path | None = None) -> AuditReport:
79
+ """Inspect all registered agents and return a structured report."""
80
+ report = AuditReport()
81
+ try:
82
+ import patchi.core.agents.fix_agents # noqa: F401
83
+ import patchi.core.agents.test_agents # noqa: F401
84
+ import patchi.core.security.security_agents # noqa: F401
85
+ except Exception as _exc:
86
+ _log.warning('audit failed: %s', _exc)
87
+
88
+ from patchi.core.agents.base import list_agents
89
+
90
+ for group in _all_groups():
91
+ report.groups_scanned.append(group.value)
92
+ for cls in list_agents(group):
93
+ report.total_agents += 1
94
+ _audit_class(cls, group.value, report)
95
+ return report
96
+
97
+
98
+ def _audit_class(cls: Any, group: str, report: AuditReport) -> None:
99
+ name = cls.__name__
100
+ try:
101
+ src = inspect.getsource(cls)
102
+ except (OSError, TypeError):
103
+ return
104
+
105
+ low = src.lower()
106
+
107
+ # 1. NotImplementedError
108
+ if "notimplementederror" in low and "raise notimplementederror" in low.replace(" ", ""):
109
+ report.issues.append(
110
+ AuditIssue(
111
+ name, group, "raises NotImplementedError", "high", "raise NotImplementedError"
112
+ )
113
+ )
114
+ return # definitive, stop here
115
+
116
+ # 2. Placeholder / stub markers
117
+ for marker in _STUB_MARKERS:
118
+ if marker in low:
119
+ report.issues.append(
120
+ AuditIssue(name, group, f"possible stub marker '{marker}'", "medium", marker)
121
+ )
122
+ break
123
+
124
+ # 3. Old-style _run signature
125
+ run_method = getattr(cls, "_run", None)
126
+ if run_method is not None and callable(run_method):
127
+ try:
128
+ sig = inspect.signature(run_method)
129
+ params = [p for p in sig.parameters if p != "self"]
130
+ # New style: _run(self, inp, result) -> None (2 params beyond self)
131
+ # Old style: _run(self, inp) -> AgentResult (1 param beyond self)
132
+ if len(params) == 1:
133
+ report.issues.append(
134
+ AuditIssue(
135
+ name,
136
+ group,
137
+ "old-style _run(self, inp) signature",
138
+ "low",
139
+ "expected _run(self, inp, result)",
140
+ )
141
+ )
142
+ except (ValueError, TypeError):
143
+ pass
144
+
145
+
146
+ def main() -> None:
147
+ rep = audit()
148
+ for _i in rep.issues:
149
+ pass
150
+
151
+
152
+ if __name__ == "__main__":
153
+ main()
@@ -0,0 +1,277 @@
1
+ """
2
+ Agent Profiler — self-profiling for latency, cost, and accuracy optimization.
3
+
4
+ Tracks per-agent execution metrics across scan cycles:
5
+ - Latency (wall time, p50/p95)
6
+ - Token cost (input/output tokens, dollar estimate)
7
+ - Accuracy (true-positive rate based on accept/reject feedback)
8
+ - Memory usage (peak RSS)
9
+
10
+ Feeds into the ModelRouter to prefer faster/cheaper agents when accuracy
11
+ is equivalent, and into the Coordinator to schedule agents intelligently.
12
+
13
+ All data persisted to .patchi/agent_profile.json.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import logging
20
+ import time
21
+ from contextlib import contextmanager
22
+ from dataclasses import asdict, dataclass
23
+ from pathlib import Path
24
+
25
+ _log = logging.getLogger("patchi.ai.agent_profiler")
26
+
27
+ _PROFILE_FILE = ".patchi/agent_profile.json"
28
+ _MAX_ENTRIES_PER_AGENT = 200
29
+
30
+
31
+ @dataclass
32
+ class AgentRun:
33
+ """One recorded execution of an agent."""
34
+
35
+ agent: str
36
+ start_time: float = 0.0
37
+ end_time: float = 0.0
38
+ wall_ms: float = 0.0
39
+ prompt_tokens: int = 0
40
+ completion_tokens: int = 0
41
+ cost_usd: float = 0.0
42
+ files_scanned: int = 0
43
+ findings_produced: int = 0
44
+ accepted: int = 0
45
+ rejected: int = 0
46
+ model_used: str = ""
47
+ peak_rss_mb: float = 0.0
48
+ error: str = ""
49
+
50
+ def to_dict(self) -> dict:
51
+ return asdict(self)
52
+
53
+ @classmethod
54
+ def from_dict(cls, d: dict) -> AgentRun:
55
+ return cls(**{k: v for k, v in d.items() if k in cls.__dataclass_fields__})
56
+
57
+
58
+ @dataclass
59
+ class AgentProfile:
60
+ """Aggregated profile for one agent across all recorded runs."""
61
+
62
+ agent: str
63
+ run_count: int = 0
64
+ total_wall_ms: float = 0.0
65
+ p50_wall_ms: float = 0.0
66
+ p95_wall_ms: float = 0.0
67
+ total_cost_usd: float = 0.0
68
+ total_findings: int = 0
69
+ total_accepted: int = 0
70
+ total_rejected: int = 0
71
+ accuracy: float = 0.5 # accept / (accept + reject), 0.5 when unknown
72
+ avg_findings_per_run: float = 0.0
73
+ most_used_model: str = ""
74
+ last_run: float = 0.0
75
+
76
+ def to_dict(self) -> dict:
77
+ return asdict(self)
78
+
79
+
80
+ def _load(root: Path) -> dict[str, list[dict]]:
81
+ path = root / _PROFILE_FILE
82
+ if not path.exists():
83
+ return {}
84
+ try:
85
+ return json.loads(path.read_text(encoding="utf-8"))
86
+ except Exception as exc:
87
+ _log.warning("Failed to load agent profile: %s", exc)
88
+ return {}
89
+
90
+
91
+ def _save(root: Path, data: dict[str, list[dict]]) -> None:
92
+ path = root / _PROFILE_FILE
93
+ path.parent.mkdir(parents=True, exist_ok=True)
94
+ tmp = path.with_suffix(".json.tmp")
95
+ tmp.write_text(json.dumps(data, indent=2), encoding="utf-8")
96
+ tmp.replace(path)
97
+
98
+
99
+ @contextmanager
100
+ def record_run(
101
+ root: Path,
102
+ agent: str,
103
+ *,
104
+ model: str = "",
105
+ files_scanned: int = 0,
106
+ ):
107
+ """Context manager that records an agent execution.
108
+
109
+ Usage::
110
+
111
+ with record_run(root, "auth_agent", model="gpt-4o-mini") as run:
112
+ findings = run_agent(...)
113
+ run.findings_produced = len(findings)
114
+ """
115
+ import resource
116
+
117
+ run = AgentRun(
118
+ agent=agent,
119
+ start_time=time.time(),
120
+ model_used=model,
121
+ files_scanned=files_scanned,
122
+ )
123
+ try:
124
+ yield run
125
+ except Exception as exc:
126
+ run.error = str(exc)[:200]
127
+ raise
128
+ finally:
129
+ run.end_time = time.time()
130
+ run.wall_ms = (run.end_time - run.start_time) * 1000
131
+ # Peak RSS (Linux/macOS only; returns 0 on Windows)
132
+ try:
133
+ usage = resource.getrusage(resource.RUSAGE_SELF)
134
+ run.peak_rss_mb = usage.ru_maxrss / 1024 # KB → MB
135
+ except Exception as _exc:
136
+ _log.warning('record_run failed: %s', _exc)
137
+ _persist_run(root, run)
138
+
139
+
140
+ def _persist_run(root: Path, run: AgentRun) -> None:
141
+ data = _load(root)
142
+ runs = data.setdefault(run.agent, [])
143
+ runs.append(run.to_dict())
144
+ # Trim to last N entries
145
+ data[run.agent] = runs[-_MAX_ENTRIES_PER_AGENT:]
146
+ _save(root, data)
147
+ _log.debug(
148
+ "Recorded %s: %.0fms, %d findings, $%.4f",
149
+ run.agent,
150
+ run.wall_ms,
151
+ run.findings_produced,
152
+ run.cost_usd,
153
+ )
154
+
155
+
156
+ def record_tokens(root: Path, agent: str, prompt_tokens: int, completion_tokens: int) -> None:
157
+ """Update the last run for an agent with token counts (call after LLM usage)."""
158
+ data = _load(root)
159
+ runs = data.get(agent, [])
160
+ if not runs:
161
+ return
162
+ last = runs[-1]
163
+ last["prompt_tokens"] = prompt_tokens
164
+ last["completion_tokens"] = completion_tokens
165
+ # Estimate cost from cost_tracker's per-model rates
166
+ model = last.get("model_used", "gpt-4o-mini")
167
+ try:
168
+ from patchi.core.ai.model_router import MODEL_PROFILES
169
+
170
+ profile = MODEL_PROFILES.get(model)
171
+ if profile:
172
+ last["cost_usd"] = (
173
+ prompt_tokens * profile.cost_per_1k_input / 1000
174
+ + completion_tokens * profile.cost_per_1k_output / 1000
175
+ )
176
+ except Exception as _exc:
177
+ _log.warning('record_tokens failed: %s', _exc)
178
+ _save(root, data)
179
+
180
+
181
+ def record_outcome(root: Path, agent: str, accepted: int, rejected: int) -> None:
182
+ """Update the last run for an agent with accept/reject counts."""
183
+ data = _load(root)
184
+ runs = data.get(agent, [])
185
+ if not runs:
186
+ return
187
+ last = runs[-1]
188
+ last["accepted"] = accepted
189
+ last["rejected"] = rejected
190
+ _save(root, data)
191
+
192
+
193
+ def get_profile(root: Path, agent: str) -> AgentProfile:
194
+ """Get aggregated profile for one agent."""
195
+ data = _load(root)
196
+ runs = [AgentRun.from_dict(r) for r in data.get(agent, [])]
197
+ if not runs:
198
+ return AgentProfile(agent=agent)
199
+
200
+ walls = sorted(r.wall_ms for r in runs)
201
+ n = len(walls)
202
+ total_acc = sum(r.accepted for r in runs)
203
+ total_rej = sum(r.rejected for r in runs)
204
+ total = total_acc + total_rej
205
+
206
+ # Most used model
207
+ models = [r.model_used for r in runs if r.model_used]
208
+ most_used = max(set(models), key=models.count) if models else ""
209
+
210
+ return AgentProfile(
211
+ agent=agent,
212
+ run_count=n,
213
+ total_wall_ms=sum(walls),
214
+ p50_wall_ms=walls[n // 2] if n else 0,
215
+ p95_wall_ms=walls[int(n * 0.95)] if n else 0,
216
+ total_cost_usd=sum(r.cost_usd for r in runs),
217
+ total_findings=sum(r.findings_produced for r in runs),
218
+ total_accepted=total_acc,
219
+ total_rejected=total_rej,
220
+ accuracy=total_acc / total if total >= 3 else 0.5,
221
+ avg_findings_per_run=sum(r.findings_produced for r in runs) / n,
222
+ most_used_model=most_used,
223
+ last_run=max(r.end_time for r in runs),
224
+ )
225
+
226
+
227
+ def get_all_profiles(root: Path) -> dict[str, AgentProfile]:
228
+ """Get profiles for all agents."""
229
+ data = _load(root)
230
+ return {agent: get_profile(root, agent) for agent in data}
231
+
232
+
233
+ def get_slowest_agents(root: Path, limit: int = 10) -> list[AgentProfile]:
234
+ """Return the slowest agents by p95 wall time."""
235
+ profiles = get_all_profiles(root)
236
+ ranked = sorted(profiles.values(), key=lambda p: -p.p95_wall_ms)
237
+ return ranked[:limit]
238
+
239
+
240
+ def get_least_accurate(root: Path, min_runs: int = 5) -> list[AgentProfile]:
241
+ """Return agents with the worst accuracy (above minimum sample size)."""
242
+ profiles = get_all_profiles(root)
243
+ ranked = sorted(
244
+ [p for p in profiles.values() if p.run_count >= min_runs],
245
+ key=lambda p: p.accuracy,
246
+ )
247
+ return ranked
248
+
249
+
250
+ def get_profile_summary(root: Path) -> dict:
251
+ """Summary for display."""
252
+ profiles = get_all_profiles(root)
253
+ if not profiles:
254
+ # Full key set — consumers (self-improvement dashboard) read these
255
+ # unconditionally, so the empty case must carry every key.
256
+ return {
257
+ "agents": 0,
258
+ "total_runs": 0,
259
+ "total_cost": 0,
260
+ "total_findings": 0,
261
+ "avg_accuracy": 0,
262
+ "slowest": [],
263
+ }
264
+ return {
265
+ "agents": len(profiles),
266
+ "total_runs": sum(p.run_count for p in profiles.values()),
267
+ "total_cost": round(sum(p.total_cost_usd for p in profiles.values()), 4),
268
+ "total_findings": sum(p.total_findings for p in profiles.values()),
269
+ "avg_accuracy": round(
270
+ sum(p.accuracy for p in profiles.values() if p.run_count >= 3)
271
+ / max(1, sum(1 for p in profiles.values() if p.run_count >= 3)),
272
+ 3,
273
+ ),
274
+ "slowest": [
275
+ {"agent": p.agent, "p95_ms": round(p.p95_wall_ms)} for p in get_slowest_agents(root, 5)
276
+ ],
277
+ }