code-mower 0.5.0b6__tar.gz → 0.5.0b8__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 (255) hide show
  1. {code_mower-0.5.0b6/src/code_mower.egg-info → code_mower-0.5.0b8}/PKG-INFO +13 -6
  2. code_mower-0.5.0b6/PKG-INFO → code_mower-0.5.0b8/README.md +12 -17
  3. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/pyproject.toml +1 -1
  4. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud.py +1 -0
  6. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/operations.py +60 -0
  7. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/models.py +25 -0
  8. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/output.py +13 -0
  9. code_mower-0.5.0b6/README.md → code_mower-0.5.0b8/src/code_mower.egg-info/PKG-INFO +24 -5
  10. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_cloud_client.py +54 -0
  11. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_output.py +13 -0
  12. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_registry.py +8 -0
  13. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_release_hygiene.py +39 -34
  14. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/CODE_OF_CONDUCT.md +0 -0
  15. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/LICENSE +0 -0
  16. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/MANIFEST.in +0 -0
  17. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/NOTICE +0 -0
  18. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/SUPPORT.md +0 -0
  19. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/requirements/requirements.txt +0 -0
  20. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/setup.cfg +0 -0
  21. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/__init__.py +0 -0
  22. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/_base.py +0 -0
  23. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  24. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/gitar.py +0 -0
  25. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/greptile.py +0 -0
  26. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/adapters/qodo.py +0 -0
  27. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  28. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/audit_handoff_log.py +0 -0
  29. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/audit_labeler_lib.py +0 -0
  30. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/audit_progress.py +0 -0
  31. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/blind_review_artifacts.py +0 -0
  32. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/blind_review_coordinator.py +0 -0
  33. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/bootstrap.py +0 -0
  34. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/builder_experiment.py +0 -0
  35. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/__init__.py +0 -0
  36. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/arms.py +0 -0
  37. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/auto_discovery.py +0 -0
  38. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/commands.py +0 -0
  39. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/context_inputs.py +0 -0
  40. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/corpus.py +0 -0
  41. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/evidence.py +0 -0
  42. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/evidence_report.py +0 -0
  43. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/identity.py +0 -0
  44. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/metrics.py +0 -0
  45. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/overlap.py +0 -0
  46. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/planning.py +0 -0
  47. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/policy.py +0 -0
  48. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/results.py +0 -0
  49. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/run_results.py +0 -0
  50. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/run_status.py +0 -0
  51. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/runner.py +0 -0
  52. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/truth.py +0 -0
  53. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/calibration/value_report.py +0 -0
  54. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/checks.py +0 -0
  55. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/claude_audit_pr.py +0 -0
  56. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/claude_cli_bounce.py +0 -0
  57. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/claude_cli_environment.py +0 -0
  58. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/clear_stale.py +0 -0
  59. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cli.py +0 -0
  60. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/__init__.py +0 -0
  61. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/bundle.py +0 -0
  62. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/doctor.py +0 -0
  63. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/dogfood.py +0 -0
  64. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/endpoints.py +0 -0
  65. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/errors.py +0 -0
  66. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/events.py +0 -0
  67. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/export.py +0 -0
  68. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/git_metadata.py +0 -0
  69. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/manifest.py +0 -0
  70. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/reports.py +0 -0
  71. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/setup.py +0 -0
  72. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/cloud_client/upload.py +0 -0
  73. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/code_mower_calibration.py +0 -0
  74. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/code_mower_context_packs.py +0 -0
  75. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/code_mower_merge.py +0 -0
  76. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/code_mower_telemetry.py +0 -0
  77. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  78. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/codex_audit_env_preflight.py +0 -0
  79. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/codex_audit_pr.py +0 -0
  80. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  81. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  82. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/config.py +0 -0
  83. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor.py +0 -0
  84. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/__init__.py +0 -0
  85. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/cloud.py +0 -0
  86. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/common.py +0 -0
  87. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github.py +0 -0
  88. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions.py +0 -0
  89. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  90. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  91. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  92. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  93. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  94. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  95. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  96. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  97. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_api.py +0 -0
  98. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_branch.py +0 -0
  99. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_config.py +0 -0
  100. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_provider.py +0 -0
  101. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/github_repo.py +0 -0
  102. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/groups.py +0 -0
  103. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/presets.py +0 -0
  104. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/privacy.py +0 -0
  105. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  106. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  107. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  108. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_env.py +0 -0
  109. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  110. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  111. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  112. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  113. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  114. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  115. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  116. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  117. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  118. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  119. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/providers.py +0 -0
  120. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/registry.py +0 -0
  121. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/runner.py +0 -0
  122. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/runtime.py +0 -0
  123. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  124. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  125. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  126. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/init.py +0 -0
  127. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/__init__.py +0 -0
  128. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/aider.py +0 -0
  129. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  130. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/claude.py +0 -0
  131. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/codex.py +0 -0
  132. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/devin.py +0 -0
  133. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  134. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  135. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/lane_configs/local_llm.py +0 -0
  136. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/local_llm_audit_pr.py +0 -0
  137. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/local_llm_bakeoff.py +0 -0
  138. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/local_llm_calibration.py +0 -0
  139. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/local_llm_profiles.py +0 -0
  140. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/migration.py +0 -0
  141. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/migration_install.py +0 -0
  142. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/migration_mirror.py +0 -0
  143. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/migration_readiness.py +0 -0
  144. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/migration_rehearsal.py +0 -0
  145. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/next_steps.py +0 -0
  146. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package.py +0 -0
  147. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package_content.py +0 -0
  148. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package_manifest.py +0 -0
  149. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package_paths.py +0 -0
  150. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package_rendering.py +0 -0
  151. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/package_static.py +0 -0
  152. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/prompts.py +0 -0
  153. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_registry.py +0 -0
  154. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/__init__.py +0 -0
  155. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/comments.py +0 -0
  156. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/git.py +0 -0
  157. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/github_auth.py +0 -0
  158. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/github_pr.py +0 -0
  159. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/process.py +0 -0
  160. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/repo_paths.py +0 -0
  161. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/text_schema.py +0 -0
  162. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  163. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/provider_runners/workspace.py +0 -0
  164. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/release_readiness.py +0 -0
  165. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/reviewer_metrics.py +0 -0
  166. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/saas_reviewer_labeler.py +0 -0
  167. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/secrets.py +0 -0
  168. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/builder-experiment.example.json +0 -0
  169. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  170. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/calibration-corpus.json +0 -0
  171. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/code-mower.example.yml +0 -0
  172. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/context-packs.example.json +0 -0
  173. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  174. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  175. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  176. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  177. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  178. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  179. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  180. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  181. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/code_mower +0 -0
  182. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  183. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  184. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  185. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  186. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  187. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/providers.yml +0 -0
  188. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  189. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  190. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  191. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  192. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/trailer_comment_labeler.py +0 -0
  193. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower/versioning.py +0 -0
  194. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower.egg-info/SOURCES.txt +0 -0
  195. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower.egg-info/dependency_links.txt +0 -0
  196. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower.egg-info/entry_points.txt +0 -0
  197. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower.egg-info/requires.txt +0 -0
  198. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/src/code_mower.egg-info/top_level.txt +0 -0
  199. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/builder-experiment.example.json +0 -0
  200. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/calibration-corpus.example.json +0 -0
  201. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/calibration-corpus.json +0 -0
  202. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/code-mower.yml.j2 +0 -0
  203. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/context-packs.example.json +0 -0
  204. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/cursor/BUGBOT.md +0 -0
  205. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/acp_bridge.yml +0 -0
  206. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/aider.yml +0 -0
  207. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/antigravity_cli.yml +0 -0
  208. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/claude_audit.yml +0 -0
  209. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/claude_review.yml +0 -0
  210. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/coderabbit_cli.yml +0 -0
  211. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/codex.yml +0 -0
  212. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/cursor_bugbot.yml +0 -0
  213. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/devin.yml +0 -0
  214. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/gemini_cli.yml +0 -0
  215. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/gitar.yml +0 -0
  216. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/greptile.yml +0 -0
  217. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/hermes_cli.yml +0 -0
  218. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/local_llm.yml +0 -0
  219. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers/qodo.yml +0 -0
  220. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/providers.yml +0 -0
  221. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/reviewer-spend.example.json +0 -0
  222. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/reviewer-value-report.example.md +0 -0
  223. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  224. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  225. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  226. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  227. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  228. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  229. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  230. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  231. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_calibration_truth.py +0 -0
  232. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_checks.py +0 -0
  233. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_claude_cli_bounce.py +0 -0
  234. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_clear_stale.py +0 -0
  235. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_cloud_git_metadata.py +0 -0
  236. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_cloud_manifest.py +0 -0
  237. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_cloud_reports.py +0 -0
  238. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  239. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_actions_cost_summary.py +0 -0
  240. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_actions_failure_selection.py +0 -0
  241. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_boundaries.py +0 -0
  242. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_github_checks.py +0 -0
  243. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_privacy.py +0 -0
  244. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_provider_env_required.py +0 -0
  245. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_provider_env_tokens.py +0 -0
  246. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_doctor_provider_probe.py +0 -0
  247. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_local_llm_github_helpers.py +0 -0
  248. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_comments.py +0 -0
  249. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_git.py +0 -0
  250. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_github_pr.py +0 -0
  251. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_process.py +0 -0
  252. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_repo_paths.py +0 -0
  253. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_text_schema.py +0 -0
  254. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/tests/test_provider_runners_workspace.py +0 -0
  255. {code_mower-0.5.0b6 → code_mower-0.5.0b8}/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.0b6
