code-mower 0.5.0b23__tar.gz → 0.5.0b25__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 (270) hide show
  1. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/PKG-INFO +6 -6
  2. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/README.md +5 -5
  3. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/pyproject.toml +1 -1
  4. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cli.py +63 -1
  6. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/providers/__init__.py +6 -0
  7. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/providers/provenance.py +94 -0
  8. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/PKG-INFO +6 -6
  9. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_cloud_client.py +1 -1
  10. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_local_cli.py +90 -3
  11. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_release_hygiene.py +34 -34
  12. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/CODE_OF_CONDUCT.md +0 -0
  13. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/LICENSE +0 -0
  14. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/MANIFEST.in +0 -0
  15. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/NOTICE +0 -0
  16. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/SUPPORT.md +0 -0
  17. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/requirements/requirements.txt +0 -0
  18. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/setup.cfg +0 -0
  19. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/__init__.py +0 -0
  20. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/_base.py +0 -0
  21. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  22. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/gitar.py +0 -0
  23. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/greptile.py +0 -0
  24. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/adapters/qodo.py +0 -0
  25. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  26. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/audit_handoff_log.py +0 -0
  27. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/audit_labeler_lib.py +0 -0
  28. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/audit_progress.py +0 -0
  29. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/blind_review_artifacts.py +0 -0
  30. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/blind_review_coordinator.py +0 -0
  31. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/bootstrap.py +0 -0
  32. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/builder_experiment.py +0 -0
  33. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/__init__.py +0 -0
  34. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/arms.py +0 -0
  35. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/auto_discovery.py +0 -0
  36. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/commands.py +0 -0
  37. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/context_inputs.py +0 -0
  38. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/corpus.py +0 -0
  39. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/effect_report.py +0 -0
  40. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/evidence.py +0 -0
  41. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/evidence_report.py +0 -0
  42. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/identity.py +0 -0
  43. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/metrics.py +0 -0
  44. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/overlap.py +0 -0
  45. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/planning.py +0 -0
  46. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/policy.py +0 -0
  47. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/results.py +0 -0
  48. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/run_results.py +0 -0
  49. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/run_status.py +0 -0
  50. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/runner.py +0 -0
  51. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/truth.py +0 -0
  52. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/calibration/value_report.py +0 -0
  53. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/checks.py +0 -0
  54. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/claude_audit_pr.py +0 -0
  55. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/claude_cli_bounce.py +0 -0
  56. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/claude_cli_environment.py +0 -0
  57. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/clear_stale.py +0 -0
  58. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud.py +0 -0
  59. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/__init__.py +0 -0
  60. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/bundle.py +0 -0
  61. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/doctor.py +0 -0
  62. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/dogfood.py +0 -0
  63. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/endpoints.py +0 -0
  64. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/errors.py +0 -0
  65. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/events.py +0 -0
  66. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/export.py +0 -0
  67. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/git_metadata.py +0 -0
  68. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/manifest.py +0 -0
  69. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/operations.py +0 -0
  70. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/reports.py +0 -0
  71. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/setup.py +0 -0
  72. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/cloud_client/upload.py +0 -0
  73. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/code_mower_calibration.py +0 -0
  74. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/code_mower_context_packs.py +0 -0
  75. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/code_mower_merge.py +0 -0
  76. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/code_mower_telemetry.py +0 -0
  77. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  78. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/codex_audit_env_preflight.py +0 -0
  79. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/codex_audit_pr.py +0 -0
  80. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  81. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  82. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/config.py +0 -0
  83. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor.py +0 -0
  84. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/__init__.py +0 -0
  85. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/cloud.py +0 -0
  86. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/common.py +0 -0
  87. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github.py +0 -0
  88. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions.py +0 -0
  89. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  90. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  91. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  92. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  93. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  94. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  95. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  96. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  97. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_api.py +0 -0
  98. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_branch.py +0 -0
  99. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_config.py +0 -0
  100. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_provider.py +0 -0
  101. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/github_repo.py +0 -0
  102. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/groups.py +0 -0
  103. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/models.py +0 -0
  104. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/output.py +0 -0
  105. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/presets.py +0 -0
  106. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/privacy.py +0 -0
  107. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  108. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  109. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  110. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_env.py +0 -0
  111. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  112. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  113. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  114. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  115. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  116. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  117. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  118. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  119. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  120. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  121. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  122. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/providers.py +0 -0
  123. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/registry.py +0 -0
  124. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/runner.py +0 -0
  125. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/runtime.py +0 -0
  126. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  127. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  128. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  129. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/init.py +0 -0
  130. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/__init__.py +0 -0
  131. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/aider.py +0 -0
  132. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  133. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/claude.py +0 -0
  134. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/codex.py +0 -0
  135. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/devin.py +0 -0
  136. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  137. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  138. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/lane_configs/local_llm.py +0 -0
  139. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/local_llm_audit_pr.py +0 -0
  140. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/local_llm_bakeoff.py +0 -0
  141. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/local_llm_calibration.py +0 -0
  142. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/local_llm_profiles.py +0 -0
  143. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/migration.py +0 -0
  144. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/migration_install.py +0 -0
  145. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/migration_mirror.py +0 -0
  146. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/migration_readiness.py +0 -0
  147. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/migration_rehearsal.py +0 -0
  148. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/next_steps.py +0 -0
  149. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package.py +0 -0
  150. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package_content.py +0 -0
  151. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package_manifest.py +0 -0
  152. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package_paths.py +0 -0
  153. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package_rendering.py +0 -0
  154. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/package_static.py +0 -0
  155. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/prompts.py +0 -0
  156. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_registry.py +0 -0
  157. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/__init__.py +0 -0
  158. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/comments.py +0 -0
  159. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/git.py +0 -0
  160. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/github_auth.py +0 -0
  161. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/github_pr.py +0 -0
  162. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  163. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/process.py +0 -0
  164. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/repo_paths.py +0 -0
  165. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/text_schema.py +0 -0
  166. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  167. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/provider_runners/workspace.py +0 -0
  168. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/providers/local_cli.py +0 -0
  169. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/release_readiness.py +0 -0
  170. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/reviewer_metrics.py +0 -0
  171. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/saas_reviewer_labeler.py +0 -0
  172. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/secrets.py +0 -0
  173. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/builder-experiment.example.json +0 -0
  174. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  175. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/calibration-corpus.json +0 -0
  176. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/code-mower.example.yml +0 -0
  177. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/context-packs.example.json +0 -0
  178. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  179. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  180. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  181. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  182. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  183. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  184. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  185. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  186. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/code_mower +0 -0
  187. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  188. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  189. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  190. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  191. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  192. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/providers.yml +0 -0
  193. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  194. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  195. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  196. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  197. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  198. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  199. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  200. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  201. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  202. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/trailer_comment_labeler.py +0 -0
  203. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower/versioning.py +0 -0
  204. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/SOURCES.txt +0 -0
  205. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/dependency_links.txt +0 -0
  206. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/entry_points.txt +0 -0
  207. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/requires.txt +0 -0
  208. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/src/code_mower.egg-info/top_level.txt +0 -0
  209. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/builder-experiment.example.json +0 -0
  210. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/calibration-corpus.example.json +0 -0
  211. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/calibration-corpus.json +0 -0
  212. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/code-mower.yml.j2 +0 -0
  213. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/context-packs.example.json +0 -0
  214. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/cursor/BUGBOT.md +0 -0
  215. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/acp_bridge.yml +0 -0
  216. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/aider.yml +0 -0
  217. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/antigravity_cli.yml +0 -0
  218. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/claude_audit.yml +0 -0
  219. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/claude_review.yml +0 -0
  220. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/coderabbit_cli.yml +0 -0
  221. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/codex.yml +0 -0
  222. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/cursor_bugbot.yml +0 -0
  223. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/devin.yml +0 -0
  224. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/gemini_cli.yml +0 -0
  225. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/gitar.yml +0 -0
  226. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/greptile.yml +0 -0
  227. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/hermes_cli.yml +0 -0
  228. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/local_llm.yml +0 -0
  229. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers/qodo.yml +0 -0
  230. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/providers.yml +0 -0
  231. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/reviewer-spend.example.json +0 -0
  232. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/reviewer-value-report.example.md +0 -0
  233. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  234. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  235. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  236. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  237. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  238. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  239. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  240. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  241. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_calibration_effect_report.py +0 -0
  242. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_calibration_truth.py +0 -0
  243. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_checks.py +0 -0
  244. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_claude_cli_bounce.py +0 -0
  245. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_clear_stale.py +0 -0
  246. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_cloud_git_metadata.py +0 -0
  247. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_cloud_manifest.py +0 -0
  248. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_cloud_reports.py +0 -0
  249. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  250. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_actions_cost_summary.py +0 -0
  251. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_actions_failure_selection.py +0 -0
  252. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_boundaries.py +0 -0
  253. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_github_checks.py +0 -0
  254. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_output.py +0 -0
  255. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_privacy.py +0 -0
  256. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_provider_env_required.py +0 -0
  257. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_provider_env_tokens.py +0 -0
  258. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_provider_probe.py +0 -0
  259. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_provider_review_hygiene.py +0 -0
  260. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_doctor_registry.py +0 -0
  261. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_local_llm_github_helpers.py +0 -0
  262. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_comments.py +0 -0
  263. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_git.py +0 -0
  264. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_github_pr.py +0 -0
  265. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_pr_worktree.py +0 -0
  266. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_process.py +0 -0
  267. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_repo_paths.py +0 -0
  268. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_text_schema.py +0 -0
  269. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_provider_runners_workspace.py +0 -0
  270. {code_mower-0.5.0b23 → code_mower-0.5.0b25}/tests/test_reviewer_metrics_core.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b23
