code-mower 0.5.0b50__tar.gz → 0.5.0b51__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 (307) hide show
  1. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/PKG-INFO +6 -6
  2. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/README.md +5 -5
  3. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/pyproject.toml +1 -1
  4. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cli.py +1 -1
  6. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_branch.py +40 -2
  7. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/init.py +12 -0
  8. {code_mower-0.5.0b50 → code_mower-0.5.0b51/src/code_mower}/templates/workflows/builder-provenance.yml.j2 +1 -1
  9. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +34 -1
  10. {code_mower-0.5.0b50 → code_mower-0.5.0b51/src/code_mower}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +44 -2
  11. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +3 -1
  12. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/PKG-INFO +6 -6
  13. {code_mower-0.5.0b50/src/code_mower → code_mower-0.5.0b51}/templates/workflows/builder-provenance.yml.j2 +1 -1
  14. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +34 -1
  15. {code_mower-0.5.0b50/src/code_mower → code_mower-0.5.0b51}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +44 -2
  16. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/code-mower-gate.yml.j2 +3 -1
  17. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_github_checks.py +35 -2
  18. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_release_hygiene.py +50 -35
  19. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/CODE_OF_CONDUCT.md +0 -0
  20. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/LICENSE +0 -0
  21. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/MANIFEST.in +0 -0
  22. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/NOTICE +0 -0
  23. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/SUPPORT.md +0 -0
  24. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/requirements/requirements.txt +0 -0
  25. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/setup.cfg +0 -0
  26. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/__init__.py +0 -0
  27. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/_base.py +0 -0
  28. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  29. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/gitar.py +0 -0
  30. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/greptile.py +0 -0
  31. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/adapters/qodo.py +0 -0
  32. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  33. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/audit_handoff_log.py +0 -0
  34. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/audit_labeler_lib.py +0 -0
  35. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/audit_progress.py +0 -0
  36. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/blind_review_artifacts.py +0 -0
  37. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/blind_review_coordinator.py +0 -0
  38. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/bootstrap.py +0 -0
  39. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/builder_experiment.py +0 -0
  40. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/builder_runs.py +0 -0
  41. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/__init__.py +0 -0
  42. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/arms.py +0 -0
  43. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/auto_discovery.py +0 -0
  44. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/commands.py +0 -0
  45. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/context_inputs.py +0 -0
  46. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/corpus.py +0 -0
  47. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/effect_report.py +0 -0
  48. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/evidence.py +0 -0
  49. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/evidence_report.py +0 -0
  50. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/identity.py +0 -0
  51. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/metrics.py +0 -0
  52. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/overlap.py +0 -0
  53. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/planning.py +0 -0
  54. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/policy.py +0 -0
  55. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/results.py +0 -0
  56. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/run_results.py +0 -0
  57. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/run_status.py +0 -0
  58. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/runner.py +0 -0
  59. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/truth.py +0 -0
  60. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/calibration/value_report.py +0 -0
  61. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/checks.py +0 -0
  62. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/claude_audit_pr.py +0 -0
  63. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/claude_cli_bounce.py +0 -0
  64. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/claude_cli_environment.py +0 -0
  65. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/clear_stale.py +0 -0
  66. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud.py +0 -0
  67. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/__init__.py +0 -0
  68. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/bundle.py +0 -0
  69. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/doctor.py +0 -0
  70. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/dogfood.py +0 -0
  71. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/endpoints.py +0 -0
  72. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/errors.py +0 -0
  73. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/events.py +0 -0
  74. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/export.py +0 -0
  75. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/git_metadata.py +0 -0
  76. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/manifest.py +0 -0
  77. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/operations.py +0 -0
  78. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/reports.py +0 -0
  79. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/setup.py +0 -0
  80. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/cloud_client/upload.py +0 -0
  81. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/code_mower_calibration.py +0 -0
  82. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/code_mower_context_packs.py +0 -0
  83. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/code_mower_merge.py +0 -0
  84. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/code_mower_telemetry.py +0 -0
  85. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  86. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/codex_audit_env_preflight.py +0 -0
  87. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/codex_audit_pr.py +0 -0
  88. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  89. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  90. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/config.py +0 -0
  91. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor.py +0 -0
  92. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/__init__.py +0 -0
  93. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/cloud.py +0 -0
  94. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/common.py +0 -0
  95. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github.py +0 -0
  96. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions.py +0 -0
  97. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  98. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  99. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  100. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  101. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  102. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  103. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  104. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  105. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_api.py +0 -0
  106. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_config.py +0 -0
  107. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_human_token.py +0 -0
  108. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_provider.py +0 -0
  109. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/github_repo.py +0 -0
  110. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/groups.py +0 -0
  111. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/models.py +0 -0
  112. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/output.py +0 -0
  113. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/presets.py +0 -0
  114. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/privacy.py +0 -0
  115. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  116. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  117. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  118. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_env.py +0 -0
  119. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  120. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  121. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  122. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  123. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  124. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  125. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  126. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  127. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  128. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  129. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  130. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/providers.py +0 -0
  131. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/registry.py +0 -0
  132. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/runner.py +0 -0
  133. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/runtime.py +0 -0
  134. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  135. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/gate_health.py +0 -0
  136. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  137. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/grok_build_audit_pr.py +0 -0
  138. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  139. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/__init__.py +0 -0
  140. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/aider.py +0 -0
  141. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  142. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/claude.py +0 -0
  143. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/codex.py +0 -0
  144. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/devin.py +0 -0
  145. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  146. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/grok_build.py +0 -0
  147. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  148. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/lane_configs/local_llm.py +0 -0
  149. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/local_llm_audit_pr.py +0 -0
  150. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/local_llm_bakeoff.py +0 -0
  151. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/local_llm_calibration.py +0 -0
  152. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/local_llm_profiles.py +0 -0
  153. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/migration.py +0 -0
  154. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/migration_install.py +0 -0
  155. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/migration_mirror.py +0 -0
  156. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/migration_readiness.py +0 -0
  157. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/migration_rehearsal.py +0 -0
  158. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/next_steps.py +0 -0
  159. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package.py +0 -0
  160. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package_content.py +0 -0
  161. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package_manifest.py +0 -0
  162. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package_paths.py +0 -0
  163. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package_rendering.py +0 -0
  164. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/package_static.py +0 -0
  165. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/plan_context.py +0 -0
  166. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/prompts.py +0 -0
  167. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_registry.py +0 -0
  168. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/__init__.py +0 -0
  169. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/comments.py +0 -0
  170. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/git.py +0 -0
  171. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/github_auth.py +0 -0
  172. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/github_pr.py +0 -0
  173. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  174. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/process.py +0 -0
  175. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/repo_paths.py +0 -0
  176. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/text_schema.py +0 -0
  177. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  178. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/provider_runners/workspace.py +0 -0
  179. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/providers/__init__.py +0 -0
  180. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/providers/local_cli.py +0 -0
  181. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/providers/provenance.py +0 -0
  182. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/release_readiness.py +0 -0
  183. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/reviewer_metrics.py +0 -0
  184. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/reviewer_spend.py +0 -0
  185. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/saas_reviewer_labeler.py +0 -0
  186. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/secrets.py +0 -0
  187. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/builder-experiment.example.json +0 -0
  188. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  189. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/calibration-corpus.json +0 -0
  190. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/code-mower.example.yml +0 -0
  191. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/context-packs.example.json +0 -0
  192. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  193. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  194. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  195. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  196. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  197. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  198. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  199. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
  200. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  201. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/code_mower +0 -0
  202. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  203. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  204. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  205. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  206. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  207. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/product-support/status_report.py +0 -0
  208. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/providers.yml +0 -0
  209. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  210. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  211. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  212. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  213. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  214. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  215. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
  216. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  217. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  218. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  219. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  220. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  221. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
  222. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/trailer_comment_labeler.py +0 -0
  223. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/versioning.py +0 -0
  224. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower/work_orders.py +0 -0
  225. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/SOURCES.txt +0 -0
  226. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/dependency_links.txt +0 -0
  227. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/entry_points.txt +0 -0
  228. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/requires.txt +0 -0
  229. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/src/code_mower.egg-info/top_level.txt +0 -0
  230. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/builder-experiment.example.json +0 -0
  231. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/calibration-corpus.example.json +0 -0
  232. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/calibration-corpus.json +0 -0
  233. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/code-mower.yml.j2 +0 -0
  234. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/context-packs.example.json +0 -0
  235. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/cursor/BUGBOT.md +0 -0
  236. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/acp_bridge.yml +0 -0
  237. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/aider.yml +0 -0
  238. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/antigravity_cli.yml +0 -0
  239. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/claude_audit.yml +0 -0
  240. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/claude_review.yml +0 -0
  241. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/coderabbit_cli.yml +0 -0
  242. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/codex.yml +0 -0
  243. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/cursor_bugbot.yml +0 -0
  244. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/devin.yml +0 -0
  245. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/gemini_cli.yml +0 -0
  246. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/gitar.yml +0 -0
  247. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/greptile.yml +0 -0
  248. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/hermes_cli.yml +0 -0
  249. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/local_llm.yml +0 -0
  250. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers/qodo.yml +0 -0
  251. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/providers.yml +0 -0
  252. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/reviewer-spend.example.json +0 -0
  253. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/reviewer-value-report.example.md +0 -0
  254. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  255. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  256. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  257. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  258. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  259. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  260. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  261. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  262. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  263. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  264. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_audit_comment_posture.py +0 -0
  265. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_builder_identity.py +0 -0
  266. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_builder_runs.py +0 -0
  267. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_calibration_effect_report.py +0 -0
  268. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_calibration_truth.py +0 -0
  269. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_checks.py +0 -0
  270. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_claude_audit_pr.py +0 -0
  271. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_claude_cli_bounce.py +0 -0
  272. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_clear_stale.py +0 -0
  273. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_cloud_client.py +0 -0
  274. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_cloud_git_metadata.py +0 -0
  275. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_cloud_manifest.py +0 -0
  276. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_cloud_reports.py +0 -0
  277. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  278. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_codex_audit_env_preflight.py +0 -0
  279. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_codex_audit_pr.py +0 -0
  280. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_actions_cost_summary.py +0 -0
  281. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_actions_failure_selection.py +0 -0
  282. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_boundaries.py +0 -0
  283. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_output.py +0 -0
  284. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_privacy.py +0 -0
  285. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_provider_env_required.py +0 -0
  286. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_provider_env_tokens.py +0 -0
  287. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_provider_probe.py +0 -0
  288. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_provider_review_hygiene.py +0 -0
  289. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_registry.py +0 -0
  290. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_doctor_runtime.py +0 -0
  291. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_gate_health.py +0 -0
  292. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_local_llm_github_helpers.py +0 -0
  293. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_plan_context.py +0 -0
  294. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_prompts.py +0 -0
  295. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_local_cli.py +0 -0
  296. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_comments.py +0 -0
  297. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_git.py +0 -0
  298. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_github_pr.py +0 -0
  299. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_pr_worktree.py +0 -0
  300. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_process.py +0 -0
  301. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_repo_paths.py +0 -0
  302. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_text_schema.py +0 -0
  303. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_provider_runners_workspace.py +0 -0
  304. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_reviewer_metrics_core.py +0 -0
  305. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_reviewer_spend.py +0 -0
  306. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_trailer_comment_labeler.py +0 -0
  307. {code_mower-0.5.0b50 → code_mower-0.5.0b51}/tests/test_work_orders.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b50