3
+ Version: 0.5.0b8
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -98,11 +98,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
98
98
 
99
99
  ```bash
100
100
  python3.12 --version
101
- pipx install --python python3.12 code-mower==0.5.0b6
101
+ pipx install --python python3.12 code-mower==0.5.0b8
102
102
  code-mower --version
103
103
  ```
104
104
 
105
- `0.5.0b6` is a beta release. Until Code Mower publishes a stable `1.0`
105
+ `0.5.0b8` is a beta release. Until Code Mower publishes a stable `1.0`
106
106
  line, use the explicit beta version above or allow prereleases with:
107
107
 
108
108
  ```bash
@@ -174,7 +174,8 @@ The cloud value loop is:
174
174
  2. inspect the metadata-only bundle or dogfood preview;
175
175
  3. upload only with `--yes`; and
176
176
  4. use [CodeMower.com](https://codemower.com) to see repo rollups, provider/lens
177
- signal, cost/latency, noisy lanes, and next-lane recommendations over time.
177
+ signal, cost/latency, noisy lanes, next-lane recommendations, and
178
+ token-safe evidence/detail pages over time.
178
179
 
179
180
  Start with a dry run:
180
181
 
@@ -184,6 +185,12 @@ code-mower cloud dogfood --json
184
185
 
185
186
  Nothing uploads unless you pass `--yes`.
186
187
 
188
+ Current dogfood uploads, historical catch-up imports, and calibrated
189
+ reviewer/lens evidence are intentionally separate. Imported GitHub Actions
190
+ history can prove activity and upload health; it should not be treated as
191
+ reviewer-quality evidence until it is calibrated against known-clean and
192
+ known-blocked cases.
193
+
187
194
  To connect to [CodeMower.com](https://codemower.com), sign in at
188
195
  [https://codemower.com/login](https://codemower.com/login), create or receive a
189
196
  team token, then run:
@@ -239,9 +246,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
239
246
 
240
247
  ## Installation Status
241
248
 
242
- The current public beta is `v0.5.0-beta.6` from
249
+ The current public beta is `v0.5.0-beta.8` from
243
250
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and it
244
- is published as `code-mower==0.5.0b6` on
251
+ is published as `code-mower==0.5.0b8` on
245
252
  [PyPI](https://pypi.org/project/code-mower/). GitHub releases remain the
246
253
  auditable source for tags, build artifacts, and release notes.
247
254
 
@@ -1,15 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: code-mower
3
- Version: 0.5.0b6
4
- Summary: Multi-reviewer AI code audit orchestration
5
- License-Expression: Apache-2.0
6
- Requires-Python: >=3.11
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE
9
- License-File: NOTICE
10
- Requires-Dist: PyYAML>=6.0
11
- Dynamic: license-file
12
-
13
1
  # Code Mower
14
2
 
15
3
  Code Mower helps teams set up AI peer-programmer and reviewer lanes on real
@@ -98,11 +86,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
98
86
 
99
87
  ```bash