3
+ Version: 0.5.0b25
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -101,11 +101,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
101
101
 
102
102
  ```bash
103
103
  python3.12 --version
104
- pipx install --python python3.12 code-mower==0.5.0b23
104
+ pipx install --python python3.12 code-mower==0.5.0b25
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b23` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b25` is a beta release. Until Code Mower publishes a stable `1.0`
109
109
  line, use the explicit beta version above or allow prereleases with:
110
110
 
111
111
  ```bash
@@ -148,7 +148,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
148
148
 
149
149
  The current PyPI beta has been rehearsed end-to-end from a clean install:
150
150
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
151
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b23`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b25`.
152
152
 
153
153
  ## Why Not Just Run Codex Or Claude Yourself?
154
154
 
@@ -253,9 +253,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
253
253
 
254
254
  ## Installation Status
255
255
 
256
- The current public beta is `v0.5.0-beta.23` from
256
+ The current public beta is `v0.5.0-beta.25` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b23` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b25` on [PyPI](https://pypi.org/project/code-mower/).
259
259
  GitHub releases remain the auditable source for tags, build artifacts, and
260
260
  release notes.
261
261
 
@@ -86,11 +86,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
86
86
 
87
87
  ```bash
88
88
  python3.12 --version
89
- pipx install --python python3.12 code-mower==0.5.0b23
89
+ pipx install --python python3.12 code-mower==0.5.0b25
90
90
  code-mower --version
91
91
  ```
92
92
 
93
- `0.5.0b23` is a beta release. Until Code Mower publishes a stable `1.0`
93
+ `0.5.0b25` is a beta release. Until Code Mower publishes a stable `1.0`
94
94
  line, use the explicit beta version above or allow prereleases with:
95
95
 
96
96
  ```bash
@@ -133,7 +133,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
133
133
 
134
134
  The current PyPI beta has been rehearsed end-to-end from a clean install:
135
135
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
136
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b23`.
136
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b25`.
137
137
 
138
138
  ## Why Not Just Run Codex Or Claude Yourself?
139
139
 
@@ -238,9 +238,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
238
238
 
239
239
  ## Installation Status
240
240
 
241
- The current public beta is `v0.5.0-beta.23` from
241
+ The current public beta is `v0.5.0-beta.25` from
242
242
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
243
- as `code-mower==0.5.0b23` on [PyPI](https://pypi.org/project/code-mower/).
243
+ as `code-mower==0.5.0b25` on [PyPI](https://pypi.org/project/code-mower/).
244
244
  GitHub releases remain the auditable source for tags, build artifacts, and
245
245
  release notes.
246
246
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.5.0b23"
7
+ version = "0.5.0b25"
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.0b23"
3
+ __version__ = "0.5.0b25"
@@ -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.0b23`, or run source checkouts with "
17
+ "`pipx install code-mower==0.5.0b25`, or run source checkouts with "
18
18
  "`PYTHONPATH=src python -m code_mower.cli`."
19
19
  )
