gitpr-cli 1.4.0__tar.gz → 1.4.1__tar.gz

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 (229) hide show
  1. {gitpr_cli-1.4.0/gitpr_cli.egg-info → gitpr_cli-1.4.1}/PKG-INFO +7 -1
  2. gitpr_cli-1.4.0/PKG-INFO → gitpr_cli-1.4.1/README.md +6 -20
  3. gitpr_cli-1.4.0/README.md → gitpr_cli-1.4.1/gitpr_cli.egg-info/PKG-INFO +26 -0
  4. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/gitpr_cli.egg-info/SOURCES.txt +12 -0
  5. gitpr_cli-1.4.1/src/application/use_cases/publish_pull_request.py +270 -0
  6. gitpr_cli-1.4.1/src/application/use_cases/run_check.py +446 -0
  7. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/core.py +10 -0
  8. gitpr_cli-1.4.1/src/domain/check/__init__.py +31 -0
  9. gitpr_cli-1.4.1/src/domain/check/check_config.py +122 -0
  10. gitpr_cli-1.4.1/src/domain/check/check_output.py +112 -0
  11. gitpr_cli-1.4.1/src/domain/check/check_types.py +165 -0
  12. gitpr_cli-1.4.1/src/infrastructure/ci/__init__.py +11 -0
  13. gitpr_cli-1.4.1/src/infrastructure/ci/junit_builder.py +102 -0
  14. gitpr_cli-1.4.1/src/infrastructure/ci/masking.py +65 -0
  15. gitpr_cli-1.4.1/src/infrastructure/ci/sarif_builder.py +152 -0
  16. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/main.py +154 -27
  17. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/mcp_server.py +312 -5
  18. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/pr_publish_app.py +58 -8
  19. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/updater.py +2 -2
  20. gitpr_cli-1.4.1/tests/test_check_cli.py +118 -0
  21. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_mcp_server.py +179 -5
  22. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_pr_publish_app.py +242 -0
  23. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_skill_context.py +23 -0
  24. gitpr_cli-1.4.1/tests/test_skill_templates.py +36 -0
  25. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/LICENSE +0 -0
  26. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/gitpr_cli.egg-info/dependency_links.txt +0 -0
  27. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/gitpr_cli.egg-info/entry_points.txt +0 -0
  28. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/gitpr_cli.egg-info/requires.txt +0 -0
  29. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/gitpr_cli.egg-info/top_level.txt +0 -0
  30. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/pyproject.toml +0 -0
  31. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/setup.cfg +0 -0
  32. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/__init__.py +0 -0
  33. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ai_providers.py +0 -0
  34. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/__init__.py +0 -0
  35. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/__init__.py +0 -0
  36. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/activate_policy_pack.py +0 -0
  37. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/baseline_gate.py +0 -0
  38. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/baseline_summary.py +0 -0
  39. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/calculate_risk.py +0 -0
  40. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/compare_against_baseline.py +0 -0
  41. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/create_baseline.py +0 -0
  42. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/generate_mentor_explanation.py +0 -0
  43. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/generate_pr_explanation.py +0 -0
  44. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/generate_test_file.py +0 -0
  45. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/install_policy_pack.py +0 -0
  46. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/resolve_effective_policy.py +0 -0
  47. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/suppress_finding.py +0 -0
  48. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/application/use_cases/validate_policy_pack.py +0 -0
  49. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/blame_engine.py +0 -0
  50. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/branding/__init__.py +0 -0
  51. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/branding/badge_builder.py +0 -0
  52. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/branding/badge_data.py +0 -0
  53. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/cache.py +0 -0
  54. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/changelog_builder.py +0 -0
  55. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/chat_memory.py +0 -0
  56. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/commit_classifier.py +0 -0
  57. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/config.py +0 -0
  58. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/config_schema.py +0 -0
  59. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/__init__.py +0 -0
  60. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/demo_runner.py +0 -0
  61. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/fake_ai_provider.py +0 -0
  62. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/scenarios/__init__.py +0 -0
  63. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/scenarios/laravel_bug_fix.py +0 -0
  64. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/demo/scenarios/security_issue.py +0 -0
  65. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/diff_parser.py +0 -0
  66. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/doc_links.py +0 -0
  67. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/__init__.py +0 -0
  68. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/baseline_comparator.py +0 -0
  69. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/baseline_fingerprint.py +0 -0
  70. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/baseline_manifest.py +0 -0
  71. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/baseline_types.py +0 -0
  72. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/baseline/suppression_policy.py +0 -0
  73. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/finding/__init__.py +0 -0
  74. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/finding/finding_types.py +0 -0
  75. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/linter/__init__.py +0 -0
  76. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/linter/sast_finding_mapper.py +0 -0
  77. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/mentor/__init__.py +0 -0
  78. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/mentor/mentor_explanation_builder.py +0 -0
  79. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/__init__.py +0 -0
  80. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/policy_checksum.py +0 -0
  81. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/policy_compatibility.py +0 -0
  82. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/policy_manifest.py +0 -0
  83. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/policy_resolver.py +0 -0
  84. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/policy/policy_types.py +0 -0
  85. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/pr/__init__.py +0 -0
  86. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/pr/explain_section_builder.py +0 -0
  87. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/risk/__init__.py +0 -0
  88. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/risk/risk_calculator.py +0 -0
  89. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/risk/risk_explanation.py +0 -0
  90. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/risk/risk_rules.py +0 -0
  91. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/risk/risk_types.py +0 -0
  92. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/tests_generation/__init__.py +0 -0
  93. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/tests_generation/framework_detector.py +0 -0
  94. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/tests_generation/test_content_types.py +0 -0
  95. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/domain/tests_generation/test_scaffold_builder.py +0 -0
  96. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/__init__.py +0 -0
  97. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/apply_fix.py +0 -0
  98. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/fix_history.py +0 -0
  99. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/patch_applier.py +0 -0
  100. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/patch_extractor.py +0 -0
  101. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/patch_provenance.py +0 -0
  102. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/patch_safety_classifier.py +0 -0
  103. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/fix/rollback_fix.py +0 -0
  104. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/github_api.py +0 -0
  105. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/i18n.py +0 -0
  106. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/__init__.py +0 -0
  107. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/baseline/__init__.py +0 -0
  108. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/baseline/local_baseline_repository.py +0 -0
  109. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/__init__.py +0 -0
  110. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/identity.py +0 -0
  111. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/patch_applier.py +0 -0
  112. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/risk_history_reader.py +0 -0
  113. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/selective_stager.py +0 -0
  114. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/git/test_matcher.py +0 -0
  115. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/linter/external/__init__.py +0 -0
  116. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/linter/external/bandit_bridge.py +0 -0
  117. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/linter/external/base_bridge.py +0 -0
  118. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/linter/external/gitleaks_bridge.py +0 -0
  119. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/linter/external/semgrep_bridge.py +0 -0
  120. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/policy/__init__.py +0 -0
  121. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/policy/local_policy_repository.py +0 -0
  122. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/policy/policy_pack_loader.py +0 -0
  123. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/__init__.py +0 -0
  124. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/azure_devops_provider.py +0 -0
  125. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/base.py +0 -0
  126. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/bitbucket_provider.py +0 -0
  127. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/factory.py +0 -0
  128. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/github_provider.py +0 -0
  129. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/gitlab_provider.py +0 -0
  130. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/infrastructure/scm/web_links.py +0 -0
  131. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/issue_engine.py +0 -0
  132. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ledger.py +0 -0
  133. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/linter_engine.py +0 -0
  134. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/linter_wizard.py +0 -0
  135. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/metrics.py +0 -0
  136. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/net.py +0 -0
  137. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/laravel-quality/CHANGELOG.md +0 -0
  138. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/laravel-quality/README.md +0 -0
  139. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/laravel-quality/linter.yml +0 -0
  140. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/laravel-quality/policy.yml +0 -0
  141. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/node-quality/README.md +0 -0
  142. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/node-quality/linter.yml +0 -0
  143. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/node-quality/policy.yml +0 -0
  144. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/php-security/README.md +0 -0
  145. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/php-security/linter.yml +0 -0
  146. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/php-security/policy.yml +0 -0
  147. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/vue-quality/README.md +0 -0
  148. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/vue-quality/linter.yml +0 -0
  149. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/policy_packs/vue-quality/policy.yml +0 -0
  150. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/release_engine.py +0 -0
  151. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/review/__init__.py +0 -0
  152. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/review/diff_normalizer.py +0 -0
  153. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/review/diff_source.py +0 -0
  154. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/review/remote_pr.py +0 -0
  155. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/review/render.py +0 -0
  156. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/reviewer_resolution.py +0 -0
  157. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/reviewer_suggestion.py +0 -0
  158. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/security.py +0 -0
  159. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/security_ruleset.py +0 -0
  160. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/spinner.py +0 -0
  161. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/__init__.py +0 -0
  162. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/apply_split_plan.py +0 -0
  163. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/generate_split_plan.py +0 -0
  164. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/hunk_grouper.py +0 -0
  165. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/hunk_parser.py +0 -0
  166. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/split/split_plan.py +0 -0
  167. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/suggest_reviewers.py +0 -0
  168. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/tui_issue.py +0 -0
  169. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/__init__.py +0 -0
  170. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/chat_app.py +0 -0
  171. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/config_app.py +0 -0
  172. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/demo/__init__.py +0 -0
  173. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/demo/demo_app.py +0 -0
  174. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/demo/demo_help_screen.py +0 -0
  175. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/demo/demo_screens.py +0 -0
  176. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/help_screen.py +0 -0
  177. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/issue_app.py +0 -0
  178. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/linter_app.py +0 -0
  179. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/metrics_app.py +0 -0
  180. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/metrics_migration_app.py +0 -0
  181. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/ui/pr_publish_help.py +0 -0
  182. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/usage_log.py +0 -0
  183. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/src/version_bump.py +0 -0
  184. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_baseline_cli.py +0 -0
  185. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_blame_engine_ranges.py +0 -0
  186. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_blame_metrics.py +0 -0
  187. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_changelog_builder.py +0 -0
  188. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_chat_backend.py +0 -0
  189. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_commit_classifier.py +0 -0
  190. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_app.py +0 -0
  191. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_cli.py +0 -0
  192. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_schema.py +0 -0
  193. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_store.py +0 -0
  194. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_suggest_reviewers.py +0 -0
  195. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_config_validation.py +0 -0
  196. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_core.py +0 -0
  197. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_diff_parser.py +0 -0
  198. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_explain_command.py +0 -0
  199. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_external_linters.py +0 -0
  200. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_i18n.py +0 -0
  201. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_install_wizard.py +0 -0
  202. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_issue_engine.py +0 -0
  203. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_linter_metrics.py +0 -0
  204. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_linter_presets.py +0 -0
  205. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_main_suggest_reviewers.py +0 -0
  206. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_mcp_prompts.py +0 -0
  207. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_mcp_server_e2e.py +0 -0
  208. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_mentor_cli.py +0 -0
  209. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_metrics.py +0 -0
  210. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_net_timeouts.py +0 -0
  211. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_plugins.py +0 -0
  212. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_policy_cli.py +0 -0
  213. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_pr_publish_linter_modal.py +0 -0
  214. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_pre_save.py +0 -0
  215. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_release_cli.py +0 -0
  216. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_release_engine.py +0 -0
  217. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_reviewer_resolution.py +0 -0
  218. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_reviewer_suggestion.py +0 -0
  219. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_risk_cli.py +0 -0
  220. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_security_ruleset.py +0 -0
  221. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_skill_command.py +0 -0
  222. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_smart_excludes.py +0 -0
  223. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_suggest_reviewers.py +0 -0
  224. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_tests_command.py +0 -0
  225. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_thinking_words.py +0 -0
  226. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_updater.py +0 -0
  227. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_usage_log.py +0 -0
  228. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_version_bump.py +0 -0
  229. {gitpr_cli-1.4.0 → gitpr_cli-1.4.1}/tests/test_web_links.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitpr-cli
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: AI-powered PR automation, commit messages, and code review (Gemini, DeepSeek, and Ollama)
5
5
  Author-email: Natan Fiuza <contato@natanfiuza.dev.br>
