code-mower 0.5.0b14__tar.gz → 0.5.0b15__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 (268) hide show
  1. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/PKG-INFO +6 -6
  2. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/README.md +5 -5
  3. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/pyproject.toml +1 -1
  4. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cli.py +1 -1
  6. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/providers/provenance.py +42 -13
  7. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/release_readiness.py +6 -0
  8. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/PKG-INFO +6 -6
  9. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_local_cli.py +35 -0
  10. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_release_hygiene.py +65 -34
  11. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/CODE_OF_CONDUCT.md +0 -0
  12. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/LICENSE +0 -0
  13. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/MANIFEST.in +0 -0
  14. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/NOTICE +0 -0
  15. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/SUPPORT.md +0 -0
  16. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/requirements/requirements.txt +0 -0
  17. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/setup.cfg +0 -0
  18. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/__init__.py +0 -0
  19. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/_base.py +0 -0
  20. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  21. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/gitar.py +0 -0
  22. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/greptile.py +0 -0
  23. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/adapters/qodo.py +0 -0
  24. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  25. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/audit_handoff_log.py +0 -0
  26. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/audit_labeler_lib.py +0 -0
  27. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/audit_progress.py +0 -0
  28. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/blind_review_artifacts.py +0 -0
  29. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/blind_review_coordinator.py +0 -0
  30. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/bootstrap.py +0 -0
  31. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/builder_experiment.py +0 -0
  32. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/__init__.py +0 -0
  33. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/arms.py +0 -0
  34. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/auto_discovery.py +0 -0
  35. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/commands.py +0 -0
  36. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/context_inputs.py +0 -0
  37. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/corpus.py +0 -0
  38. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/effect_report.py +0 -0
  39. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/evidence.py +0 -0
  40. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/evidence_report.py +0 -0
  41. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/identity.py +0 -0
  42. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/metrics.py +0 -0
  43. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/overlap.py +0 -0
  44. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/planning.py +0 -0
  45. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/policy.py +0 -0
  46. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/results.py +0 -0
  47. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/run_results.py +0 -0
  48. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/run_status.py +0 -0
  49. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/runner.py +0 -0
  50. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/truth.py +0 -0
  51. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/calibration/value_report.py +0 -0
  52. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/checks.py +0 -0
  53. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/claude_audit_pr.py +0 -0
  54. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/claude_cli_bounce.py +0 -0
  55. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/claude_cli_environment.py +0 -0
  56. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/clear_stale.py +0 -0
  57. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud.py +0 -0
  58. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/__init__.py +0 -0
  59. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/bundle.py +0 -0
  60. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/doctor.py +0 -0
  61. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/dogfood.py +0 -0
  62. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/endpoints.py +0 -0
  63. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/errors.py +0 -0
  64. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/events.py +0 -0
  65. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/export.py +0 -0
  66. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/git_metadata.py +0 -0
  67. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/manifest.py +0 -0
  68. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/operations.py +0 -0
  69. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/reports.py +0 -0
  70. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/setup.py +0 -0
  71. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/cloud_client/upload.py +0 -0
  72. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/code_mower_calibration.py +0 -0
  73. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/code_mower_context_packs.py +0 -0
  74. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/code_mower_merge.py +0 -0
  75. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/code_mower_telemetry.py +0 -0
  76. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  77. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/codex_audit_env_preflight.py +0 -0
  78. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/codex_audit_pr.py +0 -0
  79. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  80. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  81. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/config.py +0 -0
  82. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor.py +0 -0
  83. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/__init__.py +0 -0
  84. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/cloud.py +0 -0
  85. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/common.py +0 -0
  86. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github.py +0 -0
  87. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions.py +0 -0
  88. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  89. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  90. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  91. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  92. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  93. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  94. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  95. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  96. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_api.py +0 -0
  97. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_branch.py +0 -0
  98. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_config.py +0 -0
  99. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_provider.py +0 -0
  100. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/github_repo.py +0 -0
  101. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/groups.py +0 -0
  102. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/models.py +0 -0
  103. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/output.py +0 -0
  104. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/presets.py +0 -0
  105. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/privacy.py +0 -0
  106. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  107. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  108. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  109. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_env.py +0 -0
  110. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  111. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  112. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  113. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  114. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  115. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  116. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  117. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  118. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  119. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  120. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/providers.py +0 -0
  121. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/registry.py +0 -0
  122. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/runner.py +0 -0
  123. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/runtime.py +0 -0
  124. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  125. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  126. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  127. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/init.py +0 -0
  128. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/__init__.py +0 -0
  129. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/aider.py +0 -0
  130. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  131. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/claude.py +0 -0
  132. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/codex.py +0 -0
  133. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/devin.py +0 -0
  134. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  135. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  136. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/lane_configs/local_llm.py +0 -0
  137. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/local_llm_audit_pr.py +0 -0
  138. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/local_llm_bakeoff.py +0 -0
  139. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/local_llm_calibration.py +0 -0
  140. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/local_llm_profiles.py +0 -0
  141. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/migration.py +0 -0
  142. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/migration_install.py +0 -0
  143. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/migration_mirror.py +0 -0
  144. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/migration_readiness.py +0 -0
  145. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/migration_rehearsal.py +0 -0
  146. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/next_steps.py +0 -0
  147. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package.py +0 -0
  148. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package_content.py +0 -0
  149. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package_manifest.py +0 -0
  150. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package_paths.py +0 -0
  151. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package_rendering.py +0 -0
  152. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/package_static.py +0 -0
  153. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/prompts.py +0 -0
  154. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_registry.py +0 -0
  155. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/__init__.py +0 -0
  156. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/comments.py +0 -0
  157. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/git.py +0 -0
  158. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/github_auth.py +0 -0
  159. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/github_pr.py +0 -0
  160. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  161. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/process.py +0 -0
  162. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/repo_paths.py +0 -0
  163. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/text_schema.py +0 -0
  164. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  165. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/provider_runners/workspace.py +0 -0
  166. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/providers/__init__.py +0 -0
  167. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/providers/local_cli.py +0 -0
  168. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/reviewer_metrics.py +0 -0
  169. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/saas_reviewer_labeler.py +0 -0
  170. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/secrets.py +0 -0
  171. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/builder-experiment.example.json +0 -0
  172. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  173. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/calibration-corpus.json +0 -0
  174. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/code-mower.example.yml +0 -0
  175. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/context-packs.example.json +0 -0
  176. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  177. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  178. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  179. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  180. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  181. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  182. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  183. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  184. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/code_mower +0 -0
  185. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  186. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  187. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  188. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  189. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  190. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/providers.yml +0 -0
  191. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  192. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  193. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  194. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  195. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  196. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  197. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  198. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  199. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  200. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/trailer_comment_labeler.py +0 -0
  201. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower/versioning.py +0 -0
  202. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/SOURCES.txt +0 -0
  203. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/dependency_links.txt +0 -0
  204. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/entry_points.txt +0 -0
  205. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/requires.txt +0 -0
  206. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/src/code_mower.egg-info/top_level.txt +0 -0
  207. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/builder-experiment.example.json +0 -0
  208. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/calibration-corpus.example.json +0 -0
  209. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/calibration-corpus.json +0 -0
  210. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/code-mower.yml.j2 +0 -0
  211. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/context-packs.example.json +0 -0
  212. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/cursor/BUGBOT.md +0 -0
  213. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/acp_bridge.yml +0 -0
  214. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/aider.yml +0 -0
  215. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/antigravity_cli.yml +0 -0
  216. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/claude_audit.yml +0 -0
  217. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/claude_review.yml +0 -0
  218. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/coderabbit_cli.yml +0 -0
  219. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/codex.yml +0 -0
  220. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/cursor_bugbot.yml +0 -0
  221. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/devin.yml +0 -0
  222. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/gemini_cli.yml +0 -0
  223. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/gitar.yml +0 -0
  224. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/greptile.yml +0 -0
  225. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/hermes_cli.yml +0 -0
  226. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/local_llm.yml +0 -0
  227. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers/qodo.yml +0 -0
  228. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/providers.yml +0 -0
  229. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/reviewer-spend.example.json +0 -0
  230. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/reviewer-value-report.example.md +0 -0
  231. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  232. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  233. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  234. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  235. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  236. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  237. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  238. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  239. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_calibration_effect_report.py +0 -0
  240. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_calibration_truth.py +0 -0
  241. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_checks.py +0 -0
  242. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_claude_cli_bounce.py +0 -0
  243. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_clear_stale.py +0 -0
  244. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_cloud_client.py +0 -0
  245. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_cloud_git_metadata.py +0 -0
  246. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_cloud_manifest.py +0 -0
  247. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_cloud_reports.py +0 -0
  248. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  249. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_actions_cost_summary.py +0 -0
  250. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_actions_failure_selection.py +0 -0
  251. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_boundaries.py +0 -0
  252. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_github_checks.py +0 -0
  253. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_output.py +0 -0
  254. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_privacy.py +0 -0
  255. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_provider_env_required.py +0 -0
  256. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_provider_env_tokens.py +0 -0
  257. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_provider_probe.py +0 -0
  258. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_doctor_registry.py +0 -0
  259. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_local_llm_github_helpers.py +0 -0
  260. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_comments.py +0 -0
  261. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_git.py +0 -0
  262. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_github_pr.py +0 -0
  263. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_pr_worktree.py +0 -0
  264. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_process.py +0 -0
  265. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_repo_paths.py +0 -0
  266. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_text_schema.py +0 -0
  267. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/tests/test_provider_runners_workspace.py +0 -0
  268. {code_mower-0.5.0b14 → code_mower-0.5.0b15}/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.0b14