100
88
  python3.12 --version
101
- pipx install --python python3.12 code-mower==0.5.0b6
89
+ pipx install --python python3.12 code-mower==0.5.0b8
102
90
  code-mower --version
103
91
  ```
104
92
 
105
- `0.5.0b6` is a beta release. Until Code Mower publishes a stable `1.0`
93
+ `0.5.0b8` is a beta release. Until Code Mower publishes a stable `1.0`
106
94
  line, use the explicit beta version above or allow prereleases with:
107
95
 
108
96
  ```bash
@@ -174,7 +162,8 @@ The cloud value loop is:
174
162
  2. inspect the metadata-only bundle or dogfood preview;
175
163
  3. upload only with `--yes`; and
176
164
  4. use [CodeMower.com](https://codemower.com) to see repo rollups, provider/lens
177
- signal, cost/latency, noisy lanes, and next-lane recommendations over time.
165
+ signal, cost/latency, noisy lanes, next-lane recommendations, and
166
+ token-safe evidence/detail pages over time.
178
167
 
179
168
  Start with a dry run:
180
169
 
@@ -184,6 +173,12 @@ code-mower cloud dogfood --json
184
173
 
185
174
  Nothing uploads unless you pass `--yes`.
186
175
 
176
+ Current dogfood uploads, historical catch-up imports, and calibrated
177
+ reviewer/lens evidence are intentionally separate. Imported GitHub Actions
178
+ history can prove activity and upload health; it should not be treated as
179
+ reviewer-quality evidence until it is calibrated against known-clean and
180
+ known-blocked cases.
181
+
187
182
  To connect to [CodeMower.com](https://codemower.com), sign in at
188
183
  [https://codemower.com/login](https://codemower.com/login), create or receive a
189
184
  team token, then run:
@@ -239,9 +234,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
239
234
 
240
235
  ## Installation Status
241
236
 
242
- The current public beta is `v0.5.0-beta.6` from
237
+ The current public beta is `v0.5.0-beta.8` from
243
238
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and it
244
- is published as `code-mower==0.5.0b6` on
239
+ is published as `code-mower==0.5.0b8` on
245
240
  [PyPI](https://pypi.org/project/code-mower/). GitHub releases remain the
246
241
  auditable source for tags, build artifacts, and release notes.
247
242
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.5.0b6"
7
+ version = "0.5.0b8"
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.0b6"
3
+ __version__ = "0.5.0b8"
@@ -601,6 +601,7 @@ def main(argv: list[str] | None = None) -> int:
601
601
  print(f"Status: {result['status']}")
602
602
  print(f"Repository: {result['repo_slug']}")
603
603
  print(f"Runs: {result['run_count']}")
604
+ print("Provenance: imported history (not calibration evidence)")
604
605
  print(f"Bundle: {result['export']['output_dir']}")
605
606
  print(f"Events: {result['export']['event_count']}")
606
607
  if result["status"] == "uploaded":
@@ -23,6 +23,56 @@ from .setup import DEFAULT_INSTALL_ID_ENV, DEFAULT_TEAM_ID_ENV
23
23
  from .upload import build_upload_payload, post_upload_payload
24
24
 
25
25
 
26
+ def build_catch_up_summary(
27
+ *,
28
+ repo_slug: str,
29
+ runs: list[dict[str, Any]],
30
+ events: list[dict[str, Any]],
31
+ requested_limit: int,
32
+ include_git_ref: bool,
33
+ ) -> dict[str, Any]:
34
+ """Summarize imported GitHub Actions history without exposing ref details."""
35
+
36
+ def increment(target: dict[str, int], raw: object) -> None:
37
+ value = str(raw or "").strip() or "unknown"
38
+ target[value] = target.get(value, 0) + 1
39
+
40
+ workflow_counts: dict[str, int] = {}
41
+ status_counts: dict[str, int] = {}
42
+ conclusion_counts: dict[str, int] = {}
43
+ created_values: list[str] = []
44
+ updated_values: list[str] = []
45
+
46
+ for run in runs:
47
+ increment(workflow_counts, run.get("name"))
48
+ increment(status_counts, run.get("status"))
49
+ increment(conclusion_counts, run.get("conclusion"))
50
+ created_at = str(run.get("createdAt") or "").strip()
51
+ updated_at = str(run.get("updatedAt") or "").strip()
52
+ if created_at:
53
+ created_values.append(created_at)
54
+ if updated_at:
55
+ updated_values.append(updated_at)
56
+
57
+ return {
58
+ "repo_slug": repo_slug,
59
+ "requested_limit": requested_limit,
60
+ "run_count": len(runs),
61
+ "event_count": len(events),
62
+ "provenance": "imported_history",
63
+ "source_category": "history",
64
+ "history_only": True,
65
+ "calibration_evidence": False,
66
+ "git_ref_included": include_git_ref,
67
+ "workflow_counts": dict(sorted(workflow_counts.items())),
68
+ "status_counts": dict(sorted(status_counts.items())),
69
+ "conclusion_counts": dict(sorted(conclusion_counts.items())),
70
+ "oldest_run_at": min(created_values) if created_values else "",
71
+ "newest_run_at": max(created_values) if created_values else "",
72
+ "last_updated_at": max(updated_values) if updated_values else "",
73
+ }
74
+
75
+
26
76
  def dogfood_upload(
27
77
  *,
28
78
  repo_path: Path,
@@ -157,6 +207,13 @@ def catch_up_upload(
157
207
  )
158
208
  for run in runs
159
209
  ]
210
+ catch_up_summary = build_catch_up_summary(
211
+ repo_slug=detected_repo_slug,
212
+ runs=runs,
213
+ events=events,
214
+ requested_limit=limit,
215
+ include_git_ref=include_git_ref,
216
+ )
160
217
  export_result = build_cloud_bundle(
161
218
  reports=[],
162
219
  events=events,
@@ -178,6 +235,7 @@ def catch_up_upload(
178
235
  "status": "doctor_failed",
179
236
  "repo_slug": detected_repo_slug,
180
237
  "run_count": len(runs),
238
+ "catch_up": catch_up_summary,
181
239
  "export": export_result,
182
240
  "doctor": doctor_result,
183
241
  }
@@ -188,6 +246,7 @@ def catch_up_upload(
188
246
  "status": "dry_run",
189
247
  "repo_slug": detected_repo_slug,
190
248
  "run_count": len(runs),
249
+ "catch_up": catch_up_summary,
191
250
  "export": export_result,
192
251
  "doctor": doctor_result,
193
252
  "upload": build_dogfood_dry_run_preview(endpoint=endpoint, payload=payload),
@@ -202,6 +261,7 @@ def catch_up_upload(
202
261
  "status": "uploaded",
203
262
  "repo_slug": detected_repo_slug,
204
263
  "run_count": len(runs),
264
+ "catch_up": catch_up_summary,
205
265
  "export": export_result,
206
266
  "doctor": doctor_result,
207
267
  "upload": post_upload_payload(
@@ -57,6 +57,30 @@ class DoctorReport:
57
57
  return STATUS_WARN
58
58
  return STATUS_PASS
59
59
 
60
+ @property
61
+ def run_plan(self) -> tuple[dict[str, Any], ...]:
62
+ """Return the structured doctor run plan when a report contains one."""
63
+
64
+ for check in self.checks:
65
+ if check.name != "doctor.plan" or not isinstance(check.detail, Mapping):
66
+ continue
67
+ stages = check.detail.get("stages")
68
+ if not isinstance(stages, list):
69
+ return ()
70
+ plan: list[dict[str, Any]] = []
71
+ for stage in stages:
72
+ if not isinstance(stage, Mapping):
73
+ continue
74
+ plan.append(
75
+ {
76
+ "id": str(stage.get("id", "")),
77
+ "group": str(stage.get("group", "")),
78
+ "optional": bool(stage.get("optional", False)),
79
+ }
80
+ )
81
+ return tuple(plan)
82
+ return ()
83
+
60
84
  def group_summary(self) -> dict[str, dict[str, int | str]]:
61
85
  summary: dict[str, dict[str, int | str]] = {}
62
86
  for group_id, label in GROUP_LABELS.items():
@@ -91,6 +115,7 @@ class DoctorReport:
91
115
  "failures": self.failures,
92
116
  "warnings": self.warnings,
93
117
  },
118
+ "run_plan": list(self.run_plan),
94
119
  "groups": self.group_summary(),
95
120
  "checks": [check.as_dict() for check in self.checks],
96
121
  }
@@ -39,6 +39,16 @@ def _format_status_summary(report: DoctorReport) -> str:
39
39
  return ", ".join(parts)
40
40
 
41
41
 
42
+ def _format_run_plan(report: DoctorReport) -> str | None:
43
+ if not report.run_plan:
44
+ return None
45
+ stages = []
46
+ for stage in report.run_plan:
47
+ suffix = " optional" if stage.get("optional") else ""
48
+ stages.append(f"{stage.get('id', '')} ({stage.get('group', '')}{suffix})")
49
+ return ", ".join(stages)
50
+
51
+
42
52
  def _format_check(check: DoctorCheck) -> list[str]:
43
53
  lane = f" [{check.lane}]" if check.lane else ""
44
54
  lines = [f"- {check.status.upper()} {check.name}{lane}: {check.message}"]
@@ -57,6 +67,9 @@ def render_doctor_text(report: DoctorReport) -> str:
57
67
  ]
58
68
  if report.profile:
59
69
  lines.append(f"Profile: {report.profile}")
70
+ run_plan = _format_run_plan(report)
71
+ if run_plan:
72
+ lines.append(f"Run plan: {run_plan}")
60
73
  lines.append(f"Checks: {_format_status_summary(report)}")
61
74
  lines.append("")
62
75
 
@@ -1,3 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: code-mower
3
+ Version: 0.5.0b8
4
+ Summary: Multi-reviewer AI code audit orchestration
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ License-File: NOTICE
10
+ Requires-Dist: PyYAML>=6.0
11
+ Dynamic: license-file
12
+
1
13
  # Code Mower
2
14
 
3
15
  Code Mower helps teams set up AI peer-programmer and reviewer lanes on real
@@ -86,11 +98,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
86
98
 
87
99
  ```bash
88
100
  python3.12 --version
89
- pipx install --python python3.12 code-mower==0.5.0b6
101
+ pipx install --python python3.12 code-mower==0.5.0b8
90
102
  code-mower --version
91
103
  ```
92
104
 
93
- `0.5.0b6` is a beta release. Until Code Mower publishes a stable `1.0`
105
+ `0.5.0b8` is a beta release. Until Code Mower publishes a stable `1.0`
94
106
  line, use the explicit beta version above or allow prereleases with:
95
107
 
96
108
  ```bash
@@ -162,7 +174,8 @@ The cloud value loop is:
162
174
  2. inspect the metadata-only bundle or dogfood preview;
163
175
  3. upload only with `--yes`; and
164
176
  4. use [CodeMower.com](https://codemower.com) to see repo rollups, provider/lens
165
- signal, cost/latency, noisy lanes, and next-lane recommendations over time.
177
+ signal, cost/latency, noisy lanes, next-lane recommendations, and
178
+ token-safe evidence/detail pages over time.
166
179
 
167
180
  Start with a dry run:
168
181
 
@@ -172,6 +185,12 @@ code-mower cloud dogfood --json
172
185
 
173
186
  Nothing uploads unless you pass `--yes`.
174
187
 
188
+ Current dogfood uploads, historical catch-up imports, and calibrated
189
+ reviewer/lens evidence are intentionally separate. Imported GitHub Actions
190
+ history can prove activity and upload health; it should not be treated as
191
+ reviewer-quality evidence until it is calibrated against known-clean and
192
+ known-blocked cases.
193
+
175
194
  To connect to [CodeMower.com](https://codemower.com), sign in at
176
195
  [https://codemower.com/login](https://codemower.com/login), create or receive a
177
196
  team token, then run:
@@ -227,9 +246,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
227
246
 
228
247
  ## Installation Status
229
248
 
230
- The current public beta is `v0.5.0-beta.6` from
249
+ The current public beta is `v0.5.0-beta.8` from
231
250
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and it
232
- is published as `code-mower==0.5.0b6` on
251
+ is published as `code-mower==0.5.0b8` on
233
252
  [PyPI](https://pypi.org/project/code-mower/). GitHub releases remain the
234
253
  auditable source for tags, build artifacts, and release notes.
235
254
 
@@ -28,6 +28,60 @@ from code_mower.cloud_client import (
28
28
  from code_mower import cloud as cloud_cli
29
29
 
30
30
 
31
+ def test_cloud_catch_up_summary_separates_history_from_calibration() -> None:
32
+ runs = [
33
+ {
34
+ "name": "CI",
35
+ "status": "completed",
36
+ "conclusion": "success",
37
+ "createdAt": "2026-06-15T00:00:00Z",
38
+ "updatedAt": "2026-06-15T00:01:00Z",
39
+ },
40
+ {
41
+ "name": "CI",
42
+ "status": "completed",
43
+ "conclusion": "failure",
44
+ "createdAt": "2026-06-16T00:00:00Z",
45
+ "updatedAt": "2026-06-16T00:02:00Z",
46
+ },
47
+ {
48
+ "name": "Dogfood",
49
+ "status": "in_progress",
50
+ "conclusion": "",
51
+ "createdAt": "2026-06-17T00:00:00Z",
52
+ "updatedAt": "2026-06-17T00:03:00Z",
53
+ },
54
+ ]
55
+
56
+ summary = cloud_operations.build_catch_up_summary(
57
+ repo_slug="owner/repo",
58
+ runs=runs,
59
+ events=[{"event_type": "workflow_run"} for _ in runs],
60
+ requested_limit=50,
61
+ include_git_ref=False,
62
+ )
63
+
64
+ assert summary["repo_slug"] == "owner/repo"
65
+ assert summary["requested_limit"] == 50
66
+ assert summary["run_count"] == 3
67
+ assert summary["event_count"] == 3
68
+ assert summary["provenance"] == "imported_history"
69
+ assert summary["source_category"] == "history"
70
+ assert summary["history_only"] is True
71
+ assert summary["calibration_evidence"] is False
72
+ assert summary["git_ref_included"] is False
73
+ assert summary["workflow_counts"] == {"CI": 2, "Dogfood": 1}
74
+ assert summary["status_counts"] == {"completed": 2, "in_progress": 1}
75
+ assert summary["conclusion_counts"] == {
76
+ "failure": 1,
77
+ "success": 1,
78
+ "unknown": 1,
79
+ }
80
+ assert summary["oldest_run_at"] == "2026-06-15T00:00:00Z"
81
+ assert summary["newest_run_at"] == "2026-06-17T00:00:00Z"
82
+ assert summary["last_updated_at"] == "2026-06-17T00:03:00Z"
83
+
84
+
31
85
  def test_cloud_setup_round_trip_writes_private_file() -> None:
32
86
  with tempfile.TemporaryDirectory() as tmp:
33
87
  root = Path(tmp)
@@ -26,6 +26,14 @@ class DoctorOutputTests(unittest.TestCase):
26
26
  name="doctor.plan",
27
27
  status=STATUS_PASS,
28
28
  message="doctor run plan: load-inputs, select-profile, runtime, providers",
29
+ detail={
30
+ "stages": [
31
+ {"id": "load-inputs", "group": "runtime", "optional": False},
32
+ {"id": "select-profile", "group": "runtime", "optional": False},
33
+ {"id": "runtime", "group": "runtime", "optional": False},
34
+ {"id": "providers", "group": "providers", "optional": False},
35
+ ]
36
+ },
29
37
  ),
30
38
  DoctorCheck(
31
39
  name="runtime.python",
@@ -59,6 +67,11 @@ class DoctorOutputTests(unittest.TestCase):
59
67
 
60
68
  rendered = output.render_doctor_text(report)
61
69
 
70
+ self.assertIn(
71
+ "Run plan: load-inputs (runtime), select-profile (runtime), "
72
+ "runtime (runtime), providers (providers)",
73
+ rendered,
74
+ )
62
75
  self.assertIn("Checks: 7 total, 2 warnings, 1 skipped", rendered)
63
76
  self.assertLess(rendered.index("Setup"), rendered.index("Runtime"))
64
77
  self.assertLess(rendered.index("Runtime"), rendered.index("Provider lanes"))
@@ -54,6 +54,14 @@ class DoctorRegistryTests(unittest.TestCase):
54
54
  tuple(stage["id"] for stage in plan_check.detail["stages"]),
55
55
  ("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
56
56
  )
57
+ self.assertEqual(
58
+ tuple(stage["id"] for stage in report.run_plan),
59
+ ("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
60
+ )
61
+ self.assertEqual(
62
+ tuple(stage["id"] for stage in report.as_dict()["run_plan"]),
63
+ ("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
64
+ )
57
65
 
58
66
 
59
67
  if __name__ == "__main__":