6
6
  Requires-Python: >=3.10
@@ -170,6 +170,7 @@ You can pass the following *flags* for specific actions:
170
170
  * `gitpr risk`: **Local Risk Scoring for Diffs.** Computes a deterministic, explainable risk score (0.0 to 100.0) and badge (`LOW 🟢`, `MEDIUM 🟡`, `HIGH 🟠`, `CRITICAL 🔴`) using local repository signals (critical paths, missing tests, migrations, bug history, and static findings). Use `--file <path>`, `--format json`, `--base <ref>`, or `--no-history`. Automatically included in code reviews (`GITPR_RISK_INCLUDE_IN_REVIEW=true`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/risk-scoring.md)
171
171
  * `gitpr policy`: **Shared quality policy for the repository.** Adopts a versioned YAML **Policy Pack** — review skills, linter rules, severity overrides, critical paths, risk weights and PR/commit conventions — and records the choice in `.gitpr/policy.lock.yml`, so the review, the linter and the risk score all run under the same policy, with a checksum per pack. `list`, `validate`, `show`, `use`, `init`, `install`, `off`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/policy-packs.md)
172
172
  * `gitpr baseline`: **Baseline and auditable suppressions for legacy adoption.** Records the findings a repository already has in `.gitpr/baseline.json`, so a run classifies every finding as `new`, `existing`, `resolved`, `ignored` or `accepted_debt` and **only `new` blocks**. Every suppression carries a reason, and accepted debt carries an owner and an optional deadline. `create`, `show`, `validate`, `update`, `suppress`, `unsuppress`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/baseline-suppressions.md)