20
20
 
@@ -52,6 +52,8 @@ from . import prompts as code_mower_prompts
52
52
  from . import reviewer_metrics
53
53
  from . import saas_reviewer_labeler
54
54
  from . import trailer_comment_labeler
55
+ from .provider_registry import REFERENCE_PROVIDERS
56
+ from .providers import build_provider_model_env_report
55
57
 
56
58
 
57
59
  def _has_positional_config(argv: list[str], options_with_values: set[str]) -> bool:
@@ -120,6 +122,19 @@ def _providers_main(argv: list[str]) -> int:
120
122
  show = subparsers.add_parser("show")
121
123
  show.add_argument("provider")
122
124
  show.add_argument("--json", action="store_true")
125
+ provenance_env = subparsers.add_parser("provenance-env")
126
+ provenance_env.add_argument(
127
+ "--provider",
128
+ action="append",
129
+ default=[],
130
+ help="Limit to a lane id or provider name. May be passed more than once.",
131
+ )
132
+ provenance_env.add_argument("--json", action="store_true")
133
+ provenance_env.add_argument(
134
+ "--shell",
135
+ action="store_true",
136
+ help="Print export command templates for missing model provenance.",
137
+ )
123
138
  args = parser.parse_args(argv)
124
139
 
125
140
  try:
@@ -141,6 +156,53 @@ def _providers_main(argv: list[str]) -> int:
141
156
  print(provider)
142
157
  return 0
143
158
 
159
+ if args.command == "provenance-env":
160
+ report = build_provider_model_env_report(
161
+ REFERENCE_PROVIDERS,
162
+ providers=tuple(args.provider),
163
+ )
164
+ if args.json:
165
+ print(json.dumps(report, indent=2, sort_keys=True))
166
+ elif args.shell:
167
+ for row in report["providers"]:
168
+ if row["action"] == "set_model_env":
169
+ print(f"# {row['lane_id']} ({row['provider']})")
170
+ print(row["export_command"])
171
+ if not any(row["action"] == "set_model_env" for row in report["providers"]):
172
+ print("# No missing model-provenance env vars found.")
173
+ else:
174
+ print("Code Mower provider model provenance env setup")
175
+ print(f"Status: {report['status']}")
176
+ print(f"Providers: {report['provider_count']}")
177
+ print(f"Missing model env: {report['missing_model_env_count']}")
178
+ for row in report["providers"]:
179
+ if row["action"] == "set_model_env":
180
+ aliases = ", ".join(row["env_names"]) or "none"
181
+ print(
182
+ f"- {row['lane_id']}: set {row['preferred_env']} "
183
+ f"(aliases: {aliases})"
184
+ )
185
+ elif row["model_source"] == "vendor_hidden":
186
+ print(f"- {row['lane_id']}: provider hides model/version metadata")
187
+ elif row["model_source"] == "default":
188
+ print(f"- {row['lane_id']}: using configured default model")
189
+ elif row["model_source"].startswith("profile:"):
190
+ print(f"- {row['lane_id']}: using profile model")
191
+ elif row["model_source"] == "env":
192
+ print(f"- {row['lane_id']}: model env is configured")
193
+ elif row["model_source"] == "not_applicable":
194
+ print(f"- {row['lane_id']}: model env is not applicable")
195
+ else:
196
+ print(f"- {row['lane_id']}: model provenance is unknown")
197
+ if report["unknown_providers"]:
198
+ print(
199
+ "error: unknown provider(s): "
200
+ + ", ".join(report["unknown_providers"]),
201
+ file=sys.stderr,
202
+ )
203
+ return 1
204
+ return 0
205
+
144
206
  if args.command == "show":
