code-mower 0.5.0b26__tar.gz → 0.5.0b28__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.0b26 → code_mower-0.5.0b28}/PKG-INFO +6 -6
  2. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/README.md +5 -5
  3. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/pyproject.toml +1 -1
  4. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cli.py +4 -1
  6. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/doctor.py +35 -9
  7. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/providers/provenance.py +21 -2
  8. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/PKG-INFO +6 -6
  9. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_cloud_client.py +63 -1
  10. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_local_cli.py +61 -2
  11. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_release_hygiene.py +34 -34
  12. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/CODE_OF_CONDUCT.md +0 -0
  13. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/LICENSE +0 -0
  14. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/MANIFEST.in +0 -0
  15. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/NOTICE +0 -0
  16. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/SUPPORT.md +0 -0
  17. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/requirements/requirements.txt +0 -0
  18. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/setup.cfg +0 -0
  19. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/__init__.py +0 -0
  20. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/_base.py +0 -0
  21. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  22. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/gitar.py +0 -0
  23. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/greptile.py +0 -0
  24. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/adapters/qodo.py +0 -0
  25. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  26. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/audit_handoff_log.py +0 -0
  27. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/audit_labeler_lib.py +0 -0
  28. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/audit_progress.py +0 -0
  29. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/blind_review_artifacts.py +0 -0
  30. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/blind_review_coordinator.py +0 -0
  31. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/bootstrap.py +0 -0
  32. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/builder_experiment.py +0 -0
  33. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/__init__.py +0 -0
  34. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/arms.py +0 -0
  35. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/auto_discovery.py +0 -0
  36. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/commands.py +0 -0
  37. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/context_inputs.py +0 -0
  38. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/corpus.py +0 -0
  39. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/effect_report.py +0 -0
  40. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/evidence.py +0 -0
  41. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/evidence_report.py +0 -0
  42. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/identity.py +0 -0
  43. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/metrics.py +0 -0
  44. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/overlap.py +0 -0
  45. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/planning.py +0 -0
  46. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/policy.py +0 -0
  47. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/results.py +0 -0
  48. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/run_results.py +0 -0
  49. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/run_status.py +0 -0
  50. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/runner.py +0 -0
  51. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/truth.py +0 -0
  52. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/calibration/value_report.py +0 -0
  53. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/checks.py +0 -0
  54. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/claude_audit_pr.py +0 -0
  55. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/claude_cli_bounce.py +0 -0
  56. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/claude_cli_environment.py +0 -0
  57. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/clear_stale.py +0 -0
  58. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud.py +0 -0
  59. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/__init__.py +0 -0
  60. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/bundle.py +0 -0
  61. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/dogfood.py +0 -0
  62. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/endpoints.py +0 -0
  63. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/errors.py +0 -0
  64. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/events.py +0 -0
  65. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/export.py +0 -0
  66. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/git_metadata.py +0 -0
  67. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/manifest.py +0 -0
  68. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/operations.py +0 -0
  69. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/reports.py +0 -0
  70. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/setup.py +0 -0
  71. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/cloud_client/upload.py +0 -0
  72. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/code_mower_calibration.py +0 -0
  73. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/code_mower_context_packs.py +0 -0
  74. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/code_mower_merge.py +0 -0
  75. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/code_mower_telemetry.py +0 -0
  76. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  77. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/codex_audit_env_preflight.py +0 -0
  78. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/codex_audit_pr.py +0 -0
  79. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  80. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  81. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/config.py +0 -0
  82. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor.py +0 -0
  83. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/__init__.py +0 -0
  84. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/cloud.py +0 -0
  85. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/common.py +0 -0
  86. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github.py +0 -0
  87. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions.py +0 -0
  88. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  89. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  90. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  91. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  92. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  93. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  94. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  95. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  96. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_api.py +0 -0
  97. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_branch.py +0 -0
  98. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_config.py +0 -0
  99. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_provider.py +0 -0
  100. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/github_repo.py +0 -0
  101. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/groups.py +0 -0
  102. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/models.py +0 -0
  103. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/output.py +0 -0
  104. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/presets.py +0 -0
  105. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/privacy.py +0 -0
  106. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  107. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  108. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  109. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_env.py +0 -0
  110. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  111. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  112. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  113. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  114. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  115. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  116. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  117. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  118. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  119. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  120. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  121. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/providers.py +0 -0
  122. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/registry.py +0 -0
  123. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/runner.py +0 -0
  124. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/runtime.py +0 -0
  125. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  126. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  127. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  128. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/init.py +0 -0
  129. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/__init__.py +0 -0
  130. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/aider.py +0 -0
  131. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  132. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/claude.py +0 -0
  133. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/codex.py +0 -0
  134. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/devin.py +0 -0
  135. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  136. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  137. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/lane_configs/local_llm.py +0 -0
  138. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/local_llm_audit_pr.py +0 -0
  139. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/local_llm_bakeoff.py +0 -0
  140. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/local_llm_calibration.py +0 -0
  141. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/local_llm_profiles.py +0 -0
  142. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/migration.py +0 -0
  143. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/migration_install.py +0 -0
  144. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/migration_mirror.py +0 -0
  145. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/migration_readiness.py +0 -0
  146. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/migration_rehearsal.py +0 -0
  147. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/next_steps.py +0 -0
  148. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package.py +0 -0
  149. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package_content.py +0 -0
  150. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package_manifest.py +0 -0
  151. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package_paths.py +0 -0
  152. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package_rendering.py +0 -0
  153. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/package_static.py +0 -0
  154. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/prompts.py +0 -0
  155. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_registry.py +0 -0
  156. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/__init__.py +0 -0
  157. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/comments.py +0 -0
  158. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/git.py +0 -0
  159. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/github_auth.py +0 -0
  160. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/github_pr.py +0 -0
  161. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  162. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/process.py +0 -0
  163. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/repo_paths.py +0 -0
  164. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/text_schema.py +0 -0
  165. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  166. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/provider_runners/workspace.py +0 -0
  167. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/providers/__init__.py +0 -0
  168. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/providers/local_cli.py +0 -0
  169. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/release_readiness.py +0 -0
  170. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/reviewer_metrics.py +0 -0
  171. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/saas_reviewer_labeler.py +0 -0
  172. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/secrets.py +0 -0
  173. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/builder-experiment.example.json +0 -0
  174. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  175. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/calibration-corpus.json +0 -0
  176. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/code-mower.example.yml +0 -0
  177. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/context-packs.example.json +0 -0
  178. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  179. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  180. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  181. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  182. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  183. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  184. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  185. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  186. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/code_mower +0 -0
  187. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  188. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  189. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  190. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  191. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  192. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/providers.yml +0 -0
  193. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  194. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  195. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  196. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  197. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  198. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  199. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  200. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  201. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  202. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/trailer_comment_labeler.py +0 -0
  203. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower/versioning.py +0 -0
  204. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/SOURCES.txt +0 -0
  205. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/dependency_links.txt +0 -0
  206. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/entry_points.txt +0 -0
  207. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/requires.txt +0 -0
  208. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/src/code_mower.egg-info/top_level.txt +0 -0
  209. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/builder-experiment.example.json +0 -0
  210. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/calibration-corpus.example.json +0 -0
  211. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/calibration-corpus.json +0 -0
  212. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/code-mower.yml.j2 +0 -0
  213. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/context-packs.example.json +0 -0
  214. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/cursor/BUGBOT.md +0 -0
  215. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/acp_bridge.yml +0 -0
  216. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/aider.yml +0 -0
  217. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/antigravity_cli.yml +0 -0
  218. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/claude_audit.yml +0 -0
  219. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/claude_review.yml +0 -0
  220. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/coderabbit_cli.yml +0 -0
  221. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/codex.yml +0 -0
  222. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/cursor_bugbot.yml +0 -0
  223. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/devin.yml +0 -0
  224. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/gemini_cli.yml +0 -0
  225. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/gitar.yml +0 -0
  226. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/greptile.yml +0 -0
  227. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/hermes_cli.yml +0 -0
  228. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/local_llm.yml +0 -0
  229. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers/qodo.yml +0 -0
  230. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/providers.yml +0 -0
  231. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/reviewer-spend.example.json +0 -0
  232. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/reviewer-value-report.example.md +0 -0
  233. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  234. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  235. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  236. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  237. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  238. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  239. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  240. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  241. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_calibration_effect_report.py +0 -0
  242. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_calibration_truth.py +0 -0
  243. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_checks.py +0 -0
  244. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_claude_cli_bounce.py +0 -0
  245. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_clear_stale.py +0 -0
  246. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_cloud_git_metadata.py +0 -0
  247. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_cloud_manifest.py +0 -0
  248. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_cloud_reports.py +0 -0
  249. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  250. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_actions_cost_summary.py +0 -0
  251. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_actions_failure_selection.py +0 -0
  252. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_boundaries.py +0 -0
  253. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_github_checks.py +0 -0
  254. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_output.py +0 -0
  255. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_privacy.py +0 -0
  256. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_provider_env_required.py +0 -0
  257. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_provider_env_tokens.py +0 -0
  258. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_provider_probe.py +0 -0
  259. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_provider_review_hygiene.py +0 -0
  260. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_doctor_registry.py +0 -0
  261. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_local_llm_github_helpers.py +0 -0
  262. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_comments.py +0 -0
  263. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_git.py +0 -0
  264. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_github_pr.py +0 -0
  265. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_pr_worktree.py +0 -0
  266. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_process.py +0 -0
  267. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_repo_paths.py +0 -0
  268. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_text_schema.py +0 -0
  269. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/tests/test_provider_runners_workspace.py +0 -0
  270. {code_mower-0.5.0b26 → code_mower-0.5.0b28}/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.0b26