173
+ * `gitpr check`: **Unified CI check command.** Consolidates static linter, secret scanning, external bridges (Semgrep, Gitleaks, Bandit), optional AI code review, risk scoring, and baseline into a single CI pipeline command. Emits machine-readable artifacts in **SARIF 2.1.0**, **JSON**, or **JUnit XML** with deterministic exit codes (`0`, `1`, `2`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/check-ci.md)
173
174
  * `-c` or `--commit`: Runs a local `git diff` and displays **only the suggested commit message**.
174
175
  * `-r` or `--review`: Performs a detailed **Code Review** of local changes. Use with `--mentor` to append pedagogical mentoring explanations for each finding.
175
176
  * `-f` or `--fullreview`: Performs a **Full Code Review** analyzing all changes since the remote branch. Use with `--mentor` to append pedagogical mentoring explanations.
@@ -458,6 +459,8 @@ Once configured, use natural language in your editor's AI chat:
458
459
  | `analyze_unstaged_diff` | Unstaged diff only (working tree vs index) |
459
460
  | `list_fix_candidates` | Fix candidates of the last review: patch, classification, id (read-only) |
460
461
  | `review_remote_pr` | AI review of a pull request already open on the forge, fetched by number (read-only) |
462
+ | `run_check` | Structured CI/Editor quality gate returning normalized findings and pass/fail status |
463
+ | `publish_pull_request` | Publish or update a Pull Request on the remote forge from title and body |
461
464
 
462
465
  ### Direct CLI Invocation
463
466
 
@@ -478,6 +481,8 @@ This is useful for scripting, CI/CD pipelines, and one-off queries where you don
478
481
 
