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,445 @@
1
+ """
2
+ `p dev` — Developer utilities, testing docs, and diagnostics.
3
+
4
+ Usage:
5
+ p dev — show all development info
6
+ p dev info — show project health, config, security status
7
+ p dev test — show testing tool documentation
8
+ p dev playwright — show Playwright/browser testing docs
9
+ p dev security — show security pipeline status
10
+ p dev docs — show all CLI commands reference
11
+ p dev hook — install pre-commit hook (ruff + pytest + scan --changed)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+
18
+ from rich.console import Console
19
+ from rich.panel import Panel
20
+ from rich.table import Table
21
+
22
+ from patchi.cli.console import con
23
+ from patchi.core import config as cfg
24
+ from patchi.core.agents.base import AgentGroup, list_agents
25
+
26
+ _log = logging.getLogger("patchi.cli.dev_cmd")
27
+
28
+
29
+ def run(action: str | None = None, verbose: bool = False, json_output: bool = False, strict: bool = False, auto_fix: bool = False, fast: bool = False) -> None:
30
+
31
+ if action == "test":
32
+ _show_test_docs(con)
33
+ elif action == "playwright":
34
+ _show_playwright_docs(con)
35
+ elif action == "security":
36
+ _show_security_status(con)
37
+ elif action == "docs":
38
+ _show_cli_reference(con)
39
+ elif action == "hook":
40
+ _install_hook(con, strict=strict, auto_fix=auto_fix)
41
+ elif action == "check":
42
+ from patchi.cli.commands.dev_check_cmd import run as check_run
43
+ check_run(json_output=json_output, fast=fast)
44
+ else:
45
+ _show_dev_overview(con, verbose)
46
+
47
+
48
+ def _show_dev_overview(con: Console, verbose: bool) -> None:
49
+ con.print()
50
+ con.print(Panel.fit("[bold cyan]Patchi Developer Console[/bold cyan]", border_style="cyan"))
51
+ con.print()
52
+
53
+ try:
54
+ root = cfg.require_project_root()
55
+ config = cfg.load(root)
56
+ except Exception as e:
57
+ _log.warning("_show_dev_overview failed: %s", e)
58
+ root = None
59
+ config = {}
60
+
61
+ info = Table.grid(padding=(0, 2))
62
+ info.add_column()
63
+ info.add_column()
64
+
65
+ info.add_row("[bold]Project Root:[/bold]", str(root or "Not initialized"))
66
+ mode = config.get("mode", "unknown")
67
+ info.add_row("[bold]Mode:[/bold]", mode)
68
+ pipeline_enabled = config.get("pipeline", {}).get("enabled", False)
69
+ info.add_row("[bold]Security Pipeline:[/bold]", "ENABLED" if pipeline_enabled else "DISABLED")
70
+ interceptor_enabled = config.get("pipeline", {}).get("interceptor", {}).get("enabled", False)
71
+ info.add_row(
72
+ "[bold]Request Interceptor:[/bold]", "ENABLED" if interceptor_enabled else "DISABLED"
73
+ )
74
+ ai_keys = config.get("ai", {}).get("keys", [])
75
+ info.add_row("[bold]AI Keys:[/bold]", f"{len(ai_keys)} configured")
76
+ info.add_row("[bold]Agent Queue:[/bold]", config.get("queue_mode", "single"))
77
+ info.add_row("[bold]Version:[/bold]", _get_version())
78
+ con.print(info)
79
+ con.print()
80
+
81
+ _show_quick_commands(con)
82
+ con.print()
83
+ con.print(
84
+ "[dim]Run [bold]p dev test[/bold] for testing docs, [bold]p dev security[/bold] for security status, [bold]p dev docs[/bold] for all commands[/dim]"
85
+ )
86
+
87
+
88
+ def _show_quick_commands(con: Console) -> None:
89
+ t = Table(title="Quick Reference", box=None)
90
+ t.add_column("Command", style="cyan")
91
+ t.add_column("Description")
92
+ t.add_row("p dev test", "Show all testing tools and commands")
93
+ t.add_row("p dev playwright", "Show Playwright/browser testing docs")
94
+ t.add_row("p dev security", "Show security pipeline status")
95
+ t.add_row("p dev docs", "Show all CLI commands reference")
96
+ t.add_row("p scan", "Run a full scan")
97
+ t.add_row("p scan --pipeline", "Run scan with full security pipeline")
98
+ t.add_row("p security all", "Run all 34 security agents")
99
+ t.add_row("p test full", "Run all test agents")
100
+ t.add_row("p test smoke", "Quick smoke test (buttons + layout + a11y)")
101
+ t.add_row("p test e2e", "AI-generated Playwright E2E tests")
102
+ t.add_row("p web", "Launch the Patchi web dashboard")
103
+ t.add_row("p doctor", "Validate setup and dependencies")
104
+ t.add_row("p audit", "Full project audit in one shot")
105
+ con.print(t)
106
+
107
+
108
+ def _show_test_docs(con: Console) -> None:
109
+ con.print()
110
+ con.print(
111
+ Panel.fit("[bold yellow]Testing Tools Reference[/bold yellow]", border_style="yellow")
112
+ )
113
+ con.print()
114
+
115
+ t = Table(title="Test Commands")
116
+ t.add_column("Command", style="cyan")
117
+ t.add_column("Type")
118
+ t.add_column("Description")
119
+
120
+ t.add_row("p test", "default", "Run unit + regression tests")
121
+ t.add_row("p test unit", "unit", "Run pytest/unittest/jest/mocha tests via UnitTestAgent")
122
+ t.add_row(
123
+ "p test browser", "browser", "Run Playwright critical-flow tests via BrowserTestAgent"
124
+ )
125
+ t.add_row("p test e2e", "e2e", "AI-generated end-to-end Playwright tests via E2EFlowAgent")
126
+ t.add_row("p test buttons", "buttons", "Button/form/interaction tests via UIButtonAgent")
127
+ t.add_row(
128
+ "p test layout",
129
+ "layout",
130
+ "Responsive layout tests at 320/768/1024/1440px via UILayoutAgent",
131
+ )
132
+ t.add_row(
133
+ "p test accessibility",
134
+ "accessibility",
135
+ "WCAG a11y via axe-core injection via UIAccessibilityAgent",
136
+ )
137
+ t.add_row("p test visual", "visual", "Screenshot comparison at 3 viewports via VisualRegressionAgent")
138
+ t.add_row("p test api", "api", "OpenAPI/JSON Schema contract tests via APIContractAgent")
139
+ t.add_row("p test stress", "stress", "Locust load testing via StressTestAgent")
140
+ t.add_row(
141
+ "p test security",
142
+ "security",
143
+ "Route-specific security pytest generation via SecurityTestAgent",
144
+ )
145
+ t.add_row("p test regression", "regression", "Snapshot-based regression tests via RegressionAgent")
146
+ t.add_row("p test smoke", "smoke", "Quick smoke: buttons + layout + accessibility")
147
+ t.add_row("p test full", "full", f"ALL test agents ({len(list_agents(AgentGroup.TEST))} agents)")
148
+ t.add_row("p test generate", "generate", "AI generates a full test suite")
149
+ t.add_row("p test report", "report", "Show test run history (last 50)")
150
+ t.add_row("p test config show", "config", "Show test configuration")
151
+ t.add_row("p test config set <k> <v>", "config", "Set a config value")
152
+ t.add_row("p security browsertest", "security", "Security-focused Playwright browser tests")
153
+
154
+ con.print(t)
155
+ con.print()
156
+
157
+ t2 = Table(title="Test Agents (12 total)")
158
+ t2.add_column("Agent", style="green")
159
+ t2.add_column("File")
160
+ t2.add_column("Framework")
161
+
162
+ t2.add_row("UnitTestAgent", "unit_test_agent.py", "pytest / jest / mocha")
163
+ t2.add_row("BrowserTestAgent", "browser_test_agent.py", "Playwright")
164
+ t2.add_row("E2EFlowAgent", "e2e_flow_agent.py", "Playwright + AI")
165
+ t2.add_row("UIButtonAgent", "ui_button_agent.py", "Playwright")
166
+ t2.add_row("UILayoutAgent", "ui_layout_agent.py", "Playwright")
167
+ t2.add_row("UIAccessibilityAgent", "ui_accessibility_agent.py", "Playwright + axe-core")
168
+ t2.add_row("VisualRegressionAgent", "visual_regression_agent.py", "Playwright screenshots")
169
+ t2.add_row("AccessibilityAgent", "accessibility_agent.py", "Playwright + axe-core")
170
+ t2.add_row("APIContractAgent", "api_contract_agent.py", "OpenAPI / JSON Schema")
171
+ t2.add_row("RegressionAgent", "regression_agent.py", "Snapshot baselines")
172
+ t2.add_row("StressTestAgent", "stress_test_agent.py", "Locust")
173
+ t2.add_row("SecurityTestAgent", "security_test_agent.py", "pytest generation")
174
+
175
+ con.print(t2)
176
+ con.print()
177
+
178
+ t3 = Table(title="Security Tester", box=None)
179
+ t3.add_column("Tool", style="red")
180
+ t3.add_column("Description")
181
+ t3.add_row("BrowserTesterAgent (security)", "Playwright auth bypass / XSS / SQLi testing")
182
+ con.print(t3)
183
+
184
+
185
+ def _show_playwright_docs(con: Console) -> None:
186
+ con.print()
187
+ con.print(
188
+ Panel.fit(
189
+ "[bold magenta]Playwright / Browser Testing Reference[/bold magenta]",
190
+ border_style="magenta",
191
+ )
192
+ )
193
+ con.print()
194
+
195
+ t = Table(title="Playwright Test Types")
196
+ t.add_column("Command", style="cyan")
197
+ t.add_column("What It Tests")
198
+ t.add_column("Viewports")
199
+
200
+ t.add_row("p test browser", "Critical flows: login, forms, navigation, API calls", "N/A")
201
+ t.add_row("p test e2e", "AI-generated full user flows", "N/A")
202
+ t.add_row("p test buttons", "Buttons, forms, hover/focus, keyboard, disabled states", "N/A")
203
+ t.add_row(
204
+ "p test layout",
205
+ "Responsive design, overflow, overlap, touch targets",
206
+ "320 / 768 / 1024 / 1440",
207
+ )
208
+ t.add_row("p test accessibility", "WCAG: contrast, alt text, labels, ARIA, landmarks", "N/A")
209
+ t.add_row("p test visual", "Screenshot diff detection", "375 / 768 / 1440")
210
+ t.add_row("p security browsertest", "Auth bypass, XSS injection, SQLi injection", "N/A")
211
+
212
+ con.print(t)
213
+ con.print()
214
+
215
+ con.print("[bold]Playwright Browsers:[/bold]")
216
+ con.print(" Playwright is a core dependency (playwright>=1.40 in pyproject.toml)")
217
+ con.print(" Browser binaries must be installed separately:")
218
+ con.print()
219
+ con.print(" [bold]p npm playwright install chromium[/bold] — or —")
220
+ con.print(" [bold]playwright install chromium[/bold] — in activated venv")
221
+ con.print()
222
+ con.print("[dim]All Playwright agents gracefully skip if Playwright is not installed.[/dim]")
223
+ con.print()
224
+
225
+ con.print("[bold]Web UI Events for Test Agents:[/bold]")
226
+ con.print(" test.suite.started — When a test run begins")
227
+ con.print(" test.case.passed — Individual test passed")
228
+ con.print(" test.case.failed — Individual test failed (screenshot on fail)")
229
+ con.print(" test.browser.flow_started — Browser flow started")
230
+ con.print(" test.browser.step_passed — Browser step passed")
231
+ con.print(" test.browser.step_failed — Browser step failed")
232
+ con.print(" test.stress.update — Load test stats")
233
+ con.print(" test.stress.break_found — Load test breakpoint")
234
+ con.print()
235
+ con.print("[dim]Open [bold]p web[/bold] and watch the dashboard while tests run![/dim]")
236
+
237
+
238
+ def _show_security_status(con: Console) -> None:
239
+ con.print()
240
+ con.print(Panel.fit("[bold red]Security Pipeline Status[/bold red]", border_style="red"))
241
+ con.print()
242
+
243
+ try:
244
+ root = cfg.require_project_root()
245
+ config = cfg.load(root)
246
+ except Exception as e:
247
+ _log.warning("_show_security_status: %s", e)
248
+ root = None
249
+ config = {}
250
+
251
+ pipeline = config.get("pipeline", {})
252
+ interceptor = pipeline.get("interceptor", {})
253
+ ai_keys = config.get("ai", {}).get("keys", [])
254
+
255
+ t = Table(box=None)
256
+ t.add_column("Component", style="cyan")
257
+ t.add_column("Status")
258
+ t.add_column("Detail")
259
+
260
+ t.add_row(
261
+ "Security Pipeline",
262
+ "ENABLED" if pipeline.get("enabled") else "DISABLED",
263
+ "DetectionPipeline + ConfidenceGate + Layer2Orchestrator + DefenseLayer",
264
+ )
265
+ t.add_row(
266
+ "Request Interceptor",
267
+ "ENABLED" if interceptor.get("enabled") else "DISABLED",
268
+ f"ASGI middleware, threshold={interceptor.get('block_threshold', 0.7)}, rate={interceptor.get('rate_limit', 100)}/min",
269
+ )
270
+ t.add_row(
271
+ "Security Agents",
272
+ f"{len(list_agents(AgentGroup.SECURITY))} agents",
273
+ "All registered via @register decorator",
274
+ )
275
+ t.add_row("ConfidenceGate", "Active", "Routes findings: defend / ai_analyze / human_review / discard")
276
+ t.add_row(
277
+ "Layer2 AI",
278
+ "Active" if ai_keys else "No AI keys",
279
+ "Batches medium-confidence findings for AI confirmation",
280
+ )
281
+ t.add_row("DefenseLayer", "Active", "Creates patches / blocks IPs / rotates secrets / escalates")
282
+ t.add_row("RiskGate", "Always active", "Enforces mode, no-touch paths, quiet hours, secrets gate")
283
+ t.add_row("Sigma Engine", "Standby", "Loaded from .patchi/sigma/ (if rules exist)")
284
+ t.add_row("SecretsGuard", "Always active", "Gate-checks proposed code for secrets before apply")
285
+
286
+ con.print(t)
287
+ con.print()
288
+
289
+ con.print("[bold]Security Commands:[/bold]")
290
+ con.print(" p security all — Run all 34 security scanners")
291
+ con.print(
292
+ " p security <type> — Run specific security scan (sqli, xss, jwt, crypto, etc.)"
293
+ )
294
+ con.print(" p security report — Show correlated security report")
295
+ con.print(" p security browsertest — Run Playwright security browser tests")
296
+ con.print(" p scan --pipeline — Full scan + security pipeline + auto-defense")
297
+ con.print(" p audit — Full project audit in one shot")
298
+ con.print()
299
+ con.print("[bold]Defense Actions:[/bold]")
300
+ con.print(" fix_code — Creates Patch, passes RiskGate, applies if allowed")
301
+ con.print(" update_dependency — Runs pip/npm update + patches manifest")
302
+ con.print(" block_ip — Persists to .patchi/blocked_ips.json + iptables")
303
+ con.print(" rotate_secret — Generates 256-bit secret, replaces in .env")
304
+ con.print(" patch_config — Edits config files with known-good values")
305
+ con.print(" auth_middleware — Adds auth middleware/decorator templates")
306
+ con.print(" invalidate_session — Queues to .patchi/invalidate_sessions.json")
307
+ con.print(" suspend_account — Queues to .patchi/suspend_accounts.json")
308
+ con.print(" block_ws_origin — Persists to .patchi/blocked_ws_origins.json")
309
+
310
+
311
+ def _show_cli_reference(con: Console) -> None:
312
+ con.print()
313
+ con.print(
314
+ Panel.fit(
315
+ "[bold green]Patchi CLI Reference — All Commands[/bold green]", border_style="green"
316
+ )
317
+ )
318
+ con.print()
319
+
320
+ t = Table(box=None)
321
+ t.add_column("Command", style="cyan", width=20)
322
+ t.add_column("Description")
323
+ t.add_column("File")
324
+
325
+ cmds = [
326
+ ("p init", "Initialize .patchi in a project", "init.py (436 lines)"),
327
+ ("p scan", "Run scanner agents", "scan_cmd.py (947 lines)"),
328
+ ("p status", "Show project health overview", "status_cmd.py (167 lines)"),
329
+ ("p watch", "Watch mode — auto-rescan on file changes", "watch_cmd.py (109 lines)"),
330
+ ("p doctor", "Validate setup, check deps, test AI", "doctor_cmd.py (386 lines)"),
331
+ ("p fix", "Auto-fix findings", "fix_cmd.py (374 lines)"),
332
+ ("p review", "Review pending patches", "review_cmd.py (225 lines)"),
333
+ ("p patch", "Manage patches (list/show/apply/reject)", "patch_cmd.py (215 lines)"),
334
+ ("p undo / redo / rollback", "Undo/redo/rollback patches", "undo_cmd.py (233 lines)"),
335
+ (
336
+ "p test",
337
+ f"Run test agents ({len(list_agents(AgentGroup.TEST))} types)",
338
+ "test_cmd.py (699 lines)",
339
+ ),
340
+ (
341
+ "p security",
342
+ f"Run security agents ({len(list_agents(AgentGroup.SECURITY))} types)",
343
+ "security_cmd.py (538 lines)",
344
+ ),
345
+ ("p memory", "Show/manage brain memory", "memory_cmd.py (219 lines)"),
346
+ ("p queue", "Manage agent queue", "queue_cmd.py (154 lines)"),
347
+ ("p mode", "Set confirm/auto/autopilot mode", "mode_cmd.py (78 lines)"),
348
+ ("p restrict", "Add/remove path restrictions", "restrict_cmd.py (128 lines)"),
349
+ ("p settings", "Show/edit settings", "inline in main.py"),
350
+ ("p key", "Manage API keys (10 providers)", "key_cmd.py (505 lines)"),
351
+ ("p ai", "AI status, test, horde management", "ai_cmd.py (205 lines)"),
352
+ ("p model", "Set/list AI models", "model_cmd.py (205 lines)"),
353
+ ("p access", "Manage dev access tokens", "inline in main.py"),
354
+ ("p notify", "Notification channels", "notify_cmd.py (213 lines)"),
355
+ ("p agents", "List/status/reset agents", "agents_cmd.py (185 lines)"),
356
+ ("p hosted", "Hosted mode management", "hosted_cmd.py (957 lines)"),
357
+ ("p report", "Export reports (JSON/HTML/markdown)", "report_cmd.py (414 lines)"),
358
+ ("p chat", "Interactive AI chat", "chat_cmd.py (134 lines)"),
359
+ ("p web", "Launch web dashboard", "web_cmd.py (102 lines)"),
360
+ ("p explain", "Explain a finding", "explain_cmd.py (330 lines)"),
361
+ ("p blast", "Blast radius analysis", "blast_cmd.py (318 lines)"),
362
+ ("p scan", "Scan project and auto-generate BRAIN.md", "scan_cmd.py"),
363
+ ("p trend", "Health quality trends", "trend_cmd.py (298 lines)"),
364
+ ("p blame", "Git blame for a file", "blame_cmd.py (52 lines)"),
365
+ ("p log", "Git changelog", "log_cmd.py (59 lines)"),
366
+ ("p deps", "Supply chain security scan", "deps_cmd.py (79 lines)"),
367
+ ("p audit", "Full project audit in one shot", "audit_cmd.py (381 lines)"),
368
+ ("p learn", "Learn project conventions", "learn_cmd.py (375 lines)"),
369
+ ("p dev", "Developer utilities (this command)", "dev_cmd.py"),
370
+ ]
371
+
372
+ for cmd, desc, src in cmds:
373
+ t.add_row(cmd, desc, src)
374
+
375
+ con.print(t)
376
+
377
+
378
+ def _get_version() -> str:
379
+ try:
380
+ from patchi import __version__
381
+
382
+ return __version__
383
+ except Exception as e:
384
+ _log.warning("_get_version failed: %s", e)
385
+ return "unknown"
386
+
387
+
388
+ def _install_hook(con: Console, strict: bool = False, auto_fix: bool = False) -> None:
389
+ """Install the Patchi pre-commit hook."""
390
+ from patchi.core.config import require_project_root
391
+ from patchi.core.security.precommit_hook import install_hook, read_hook_status
392
+
393
+ try:
394
+ root = require_project_root()
395
+ except RuntimeError as e:
396
+ con.print(f"[red]{e}[/red]")
397
+ return
398
+
399
+ # Show current status
400
+ status = read_hook_status(root)
401
+ if status.get("installed"):
402
+ con.print(f"[dim]Current hook:[/dim] {status.get('path', '?')}")
403
+ parts = []
404
+ if status.get("auto_fix"):
405
+ parts.append("auto-fix")
406
+ if status.get("has_ruff"):
407
+ parts.append("ruff")
408
+ if status.get("has_pytest"):
409
+ parts.append("pytest")
410
+ if status.get("has_scan"):
411
+ parts.append("scan --changed")
412
+ if status.get("strict"):
413
+ parts.append("strict")
414
+ con.print(f" Gates: {', '.join(parts) or 'none'}")
415
+ con.print()
416
+
417
+ # Install
418
+ mode_label = "[bold red]STRICT[/bold red]" if strict else "[dim]warn-only[/dim]"
419
+ fix_label = "[bold green]ON[/bold green]" if auto_fix else "[dim]OFF[/dim]"
420
+ try:
421
+ hook_path = install_hook(root, strict=strict, with_tests=True, with_scan=True, auto_fix=auto_fix)
422
+ con.print(f"[#4ADE80]✓[/#4ADE80] Pre-commit hook installed: [bold]{hook_path}[/bold]")
423
+ con.print(f" Mode: {mode_label} | Auto-fix: {fix_label}")
424
+ con.print()
425
+ con.print(" Gates on every commit:")
426
+ if auto_fix:
427
+ con.print(" 1. [dim]proactive auto-fix[/dim] — charter violations (imports, headers)")
428
+ step = 1 if auto_fix else 0
429
+ step += 1
430
+ con.print(f" {step}. [dim]ruff check patchi/[/dim] — lint")
431
+ step += 1
432
+ con.print(f" {step}. [dim]pytest tests/[/dim] — tests")
433
+ step += 1
434
+ con.print(f" {step}. [dim]p scan --changed[/dim] — security scan of changed files")
435
+ con.print()
436
+ if strict:
437
+ con.print("[bold red]Strict mode ON:[/bold red] violations block the commit.")
438
+ else:
439
+ con.print("[dim]Run [bold]p dev hook --strict[/bold] to fail commits on violations.[/dim]")
440
+ if auto_fix:
441
+ con.print("[dim]Auto-fix will fix safe charter violations (headers, imports) automatically.[/dim]")
442
+ else:
443
+ con.print("[dim]Run [bold]p dev hook --auto-fix[/bold] to auto-fix charter violations on commit.[/dim]")
444
+ except Exception as e:
445
+ con.print(f"[red]Failed to install hook: {e}[/red]")