3
+ Version: 0.5.0b51
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -103,11 +103,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
103
103
 
104
104
  ```bash
105
105
  python3.12 --version
106
- pipx install --python python3.12 code-mower==0.5.0b50
106
+ pipx install --python python3.12 code-mower==0.5.0b51
107
107
  code-mower --version
108
108
  ```
109
109
 
110
- `0.5.0b50` is a beta release. Until Code Mower publishes a stable `1.0`
110
+ `0.5.0b51` is a beta release. Until Code Mower publishes a stable `1.0`
111
111
  line, use the explicit beta version above or allow prereleases with:
112
112
 
113
113
  ```bash
@@ -155,7 +155,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
155
155
 
156
156
  The current PyPI beta has been rehearsed end-to-end from a clean install:
157
157
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
158
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b50`.
158
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b51`.
159
159
 
160
160
  ## Optional: Plan Before Coding
161
161
 
@@ -310,9 +310,9 @@ builder provenance, start with
310
310
 
311
311
  ## Installation Status
312
312
 
313
- The current public beta is `v0.5.0-beta.50` from
313
+ The current public beta is `v0.5.0-beta.51` from
314
314
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
315
- as `code-mower==0.5.0b50` on [PyPI](https://pypi.org/project/code-mower/).
315
+ as `code-mower==0.5.0b51` on [PyPI](https://pypi.org/project/code-mower/).
316
316
  GitHub releases remain the auditable source for tags, build artifacts, and
317
317
  release notes.
318
318
 
@@ -88,11 +88,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
88
88
 
89
89
  ```bash