479
482
  📖 **Full documentation:** [docs/mcp-integration.md](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-integration.md) — available in 5 languages (EN, PT-BR, PT-PT, ES, FR).
480
483
 
484
+ > 🧩 **Official VS Code & Cursor Extension** — Prefer native editor commands, SCM toolbar buttons, and inline `Problems` diagnostics? Install the thin-client extension in [`extensions/vscode/`](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md), powered by `gitpr-mcp`.
485
+
481
486
  > 💬 **MCP Prompts** — GitPR also exposes 7 pre-defined message templates (prompts) for common flows like "Review PR", "Generate Commit Message", and "Create Issue from Diff". See the [MCP Prompts guide](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-prompts.md) for the full list.
482
487
 
483
488
  ## 🎯 Smart Excludes (Token Optimization)
@@ -570,6 +575,7 @@ If you want to implement GitPR as an automated quality barrier in your team, che
570
575
 
571
576
  ### Configuration & Infrastructure
572
577
 
578
+ * [**Editor Extension (VS Code & Cursor)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md) — Thin-client VSIX extension driving `gitpr-mcp` over stdio for SCM commit generation, Markdown code reviews, two-step PR publishing, and inline `Problems` diagnostics.
573
579
  * [**Interactive Configuration TUI (gitpr config)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/config-tui.md) — Master-detail terminal interface to view, edit, and validate settings in `~/.gitpr/.env`.
574
580
  * [**Multi-Forge SCM Integration**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/scm-multiforge.md) — Unified SCM provider layer for GitHub, GitLab, Bitbucket Cloud, and Azure DevOps with `--init` wizard.
575
581
  * [**Suggested Reviewers**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/suggested-reviewers.md) — Automatic reviewer suggestion via Git blame of added lines mapped to forge logins.
@@ -1,23 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: gitpr-cli
3
- Version: 1.4.0
4
- Summary: AI-powered PR automation, commit messages, and code review (Gemini, DeepSeek, and Ollama)
5
- Author-email: Natan Fiuza <contato@natanfiuza.dev.br>
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE
9
- Requires-Dist: click>=8.0.0
10
- Requires-Dist: google-genai
11
- Requires-Dist: openai
12
- Requires-Dist: python-dotenv
13
- Requires-Dist: cryptography
14
- Requires-Dist: pyyaml
15
- Requires-Dist: textual
16
- Requires-Dist: requests
17
- Requires-Dist: mcp>=1.0.0
18
- Requires-Dist: packaging>=23.0
19
- Dynamic: license-file
20
-
21
1
 
22
2
  # **GitPR CLI 🚀**
23
3
 
@@ -170,6 +150,7 @@ You can pass the following *flags* for specific actions:
170
150
  * `gitpr risk`: **Local Risk Scoring for Diffs.** Computes a deterministic, explainable risk score (0.0 to 100.0) and badge (`LOW 🟢`, `MEDIUM 🟡`, `HIGH 🟠`, `CRITICAL 🔴`) using local repository signals (critical paths, missing tests, migrations, bug history, and static findings). Use `--file <path>`, `--format json`, `--base <ref>`, or `--no-history`. Automatically included in code reviews (`GITPR_RISK_INCLUDE_IN_REVIEW=true`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/risk-scoring.md)
171
151
  * `gitpr policy`: **Shared quality policy for the repository.** Adopts a versioned YAML **Policy Pack** — review skills, linter rules, severity overrides, critical paths, risk weights and PR/commit conventions — and records the choice in `.gitpr/policy.lock.yml`, so the review, the linter and the risk score all run under the same policy, with a checksum per pack. `list`, `validate`, `show`, `use`, `init`, `install`, `off`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/policy-packs.md)
172
152
  * `gitpr baseline`: **Baseline and auditable suppressions for legacy adoption.** Records the findings a repository already has in `.gitpr/baseline.json`, so a run classifies every finding as `new`, `existing`, `resolved`, `ignored` or `accepted_debt` and **only `new` blocks**. Every suppression carries a reason, and accepted debt carries an owner and an optional deadline. `create`, `show`, `validate`, `update`, `suppress`, `unsuppress`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/baseline-suppressions.md)
153
+ * `gitpr check`: **Unified CI check command.** Consolidates static linter, secret scanning, external bridges (Semgrep, Gitleaks, Bandit), optional AI code review, risk scoring, and baseline into a single CI pipeline command. Emits machine-readable artifacts in **SARIF 2.1.0**, **JSON**, or **JUnit XML** with deterministic exit codes (`0`, `1`, `2`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/check-ci.md)
173
154
  * `-c` or `--commit`: Runs a local `git diff` and displays **only the suggested commit message**.
174
155
  * `-r` or `--review`: Performs a detailed **Code Review** of local changes. Use with `--mentor` to append pedagogical mentoring explanations for each finding.
175
156
  * `-f` or `--fullreview`: Performs a **Full Code Review** analyzing all changes since the remote branch. Use with `--mentor` to append pedagogical mentoring explanations.
@@ -458,6 +439,8 @@ Once configured, use natural language in your editor's AI chat:
458
439
  | `analyze_unstaged_diff` | Unstaged diff only (working tree vs index) |