3
+ Version: 0.5.0b15
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.0b14
104
+ pipx install --python python3.12 code-mower==0.5.0b15
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b14` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b15` 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.0b14`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b15`.
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.14` from
256
+ The current public beta is `v0.5.0-beta.15` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b14` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b15` 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.0b14
89
+ pipx install --python python3.12 code-mower==0.5.0b15
90
90
  code-mower --version
91
91
  ```
92
92
 
93
- `0.5.0b14` is a beta release. Until Code Mower publishes a stable `1.0`
93
+ `0.5.0b15` 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.0b14`.
136
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b15`.
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.14` from
241
+ The current public beta is `v0.5.0-beta.15` from
242
242
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
243
- as `code-mower==0.5.0b14` on [PyPI](https://pypi.org/project/code-mower/).
243
+ as `code-mower==0.5.0b15` 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.0b14"
7
+ version = "0.5.0b15"
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.0b14"
3
+ __version__ = "0.5.0b15"
@@ -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.0b14`, or run source checkouts with "
17
+ "`pipx install code-mower==0.5.0b15`, or run source checkouts with "
18
18
  "`PYTHONPATH=src python -m code_mower.cli`."
19
19
  )
20
20
 
@@ -143,22 +143,50 @@ def _first_text(values: Any) -> str:
143
143
  return ""