145
207
  provider = providers.get(args.provider)
146
208
  if not isinstance(provider, dict):
@@ -7,9 +7,12 @@ public CLI remains the stable surface while provider internals settle.
7
7
 
8
8
  from .provenance import (
9
9
  TOOL_PROVENANCE_SCHEMA,
10
+ build_provider_model_env_report,
10
11
  build_provider_lane_tool_provenance,
11
12
  build_code_mower_tool_provenance,
13
+ model_env_names,
12
14
  normalize_tool_provenance,
15
+ preferred_model_env_name,
13
16
  runtime_environment,
14
17
  )
15
18
  from .local_cli import detect_local_cli_version, safe_version_line
@@ -18,8 +21,11 @@ __all__ = [
18
21
  "TOOL_PROVENANCE_SCHEMA",
19
22
  "build_code_mower_tool_provenance",
20
23
  "build_provider_lane_tool_provenance",
24
+ "build_provider_model_env_report",
21
25
  "detect_local_cli_version",
26
+ "model_env_names",
22
27
  "normalize_tool_provenance",
28
+ "preferred_model_env_name",
23
29
  "runtime_environment",
24
30
  "safe_version_line",
25
31
  ]
@@ -183,6 +183,100 @@ def _env_value_any(config: Mapping[str, Any], key: str, any_key: str) -> str:
183
183
  return ""
184
184
 
185
185
 
186
+ def model_env_names(config: Mapping[str, Any]) -> tuple[str, ...]:
187
+ """Return ordered model env vars for a provider config.
188
+
189
+ The primary provider env var is listed first, followed by aliases from
190
+ ``model_env_any``. Duplicate names are removed while preserving order.
191
+ """
192
+
193
+ env_names: list[str] = []
194
+ primary = _safe_text(config.get("model_env"))
195
+ if primary:
196
+ env_names.append(primary)
197
+ for env_name in _text_values(config.get("model_env_any")):
198
+ if env_name not in env_names:
199
+ env_names.append(env_name)
200
+ return tuple(env_names)
201
+
202
+
203
+ def preferred_model_env_name(config: Mapping[str, Any]) -> str:
204
+ """Choose the env var Code Mower should recommend setting.
205
+
206
+ Prefer the Code Mower-specific alias when present so users can record
207
+ benchmark model identity without changing the behavior of the provider CLI
208
+ itself.
209
+ """
210
+
211
+ names = model_env_names(config)
212
+ for name in names:
213
+ if name.startswith("CODE_MOWER_"):
214
+ return name
215
+ return names[0] if names else ""
216
+
217
+
218
+ def build_provider_model_env_report(
219
+ lanes: Mapping[str, Any],
220
+ *,
221
+ providers: tuple[str, ...] = (),
222
+ ) -> dict[str, Any]:
223
+ """Build a privacy-safe model-provenance setup report for provider lanes."""
224
+
225
+ requested = {provider.strip() for provider in providers if provider.strip()}
226
+ rows: list[dict[str, Any]] = []
227
+ matched: set[str] = set()
228
+ for lane_id, lane in sorted(lanes.items()):
229
+ provider = _safe_text(_lane_value(lane, "provider")) or lane_id
230
+ if requested and lane_id not in requested and provider not in requested:
231
+ continue
232
+ if lane_id in requested:
233
+ matched.add(lane_id)
234
+ if provider in requested:
235
+ matched.add(provider)
236
+ config = _provider_config(lane)
237
+ driver = _safe_text(_lane_value(lane, "driver")) or "unknown"
238
+ model, model_source = _configured_model(config, driver)
239
+ env_names = model_env_names(config)
240
+ preferred_env = preferred_model_env_name(config)
241
+ env_status = [
242
+ {"name": name, "is_set": bool(os.environ.get(name, "").strip())}
243
+ for name in env_names
244
+ ]
245
+ if model_source == "missing" and preferred_env:
246
+ action = "set_model_env"
247
+ export_command = f'export {preferred_env}="TODO_MODEL_NAME"'
248
+ elif model_source == "missing":
249
+ action = "not_configurable"
250
+ export_command = ""
251
+ else:
252
+ action = "none"
253
+ export_command = ""
254
+ rows.append(
255
+ {
256
+ "lane_id": lane_id,
257
+ "provider": provider,
258
+ "driver": driver,
259
+ "model_known": bool(model),
260
+ "model_source": model_source,
261
+ "env_names": list(env_names),
262
+ "preferred_env": preferred_env,
263
+ "env_status": env_status,
264
+ "action": action,
265
+ "export_command": export_command,
266
+ }
267
+ )
268
+ unknown = sorted(requested - matched)
269
+ missing = [row for row in rows if row["action"] == "set_model_env"]
270
+ return {
271
+ "mode": "code-mower-provider-model-env-report",
272
+ "providers": rows,
273
+ "provider_count": len(rows),
274
+ "missing_model_env_count": len(missing),
275
+ "unknown_providers": unknown,
276
+ "status": "fail" if unknown else "pass",
277
+ }
278
+
279
+
186
280
  def _profile_model(config: Mapping[str, Any]) -> tuple[str, str]:
187
281
  profile_env = _safe_text(config.get("profile_env"))
188
282
  profile_id = _safe_text(os.environ.get(profile_env)) if profile_env else ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b23
3
+ Version: 0.5.0b25
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -101,11 +101,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
101
101
 
102
102
  ```bash
103
103
  python3.12 --version
104
- pipx install --python python3.12 code-mower==0.5.0b23
104
+ pipx install --python python3.12 code-mower==0.5.0b25
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b23` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b25` is a beta release. Until Code Mower publishes a stable `1.0`
109
109
  line, use the explicit beta version above or allow prereleases with:
110
110
 
111
111
  ```bash
@@ -148,7 +148,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
148
148
 
149
149
  The current PyPI beta has been rehearsed end-to-end from a clean install:
150
150
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
151
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b23`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b25`.
152
152
 
153
153
  ## Why Not Just Run Codex Or Claude Yourself?
154
154
 
@@ -253,9 +253,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
253
253
 
254
254
  ## Installation Status
255
255
 
256
- The current public beta is `v0.5.0-beta.23` from
256
+ The current public beta is `v0.5.0-beta.25` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b23` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b25` on [PyPI](https://pypi.org/project/code-mower/).
259
259
  GitHub releases remain the auditable source for tags, build artifacts, and
260
260
  release notes.
261
261
 
@@ -299,7 +299,7 @@ def test_provenance_summary_preserves_source_quality_fields() -> None:
299
299
  "tool": {
300
300
  "role": "reporter",
301
301
  "tool_name": "code-mower",
302
- "tool_version": "0.5.0b23",
302
+ "tool_version": "0.5.0b25",
303
303
  "provider": "code-mower",
304
304
  "model": "",
305
305
  "model_source": "not_applicable",
@@ -4,8 +4,12 @@ import os
4
4
  from pathlib import Path
5
5
 
6
6
  from code_mower.provider_registry import REFERENCE_PROVIDERS
7
+ from code_mower import cli as code_mower_cli
7
8
  from code_mower.providers import build_provider_lane_tool_provenance
8
- from code_mower.providers.provenance import build_code_mower_tool_provenance
9
+ from code_mower.providers.provenance import (
10
+ build_code_mower_tool_provenance,
11
+ build_provider_model_env_report,
12
+ )
9
13
  from code_mower.providers.local_cli import detect_local_cli_version, safe_version_line
10
14
 
11
15
 
@@ -129,6 +133,89 @@ def test_provider_lane_tool_provenance_reads_model_env_aliases(
129
133
  assert detail["model_source"] == "env"
130
134
 
131
135
 
136
+ def test_provider_model_env_report_prefers_code_mower_alias(monkeypatch) -> None:
137
+ monkeypatch.delenv("CODE_MOWER_CODEX_MODEL", raising=False)
138
+ monkeypatch.delenv("CODEX_MODEL", raising=False)
139
+ monkeypatch.delenv("OPENAI_MODEL", raising=False)
140
+
141
+ report = build_provider_model_env_report(
142
+ REFERENCE_PROVIDERS,
143
+ providers=("codex",),
144
+ )
145
+
146
+ assert report["status"] == "pass"
147
+ assert report["missing_model_env_count"] == 1
148
+ row = report["providers"][0]
149
+ assert row["lane_id"] == "codex"
150
+ assert row["preferred_env"] == "CODE_MOWER_CODEX_MODEL"
151
+ assert row["env_names"] == [
152
+ "CODE_MOWER_CODEX_MODEL",
153
+ "CODEX_MODEL",
154
+ "OPENAI_MODEL",
155
+ ]
156
+ assert row["action"] == "set_model_env"
157
+ assert row["export_command"] == 'export CODE_MOWER_CODEX_MODEL="TODO_MODEL_NAME"'
158
+
159
+
160
+ def test_provider_model_env_report_never_exposes_env_value(monkeypatch) -> None:
161
+ monkeypatch.setenv("CODE_MOWER_GEMINI_MODEL", "sensitive-model-name")
162
+
163
+ report = build_provider_model_env_report(
164
+ REFERENCE_PROVIDERS,
165
+ providers=("gemini_cli",),
166
+ )
167
+
168
+ rendered = str(report)
169
+ assert "sensitive-model-name" not in rendered
170
+ row = report["providers"][0]
171
+ assert row["model_source"] == "env"
172
+ assert row["model_known"] is True
173
+ assert row["env_status"] == [
174
+ {"name": "GEMINI_MODEL", "is_set": False},
175
+ {"name": "CODE_MOWER_GEMINI_MODEL", "is_set": True},
176
+ {"name": "GOOGLE_GENAI_MODEL", "is_set": False},
177
+ ]
178
+ assert row["action"] == "none"
179
+
180
+
181
+ def test_providers_provenance_env_cli_shell_output(monkeypatch, capsys) -> None:
182
+ monkeypatch.delenv("CODE_MOWER_ANTIGRAVITY_MODEL", raising=False)
183
+ monkeypatch.delenv("ANTIGRAVITY_MODEL", raising=False)
184
+
185
+ exit_code = code_mower_cli.main(
186
+ [
187
+ "providers",
188
+ "provenance-env",
189
+ "--provider",
190
+ "antigravity_cli",
191
+ "--shell",
192
+ ]
193
+ )
194
+
195
+ captured = capsys.readouterr()
196
+ assert exit_code == 0
197
+ assert "# antigravity_cli (antigravity)" in captured.out
198
+ assert 'export CODE_MOWER_ANTIGRAVITY_MODEL="TODO_MODEL_NAME"' in captured.out
199
+ assert captured.err == ""
200
+
201
+
202
+ def test_providers_provenance_env_cli_rejects_unknown(capsys) -> None:
203
+ exit_code = code_mower_cli.main(
204
+ [
205
+ "providers",
206
+ "provenance-env",
207
+ "--provider",
208
+ "not-a-provider",
209
+ "--json",
210
+ ]
211
+ )
212
+
213
+ captured = capsys.readouterr()
214
+ assert exit_code == 1
215
+ assert '"unknown_providers": [' in captured.out
216
+ assert "not-a-provider" in captured.err
217
+
218
+
132
219
  def test_provider_lane_tool_provenance_prefers_primary_model_env(
133
220
  monkeypatch,
134
221
  tmp_path: Path,
@@ -290,11 +377,11 @@ def test_provider_lane_tool_provenance_reads_model_from_selected_profile(
290
377
  def test_code_mower_reporter_provenance_marks_model_not_applicable() -> None:
291
378
  tool = build_code_mower_tool_provenance(
292
379
  source="unit-test",
293
- version="0.5.0b23",
380
+ version="0.5.0b25",
294
381
  )
295
382
 
296
383
  assert tool["tool_name"] == "code-mower"
297
- assert tool["tool_version"] == "0.5.0b23"
384
+ assert tool["tool_version"] == "0.5.0b25"
298
385
  assert tool["provider"] == "code-mower"
299
386
  assert tool["model"] == ""
300
387
  assert tool["model_source"] == "not_applicable"