459
440
  | `list_fix_candidates` | Fix candidates of the last review: patch, classification, id (read-only) |
460
441
  | `review_remote_pr` | AI review of a pull request already open on the forge, fetched by number (read-only) |
442
+ | `run_check` | Structured CI/Editor quality gate returning normalized findings and pass/fail status |
443
+ | `publish_pull_request` | Publish or update a Pull Request on the remote forge from title and body |
461
444
 
462
445
  ### Direct CLI Invocation
463
446
 
@@ -478,6 +461,8 @@ This is useful for scripting, CI/CD pipelines, and one-off queries where you don
478
461
 
479
462
  📖 **Full documentation:** [docs/mcp-integration.md](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-integration.md) — available in 5 languages (EN, PT-BR, PT-PT, ES, FR).
480
463
 
464
+ > 🧩 **Official VS Code & Cursor Extension** — Prefer native editor commands, SCM toolbar buttons, and inline `Problems` diagnostics? Install the thin-client extension in [`extensions/vscode/`](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md), powered by `gitpr-mcp`.
465
+
481
466
  > 💬 **MCP Prompts** — GitPR also exposes 7 pre-defined message templates (prompts) for common flows like "Review PR", "Generate Commit Message", and "Create Issue from Diff". See the [MCP Prompts guide](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-prompts.md) for the full list.
482
467
 
483
468
  ## 🎯 Smart Excludes (Token Optimization)
@@ -570,6 +555,7 @@ If you want to implement GitPR as an automated quality barrier in your team, che
570
555
 
571
556
  ### Configuration & Infrastructure
572
557
 
558
+ * [**Editor Extension (VS Code & Cursor)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md) — Thin-client VSIX extension driving `gitpr-mcp` over stdio for SCM commit generation, Markdown code reviews, two-step PR publishing, and inline `Problems` diagnostics.
573
559
  * [**Interactive Configuration TUI (gitpr config)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/config-tui.md) — Master-detail terminal interface to view, edit, and validate settings in `~/.gitpr/.env`.
574
560
  * [**Multi-Forge SCM Integration**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/scm-multiforge.md) — Unified SCM provider layer for GitHub, GitLab, Bitbucket Cloud, and Azure DevOps with `--init` wizard.
575
561
  * [**Suggested Reviewers**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/suggested-reviewers.md) — Automatic reviewer suggestion via Git blame of added lines mapped to forge logins.
@@ -1,3 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitpr-cli
3
+ Version: 1.4.1
4
+ Summary: AI-powered PR automation, commit messages, and code review (Gemini, DeepSeek, and Ollama)
5
+ Author-email: Natan Fiuza <contato@natanfiuza.dev.br>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: click>=8.0.0
10
+ Requires-Dist: google-genai
11
+ Requires-Dist: openai
12
+ Requires-Dist: python-dotenv
13
+ Requires-Dist: cryptography
14
+ Requires-Dist: pyyaml
15
+ Requires-Dist: textual
16
+ Requires-Dist: requests
17
+ Requires-Dist: mcp>=1.0.0
18
+ Requires-Dist: packaging>=23.0
19
+ Dynamic: license-file
20
+
1
21
 
2
22
  # **GitPR CLI 🚀**
3
23
 
@@ -150,6 +170,7 @@ You can pass the following *flags* for specific actions:
150
170
  * `gitpr risk`: **Local Risk Scoring for Diffs.** Computes a deterministic, explainable risk score (0.0 to 100.0) and badge (`LOW 🟢`, `MEDIUM 🟡`, `HIGH 🟠`, `CRITICAL 🔴`) using local repository signals (critical paths, missing tests, migrations, bug history, and static findings). Use `--file <path>`, `--format json`, `--base <ref>`, or `--no-history`. Automatically included in code reviews (`GITPR_RISK_INCLUDE_IN_REVIEW=true`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/risk-scoring.md)
151
171
  * `gitpr policy`: **Shared quality policy for the repository.** Adopts a versioned YAML **Policy Pack** — review skills, linter rules, severity overrides, critical paths, risk weights and PR/commit conventions — and records the choice in `.gitpr/policy.lock.yml`, so the review, the linter and the risk score all run under the same policy, with a checksum per pack. `list`, `validate`, `show`, `use`, `init`, `install`, `off`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/policy-packs.md)
152
172
  * `gitpr baseline`: **Baseline and auditable suppressions for legacy adoption.** Records the findings a repository already has in `.gitpr/baseline.json`, so a run classifies every finding as `new`, `existing`, `resolved`, `ignored` or `accepted_debt` and **only `new` blocks**. Every suppression carries a reason, and accepted debt carries an owner and an optional deadline. `create`, `show`, `validate`, `update`, `suppress`, `unsuppress`. 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/baseline-suppressions.md)
173
+ * `gitpr check`: **Unified CI check command.** Consolidates static linter, secret scanning, external bridges (Semgrep, Gitleaks, Bandit), optional AI code review, risk scoring, and baseline into a single CI pipeline command. Emits machine-readable artifacts in **SARIF 2.1.0**, **JSON**, or **JUnit XML** with deterministic exit codes (`0`, `1`, `2`). 📖 [Full docs](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/check-ci.md)
153
174
  * `-c` or `--commit`: Runs a local `git diff` and displays **only the suggested commit message**.