144
144
 
145
145
 
146
+ def _text_values(values: Any) -> tuple[str, ...]:
147
+ if isinstance(values, str):
148
+ text = _safe_text(values)
149
+ return (text,) if text else ()
150
+ if isinstance(values, (list, tuple)):
151
+ result: list[str] = []
152
+ for value in values:
153
+ text = _safe_text(value)
154
+ if text and text not in result:
155
+ result.append(text)
156
+ return tuple(result)
157
+ return ()
158
+
159
+
146
160
  def _env_value(config: Mapping[str, Any], key: str) -> str:
147
161
  env_name = _safe_text(config.get(key))
148
162
  return _safe_text(os.environ.get(env_name)) if env_name else ""
149
163
 
150
164
 
151
- def _configured_command(config: Mapping[str, Any], provider: str) -> str:
165
+ def _configured_command_candidates(
166
+ config: Mapping[str, Any],
167
+ provider: str,
168
+ ) -> tuple[str, ...]:
152
169
  override = _env_value(config, "command_env")
153
170
  if override:
154
- return override
171
+ return (override,)
172
+ candidates: list[str] = []
155
173
  command = _safe_text(config.get("command"))
156
174
  if command:
157
- return command
158
- alternate = _first_text(config.get("alternate_commands"))
159
- if alternate:
160
- return alternate
161
- return provider
175
+ candidates.append(command)
176
+ for alternate in _text_values(config.get("alternate_commands")):
177
+ if alternate not in candidates:
178
+ candidates.append(alternate)
179
+ if not candidates:
180
+ candidates.append(provider)
181
+ return tuple(candidates)
182
+
183
+
184
+ def _select_available_command(candidates: tuple[str, ...]) -> tuple[str, str]:
185
+ for command in candidates:
186
+ resolved = shutil.which(command)
187
+ if resolved:
188
+ return command, resolved
189
+ return (candidates[0] if candidates else "", "")
162
190
 