3
+ Version: 0.5.0b28
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.0b26
104
+ pipx install --python python3.12 code-mower==0.5.0b28
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b26` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b28` 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.0b26`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b28`.
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.26` from
256
+ The current public beta is `v0.5.0-beta.28` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b26` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b28` 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.0b26
89
+ pipx install --python python3.12 code-mower==0.5.0b28
90
90
  code-mower --version
91
91
  ```
92
92
 
93
- `0.5.0b26` is a beta release. Until Code Mower publishes a stable `1.0`
93
+ `0.5.0b28` 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.0b26`.
136
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b28`.
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.26` from
241
+ The current public beta is `v0.5.0-beta.28` from
242
242
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
243
- as `code-mower==0.5.0b26` on [PyPI](https://pypi.org/project/code-mower/).
243
+ as `code-mower==0.5.0b28` 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.0b26"
7
+ version = "0.5.0b28"
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.0b26"
3
+ __version__ = "0.5.0b28"
@@ -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.0b26`, or run source checkouts with "
17
+ "`pipx install code-mower==0.5.0b28`, or run source checkouts with "
18
18
  "`PYTHONPATH=src python -m code_mower.cli`."
19
19
  )
20
20
 
@@ -175,6 +175,7 @@ def _providers_main(argv: list[str]) -> int:
175
175
  print(f"Status: {report['status']}")