154
175
  * `-r` or `--review`: Performs a detailed **Code Review** of local changes. Use with `--mentor` to append pedagogical mentoring explanations for each finding.
155
176
  * `-f` or `--fullreview`: Performs a **Full Code Review** analyzing all changes since the remote branch. Use with `--mentor` to append pedagogical mentoring explanations.
@@ -438,6 +459,8 @@ Once configured, use natural language in your editor's AI chat:
438
459
  | `analyze_unstaged_diff` | Unstaged diff only (working tree vs index) |
439
460
  | `list_fix_candidates` | Fix candidates of the last review: patch, classification, id (read-only) |
440
461
  | `review_remote_pr` | AI review of a pull request already open on the forge, fetched by number (read-only) |
462
+ | `run_check` | Structured CI/Editor quality gate returning normalized findings and pass/fail status |
463
+ | `publish_pull_request` | Publish or update a Pull Request on the remote forge from title and body |
441
464
 
442
465
  ### Direct CLI Invocation
443
466
 
@@ -458,6 +481,8 @@ This is useful for scripting, CI/CD pipelines, and one-off queries where you don
458
481
 
459
482
  📖 **Full documentation:** [docs/mcp-integration.md](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-integration.md) — available in 5 languages (EN, PT-BR, PT-PT, ES, FR).
460
483
 
484
+ > 🧩 **Official VS Code & Cursor Extension** — Prefer native editor commands, SCM toolbar buttons, and inline `Problems` diagnostics? Install the thin-client extension in [`extensions/vscode/`](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md), powered by `gitpr-mcp`.
485
+
461
486
  > 💬 **MCP Prompts** — GitPR also exposes 7 pre-defined message templates (prompts) for common flows like "Review PR", "Generate Commit Message", and "Create Issue from Diff". See the [MCP Prompts guide](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/mcp-prompts.md) for the full list.
462
487
 
463
488
  ## 🎯 Smart Excludes (Token Optimization)
@@ -550,6 +575,7 @@ If you want to implement GitPR as an automated quality barrier in your team, che
550
575
 
551
576
  ### Configuration & Infrastructure
552
577
 
578
+ * [**Editor Extension (VS Code & Cursor)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/editor-extension.md) — Thin-client VSIX extension driving `gitpr-mcp` over stdio for SCM commit generation, Markdown code reviews, two-step PR publishing, and inline `Problems` diagnostics.
553
579
  * [**Interactive Configuration TUI (gitpr config)**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/config-tui.md) — Master-detail terminal interface to view, edit, and validate settings in `~/.gitpr/.env`.
554
580
  * [**Multi-Forge SCM Integration**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/scm-multiforge.md) — Unified SCM provider layer for GitHub, GitLab, Bitbucket Cloud, and Azure DevOps with `--init` wizard.