163
191
 
164
192
  def build_provider_lane_tool_provenance(
@@ -178,7 +206,8 @@ def build_provider_lane_tool_provenance(
178
206
  config = _provider_config(lane)
179
207
  provider = _safe_text(_lane_value(lane, "provider")) or lane_id
180
208
  driver = _safe_text(_lane_value(lane, "driver")) or "unknown"
181
- command = _configured_command(config, provider)
209
+ command_candidates = _configured_command_candidates(config, provider)
210
+ command, resolved_command = _select_available_command(command_candidates)
182
211
  model = _env_value(config, "model_env") or _safe_text(config.get("default_model"))
183
212
  provider_from_env = _env_value(config, "provider_env")
184
213
  if provider_from_env:
@@ -197,16 +226,16 @@ def build_provider_lane_tool_provenance(
197
226
  "lane_id": lane_id,
198
227
  "driver": driver,
199
228
  "command": command if driver == "local_cli" else "",
229
+ "command_candidates": list(command_candidates) if driver == "local_cli" else [],
200
230
  "model_known": bool(model),
201
231
  "version_known": False,
202
232
  }
203
233
  tool_version = ""
204
234
  if driver == "local_cli" and include_version_probe and command:
205
- resolved = shutil.which(command)
206
- detail["command_found"] = bool(resolved)
207
- if resolved:
208
- detail["path_basename"] = os.path.basename(resolved)
209
- version_detail = detect_local_cli_version(resolved)
235
+ detail["command_found"] = bool(resolved_command)
236
+ if resolved_command:
237
+ detail["path_basename"] = os.path.basename(resolved_command)
238
+ version_detail = detect_local_cli_version(resolved_command)
210
239
  tool_version = _safe_text(version_detail.get("tool_version"))
211
240
  detail["version_known"] = bool(tool_version)
212
241
  detail["tool_version_available"] = bool(
@@ -358,6 +358,9 @@ def render_release_readiness(repo_path: Path) -> dict[str, Any]:
358
358
  if (
359
359
  _needs_job(testpypi_job, "verify-distributions")
360
360
  and "inputs.publish_testpypi" in testpypi_job_text
361
+ and "inputs.publish_testpypi == true" in testpypi_job_text
362
+ and "github.event_name == 'workflow_dispatch'" in testpypi_job_text
363
+ and "github.event_name == 'release'" in testpypi_job_text
361
364
  and "CODE_MOWER_TESTPYPI_PUBLISH" in testpypi_job_text
362
365
  and _job_uses_environment(testpypi_job, "testpypi")
363
366
  and _permissions_include(testpypi_job, "id-token", "write")
@@ -376,6 +379,9 @@ def render_release_readiness(repo_path: Path) -> dict[str, Any]:
376
379
  if (
377
380
  _needs_job(pypi_job, "verify-distributions")
378
381
  and "inputs.publish_pypi" in pypi_job_text
382
+ and "inputs.publish_pypi == true" in pypi_job_text
383
+ and "github.event_name == 'workflow_dispatch'" in pypi_job_text
384
+ and "github.event_name == 'release'" in pypi_job_text
379
385
  and "CODE_MOWER_PYPI_PUBLISH" in pypi_job_text
380
386
  and _job_uses_environment(pypi_job, "pypi")
381
387
  and _permissions_include(pypi_job, "id-token", "write")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.5.0b14
3
+ Version: 0.5.0b15
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.0b14
104
+ pipx install --python python3.12 code-mower==0.5.0b15
105
105
  code-mower --version
106
106
  ```
107
107
 
108
- `0.5.0b14` is a beta release. Until Code Mower publishes a stable `1.0`
108
+ `0.5.0b15` 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.0b14`.
151
+ the latest 10/10 public-package readiness proof for `code-mower==0.5.0b15`.
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.14` from
256
+ The current public beta is `v0.5.0-beta.15` from
257
257
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
258
- as `code-mower==0.5.0b14` on [PyPI](https://pypi.org/project/code-mower/).
258
+ as `code-mower==0.5.0b15` 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
 
@@ -83,6 +83,41 @@ def test_provider_lane_tool_provenance_reads_version_and_model_env(
83
83
  assert tool["model"] == "model-v1"
84
84
  assert tool["lens"] == "security-threat-model"
85
85
  assert detail["lane_id"] == "gemini_cli"
86
+ assert detail["command_candidates"] == ["provider-cli"]
86
87
  assert detail["command_found"] is True
87
88
  assert detail["model_known"] is True
88
89
  assert detail["version_known"] is True
90
+
91
+
92
+ def test_provider_lane_tool_provenance_uses_available_alternate_command(
93
+ monkeypatch,
94
+ tmp_path: Path,
95
+ ) -> None:
96
+ executable = _write_executable(
97
+ tmp_path / "antigravity",
98
+ "#!/bin/sh\nprintf 'antigravity 1.2.3\\n'\n",
99
+ )
100
+ monkeypatch.setenv("PATH", os.fspath(executable.parent))
101
+ lane = {
102
+ "driver": "local_cli",
103
+ "provider": "antigravity",
104
+ "provider_config": {
105
+ "command": "agy",
106
+ "alternate_commands": ("antigravity",),
107
+ "model_env": "ANTIGRAVITY_MODEL",
108
+ },
109
+ }
110
+
111
+ tool, detail = build_provider_lane_tool_provenance(
112
+ "antigravity_cli",
113
+ lane,
114
+ source="unit-test",
115
+ )
116
+
117
+ assert tool["tool_name"] == "antigravity"
118
+ assert tool["tool_version"] == "antigravity 1.2.3"
119
+ assert tool["provider"] == "antigravity"
120
+ assert detail["command"] == "antigravity"
121
+ assert detail["command_candidates"] == ["agy", "antigravity"]
122
+ assert detail["command_found"] is True
123
+ assert detail["version_known"] is True
@@ -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.0b14")
52
+ self.assertEqual(__version__, "0.5.0b15")
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")
@@ -81,6 +81,9 @@ class ReleaseHygieneTests(unittest.TestCase):
81
81
  )[0]
82
82
  self.assertIn(" needs: verify-distributions\n", testpypi_job)
83
83
  self.assertIn("inputs.publish_testpypi", testpypi_job)
84
+ self.assertIn("inputs.publish_testpypi == true", testpypi_job)
85
+ self.assertIn("github.event_name == 'workflow_dispatch'", testpypi_job)
86
+ self.assertIn("github.event_name == 'release'", testpypi_job)
84
87
  self.assertIn("CODE_MOWER_TESTPYPI_PUBLISH", testpypi_job)
85
88
  self.assertIn(" environment: testpypi\n", testpypi_job)
86
89
  self.assertIn("repository-url: https://test.pypi.org/legacy/", testpypi_job)
@@ -90,10 +93,38 @@ class ReleaseHygieneTests(unittest.TestCase):
90
93
  )
91
94
  production_job = workflow.split(" publish-pypi:\n", 1)[1]
92
95
  self.assertIn("inputs.publish_pypi", production_job)
96
+ self.assertIn("inputs.publish_pypi == true", production_job)
97
+ self.assertIn("github.event_name == 'workflow_dispatch'", production_job)
98
+ self.assertIn("github.event_name == 'release'", production_job)
93
99
  self.assertIn("CODE_MOWER_PYPI_PUBLISH", production_job)
94
100
  self.assertIn(" environment: pypi\n", production_job)
95
101
  self.assertNotIn("test.pypi.org", production_job)
96
102
 
103
+ def test_release_workflow_variables_only_apply_to_release_events(self) -> None:
104
+ workflow = (ROOT / ".github/workflows/release.yml").read_text(encoding="utf-8")
105
+ testpypi_job = workflow.split(" publish-testpypi:\n", 1)[1].split(
106
+ " publish-pypi:\n",
107
+ 1,
108
+ )[0]
109
+ production_job = workflow.split(" publish-pypi:\n", 1)[1]
110
+
111
+ self.assertIn(
112
+ "(github.event_name == 'release' && vars.CODE_MOWER_TESTPYPI_PUBLISH == 'true')",
113
+ testpypi_job,
114
+ )
115
+ self.assertIn(
116
+ "(github.event_name == 'release' && vars.CODE_MOWER_PYPI_PUBLISH == 'true')",
117
+ production_job,
118
+ )
119
+ self.assertNotIn(
120
+ "(github.event_name == 'workflow_dispatch' && vars.CODE_MOWER_TESTPYPI_PUBLISH",
121
+ testpypi_job,
122
+ )
123
+ self.assertNotIn(
124
+ "(github.event_name == 'workflow_dispatch' && vars.CODE_MOWER_PYPI_PUBLISH",
125
+ production_job,
126
+ )
127
+
97
128
  def test_ci_workflow_runs_release_readiness_gate(self) -> None:
98
129
  workflow = (ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8")
99
130
 
@@ -168,7 +199,7 @@ class ReleaseHygieneTests(unittest.TestCase):
168
199
  self.assertIn(
169
200
  (
170
201
  "code-mower migration package-install-rehearsal --package-spec "
171
- "code-mower==0.5.0b14 --json"
202
+ "code-mower==0.5.0b15 --json"
172
203
  ),
173
204
  help_text,
174
205
  )
@@ -1583,8 +1614,8 @@ printf '%s\\n' "${lane}"
1583
1614
  fromlist=["current_alpha_package_spec"],
1584
1615
  )
1585
1616
  self.assertEqual(
1586
- legacy_module.current_alpha_package_spec("0.5.0b14"),
1587
- "code-mower==0.5.0b14",
1617
+ legacy_module.current_alpha_package_spec("0.5.0b15"),
1618
+ "code-mower==0.5.0b15",
1588
1619
  )
1589
1620
  finally:
1590
1621
  sys.path[:] = original_path
@@ -1621,7 +1652,7 @@ printf '%s\\n' "${lane}"
1621
1652
  "-c",
1622
1653
  (
1623
1654
  "from tools import code_mower_package_content as c; "
1624
- "print(c.current_alpha_package_spec('0.5.0b14'))"
1655
+ "print(c.current_alpha_package_spec('0.5.0b15'))"
1625
1656
  ),
1626
1657
  ],
1627
1658
  cwd=tmp_path,
@@ -1634,7 +1665,7 @@ printf '%s\\n' "${lane}"
1634
1665
  self.assertEqual(completed.returncode, 0, completed.stderr)
1635
1666
  self.assertEqual(
1636
1667
  completed.stdout.strip(),
1637
- "code-mower==0.5.0b14",
1668
+ "code-mower==0.5.0b15",
1638
1669
  )
1639
1670
 
1640
1671
  def test_package_rendering_legacy_fallback_stays_valid_yaml_subset(self) -> None:
@@ -1710,11 +1741,11 @@ printf '%s\\n' "${lane}"
1710
1741
  (output_dir / "src/code_mower/cloud_client/dogfood.py").is_file()
1711
1742
  )
1712
1743
  self.assertIn(
1713
- 'version = "0.5.0b14"',
1744
+ 'version = "0.5.0b15"',
1714
1745
  (output_dir / "pyproject.toml").read_text(encoding="utf-8"),
1715
1746
  )
1716
1747
  self.assertIn(
1717
- '__version__ = "0.5.0b14"',
1748
+ '__version__ = "0.5.0b15"',
1718
1749
  (output_dir / "src/code_mower/__init__.py").read_text(
1719
1750
  encoding="utf-8"
1720
1751
  ),
@@ -3205,7 +3236,7 @@ def main():
3205
3236
  {
3206
3237
  "status": "pass",
3207
3238
  "package_spec": "code-mower",
3208
- "version": "code-mower 0.5.0b14",
3239
+ "version": "code-mower 0.5.0b15",
3209
3240
  "work_dir": "/tmp/code-mower-rehearsal",
3210
3241
  "toy_repo": "/tmp/code-mower-rehearsal/toy-repo",
3211
3242
  "step_count": 1,
@@ -3317,7 +3348,7 @@ def main():
3317
3348
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3318
3349
  toy_repo=toy_repo,
3319
3350
  outputs=outputs,
3320
- version="code-mower 0.5.0b14",
3351
+ version="code-mower 0.5.0b15",
3321
3352
  steps=[
3322
3353
  {
3323
3354
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3396,7 +3427,7 @@ def main():
3396
3427
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3397
3428
  toy_repo=toy_repo,
3398
3429
  outputs=outputs,
3399
- version="code-mower 0.5.0b14",
3430
+ version="code-mower 0.5.0b15",
3400
3431
  steps=[
3401
3432
  {
3402
3433
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3458,7 +3489,7 @@ def main():
3458
3489
  scorecard = code_mower_migration._first_user_readiness_scorecard(
3459
3490
  toy_repo=toy_repo,
3460
3491
  outputs=outputs,
3461
- version="code-mower 0.5.0b14",
3492
+ version="code-mower 0.5.0b15",
3462
3493
  steps=[
3463
3494
  {
3464
3495
  "command": ["code-mower", "doctor", "--easy", "--json"],
@@ -3524,24 +3555,24 @@ def main():
3524
3555
  )
3525
3556
  self.assertEqual(
3526
3557
  code_mower_migration._resolve_install_package_spec(
3527
- "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.14",
3558
+ "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.15",
3528
3559
  base_dir=package,
3529
3560
  ),
3530
- "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.14",
3561
+ "git+https://github.com/codemower-ai/code-mower.git@v0.5.0-beta.15",
3531
3562
  )
3532
3563
  self.assertEqual(
3533
3564
  code_mower_migration._resolve_install_package_spec(
3534
- "code-mower==0.5.0b14",
3565
+ "code-mower==0.5.0b15",
3535
3566
  base_dir=package,
3536
3567
  ),
3537
- "code-mower==0.5.0b14",
3568
+ "code-mower==0.5.0b15",
3538
3569
  )
3539
3570
 
3540
3571
  def test_package_install_rehearsal_supports_index_aware_pip_install(self) -> None:
3541
3572
  self.assertEqual(
3542
3573
  code_mower_migration._pip_install_command(
3543
3574
  Path("/tmp/venv/bin/python"),
3544
- "code-mower==0.5.0b14",
3575
+ "code-mower==0.5.0b15",
3545
3576
  pip_index_url="https://test.pypi.org/simple/",
3546
3577
  pip_extra_index_urls=["https://pypi.org/simple/"],
3547
3578
  ),
@@ -3554,7 +3585,7 @@ def main():
3554
3585
  "https://test.pypi.org/simple/",
3555
3586
  "--extra-index-url",
3556
3587
  "https://pypi.org/simple/",
3557
- "code-mower==0.5.0b14",
3588
+ "code-mower==0.5.0b15",
3558
3589
  ],
3559
3590
  )
3560
3591
 
@@ -3574,10 +3605,10 @@ def main():
3574
3605
  payload = release_readiness.render_release_readiness(ROOT)
3575
3606
 
3576
3607
  self.assertEqual(payload["status"], "pass")
3577
- self.assertEqual(payload["version"], "0.5.0b14")
3578
- self.assertEqual(payload["release_tag"], "v0.5.0-beta.14")
3579
- self.assertEqual(payload["alpha_tag"], "v0.5.0-beta.14")
3580
- self.assertEqual(payload["package_index_spec"], "code-mower==0.5.0b14")
3608
+ self.assertEqual(payload["version"], "0.5.0b15")
3609
+ self.assertEqual(payload["release_tag"], "v0.5.0-beta.15")
3610
+ self.assertEqual(payload["alpha_tag"], "v0.5.0-beta.15")
3611
+ self.assertEqual(payload["package_index_spec"], "code-mower==0.5.0b15")
3581
3612
  check_ids = {check["id"]: check for check in payload["checks"]}
3582
3613
  self.assertEqual(check_ids["package-version-consistency"]["status"], "pass")
3583
3614
  self.assertEqual(
@@ -3626,7 +3657,7 @@ def main():
3626
3657
  check_ids = {check["id"]: check for check in payload["checks"]}
3627
3658
  check = check_ids["materialized-package-version-consistency"]
3628
3659
  self.assertEqual(check["status"], "fail")
3629
- self.assertEqual(check["detail"]["source_version"], "0.5.0b14")
3660
+ self.assertEqual(check["detail"]["source_version"], "0.5.0b15")
3630
3661
  self.assertEqual(check["detail"]["generated_init_version"], "0.0.0")
3631
3662
 
3632
3663
  def test_public_support_docs_are_packaged_and_privacy_forward(self) -> None:
@@ -3706,20 +3737,20 @@ def main():
3706
3737
 
3707
3738
  def test_release_readiness_tag_derivation_supports_release_stages(self) -> None:
3708
3739
  self.assertEqual(
3709
- release_readiness._release_tag_for_version("0.5.0b14"),
3710
- "v0.5.0-beta.14",
3740
+ release_readiness._release_tag_for_version("0.5.0b15"),
3741
+ "v0.5.0-beta.15",
3711
3742
  )
3712
3743
  self.assertEqual(
3713
- code_mower_versioning.release_tag_for_version("0.5.0b14"),
3714
- "v0.5.0-beta.14",
3744
+ code_mower_versioning.release_tag_for_version("0.5.0b15"),
3745
+ "v0.5.0-beta.15",
3715
3746
  )
3716
3747
  self.assertEqual(
3717
- release_readiness._release_tag_for_version("0.5.0b14"),
3718
- "v0.5.0-beta.14",
3748
+ release_readiness._release_tag_for_version("0.5.0b15"),
3749
+ "v0.5.0-beta.15",
3719
3750
  )
3720
3751
  self.assertEqual(
3721
- code_mower_versioning.release_tag_for_version("0.5.0b14"),
3722
- "v0.5.0-beta.14",
3752
+ code_mower_versioning.release_tag_for_version("0.5.0b15"),
3753
+ "v0.5.0-beta.15",
3723
3754
  )
3724
3755
  self.assertEqual(
3725
3756
  release_readiness._release_tag_for_version("1.0.0rc1"),
@@ -3748,8 +3779,8 @@ def main():
3748
3779
  next_steps.current_alpha_package_spec(),
3749
3780
  )
3750
3781
  self.assertEqual(
3751
- code_mower_package_content.current_alpha_package_spec("0.5.0b14"),
3752
- "code-mower==0.5.0b14",
3782
+ code_mower_package_content.current_alpha_package_spec("0.5.0b15"),
3783
+ "code-mower==0.5.0b15",
3753
3784
  )
3754
3785
  self.assertNotIn(next_steps.current_public_tag(), package_content_text)
3755
3786
  self.assertNotIn("v0.0.0", package_content_text)
@@ -3921,7 +3952,7 @@ def main():
3921
3952
  step for step in plan["steps"] if step["id"] == "package-install-rehearsal"
3922
3953
  )
3923
3954
  self.assertIn("doctor --v05", doctor_step["command"])
3924
- self.assertIn("code-mower==0.5.0b14", package_step["command"])
3955
+ self.assertIn("code-mower==0.5.0b15", package_step["command"])
3925
3956
  self.assertIn("current published PyPI prerelease", package_step["why"])
3926
3957
  self.assertIn("first_user_readiness", package_step["why"])
3927
3958
  self.assertEqual(
File without changes
File without changes
File without changes
File without changes
File without changes