176
176
  print(f"Providers: {report['provider_count']}")
177
177
  print(f"Missing model env: {report['missing_model_env_count']}")
178
+ print(f"Missing CLI version probes: {report['missing_version_probe_count']}")
178
179
  for row in report["providers"]:
179
180
  if row["action"] == "set_model_env":
180
181
  aliases = ", ".join(row["env_names"]) or "none"
@@ -182,6 +183,8 @@ def _providers_main(argv: list[str]) -> int:
182
183
  f"- {row['lane_id']}: set {row['preferred_env']} "
183
184
  f"(aliases: {aliases})"
184
185
  )
186
+ elif row["driver"] == "local_cli" and row["version_source"] == "missing":
187
+ print(f"- {row['lane_id']}: CLI version probe is missing")
185
188
  elif row["model_source"] == "vendor_hidden":
186
189
  print(f"- {row['lane_id']}: provider hides model/version metadata")
187
190
  elif row["model_source"] == "default":
@@ -64,10 +64,19 @@ def _provider_model_env_names(providers: list[str]) -> dict[str, list[str]]:
64
64
  def _provider_model_env_commands(providers: list[str]) -> list[str]:
65
65
  if not providers:
66
66
  return ["code-mower providers provenance-env --shell"]
67
+ return [
68
+ f"code-mower providers provenance-env --provider {shlex.quote(provider)} --shell"
69
+ for provider in sorted(providers)
70
+ ]
71
+
72
+
73
+ def _provider_model_env_command_all(providers: list[str]) -> str:
74
+ if not providers:
75
+ return "code-mower providers provenance-env --shell"
67
76
  provider_args = " ".join(
68
77
  f"--provider {shlex.quote(provider)}" for provider in sorted(providers)
69
78
  )
70
- return [f"code-mower providers provenance-env {provider_args} --shell"]
79
+ return f"code-mower providers provenance-env {provider_args} --shell"
71
80
 
72
81
 