555
581
  * [**Suggested Reviewers**](https://github.com/gitpr-cli/gitpr.git/blob/main/docs/suggested-reviewers.md) — Automatic reviewer suggestion via Git blame of added lines mapped to forge logins.
@@ -52,7 +52,9 @@ src/application/use_cases/generate_mentor_explanation.py
52
52
  src/application/use_cases/generate_pr_explanation.py
53
53
  src/application/use_cases/generate_test_file.py
54
54
  src/application/use_cases/install_policy_pack.py
55
+ src/application/use_cases/publish_pull_request.py
55
56
  src/application/use_cases/resolve_effective_policy.py
57
+ src/application/use_cases/run_check.py
56
58
  src/application/use_cases/suppress_finding.py
57
59
  src/application/use_cases/validate_policy_pack.py
58
60
  src/branding/__init__.py
@@ -70,6 +72,10 @@ src/domain/baseline/baseline_fingerprint.py
70
72
  src/domain/baseline/baseline_manifest.py
71
73
  src/domain/baseline/baseline_types.py
72
74
  src/domain/baseline/suppression_policy.py
75
+ src/domain/check/__init__.py
76
+ src/domain/check/check_config.py
77
+ src/domain/check/check_output.py
78
+ src/domain/check/check_types.py
73
79
  src/domain/finding/__init__.py
74
80
  src/domain/finding/finding_types.py
75
81
  src/domain/linter/__init__.py
@@ -104,6 +110,10 @@ src/fix/rollback_fix.py
104
110
  src/infrastructure/__init__.py
105
111
  src/infrastructure/baseline/__init__.py
106
112
  src/infrastructure/baseline/local_baseline_repository.py
113
+ src/infrastructure/ci/__init__.py
114
+ src/infrastructure/ci/junit_builder.py
115
+ src/infrastructure/ci/masking.py
116
+ src/infrastructure/ci/sarif_builder.py
107
117
  src/infrastructure/git/__init__.py
108
118
  src/infrastructure/git/identity.py
109
119
  src/infrastructure/git/patch_applier.py
@@ -169,6 +179,7 @@ tests/test_blame_engine_ranges.py
169
179
  tests/test_blame_metrics.py
170
180
  tests/test_changelog_builder.py
171
181
  tests/test_chat_backend.py
182
+ tests/test_check_cli.py
172
183
  tests/test_commit_classifier.py
173
184
  tests/test_config_app.py
174
185
  tests/test_config_cli.py
@@ -205,6 +216,7 @@ tests/test_risk_cli.py
205
216
  tests/test_security_ruleset.py
206
217
  tests/test_skill_command.py
207
218
  tests/test_skill_context.py
219
+ tests/test_skill_templates.py
208
220
  tests/test_smart_excludes.py
209
221
  tests/test_suggest_reviewers.py
210
222
  tests/test_tests_command.py
@@ -0,0 +1,270 @@
1
+ """Use case: Publish a pull request directly to the configured SCM forge.
2
+
3
+ Shared by the CLI ``--no-edit`` flow and the MCP ``publish_pull_request`` tool.
4
+ Never commits or pushes; checks for existing PRs or unpushed branches when
5
+ requested, maps forge errors into structured outcomes, and applies defense-in-depth
6
+ secret masking on error messages.
7
+ """
8
+
9
+ from dataclasses import dataclass
10
+ import subprocess
11
+ from typing import Optional
12
+
13
+ import src.domain.check.check_types # noqa: F401 - avoid circular import through src.infrastructure.ci
14
+ from src.i18n import __
15
+ from src.infrastructure.ci.masking import mask_sensitive_text
16
+ from src.infrastructure.scm import (
17
+ PullRequestRequest,
18
+ PullRequestResult,
19
+ RepoRef,
20
+ ScmProvider,
21
+ ScmProviderError,
22
+ provider_display_name,
23
+ )
24
+
25
+
26
+ @dataclass
27
+ class PublishPrOutcome:
28
+ """Structured result of a pull request publication attempt.
29
+
30
+ status is one of:
31
+ - "success" : PR created on the forge (url and number populated)
32
+ - "already_exists" : an open PR already exists for source_branch (url and number populated)
33
+ - "needs_push" : source_branch is not on origin or has unpushed commits
34
+ - "auth_required" : missing or invalid/expired SCM token (HTTP 401/403)
35
+ - "error" : any other validation or API error
36
+ """
37
+
38
+ status: str
39
+ url: str = ""
40
+ number: int = 0
41
+ provider: str = ""
42
+ source_branch: str = ""
43
+ target_branch: str = ""
44
+ http_status: int = 0
45
+ message: str = ""
46
+
47
+
48
+ def format_recommended_commit_body(commit_message: str, pr_body: str) -> str:
49
+ """Formats the full PR body with the recommended commit message header (used by --no-edit)."""
50
+ return (
51
+ __("**Recommended Commit Message:**\n")
52
+ + "```text\n"
53
+ + f"{commit_message}\n"
54
+ + "```\n\n---\n\n"
55
+ + pr_body
56
+ )
57
+
58
+
59
+ def _branch_needs_push(source_branch: str, repo_path: Optional[str] = None) -> bool:
60
+ """True when origin/<source_branch> does not exist or local HEAD is ahead of it."""
61
+ if not source_branch or source_branch == "HEAD":
62
+ return False
63
+ remote_ref = f"refs/remotes/origin/{source_branch}"
64
+ try:
65
+ proc = subprocess.run(
66
+ ["git", "rev-parse", "--verify", remote_ref],
67
+ capture_output=True,
68
+ stdin=subprocess.DEVNULL,
69
+ text=True,
70
+ encoding="utf-8",
71
+ errors="replace",
72
+ cwd=repo_path or None,
73
+ )
74
+ if proc.returncode != 0:
75
+ return True
76
+ ahead = subprocess.run(
77
+ ["git", "rev-list", "--count", f"origin/{source_branch}..HEAD"],
78
+ capture_output=True,
79
+ stdin=subprocess.DEVNULL,
80
+ text=True,
81
+ encoding="utf-8",
82
+ errors="replace",
83
+ cwd=repo_path or None,
84
+ )
85
+ if ahead.returncode == 0:
86
+ count = int((ahead.stdout or "0").strip() or "0")
87
+ return count > 0
88
+ except (OSError, ValueError):
89
+ return False
90
+ return False
91
+
92
+
93
+ def publish_pull_request_use_case(
94
+ provider: ScmProvider,
95
+ repo_ref: RepoRef,
96
+ title: str,
97
+ description: str,
98
+ source_branch: str,
99
+ target_branch: str,
100
+ draft: bool = False,
101
+ check_remote_state: bool = False,
102
+ repo_path: Optional[str] = None,
103
+ ) -> PublishPrOutcome:
104
+ """Creates a pull request on *provider* and returns a structured PublishPrOutcome.
105
+
106
+ When *check_remote_state* is True (MCP flow), verifies that a token is present,
107
+ checks whether the branch needs to be pushed first, and checks whether an open
108
+ PR already exists for *source_branch* before attempting creation.
109
+ """
110
+ label = provider_display_name(provider)
111
+ clean_title = (title or "").strip()
112
+ clean_body = (description or "").strip()
113
+
114
+ if not clean_title:
115
+ return PublishPrOutcome(
116
+ status="error",
117
+ provider=provider.name,
118
+ source_branch=source_branch,
119
+ target_branch=target_branch,
120
+ message=__("Pull request title must not be empty."),
121
+ )
122
+
123
+ if not clean_body:
124
+ return PublishPrOutcome(
125
+ status="error",
126
+ provider=provider.name,
127
+ source_branch=source_branch,
128
+ target_branch=target_branch,
129
+ message=__("PR description must not be empty."),
130
+ )
131
+
132
+ if not getattr(provider, "token", ""):
133
+ return PublishPrOutcome(
134
+ status="auth_required",
135
+ provider=provider.name,
136
+ source_branch=source_branch,
137
+ target_branch=target_branch,
138
+ http_status=401,
139
+ message=__(
140
+ "{provider} token is not configured. Run 'gitpr' in a terminal to authenticate.",
141
+ provider=label,
142
+ ),
143
+ )
144
+
145
+ if check_remote_state:
146
+ try:
147
+ existing: Optional[PullRequestResult] = provider.check_existing_pull_request(
148
+ repo_ref, source_branch
149
+ )
150
+ except ScmProviderError as exc:
151
+ if exc.http_status in (401, 403):
152
+ return PublishPrOutcome(
153
+ status="auth_required",
154
+ provider=provider.name,
155
+ source_branch=source_branch,
156
+ target_branch=target_branch,
157
+ http_status=exc.http_status,
158
+ message=mask_sensitive_text(
159
+ __(
160
+ "{provider} token expired or invalid. Run 'gitpr' in a terminal to re-authenticate.",
161
+ provider=label,
162
+ )
163
+ ),
164
+ )
165
+ existing = None
166
+ except Exception:
167
+ existing = None
168
+
169
+ if existing is not None:
170
+ return PublishPrOutcome(
171
+ status="already_exists",
172
+ url=existing.url,
173
+ number=existing.number,
174
+ provider=provider.name,
175
+ source_branch=source_branch,
176
+ target_branch=existing.target_branch or target_branch,
177
+ message=__(
178
+ "An open Pull Request already exists for branch '{branch}': {url}",
179
+ branch=source_branch,
180
+ url=existing.url,
181
+ ),
182
+ )
183
+
184
+ if _branch_needs_push(source_branch, repo_path=repo_path):
185
+ return PublishPrOutcome(
186
+ status="needs_push",
187
+ provider=provider.name,
188
+ source_branch=source_branch,
189
+ target_branch=target_branch,
190
+ message=__(
191
+ "Branch '{branch}' has not been pushed to origin or has unpushed commits.",
192
+ branch=source_branch,
193
+ ),
194
+ )
195
+
196
+ try:
197
+ result = provider.create_pull_request(
198
+ repo_ref,
199
+ PullRequestRequest(
200
+ title=clean_title,
201
+ description=clean_body,
202
+ source_branch=source_branch,
203
+ target_branch=target_branch,
204
+ draft=bool(draft),
205
+ ),
206
+ )
207
+ except ScmProviderError as exc:
208
+ masked_msg = mask_sensitive_text(exc.message)
209
+ if exc.http_status == 401:
210
+ return PublishPrOutcome(
211
+ status="auth_required",
212
+ provider=provider.name,
213
+ source_branch=source_branch,
214
+ target_branch=target_branch,
215
+ http_status=exc.http_status,
216
+ message=masked_msg,
217
+ )
218
+ lower_msg = masked_msg.lower()
219
+ if exc.http_status in (400, 409, 422) and "already exists" in lower_msg:
220
+ return PublishPrOutcome(
221
+ status="already_exists",
222
+ provider=provider.name,
223
+ source_branch=source_branch,
224
+ target_branch=target_branch,
225
+ http_status=exc.http_status,
226
+ message=masked_msg,
227
+ )
228
+ if exc.http_status in (400, 404, 422) and (
229
+ "head" in lower_msg or "source" in lower_msg or "branch" in lower_msg
230
+ ) and _branch_needs_push(source_branch, repo_path=repo_path):
231
+ return PublishPrOutcome(
232
+ status="needs_push",
233
+ provider=provider.name,
234
+ source_branch=source_branch,
235
+ target_branch=target_branch,
236
+ http_status=exc.http_status,
237
+ message=masked_msg,
238
+ )
239
+ return PublishPrOutcome(
240
+ status="error",
241
+ provider=provider.name,
242
+ source_branch=source_branch,
243
+ target_branch=target_branch,
244
+ http_status=exc.http_status,
245
+ message=masked_msg,
246
+ )
247
+ except Exception as exc:
248
+ return PublishPrOutcome(
249
+ status="error",
250
+ provider=provider.name,
251
+ source_branch=source_branch,
252
+ target_branch=target_branch,
253
+ http_status=0,
254
+ message=mask_sensitive_text(str(exc)),
255
+ )
256
+
257
+ return PublishPrOutcome(
258
+ status="success",
259
+ url=result.url,
260
+ number=result.number,
261
+ provider=provider.name,
262
+ source_branch=source_branch,
263
+ target_branch=target_branch,
264
+ http_status=201,
265
+ message=__(
266
+ "PR successfully created on {provider}: {pr_url}",
267
+ provider=label,
268
+ pr_url=result.url,
269
+ ),
270
+ )