90
90
  python3.12 --version
91
- pipx install --python python3.12 code-mower==0.5.0b50
91
+ pipx install --python python3.12 code-mower==0.5.0b51
92
92
  code-mower --version
93
93
  ```
94
94
 
95
- `0.5.0b50` is a beta release. Until Code Mower publishes a stable `1.0`
95
+ `0.5.0b51` is a beta release. Until Code Mower publishes a stable `1.0`
96
96
  line, use the explicit beta version above or allow prereleases with:
97
97
 
98
98
  ```bash
@@ -140,7 +140,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
140
140
 
141
141
  The current PyPI beta has been rehearsed end-to-end from a clean install:
142
142
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
143
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b50`.
143
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b51`.
144
144
 
145
145
  ## Optional: Plan Before Coding
146
146
 
@@ -295,9 +295,9 @@ builder provenance, start with
295
295
 
296
296
  ## Installation Status
297
297
 
298
- The current public beta is `v0.5.0-beta.50` from
298
+ The current public beta is `v0.5.0-beta.51` from
299
299
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
300
- as `code-mower==0.5.0b50` on [PyPI](https://pypi.org/project/code-mower/).
300
+ as `code-mower==0.5.0b51` on [PyPI](https://pypi.org/project/code-mower/).
301
301
  GitHub releases remain the auditable source for tags, build artifacts, and
302
302
  release notes.
303
303
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.5.0b50"
7
+ version = "0.5.0b51"
8
8
  description = "Multi-reviewer AI code audit orchestration"
9
9
  requires-python = ">=3.11"
10
10
  readme = "README.md"
@@ -1,3 +1,3 @@
1
1
  """Code Mower package."""
2
2
 
3
- __version__ = "0.5.0b50"
3
+ __version__ = "0.5.0b51"
@@ -14,7 +14,7 @@ from pathlib import Path
14
14
  if __package__ in {None, ""}:
15
15
  raise SystemExit(
16
16
  "code_mower.cli is a packaged entrypoint. Install Code Mower with "
17
- "`pipx install code-mower==0.5.0b50`, or run source checkouts with "
17
+ "`pipx install code-mower==0.5.0b51`, or run source checkouts with "
18
18
  "`PYTHONPATH=src python -m code_mower.cli`."
19
19
  )
20
20
 
@@ -8,6 +8,8 @@ from typing import Mapping
8
8
  from .common import DoctorCheck, STATUS_PASS, STATUS_WARN
9
9
  from .github_api import _github_api_json
10
10
 
11
+ GITHUB_ACTIONS_APP_ID = 15368
12
+
11
13
 
12
14
  def check_branch_protection(
13
15
  *,
@@ -41,6 +43,7 @@ def check_branch_protection(
41
43
 
42
44
  required_checks = protection_payload.get("required_status_checks")
43
45
  contexts: list[str] = []
46
+ check_bindings: list[dict[str, object]] = []
44
47
  if isinstance(required_checks, Mapping):
45
48
  raw_contexts = required_checks.get("contexts")
46
49
  if isinstance(raw_contexts, list):
@@ -49,8 +52,42 @@ def check_branch_protection(
49
52
  if isinstance(raw_checks, list):
50
53
  for check in raw_checks:
51
54
  if isinstance(check, Mapping) and check.get("context"):
52
- contexts.append(str(check["context"]))
55
+ context = str(check["context"])
56
+ contexts.append(context)
57
+ check_bindings.append(
58
+ {"context": context, "app_id": check.get("app_id")}
59
+ )
53
60
  contexts = list(dict.fromkeys(contexts))
61
+ wrong_gate_bindings = [
62
+ binding
63
+ for binding in check_bindings
64
+ if binding.get("context") == required_status_context
65
+ and binding.get("app_id") == GITHUB_ACTIONS_APP_ID
66
+ ]
67
+ if required_status_context and wrong_gate_bindings:
68
+ return DoctorCheck(
69
+ name="github.branch_protection",
70
+ status=STATUS_WARN,
71
+ message=(
72
+ f"{slug}@{default_branch} requires {required_status_context} "
73
+ "from GitHub Actions instead of Any source"
74
+ ),
75
+ detail={
76
+ "repo": slug,
77
+ "default_branch": default_branch,
78
+ "required_status_context": required_status_context,
79
+ "required_status_contexts": contexts,
80
+ "required_status_check_count": len(contexts),
81
+ "required_status_check_bindings": check_bindings,
82
+ },
83
+ remediation=(
84
+ f"Rebind `{required_status_context}` in branch protection to "
85
+ "Any source, not GitHub Actions. In the API response, the "
86
+ f"`checks[]` entry for `{required_status_context}` should have "
87
+ "`app_id: null`; `app_id: 15368` means GitHub is evaluating "
88
+ "the Actions job check-run instead of the Code Mower commit status."
89
+ ),
90
+ )
54
91
  if required_status_context and required_status_context not in contexts:
55
92
  return DoctorCheck(
56
93
  name="github.branch_protection",
@@ -70,7 +107,7 @@ def check_branch_protection(
70
107
  "unattended merge. Inspect existing checks with "
71
108
  f"`gh api repos/{slug}/branches/{encoded_branch}/protection/required_status_checks`, "
72
109
  "then PATCH that endpoint with all existing contexts plus "
73
- f"`{required_status_context}`."
110
+ f"`{required_status_context}` from Any source."
74
111
  ),
75
112
  )
76
113
  return DoctorCheck(
@@ -86,5 +123,6 @@ def check_branch_protection(
86
123
  "default_branch": default_branch,
87
124
  "required_status_check_count": len(contexts),
88
125
  "required_status_contexts": contexts,
126
+ "required_status_check_bindings": check_bindings,
89
127
  },
90
128
  )
@@ -1828,6 +1828,18 @@ def render_init_plan(
1828
1828
  lines.extend(["", "Additional repository targets from --add-repo:"])
1829
1829
  lines.extend(f"- {slug}" for slug in add_repositories)
1830
1830
 
1831
+ if merge_authority_lanes:
1832
+ lines.extend(
1833
+ [
1834
+ "",
1835
+ "Branch protection:",
1836
+ "- require `code-mower/gate` from Any source "
1837
+ "(API checks[].app_id: null), not GitHub Actions "
1838
+ "(app_id: 15368)",
1839
+ "- inspect: gh api repos/OWNER/REPO/branches/main/protection/required_status_checks",
1840
+ ]
1841
+ )
1842
+
1831
1843
  lines.extend(["", "Required secrets/PAT fallbacks:"])
1832
1844
  if data["required_secrets"]:
1833
1845
  lines.extend(f"- {secret}" for secret in data["required_secrets"])
@@ -8,7 +8,7 @@ permissions:
8
8
  contents: read
9
9
 
10
10
  env:
11
- CODE_MOWER_PACKAGE_SPEC: code-mower==0.5.0b41
11
+ CODE_MOWER_PACKAGE_SPEC: code-mower==0.5.0b51
12
12
 
13
13
  jobs:
14
14
  auto-record:
@@ -88,6 +88,32 @@ jobs:
88
88
  echo "::error::${CODE_MOWER_DISPATCH_TOKEN_ENV} secret is missing; labels must be applied by a human-owned token so audit workflows trigger"
89
89
  exit 1
90
90
  fi
91
+ code_mower_handle_rate_limit() {
92
+ rate_limited=false
93
+ for file in "$@"; do
94
+ if [ -s "${file}" ] && grep -qiE 'API rate limit exceeded|rate limit' "${file}"; then
95
+ rate_limited=true
96
+ fi
97
+ done
98
+ [ "${rate_limited}" = "true" ] || return 1
99
+
100
+ reset_epoch="$(gh api rate_limit --jq '.resources.core.reset // .rate.reset // ""' 2>/dev/null || true)"
101
+ if [[ "${reset_epoch}" =~ ^[0-9]+$ ]]; then
102
+ now_epoch="$(date -u +%s)"
103
+ wait_seconds=$((reset_epoch - now_epoch + 5))
104
+ reset_iso="$(date -u -d "@${reset_epoch}" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "${reset_epoch}")"
105
+ if [ "${wait_seconds}" -gt 0 ] && [ "${wait_seconds}" -le 240 ]; then
106
+ echo "::notice::GitHub API rate limit hit; backing off until ${reset_iso}."
107
+ sleep "${wait_seconds}"
108
+ else
109
+ echo "::notice::GitHub API rate limit hit; reset at ${reset_iso}; exiting cleanly so a later event can retry."
110
+ fi
111
+ else
112
+ echo "::notice::GitHub API rate limit hit; reset time unavailable; exiting cleanly so a later event can retry."
113
+ fi
114
+ return 0
115
+ }
116
+
91
117
  mapfile -t remove_labels < .code-mower-agent-remove-labels.txt
92
118
  mapfile -t add_labels < .code-mower-agent-add-labels.txt
93
119
  remove_args=()
@@ -101,5 +127,12 @@ jobs:
101
127
  for label in "${add_labels[@]}"; do
102
128
  [ -n "${label}" ] && add_args+=(--add-label "${label}")
103
129
  done
104
- gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" "${add_args[@]}"
130
+ label_error="$(mktemp)"
131
+ if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" "${add_args[@]}" 2>"${label_error}"; then
132
+ if code_mower_handle_rate_limit "${label_error}"; then
133
+ exit 0
134
+ fi
135
+ cat "${label_error}" >&2
136
+ exit 1
137
+ fi
105
138
  printf '#%s (%s): %s\n' "${PR_NUMBER}" "${PR_ACTION}" "$(paste -sd ', ' .code-mower-agent-add-labels.txt)"
@@ -97,7 +97,42 @@ jobs:
97
97
  echo "::error::${CODE_MOWER_DISPATCH_TOKEN_ENV} secret is missing or empty; fix-round mentions must be posted by a human-owned token"
98
98
  exit 1
99
99
  fi
100
- bodies="$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate -q '.[].body')"
100
+ code_mower_handle_rate_limit() {
101
+ rate_limited=false
102
+ for file in "$@"; do
103
+ if [ -s "${file}" ] && grep -qiE 'API rate limit exceeded|rate limit' "${file}"; then
104
+ rate_limited=true
105
+ fi
106
+ done
107
+ [ "${rate_limited}" = "true" ] || return 1
108
+
109
+ reset_epoch="$(gh api rate_limit --jq '.resources.core.reset // .rate.reset // ""' 2>/dev/null || true)"
110
+ if [[ "${reset_epoch}" =~ ^[0-9]+$ ]]; then
111
+ now_epoch="$(date -u +%s)"
112
+ wait_seconds=$((reset_epoch - now_epoch + 5))
113
+ reset_iso="$(date -u -d "@${reset_epoch}" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "${reset_epoch}")"
114
+ if [ "${wait_seconds}" -gt 0 ] && [ "${wait_seconds}" -le 240 ]; then
115
+ echo "::notice::GitHub API rate limit hit; backing off until ${reset_iso}."
116
+ sleep "${wait_seconds}"
117
+ else
118
+ echo "::notice::GitHub API rate limit hit; reset at ${reset_iso}; exiting cleanly so a later event can retry."
119
+ fi
120
+ else
121
+ echo "::notice::GitHub API rate limit hit; reset time unavailable; exiting cleanly so a later event can retry."
122
+ fi
123
+ return 0
124
+ }
125
+
126
+ comments_output="$(mktemp)"
127
+ comments_error="$(mktemp)"
128
+ if ! gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate -q '.[].body' >"${comments_output}" 2>"${comments_error}"; then
129
+ if code_mower_handle_rate_limit "${comments_error}" "${comments_output}"; then
130
+ exit 0
131
+ fi
132
+ cat "${comments_error}" >&2
133
+ exit 1
134
+ fi
135
+ bodies="$(cat "${comments_output}")"
101
136
  if printf '%s' "${bodies}" | grep -qF -- "${MARKER}"; then
102
137
  echo "fix round already dispatched for ${HEAD_SHA} (${AUDIT_LANE}/${BUILDER_LANE})"
103
138
  exit 0
@@ -107,5 +142,12 @@ jobs:
107
142
  body="${FIX_ROUND_MENTION} The **${AUDIT_LANE}** audit lane BLOCKED this PR (head ${short_sha}). Read the latest Code Mower audit comments on this PR, address every blocking finding without scope additions, push to this branch, then re-add: \`${needs_labels}\`. If a finding is wrong, reply with evidence and add \`${NEEDS_OWNER_LABEL}\`.
108
143
 
109
144
  ${MARKER}"
110
- gh pr comment "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "${body}"
145
+ comment_error="$(mktemp)"
146
+ if ! gh pr comment "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "${body}" 2>"${comment_error}"; then
147
+ if code_mower_handle_rate_limit "${comment_error}"; then
148
+ exit 0
149
+ fi
150
+ cat "${comment_error}" >&2
151
+ exit 1
152
+ fi
111
153
  echo "dispatched fix round for #${PR_NUMBER} (${AUDIT_LANE}/${BUILDER_LANE}, ${short_sha})"
@@ -38,7 +38,7 @@ env:
38
38
 
39
39
  jobs:
40
40
  gate:
41
- name: code-mower/gate
41
+ name: publish Code Mower gate status
42
42
  runs-on: ubuntu-latest
43
43
  timeout-minutes: 5
44
44
  steps:
@@ -590,6 +590,8 @@ __GATE_AUTHOR_ENV_ASSIGNMENTS__
590
590
 
591
591
  echo "Code Mower gate: ${gate_state} - ${gate_description}"
592
592
 
593
+ # The merge signal is the commit status above. Keep expected
594
+ # pending/failure verdicts from creating a second required check-run.
593
595
  if [ "${gate_state}" != "success" ] || [ "${CODE_MOWER_GATE_ENABLE_AUTO_MERGE}" != "true" ]; then
594
596
  exit 0
595
597
  fi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b50
3
+ Version: 0.5.0b51
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -103,11 +103,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
103
103
 
104
104
  ```bash
105
105
  python3.12 --version
106
- pipx install --python python3.12 code-mower==0.5.0b50
106
+ pipx install --python python3.12 code-mower==0.5.0b51
107
107
  code-mower --version
108
108
  ```
109
109
 
110
- `0.5.0b50` is a beta release. Until Code Mower publishes a stable `1.0`
110
+ `0.5.0b51` is a beta release. Until Code Mower publishes a stable `1.0`
111
111
  line, use the explicit beta version above or allow prereleases with:
112
112
 
113
113
  ```bash
@@ -155,7 +155,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
155
155
 
156
156
  The current PyPI beta has been rehearsed end-to-end from a clean install:
157
157
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
158
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b50`.
158
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b51`.
159
159
 
160
160
  ## Optional: Plan Before Coding
161
161
 
@@ -310,9 +310,9 @@ builder provenance, start with
310
310
 
311
311
  ## Installation Status
312
312
 
313
- The current public beta is `v0.5.0-beta.50` from
313
+ The current public beta is `v0.5.0-beta.51` from
314
314
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
315
- as `code-mower==0.5.0b50` on [PyPI](https://pypi.org/project/code-mower/).
315
+ as `code-mower==0.5.0b51` on [PyPI](https://pypi.org/project/code-mower/).
316
316
  GitHub releases remain the auditable source for tags, build artifacts, and
317
317
  release notes.
318
318
 
@@ -8,7 +8,7 @@ permissions:
8
8
  contents: read
9
9
 
10
10
  env:
11
- CODE_MOWER_PACKAGE_SPEC: code-mower==0.5.0b50
11
+ CODE_MOWER_PACKAGE_SPEC: code-mower==0.5.0b51
12
12
 
13
13
  jobs:
14
14
  auto-record:
@@ -88,6 +88,32 @@ jobs:
88
88
  echo "::error::${CODE_MOWER_DISPATCH_TOKEN_ENV} secret is missing; labels must be applied by a human-owned token so audit workflows trigger"
89
89
  exit 1
90
90
  fi
91
+ code_mower_handle_rate_limit() {
92
+ rate_limited=false
93
+ for file in "$@"; do
94
+ if [ -s "${file}" ] && grep -qiE 'API rate limit exceeded|rate limit' "${file}"; then
95
+ rate_limited=true
96
+ fi
97
+ done
98
+ [ "${rate_limited}" = "true" ] || return 1
99
+
100
+ reset_epoch="$(gh api rate_limit --jq '.resources.core.reset // .rate.reset // ""' 2>/dev/null || true)"
101
+ if [[ "${reset_epoch}" =~ ^[0-9]+$ ]]; then
102
+ now_epoch="$(date -u +%s)"
103
+ wait_seconds=$((reset_epoch - now_epoch + 5))
104
+ reset_iso="$(date -u -d "@${reset_epoch}" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "${reset_epoch}")"
105
+ if [ "${wait_seconds}" -gt 0 ] && [ "${wait_seconds}" -le 240 ]; then
106
+ echo "::notice::GitHub API rate limit hit; backing off until ${reset_iso}."
107
+ sleep "${wait_seconds}"
108
+ else
109
+ echo "::notice::GitHub API rate limit hit; reset at ${reset_iso}; exiting cleanly so a later event can retry."
110
+ fi
111
+ else
112
+ echo "::notice::GitHub API rate limit hit; reset time unavailable; exiting cleanly so a later event can retry."
113
+ fi
114
+ return 0
115
+ }
116
+
91
117
  mapfile -t remove_labels < .code-mower-agent-remove-labels.txt
92
118
  mapfile -t add_labels < .code-mower-agent-add-labels.txt
93
119
  remove_args=()
@@ -101,5 +127,12 @@ jobs:
101
127
  for label in "${add_labels[@]}"; do
102
128
  [ -n "${label}" ] && add_args+=(--add-label "${label}")
103
129
  done
104
- gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" "${add_args[@]}"
130
+ label_error="$(mktemp)"
131
+ if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" "${add_args[@]}" 2>"${label_error}"; then
132
+ if code_mower_handle_rate_limit "${label_error}"; then
133
+ exit 0
134
+ fi
135
+ cat "${label_error}" >&2
136
+ exit 1
137
+ fi
105
138
  printf '#%s (%s): %s\n' "${PR_NUMBER}" "${PR_ACTION}" "$(paste -sd ', ' .code-mower-agent-add-labels.txt)"
@@ -97,7 +97,42 @@ jobs:
97
97
  echo "::error::${CODE_MOWER_DISPATCH_TOKEN_ENV} secret is missing or empty; fix-round mentions must be posted by a human-owned token"
98
98
  exit 1
99
99
  fi
100
- bodies="$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate -q '.[].body')"
100
+ code_mower_handle_rate_limit() {
101
+ rate_limited=false
102
+ for file in "$@"; do
103
+ if [ -s "${file}" ] && grep -qiE 'API rate limit exceeded|rate limit' "${file}"; then
104
+ rate_limited=true
105
+ fi
106
+ done
107
+ [ "${rate_limited}" = "true" ] || return 1
108
+
109
+ reset_epoch="$(gh api rate_limit --jq '.resources.core.reset // .rate.reset // ""' 2>/dev/null || true)"
110
+ if [[ "${reset_epoch}" =~ ^[0-9]+$ ]]; then
111
+ now_epoch="$(date -u +%s)"
112
+ wait_seconds=$((reset_epoch - now_epoch + 5))
113
+ reset_iso="$(date -u -d "@${reset_epoch}" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "${reset_epoch}")"
114
+ if [ "${wait_seconds}" -gt 0 ] && [ "${wait_seconds}" -le 240 ]; then
115
+ echo "::notice::GitHub API rate limit hit; backing off until ${reset_iso}."
116
+ sleep "${wait_seconds}"
117
+ else
118
+ echo "::notice::GitHub API rate limit hit; reset at ${reset_iso}; exiting cleanly so a later event can retry."
119
+ fi
120
+ else
121
+ echo "::notice::GitHub API rate limit hit; reset time unavailable; exiting cleanly so a later event can retry."
122
+ fi
123
+ return 0
124
+ }
125
+
126
+ comments_output="$(mktemp)"
127
+ comments_error="$(mktemp)"
128
+ if ! gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate -q '.[].body' >"${comments_output}" 2>"${comments_error}"; then
129
+ if code_mower_handle_rate_limit "${comments_error}" "${comments_output}"; then
130
+ exit 0
131
+ fi
132
+ cat "${comments_error}" >&2
133
+ exit 1
134
+ fi
135
+ bodies="$(cat "${comments_output}")"
101
136
  if printf '%s' "${bodies}" | grep -qF -- "${MARKER}"; then
102
137
  echo "fix round already dispatched for ${HEAD_SHA} (${AUDIT_LANE}/${BUILDER_LANE})"
103
138
  exit 0
@@ -107,5 +142,12 @@ jobs:
107
142
  body="${FIX_ROUND_MENTION} The **${AUDIT_LANE}** audit lane BLOCKED this PR (head ${short_sha}). Read the latest Code Mower audit comments on this PR, address every blocking finding without scope additions, push to this branch, then re-add: \`${needs_labels}\`. If a finding is wrong, reply with evidence and add \`${NEEDS_OWNER_LABEL}\`.
108
143
 
109
144
  ${MARKER}"
110
- gh pr comment "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "${body}"
145
+ comment_error="$(mktemp)"
146
+ if ! gh pr comment "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "${body}" 2>"${comment_error}"; then
147
+ if code_mower_handle_rate_limit "${comment_error}"; then
148
+ exit 0
149
+ fi
150
+ cat "${comment_error}" >&2
151
+ exit 1
152
+ fi
111
153
  echo "dispatched fix round for #${PR_NUMBER} (${AUDIT_LANE}/${BUILDER_LANE}, ${short_sha})"
@@ -38,7 +38,7 @@ env:
38
38
 
39
39
  jobs:
40
40
  gate:
41
- name: code-mower/gate
41
+ name: publish Code Mower gate status
42
42
  runs-on: ubuntu-latest
43
43
  timeout-minutes: 5
44
44
  steps:
@@ -590,6 +590,8 @@ __GATE_AUTHOR_ENV_ASSIGNMENTS__
590
590
 
591
591
  echo "Code Mower gate: ${gate_state} - ${gate_description}"
592
592
 
593
+ # The merge signal is the commit status above. Keep expected
594
+ # pending/failure verdicts from creating a second required check-run.
593
595
  if [ "${gate_state}" != "success" ] || [ "${CODE_MOWER_GATE_ENABLE_AUTO_MERGE}" != "true" ]; then
594
596
  exit 0
595
597
  fi
@@ -368,14 +368,14 @@ class GitHubDoctorCheckTests(unittest.TestCase):
368
368
  self.assertIn("code-mower/gate", check.message)
369
369
  self.assertEqual(check.detail["required_status_context"], "code-mower/gate")
370
370
 
371
- def test_branch_protection_accepts_gate_status_from_checks_array(self) -> None:
371
+ def test_branch_protection_accepts_any_source_gate_status_binding(self) -> None:
372
372
  with mock.patch(
373
373
  "code_mower.doctor_checks.github_branch._github_api_json",
374
374
  return_value=(
375
375
  {
376
376
  "required_status_checks": {
377
377
  "contexts": ["ci"],
378
- "checks": [{"context": "code-mower/gate"}],
378
+ "checks": [{"context": "code-mower/gate", "app_id": None}],
379
379
  }
380
380
  },
381
381
  {},
@@ -391,6 +391,39 @@ class GitHubDoctorCheckTests(unittest.TestCase):
391
391
 
392
392
  self.assertEqual(check.status, "pass")
393
393
  self.assertIn("code-mower/gate", check.detail["required_status_contexts"])
394
+ self.assertEqual(
395
+ check.detail["required_status_check_bindings"],
396
+ [{"context": "code-mower/gate", "app_id": None}],
397
+ )
398
+
399
+ def test_branch_protection_warns_when_gate_status_bound_to_actions(self) -> None:
400
+ with mock.patch(
401
+ "code_mower.doctor_checks.github_branch._github_api_json",
402
+ return_value=(
403
+ {
404
+ "required_status_checks": {
405
+ "contexts": ["code-mower/gate"],
406
+ "checks": [{"context": "code-mower/gate", "app_id": 15368}],
407
+ }
408
+ },
409
+ {},
410
+ ),
411
+ ):
412
+ check = check_branch_protection(
413
+ gh_path="/usr/bin/gh",
414
+ slug="owner/repo",
415
+ default_branch="main",
416
+ http_timeout=1,
417
+ required_status_context="code-mower/gate",
418
+ )
419
+
420
+ self.assertEqual(check.status, "warn")
421
+ self.assertIn("GitHub Actions instead of Any source", check.message)
422
+ self.assertIn("app_id: null", check.remediation)
423
+ self.assertEqual(
424
+ check.detail["required_status_check_bindings"],
425
+ [{"context": "code-mower/gate", "app_id": 15368}],
426
+ )
394
427
 
395
428
  def test_repo_auto_merge_warns_when_disabled(self) -> None:
396
429
  check = check_repo_auto_merge(