73
82
  def run_cloud_doctor(
@@ -198,7 +207,30 @@ def run_cloud_doctor(
198
207
  or set(MODEL_PROVENANCE_ENV_EXAMPLES)
199
208
  )
200
209
  model_env_commands = _provider_model_env_commands(missing_model_tools)
210
+ model_env_command_all = _provider_model_env_command_all(
211
+ missing_model_tools
212
+ )
201
213
  if missing_model_events:
214
+ if len(model_env_commands) == 1:
215
+ remediation_command = model_env_commands[0]
216
+ remediation = (
217
+ "Run "
218
+ + remediation_command
219
+ + " to print safe export templates, then set "
220
+ "provider-specific model env vars before export or dogfood. "
221
+ "Examples: "
222
+ + ", ".join(model_env_examples)
223
+ + "."
224
+ )
225
+ else:
226
+ remediation = (
227
+ "Run the provider-specific commands in "
228
+ "`detail.model_env_commands` to print safe export templates, "
229
+ "or run the combined `detail.model_env_command_all` command. "
230
+ "Then set model env vars before export or dogfood. Examples: "
231
+ + ", ".join(model_env_examples)
232
+ + "."
233
+ )
202
234
  checks.append(
203
235
  {
204
236
  "name": "model-provenance",
@@ -211,15 +243,9 @@ def run_cloud_doctor(
211
243
  "model_env_by_provider": model_env_by_provider,
212
244
  "model_env_examples": model_env_examples,
213
245
  "model_env_commands": model_env_commands,
246
+ "model_env_command_all": model_env_command_all,
214
247
  },
215
- "remediation": (
216
- "Run "
217
- + " && ".join(model_env_commands)
218
- + " to print safe export templates, then set provider-specific "
219
- "model env vars before export or dogfood. Examples: "
220
- + ", ".join(model_env_examples)
221
- + "."
222
- ),
248
+ "remediation": remediation,
223
249
  }
224
250
  )
225
251
  else:
@@ -235,7 +235,12 @@ def build_provider_model_env_report(
235
235
  matched.add(provider)
236
236
  config = _provider_config(lane)
237
237
  driver = _safe_text(_lane_value(lane, "driver")) or "unknown"
238
- model, model_source = _configured_model(config, driver)
238
+ tool, provenance_detail = build_provider_lane_tool_provenance(
239
+ lane_id,
240
+ lane,
241
+ source="code-mower providers provenance-env",
242
+ )
243
+ model_source = _safe_text(provenance_detail.get("model_source"))
239
244
  env_names = model_env_names(config)
240
245
  preferred_env = preferred_model_env_name(config)
241
246
  env_status = [
@@ -256,8 +261,16 @@ def build_provider_model_env_report(
256
261
  "lane_id": lane_id,
257
262
  "provider": provider,
258
263
  "driver": driver,
259
- "model_known": bool(model),
264
+ "model_known": bool(provenance_detail.get("model_known")),
260
265
  "model_source": model_source,
266
+ "tool_name": tool.get("tool_name", ""),
267
+ "tool_version": tool.get("tool_version", ""),
268
+ "version_known": bool(provenance_detail.get("version_known")),
269
+ "version_source": _safe_text(
270
+ provenance_detail.get("version_source")
271
+ ),
272
+ "command": _safe_text(provenance_detail.get("command")),
273
+ "command_found": bool(provenance_detail.get("command_found")),
261
274
  "env_names": list(env_names),
262
275
  "preferred_env": preferred_env,
263
276
  "env_status": env_status,
@@ -267,11 +280,17 @@ def build_provider_model_env_report(
267
280
  )
268
281
  unknown = sorted(requested - matched)
269
282
  missing = [row for row in rows if row["action"] == "set_model_env"]
283
+ missing_version_probe = [
284
+ row
285
+ for row in rows
286
+ if row["driver"] == "local_cli" and row["version_source"] == "missing"
287
+ ]
270
288
  return {
271
289
  "mode": "code-mower-provider-model-env-report",
272
290
  "providers": rows,
273
291
  "provider_count": len(rows),
274
292
  "missing_model_env_count": len(missing),
293
+ "missing_version_probe_count": len(missing_version_probe),
275
294
  "unknown_providers": unknown,
276
295
  "status": "fail" if unknown else "pass",
277
296
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b26
3
+ Version: 0.5.0b28
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.0b26
104
+ pipx install --python python3.12 code-mower==0.5.0b28
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b26` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b28` 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.0b26`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b28`.
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.26` from
256
+ The current public beta is `v0.5.0-beta.28` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b26` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b28` 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.0b26",
302
+ "tool_version": "0.5.0b28",
303
303
  "provider": "code-mower",
304
304
  "model": "",
305
305
  "model_source": "not_applicable",
@@ -460,6 +460,68 @@ def test_cloud_doctor_warns_when_model_provenance_is_missing() -> None:
460
460
  assert "CODE_MOWER_CODEX_MODEL" in check["remediation"]
461
461
 
462
462
 
463
+ def test_cloud_doctor_fans_out_multiple_model_provenance_commands() -> None:
464
+ with tempfile.TemporaryDirectory() as tmp:
465
+ root = Path(tmp)
466
+ build_cloud_bundle(
467
+ reports=[],
468
+ events=[
469
+ {
470
+ "event_type": "reviewer_run",
471
+ "repo_slug": "owner/repo",
472
+ "provider": "codex",
473
+ "lens": "base",
474
+ "status": "pass",
475
+ "tool": {
476
+ "role": "reviewer",
477
+ "tool_name": "codex",
478
+ "provider": "codex",
479
+ "tool_version": "0.142.0",
480
+ "model_source": "missing",
481
+ },
482
+ },
483
+ {
484
+ "event_type": "reviewer_run",
485
+ "repo_slug": "owner/repo",
486
+ "provider": "gemini",
487
+ "lens": "base",
488
+ "status": "pass",
489
+ "tool": {
490
+ "role": "reviewer",
491
+ "tool_name": "gemini",
492
+ "provider": "gemini",
493
+ "tool_version": "0.45.2",
494
+ "model_source": "missing",
495
+ },
496
+ },
497
+ ],
498
+ output_dir=root / "bundle",
499
+ repo_slug="owner/repo",
500
+ )
501
+
502
+ report = run_cloud_doctor(
503
+ bundle_dir=root / "bundle",
504
+ endpoint="https://codemower.com/api/ingest",
505
+ token_env="CODE_MOWER_TEST_CLOUD_TOKEN",
506
+ require_token=False,
507
+ )
508
+
509
+ check = next(
510
+ item for item in report["checks"] if item["name"] == "model-provenance"
511
+ )
512
+ assert check["status"] == "warn"
513
+ assert check["detail"]["model_env_commands"] == [
514
+ "code-mower providers provenance-env --provider codex --shell",
515
+ "code-mower providers provenance-env --provider gemini --shell",
516
+ ]
517
+ assert check["detail"]["model_env_command_all"] == (
518
+ "code-mower providers provenance-env --provider codex "
519
+ "--provider gemini --shell"
520
+ )
521
+ assert "detail.model_env_commands" in check["remediation"]
522
+ assert "detail.model_env_command_all" in check["remediation"]
523
+
524
+
463
525
  def test_cloud_doctor_passes_when_model_provenance_is_complete() -> None:
464
526
  with tempfile.TemporaryDirectory() as tmp:
465
527
  root = Path(tmp)
@@ -178,6 +178,65 @@ def test_provider_model_env_report_never_exposes_env_value(monkeypatch) -> None:
178
178
  assert row["action"] == "none"
179
179
 
180
180
 
181
+ def test_provider_model_env_report_includes_cli_version_status(
182
+ monkeypatch,
183
+ tmp_path: Path,
184
+ ) -> None:
185
+ executable = _write_executable(
186
+ tmp_path / "custom-reviewer",
187
+ "#!/bin/sh\nprintf 'custom-reviewer 2.0.0\\n'\n",
188
+ )
189
+ monkeypatch.setenv("PATH", os.fspath(executable.parent))
190
+ monkeypatch.setenv("CUSTOM_REVIEWER_MODEL", "do-not-render-this-model")
191
+ lanes = {
192
+ "custom_reviewer": {
193
+ "driver": "local_cli",
194
+ "provider": "custom",
195
+ "provider_config": {
196
+ "command": "custom-reviewer",
197
+ "model_env": "CUSTOM_REVIEWER_MODEL",
198
+ },
199
+ }
200
+ }
201
+
202
+ report = build_provider_model_env_report(lanes)
203
+
204
+ assert report["missing_model_env_count"] == 0
205
+ assert report["missing_version_probe_count"] == 0
206
+ row = report["providers"][0]
207
+ assert row["tool_name"] == "custom-reviewer"
208
+ assert row["tool_version"] == "custom-reviewer 2.0.0"
209
+ assert row["version_known"] is True
210
+ assert row["version_source"] == "cli_version_probe"
211
+ assert row["command"] == "custom-reviewer"
212
+ assert row["command_found"] is True
213
+ assert "do-not-render-this-model" not in str(report)
214
+
215
+
216
+ def test_provider_model_env_report_counts_missing_cli_version_probe(monkeypatch) -> None:
217
+ monkeypatch.setenv("PATH", "")
218
+ lanes = {
219
+ "missing_reviewer": {
220
+ "driver": "local_cli",
221
+ "provider": "missing",
222
+ "provider_config": {
223
+ "command": "missing-reviewer",
224
+ "model_env": "MISSING_REVIEWER_MODEL",
225
+ },
226
+ }
227
+ }
228
+
229
+ report = build_provider_model_env_report(lanes)
230
+
231
+ assert report["missing_model_env_count"] == 1
232
+ assert report["missing_version_probe_count"] == 1
233
+ row = report["providers"][0]
234
+ assert row["version_known"] is False
235
+ assert row["version_source"] == "missing"
236
+ assert row["command"] == "missing-reviewer"
237
+ assert row["command_found"] is False
238
+
239
+
181
240
  def test_providers_provenance_env_cli_shell_output(monkeypatch, capsys) -> None:
182
241
  monkeypatch.delenv("CODE_MOWER_ANTIGRAVITY_MODEL", raising=False)
183
242
  monkeypatch.delenv("ANTIGRAVITY_MODEL", raising=False)
@@ -377,11 +436,11 @@ def test_provider_lane_tool_provenance_reads_model_from_selected_profile(
377
436
  def test_code_mower_reporter_provenance_marks_model_not_applicable() -> None:
378
437
  tool = build_code_mower_tool_provenance(
379
438
  source="unit-test",
380
- version="0.5.0b26",
439
+ version="0.5.0b28",
381
440
  )
382
441
 
383
442
  assert tool["tool_name"] == "code-mower"
384
- assert tool["tool_version"] == "0.5.0b26"
443
+ assert tool["tool_version"] == "0.5.0b28"
385
444
  assert tool["provider"] == "code-mower"
386
445
  assert tool["model"] == ""
387
446
  assert tool["model_source"] == "not_applicable"
@@ -49,7 +49,7 @@ from scripts import privacy_scan
49
49
 
50
50
  class ReleaseHygieneTests(unittest.TestCase):
51
51
  def test_version_is_current_v05_prerelease(self) -> None:
52
- self.assertEqual(__version__, "0.5.0b26")
52
+ self.assertEqual(__version__, "0.5.0b28")
53
53
 
54
54
  def test_release_workflow_verifies_downloaded_distributions_before_publish(self) -> None:
55
55
  workflow = (ROOT / ".github/workflows/release.yml").read_text(encoding="utf-8")
@@ -199,7 +199,7 @@ class ReleaseHygieneTests(unittest.TestCase):
199
199
  self.assertIn(
200
200
  (
201
201
  "code-mower migration package-install-rehearsal --package-spec "
202
- "code-mower==0.5.0b26 --json"
202
+ "code-mower==0.5.0b28 --json"
203
203
  ),
204
204
  help_text,
205
205
  )
@@ -1614,8 +1614,8 @@ printf '%s\\n' "${lane}"
1614
1614
  fromlist=["current_alpha_package_spec"],
1615
1615
  )
1616
1616
  self.assertEqual(
1617
- legacy_module.current_alpha_package_spec("0.5.0b26"),
1618
- "code-mower==0.5.0b26",
1617
+ legacy_module.current_alpha_package_spec("0.5.0b28"),
1618
+ "code-mower==0.5.0b28",
1619
1619
  )
1620
1620
  finally:
1621
1621
  sys.path[:] = original_path
@@ -1652,7 +1652,7 @@ printf '%s\\n' "${lane}"
1652
1652
  "-c",
1653
1653
  (
1654
1654
  "from tools import code_mower_package_content as c; "
1655
- "print(c.current_alpha_package_spec('0.5.0b26'))"
1655
+ "print(c.current_alpha_package_spec('0.5.0b28'))"
1656
1656
  ),
1657
1657
  ],
1658
1658
  cwd=tmp_path,
@@ -1665,7 +1665,7 @@ printf '%s\\n' "${lane}"
1665
1665
  self.assertEqual(completed.returncode, 0, completed.stderr)
1666
1666
  self.assertEqual(
1667
1667
  completed.stdout.strip(),
1668
- "code-mower==0.5.0b26",
1668
+ "code-mower==0.5.0b28",
1669
1669
  )
1670
1670
 
1671
1671
  def test_package_rendering_legacy_fallback_stays_valid_yaml_subset(self) -> None:
@@ -1741,11 +1741,11 @@ printf '%s\\n' "${lane}"
1741
1741
  (output_dir / "src/code_mower/cloud_client/dogfood.py").is_file()
1742
1742
  )
1743
1743
  self.assertIn(
1744
- 'version = "0.5.0b26"',
1744
+ 'version = "0.5.0b28"',
1745
1745
  (output_dir / "pyproject.toml").read_text(encoding="utf-8"),
1746
1746
  )
1747
1747
  self.assertIn(
1748
- '__version__ = "0.5.0b26"',
1748
+ '__version__ = "0.5.0b28"',
1749
1749
  (output_dir / "src/code_mower/__init__.py").read_text(
1750
1750
  encoding="utf-8"
1751
1751
  ),
@@ -3236,7 +3236,7 @@ def main():
3236
3236
  {
3237
3237
  "status": "pass",
3238
3238
  "package_spec": "code-mower",
3239
- "version": "code-mower 0.5.0b26",
3239
+ "version": "code-mower 0.5.0b28",
3240
3240
  "work_dir": "/tmp/code-mower-rehearsal",
3241
3241
  "toy_repo": "/tmp/code-mower-rehearsal/toy-repo",
3242
3242
  "step_count": 1,
@@ -3348,7 +3348,7 @@ def main():
3348
3348
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3349
3349
  toy_repo=toy_repo,
3350
3350
  outputs=outputs,
3351
- version="code-mower 0.5.0b26",
3351
+ version="code-mower 0.5.0b28",
3352
3352
  steps=[
3353
3353
  {
3354
3354
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3427,7 +3427,7 @@ def main():
3427
3427
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3428
3428
  toy_repo=toy_repo,
3429
3429
  outputs=outputs,
3430
- version="code-mower 0.5.0b26",
3430
+ version="code-mower 0.5.0b28",
3431
3431
  steps=[
3432
3432
  {
3433
3433
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3489,7 +3489,7 @@ def main():
3489
3489
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3490
3490
  toy_repo=toy_repo,
3491
3491
  outputs=outputs,
3492
- version="code-mower 0.5.0b26",
3492
+ version="code-mower 0.5.0b28",
3493
3493
  steps=[
3494
3494
  {
3495
3495
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3555,24 +3555,24 @@ def main():
3555
3555
  )
3556
3556
  self.assertEqual(
3557
3557
  code_mower_migration._resolve_install_package_spec(
3558
- "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.26",
3558
+ "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.28",
3559
3559
  base_dir=package,
3560
3560
  ),
3561
- "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.26",
3561
+ "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.28",
3562
3562
  )
3563
3563
  self.assertEqual(
3564
3564
  code_mower_migration._resolve_install_package_spec(
3565
- "code-mower==0.5.0b26",
3565
+ "code-mower==0.5.0b28",
3566
3566
  base_dir=package,
3567
3567
  ),
3568
- "code-mower==0.5.0b26",
3568
+ "code-mower==0.5.0b28",
3569
3569
  )
3570
3570
 
3571
3571
  def test_package_install_rehearsal_supports_index_aware_pip_install(self) -> None:
3572
3572
  self.assertEqual(
3573
3573
  code_mower_migration._pip_install_command(
3574
3574
  Path("/tmp/venv/bin/python"),
3575
- "code-mower==0.5.0b26",
3575
+ "code-mower==0.5.0b28",
3576
3576
  pip_index_url="https://test.pypi.org/simple/",
3577
3577
  pip_extra_index_urls=["https://pypi.org/simple/"],
3578
3578
  ),
@@ -3585,7 +3585,7 @@ def main():
3585
3585
  "https://test.pypi.org/simple/",
3586
3586
  "--extra-index-url",
3587
3587
  "https://pypi.org/simple/",
3588
- "code-mower==0.5.0b26",
3588
+ "code-mower==0.5.0b28",
3589
3589
  ],
3590
3590
  )
3591
3591
 
@@ -3605,10 +3605,10 @@ def main():
3605
3605
  payload = release_readiness.render_release_readiness(ROOT)
3606
3606
 
3607
3607
  self.assertEqual(payload["status"], "pass")
3608
- self.assertEqual(payload["version"], "0.5.0b26")
3609
- self.assertEqual(payload["release_tag"], "v0.5.0-beta.26")
3610
- self.assertEqual(payload["alpha_tag"], "v0.5.0-beta.26")
3611
- self.assertEqual(payload["package_index_spec"], "code-mower==0.5.0b26")
3608
+ self.assertEqual(payload["version"], "0.5.0b28")
3609
+ self.assertEqual(payload["release_tag"], "v0.5.0-beta.28")
3610
+ self.assertEqual(payload["alpha_tag"], "v0.5.0-beta.28")
3611
+ self.assertEqual(payload["package_index_spec"], "code-mower==0.5.0b28")
3612
3612
  check_ids = {check["id"]: check for check in payload["checks"]}
3613
3613
  self.assertEqual(check_ids["package-version-consistency"]["status"], "pass")
3614
3614
  self.assertEqual(
@@ -3657,7 +3657,7 @@ def main():
3657
3657
  check_ids = {check["id"]: check for check in payload["checks"]}
3658
3658
  check = check_ids["materialized-package-version-consistency"]
3659
3659
  self.assertEqual(check["status"], "fail")
3660
- self.assertEqual(check["detail"]["source_version"], "0.5.0b26")
3660
+ self.assertEqual(check["detail"]["source_version"], "0.5.0b28")
3661
3661
  self.assertEqual(check["detail"]["generated_init_version"], "0.0.0")
3662
3662
 
3663
3663
  def test_public_support_docs_are_packaged_and_privacy_forward(self) -> None:
@@ -3737,20 +3737,20 @@ def main():
3737
3737
 
3738
3738
  def test_release_readiness_tag_derivation_supports_release_stages(self) -> None:
3739
3739
  self.assertEqual(
3740
- release_readiness._release_tag_for_version("0.5.0b26"),
3741
- "v0.5.0-beta.26",
3740
+ release_readiness._release_tag_for_version("0.5.0b28"),
3741
+ "v0.5.0-beta.28",
3742
3742
  )
3743
3743
  self.assertEqual(
3744
- code_mower_versioning.release_tag_for_version("0.5.0b26"),
3745
- "v0.5.0-beta.26",
3744
+ code_mower_versioning.release_tag_for_version("0.5.0b28"),
3745
+ "v0.5.0-beta.28",
3746
3746
  )
3747
3747
  self.assertEqual(
3748
- release_readiness._release_tag_for_version("0.5.0b26"),
3749
- "v0.5.0-beta.26",
3748
+ release_readiness._release_tag_for_version("0.5.0b28"),
3749
+ "v0.5.0-beta.28",
3750
3750
  )
3751
3751
  self.assertEqual(
3752
- code_mower_versioning.release_tag_for_version("0.5.0b26"),
3753
- "v0.5.0-beta.26",
3752
+ code_mower_versioning.release_tag_for_version("0.5.0b28"),
3753
+ "v0.5.0-beta.28",
3754
3754
  )
3755
3755
  self.assertEqual(
3756
3756
  release_readiness._release_tag_for_version("1.0.0rc1"),
@@ -3779,8 +3779,8 @@ def main():
3779
3779
  next_steps.current_alpha_package_spec(),
3780
3780
  )
3781
3781
  self.assertEqual(
3782
- code_mower_package_content.current_alpha_package_spec("0.5.0b26"),
3783
- "code-mower==0.5.0b26",
3782
+ code_mower_package_content.current_alpha_package_spec("0.5.0b28"),
3783
+ "code-mower==0.5.0b28",
3784
3784
  )
3785
3785
  self.assertNotIn(next_steps.current_public_tag(), package_content_text)
3786
3786
  self.assertNotIn("v0.0.0", package_content_text)
@@ -3952,7 +3952,7 @@ def main():
3952
3952
  step for step in plan["steps"] if step["id"] == "package-install-rehearsal"
3953
3953
  )
3954
3954
  self.assertIn("doctor --v05", doctor_step["command"])
3955
- self.assertIn("code-mower==0.5.0b26", package_step["command"])
3955
+ self.assertIn("code-mower==0.5.0b28", package_step["command"])
3956
3956
  self.assertIn("current published PyPI prerelease", package_step["why"])
3957
3957
  self.assertIn("first_user_readiness", package_step["why"])
3958
3958
  self.assertEqual(
File without changes
File without changes
File without changes
File without changes