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,393 @@
1
+ """
2
+ BrainContext — the single bridge that connects all brain knowledge.
3
+
4
+ Assembles:
5
+ - Enriched context (AI project understanding)
6
+ - Project insight (README, package.json, tech stack)
7
+ - Layer summaries (architectural knowledge)
8
+ - Reasoning engine (impact analysis, explain, why)
9
+ - Import graph (dependencies, circular deps)
10
+ - Active security domains
11
+ - Recent findings (for false-positive learning)
12
+
13
+ Used by:
14
+ - DetectionPipeline: context-aware finding classification
15
+ - Chat: full brain state injection
16
+ - ReasoningEngine: enriched question answering
17
+ - Web dashboard: brain state for all pages
18
+
19
+ Design: Lazy-loaded, cacheable, offline-safe.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import logging
25
+ from dataclasses import dataclass, field
26
+ from datetime import UTC
27
+ from pathlib import Path
28
+
29
+ _log = logging.getLogger("patchi.brain.context")
30
+
31
+
32
+ @dataclass
33
+ class BrainContext:
34
+ """Assembled brain knowledge for a project scan."""
35
+
36
+ root: Path = field(default_factory=lambda: Path("."))
37
+
38
+ # Enriched context (from enriched_context.py)
39
+ enriched: dict = field(default_factory=dict)
40
+ purpose: str = ""
41
+ domain: str = ""
42
+ domain_confidence: float = 0.0
43
+ tech_stack: list[str] = field(default_factory=list)
44
+ critical_dirs: list[dict] = field(default_factory=list)
45
+ top_risks: list[dict] = field(default_factory=list)
46
+ scan_focus: str = ""
47
+
48
+ # Project insight (from project_reader.py)
49
+ project_name: str = ""
50
+ project_type: str = ""
51
+ framework: str = ""
52
+ language: str = ""
53
+ entry_points: list[str] = field(default_factory=list)
54
+ readme_summary: str = ""
55
+
56
+ # Layer summaries (from layered_brain.py)
57
+ layers: dict = field(default_factory=dict)
58
+ layer_count: int = 0
59
+
60
+ # Import graph
61
+ import_graph: dict = field(default_factory=dict)
62
+ circular_deps: list = field(default_factory=list)
63
+ dead_files: list[str] = field(default_factory=list)
64
+
65
+ # Active domains
66
+ active_domains: list[str] = field(default_factory=list)
67
+
68
+ # Recent findings (for FP learning)
69
+ recent_findings: list[dict] = field(default_factory=list)
70
+ known_fps: set = field(default_factory=set)
71
+
72
+ # File corpus (for code context)
73
+ file_count: int = 0
74
+ file_criticality_ranking: list[dict] = field(default_factory=list)
75
+ language_breakdown: dict = field(default_factory=dict)
76
+ route_count: int = 0
77
+
78
+ # Health
79
+ health_score: float = 0.0
80
+ health_grade: str = "?"
81
+
82
+ # Build metadata
83
+ built_at: str = ""
84
+ build_duration_ms: int = 0
85
+ source: str = "heuristic"
86
+
87
+ def is_loaded(self) -> bool:
88
+ """Whether the context has been populated with real data."""
89
+ return self.purpose or self.project_name or self.file_count > 0
90
+
91
+ def get_summary(self) -> str:
92
+ """One-paragraph summary for AI prompts."""
93
+ parts = []
94
+ if self.purpose:
95
+ parts.append(self.purpose)
96
+ if self.project_type:
97
+ parts.append(f"Project type: {self.project_type}")
98
+ if self.framework:
99
+ parts.append(f"Framework: {self.framework}")
100
+ if self.language:
101
+ parts.append(f"Language: {self.language}")
102
+ if self.file_count:
103
+ parts.append(f"{self.file_count} files")
104
+ if self.route_count:
105
+ parts.append(f"{self.route_count} routes")
106
+ if self.active_domains:
107
+ parts.append(f"Security domains: {', '.join(self.active_domains[:5])}")
108
+ if self.top_risks:
109
+ parts.append(f"Top risks: {'; '.join(r.get('risk', '') for r in self.top_risks[:3])}")
110
+ return ". ".join(parts) + "." if parts else "No project context available."
111
+
112
+ def get_finding_context(self, file_path: str, finding_type: str, message: str) -> dict:
113
+ """Build contextual information for a specific finding.
114
+
115
+ Returns a dict with:
116
+ - is_test_fixture: True if file is in tests/
117
+ - is_docs: True if file is documentation
118
+ - is_generated: True if file appears generated
119
+ - project_relevance: how relevant this finding is to the project
120
+ - related_layers: which architectural layers are affected
121
+ - domain_matches: which security domains apply
122
+ """
123
+ result = {
124
+ "is_test_fixture": False,
125
+ "is_docs": False,
126
+ "is_generated": False,
127
+ "project_relevance": "unknown",
128
+ "related_layers": [],
129
+ "domain_matches": [],
130
+ }
131
+
132
+ fp = file_path.lower() if file_path else ""
133
+
134
+ # Test fixture detection
135
+ if any(seg in fp for seg in ("test", "spec", "fixture", "mock", "__test__")):
136
+ result["is_test_fixture"] = True
137
+ result["project_relevance"] = "low"
138
+
139
+ # Documentation detection
140
+ if any(seg in fp for seg in (".md", ".rst", ".txt", "doc", "readme")):
141
+ result["is_docs"] = True
142
+ result["project_relevance"] = "low"
143
+
144
+ # Generated code detection
145
+ _gen_segs = (".generated", "auto-generated", "__pycache__", "node_modules")
146
+ if any(seg in fp for seg in _gen_segs):
147
+ result["is_generated"] = True
148
+ result["project_relevance"] = "low"
149
+
150
+ # Relevance scoring based on critical dirs
151
+ if self.critical_dirs:
152
+ for cd in self.critical_dirs:
153
+ dir_path = cd.get("dir", "").lower()
154
+ if dir_path and dir_path in fp:
155
+ result["project_relevance"] = "high"
156
+ break
157
+
158
+ # Layer matching
159
+ if self.layers:
160
+ for layer_name, layer_data in self.layers.items():
161
+ files = layer_data.get("files", []) if isinstance(layer_data, dict) else []
162
+ if any(file_path.endswith(f) or f in file_path for f in files):
163
+ result["related_layers"].append(layer_name)
164
+
165
+ # Domain matching (lightweight keyword check)
166
+ if self.active_domains:
167
+ msg_lower = message.lower()
168
+ type_lower = finding_type.lower()
169
+ for domain in self.active_domains:
170
+ domain_words = domain.replace("-", " ").split()
171
+ if any(w in msg_lower or w in type_lower for w in domain_words if len(w) > 3):
172
+ result["domain_matches"].append(domain)
173
+
174
+ return result
175
+
176
+ def get_context_for_prompt(self, max_chars: int = 4000) -> str:
177
+ """Build a context block for AI prompts (chat, reasoning, detection)."""
178
+ lines = []
179
+
180
+ # Project identity
181
+ if self.project_name:
182
+ lines.append(f"PROJECT: {self.project_name} ({self.project_type or 'unknown'})")
183
+ if self.purpose:
184
+ lines.append(f"PURPOSE: {self.purpose}")
185
+ if self.framework or self.language:
186
+ lines.append(f"STACK: {self.framework or ''} {self.language or ''}")
187
+ if self.tech_stack:
188
+ lines.append(f"TECH: {', '.join(self.tech_stack[:8])}")
189
+
190
+ # Stats
191
+ lines.append(
192
+ f"FILES: {self.file_count} | ROUTES: {self.route_count}"
193
+ f" | HEALTH: {self.health_score}/100"
194
+ )
195
+
196
+ # Critical dirs
197
+ if self.critical_dirs:
198
+ lines.append("CRITICAL_DIRS:")
199
+ for cd in self.critical_dirs[:4]:
200
+ lines.append(f" - {cd.get('dir', '?')}: {cd.get('why', '?')}")
201
+
202
+ # Risks
203
+ if self.top_risks:
204
+ lines.append("TOP_RISKS:")
205
+ for r in self.top_risks[:3]:
206
+ lines.append(f" - {r.get('risk', '?')}: {r.get('why', '?')}")
207
+
208
+ # Layers
209
+ if self.layers:
210
+ lines.append(f"LAYERS: {len(self.layers)} architectural layers")
211
+ for name in list(self.layers.keys())[:6]:
212
+ lines.append(f" - {name}")
213
+
214
+ # Domains
215
+ if self.active_domains:
216
+ lines.append(f"SECURITY_DOMAINS: {', '.join(self.active_domains[:8])}")
217
+
218
+ # Scan focus
219
+ if self.scan_focus:
220
+ lines.append(f"SCAN_FOCUS: {self.scan_focus}")
221
+
222
+ result = "\n".join(lines)
223
+ if len(result) > max_chars:
224
+ result = result[:max_chars] + "\n... (truncated)"
225
+ return result
226
+
227
+
228
+ def build_brain_context(root: Path, config: dict | None = None) -> BrainContext:
229
+ """Build a BrainContext from all available brain sources.
230
+
231
+ This is the main entry point. It assembles context from:
232
+ 1. brain.json (enriched context, layers, file count, etc.)
233
+ 2. project_reader (README, package.json, tech stack)
234
+ 3. memory (recent findings, known FPs)
235
+ 4. domain_loader (active domains)
236
+ """
237
+ import time as _time
238
+ t0 = _time.monotonic()
239
+ ctx = BrainContext(root=root)
240
+
241
+
242
+ # 1. Load brain.json (enriched context + scan results)
243
+ try:
244
+ from patchi.core import memory as mem
245
+ brain = mem.get_brain(root)
246
+ if brain:
247
+ ctx.file_count = brain.get("file_count", 0)
248
+ ctx.route_count = brain.get("route_count", 0)
249
+ ctx.framework = brain.get("framework", "")
250
+ ctx.language_breakdown = brain.get("languages", {})
251
+ hs = brain.get("health_score")
252
+ ctx.health_score = (
253
+ hs.get("total", 0) if isinstance(hs, dict) else (hs or 0)
254
+ )
255
+ ctx.health_grade = brain.get("health_grade", "?")
256
+
257
+ # Enriched context
258
+ ec = brain.get("enriched_context", {})
259
+ if ec:
260
+ ctx.enriched = ec
261
+ ctx.purpose = ec.get("purpose_1sent", "")
262
+ ctx.domain = ec.get("domain", "")
263
+ ctx.domain_confidence = ec.get("domain_confidence", 0)
264
+ ctx.tech_stack = ec.get("tech_stack_confirmed", [])
265
+ ctx.critical_dirs = ec.get("critical_dirs_reasoned", [])
266
+ ctx.top_risks = ec.get("top_risks", [])
267
+ ctx.scan_focus = ec.get("scan_focus", "")
268
+ ctx.source = ec.get("source", "unknown")
269
+
270
+ # Layers
271
+ layers = brain.get("layers", {})
272
+ if layers and isinstance(layers, dict):
273
+ ctx.layers = layers.get("layers", layers)
274
+ ctx.layer_count = len(ctx.layers)
275
+
276
+ # Project context
277
+ pc = brain.get("project_context", {})
278
+ if pc:
279
+ ctx.project_name = pc.get("name", "")
280
+ ctx.project_type = pc.get("project_type", "")
281
+ ctx.entry_points = pc.get("entry_points", [])
282
+ except Exception as exc:
283
+ _log.debug("brain.json load failed: %s", exc)
284
+
285
+ # 2. Project reader (README, package.json, etc.)
286
+ try:
287
+ from patchi.core.brain.project_reader import read_project_insight
288
+ insight = read_project_insight(root)
289
+ if insight:
290
+ ctx.project_name = ctx.project_name or insight.name
291
+ ctx.project_type = ctx.project_type or insight.project_type
292
+ ctx.framework = ctx.framework or insight.framework
293
+ ctx.language = insight.language
294
+ ctx.entry_points = ctx.entry_points or insight.entry_points
295
+ ctx.readme_summary = insight.readme_summary
296
+ if insight.tech_stack and not ctx.tech_stack:
297
+ ctx.tech_stack = insight.tech_stack
298
+ except Exception as exc:
299
+ _log.debug("project_reader failed: %s", exc)
300
+
301
+ # 2b. File criticality ranking via body_tags + understander
302
+ try:
303
+ from patchi.core.brain.body_tags import build_body_tags
304
+ file_infos = []
305
+ try:
306
+ from patchi.core.agents.discovery import discover_project
307
+ disc = discover_project(root)
308
+ file_infos = getattr(disc, 'file_infos', [])
309
+ except Exception as _exc:
310
+ _log.debug('suppressed: %s', _exc)
311
+ body_tags = build_body_tags(root, file_infos)
312
+ if body_tags:
313
+ ranked = sorted(
314
+ body_tags.items(),
315
+ key=lambda kv: (-int(kv[1].get("score", 0)), -int(kv[1].get("fan_in", 0)), kv[0]),
316
+ )
317
+ ctx.file_criticality_ranking = [
318
+ {"path": path, "score": tag.get("score", 0), "role": tag.get("role", ""),
319
+ "system": tag.get("system", ""), "criticality": tag.get("criticality", "low")}
320
+ for path, tag in ranked[:30]
321
+ ]
322
+ except Exception as exc:
323
+ _log.debug("body_tags ranking failed: %s", exc)
324
+
325
+ # 3. Active domains
326
+ try:
327
+ from patchi.core.security.domain_loader import DomainLoader
328
+ dl = DomainLoader(root)
329
+ dl._load_all()
330
+ ctx.active_domains = list(dl._domains.keys())[:20]
331
+ except Exception as exc:
332
+ _log.debug("domain_loader failed: %s", exc)
333
+
334
+ # 4. Known false positives
335
+ try:
336
+ fp_file = root / ".patchi/memory/known_false_positives.json"
337
+ if fp_file.exists():
338
+ import json
339
+ fps = json.loads(fp_file.read_text(encoding="utf-8"))
340
+ if isinstance(fps, list):
341
+ ctx.known_fps = {tuple(fp) if isinstance(fp, list) else fp for fp in fps}
342
+ elif isinstance(fps, dict):
343
+ ctx.known_fps = set(fps.keys())
344
+ except Exception as _exc:
345
+ _log.debug('suppressed: %s', _exc)
346
+
347
+ # 5. Recent findings
348
+ try:
349
+ from patchi.core import memory as mem
350
+ scan_results = mem.get_scan_results(root)
351
+ for _scanner, data in scan_results.items():
352
+ for finding in data.get("findings", [])[-50:]:
353
+ if isinstance(finding, dict):
354
+ ctx.recent_findings.append(finding)
355
+ except Exception as _exc:
356
+ _log.debug('suppressed: %s', _exc)
357
+
358
+ from datetime import datetime as _dtnow
359
+ ctx.built_at = _dtnow.now(UTC).isoformat()
360
+ ctx.build_duration_ms = int((_time.monotonic() - t0) * 1000)
361
+
362
+ _log.info(
363
+ "BrainContext built in %dms: %d files, %d domains, %d layers, purpose=%s",
364
+ ctx.build_duration_ms,
365
+ ctx.file_count,
366
+ len(ctx.active_domains),
367
+ ctx.layer_count,
368
+ ctx.purpose[:50] if ctx.purpose else "?",
369
+ )
370
+
371
+ return ctx
372
+
373
+
374
+ # ── Singleton cache ────────────────────────────────────────────────────────────
375
+ _cached: BrainContext | None = None
376
+ _cached_root: Path | None = None
377
+
378
+
379
+ def get_brain_context(root: Path, config: dict | None = None, force: bool = False) -> BrainContext:
380
+ """Get (or build and cache) the BrainContext for a project."""
381
+ global _cached, _cached_root
382
+ if _cached is not None and _cached_root == root.resolve() and not force:
383
+ return _cached
384
+ _cached = build_brain_context(root, config)
385
+ _cached_root = root.resolve()
386
+ return _cached
387
+
388
+
389
+ def invalidate_brain_context() -> None:
390
+ """Clear the cached BrainContext (call after a scan completes)."""
391
+ global _cached, _cached_root
392
+ _cached = None
393
+ _cached_root = None