code-mower 0.9.0b1__tar.gz → 0.9.1b1__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 (353) hide show
  1. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/PKG-INFO +18 -8
  2. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/README.md +17 -7
  3. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/pyproject.toml +1 -1
  4. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/board.py +15 -7
  6. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/__init__.py +4 -0
  7. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/adoption.py +157 -9
  8. code_mower-0.9.1b1/src/code_mower/doctor_checks/github_trusted_authors.py +38 -0
  9. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/runner.py +33 -1
  10. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_status.py +59 -7
  11. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/migration.py +1 -1
  12. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package_manifest.py +5 -0
  13. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
  14. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/PKG-INFO +18 -8
  15. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/SOURCES.txt +1 -0
  16. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/builder-provenance.yml.j2 +1 -1
  17. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_board.py +3 -0
  18. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_github_checks.py +55 -0
  19. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_registry.py +208 -0
  20. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_lane_status.py +38 -0
  21. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_release_hygiene.py +87 -34
  22. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/CODE_OF_CONDUCT.md +0 -0
  23. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/LICENSE +0 -0
  24. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/MANIFEST.in +0 -0
  25. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/NOTICE +0 -0
  26. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/SUPPORT.md +0 -0
  27. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/requirements/requirements.txt +0 -0
  28. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/setup.cfg +0 -0
  29. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/__init__.py +0 -0
  30. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/_base.py +0 -0
  31. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  32. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/gitar.py +0 -0
  33. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/greptile.py +0 -0
  34. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/adapters/qodo.py +0 -0
  35. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  36. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/antigravity_sdk_probe.py +0 -0
  37. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/audit_handoff_log.py +0 -0
  38. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/audit_labeler_lib.py +0 -0
  39. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/audit_limits.py +0 -0
  40. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/audit_progress.py +0 -0
  41. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/blind_review_artifacts.py +0 -0
  42. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/blind_review_coordinator.py +0 -0
  43. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/board_store.py +0 -0
  44. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/bootstrap.py +0 -0
  45. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/builder_experiment.py +0 -0
  46. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/builder_runs.py +0 -0
  47. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/__init__.py +0 -0
  48. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/arms.py +0 -0
  49. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/auto_discovery.py +0 -0
  50. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/commands.py +0 -0
  51. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/context_inputs.py +0 -0
  52. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/corpus.py +0 -0
  53. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/effect_report.py +0 -0
  54. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/evidence.py +0 -0
  55. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/evidence_report.py +0 -0
  56. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/identity.py +0 -0
  57. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/metrics.py +0 -0
  58. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/overlap.py +0 -0
  59. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/planning.py +0 -0
  60. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/policy.py +0 -0
  61. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/results.py +0 -0
  62. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/run_results.py +0 -0
  63. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/run_status.py +0 -0
  64. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/runner.py +0 -0
  65. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/truth.py +0 -0
  66. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/calibration/value_report.py +0 -0
  67. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/checks.py +0 -0
  68. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/claude_audit_pr.py +0 -0
  69. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/claude_cli_bounce.py +0 -0
  70. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/claude_cli_environment.py +0 -0
  71. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/clear_stale.py +0 -0
  72. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cli.py +0 -0
  73. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud.py +0 -0
  74. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/__init__.py +0 -0
  75. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/bundle.py +0 -0
  76. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/doctor.py +0 -0
  77. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/dogfood.py +0 -0
  78. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/endpoints.py +0 -0
  79. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/errors.py +0 -0
  80. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/events.py +0 -0
  81. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/export.py +0 -0
  82. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/git_metadata.py +0 -0
  83. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/manifest.py +0 -0
  84. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/operations.py +0 -0
  85. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/reports.py +0 -0
  86. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/setup.py +0 -0
  87. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/tokens.py +0 -0
  88. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/cloud_client/upload.py +0 -0
  89. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/code_mower_calibration.py +0 -0
  90. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/code_mower_context_packs.py +0 -0
  91. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/code_mower_merge.py +0 -0
  92. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/code_mower_telemetry.py +0 -0
  93. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  94. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/codex_audit_env_preflight.py +0 -0
  95. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/codex_audit_pr.py +0 -0
  96. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  97. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  98. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/config.py +0 -0
  99. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/decisions.py +0 -0
  100. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor.py +0 -0
  101. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/audit_limits.py +0 -0
  102. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/cloud.py +0 -0
  103. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/common.py +0 -0
  104. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github.py +0 -0
  105. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions.py +0 -0
  106. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  107. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  108. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  109. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  110. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  111. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  112. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  113. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  114. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_api.py +0 -0
  115. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_branch.py +0 -0
  116. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_config.py +0 -0
  117. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_human_token.py +0 -0
  118. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_provider.py +0 -0
  119. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/github_repo.py +0 -0
  120. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/groups.py +0 -0
  121. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/models.py +0 -0
  122. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/output.py +0 -0
  123. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/presets.py +0 -0
  124. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/privacy.py +0 -0
  125. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  126. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  127. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  128. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_env.py +0 -0
  129. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  130. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  131. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
  132. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  133. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  134. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  135. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  136. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  137. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  138. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  139. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  140. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  141. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/providers.py +0 -0
  142. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/registry.py +0 -0
  143. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/runtime.py +0 -0
  144. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  145. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -0
  146. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/gate_health.py +0 -0
  147. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  148. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/git_identity.py +0 -0
  149. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/grok_build_audit_pr.py +0 -0
  150. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  151. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/init.py +0 -0
  152. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/__init__.py +0 -0
  153. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/aider.py +0 -0
  154. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  155. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/claude.py +0 -0
  156. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/codex.py +0 -0
  157. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/devin.py +0 -0
  158. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  159. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/grok_build.py +0 -0
  160. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  161. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/lane_configs/local_llm.py +0 -0
  162. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/local_llm_audit_pr.py +0 -0
  163. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/local_llm_bakeoff.py +0 -0
  164. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/local_llm_calibration.py +0 -0
  165. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/local_llm_profiles.py +0 -0
  166. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/migration_install.py +0 -0
  167. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/migration_mirror.py +0 -0
  168. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/migration_readiness.py +0 -0
  169. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/migration_rehearsal.py +0 -0
  170. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/next_steps.py +0 -0
  171. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/observe.py +0 -0
  172. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package.py +0 -0
  173. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package_content.py +0 -0
  174. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package_paths.py +0 -0
  175. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package_rendering.py +0 -0
  176. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/package_static.py +0 -0
  177. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/plan_context.py +0 -0
  178. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/prompts.py +0 -0
  179. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_registry.py +0 -0
  180. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/__init__.py +0 -0
  181. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/comments.py +0 -0
  182. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/exit_codes.py +0 -0
  183. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/git.py +0 -0
  184. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/github_auth.py +0 -0
  185. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/github_pr.py +0 -0
  186. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  187. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/process.py +0 -0
  188. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/repo_paths.py +0 -0
  189. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/text_schema.py +0 -0
  190. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  191. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/provider_runners/workspace.py +0 -0
  192. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/providers/__init__.py +0 -0
  193. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/providers/local_cli.py +0 -0
  194. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/providers/provenance.py +0 -0
  195. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/release_readiness.py +0 -0
  196. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/reviewer_metrics.py +0 -0
  197. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/reviewer_spend.py +0 -0
  198. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/saas_reviewer_labeler.py +0 -0
  199. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/secrets.py +0 -0
  200. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/builder-experiment.example.json +0 -0
  201. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  202. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/calibration-corpus.json +0 -0
  203. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/code-mower.example.yml +0 -0
  204. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/context-packs.example.json +0 -0
  205. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  206. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  207. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  208. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  209. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  210. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  211. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  212. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
  213. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  214. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/README.md +0 -0
  215. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/claude.md +0 -0
  216. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/codex.md +0 -0
  217. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/cursor.md +0 -0
  218. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/generic.md +0 -0
  219. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/lanes/run_mac_lane.sh +0 -0
  220. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/code_mower +0 -0
  221. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  222. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  223. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  224. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  225. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  226. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/product-support/status_report.py +0 -0
  227. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/providers.yml +0 -0
  228. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  229. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  230. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  231. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  232. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  233. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  234. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +0 -0
  235. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  236. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  237. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  238. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  239. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
  240. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  241. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  242. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  243. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  244. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  245. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
  246. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/trailer_comment_labeler.py +0 -0
  247. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/versioning.py +0 -0
  248. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/work_orders.py +0 -0
  249. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower/workflow_actionlint.py +0 -0
  250. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/dependency_links.txt +0 -0
  251. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/entry_points.txt +0 -0
  252. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/requires.txt +0 -0
  253. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/src/code_mower.egg-info/top_level.txt +0 -0
  254. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/builder-experiment.example.json +0 -0
  255. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/calibration-corpus.example.json +0 -0
  256. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/calibration-corpus.json +0 -0
  257. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/code-mower.yml.j2 +0 -0
  258. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/context-packs.example.json +0 -0
  259. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/cursor/BUGBOT.md +0 -0
  260. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/README.md +0 -0
  261. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/claude.md +0 -0
  262. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/codex.md +0 -0
  263. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/cursor.md +0 -0
  264. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/generic.md +0 -0
  265. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/lanes/run_mac_lane.sh +0 -0
  266. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/acp_bridge.yml +0 -0
  267. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/aider.yml +0 -0
  268. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/antigravity_cli.yml +0 -0
  269. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/claude_audit.yml +0 -0
  270. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/claude_review.yml +0 -0
  271. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/coderabbit_cli.yml +0 -0
  272. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/codex.yml +0 -0
  273. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/cursor_bugbot.yml +0 -0
  274. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/devin.yml +0 -0
  275. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/gemini_cli.yml +0 -0
  276. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/gitar.yml +0 -0
  277. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/greptile.yml +0 -0
  278. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/hermes_cli.yml +0 -0
  279. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/local_llm.yml +0 -0
  280. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers/qodo.yml +0 -0
  281. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/providers.yml +0 -0
  282. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/reviewer-spend.example.json +0 -0
  283. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/reviewer-value-report.example.md +0 -0
  284. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  285. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  286. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  287. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  288. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  289. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/code-mower-gate.yml.j2 +0 -0
  290. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  291. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  292. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  293. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  294. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  295. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  296. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  297. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  298. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  299. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_antigravity_sdk_probe.py +0 -0
  300. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_audit_comment_posture.py +0 -0
  301. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_audit_limits.py +0 -0
  302. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_builder_experiment.py +0 -0
  303. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_builder_identity.py +0 -0
  304. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_builder_runs.py +0 -0
  305. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_calibration_effect_report.py +0 -0
  306. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_calibration_truth.py +0 -0
  307. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_checks.py +0 -0
  308. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_claude_audit_pr.py +0 -0
  309. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_claude_cli_bounce.py +0 -0
  310. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_clear_stale.py +0 -0
  311. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_cloud_client.py +0 -0
  312. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_cloud_git_metadata.py +0 -0
  313. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_cloud_manifest.py +0 -0
  314. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_cloud_reports.py +0 -0
  315. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  316. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_codex_audit_env_preflight.py +0 -0
  317. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_codex_audit_pr.py +0 -0
  318. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_decision_audit_integration.py +0 -0
  319. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_decisions.py +0 -0
  320. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_actions_cost_summary.py +0 -0
  321. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_actions_failure_selection.py +0 -0
  322. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_boundaries.py +0 -0
  323. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_output.py +0 -0
  324. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_privacy.py +0 -0
  325. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_provider_env_required.py +0 -0
  326. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_provider_env_tokens.py +0 -0
  327. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_provider_local_audit_setup.py +0 -0
  328. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_provider_probe.py +0 -0
  329. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_provider_review_hygiene.py +0 -0
  330. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_runtime.py +0 -0
  331. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_doctor_self_hosted_runner.py +0 -0
  332. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_gate_health.py +0 -0
  333. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_init_actionlint.py +0 -0
  334. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_init_build_loop.py +0 -0
  335. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_local_llm_github_helpers.py +0 -0
  336. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_migration_setup_drift.py +0 -0
  337. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_observe.py +0 -0
  338. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_plan_context.py +0 -0
  339. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_prompts.py +0 -0
  340. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_fixture_contracts.py +0 -0
  341. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_local_cli.py +0 -0
  342. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_comments.py +0 -0
  343. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_git.py +0 -0
  344. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_github_pr.py +0 -0
  345. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_pr_worktree.py +0 -0
  346. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_process.py +0 -0
  347. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_repo_paths.py +0 -0
  348. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_text_schema.py +0 -0
  349. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_provider_runners_workspace.py +0 -0
  350. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_reviewer_metrics_core.py +0 -0
  351. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_reviewer_spend.py +0 -0
  352. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_trailer_comment_labeler.py +0 -0
  353. {code_mower-0.9.0b1 → code_mower-0.9.1b1}/tests/test_work_orders.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-mower
3
- Version: 0.9.0b1
3
+ Version: 0.9.1b1
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.12
@@ -95,12 +95,17 @@ wrappers, run `code-mower migration setup-drift --repo-path .` before copying a
95
95
  fresh `.code-mower.generated` tree. It is read-only and reports path-level
96
96
  classifications (`same`, `differs`, `new`, `repo-only`,
97
97
  `missing-from-output`) without file contents or diffs.
98
+ Use [Upgrade An Existing Repository](docs/upgrade-existing-repo.md) for the
99
+ reviewed PR flow, repo-only file handling, builder identity checks, and
100
+ wrapper/pin drift checks.
98
101
 
99
102
  After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
100
103
  see active builder/reviewer lanes, gate/check state, recent Code Mower
101
104
  workflows, local board/process hints when present, and the next operator
102
105
  action. Text and JSON output redact local cwd paths by default; use
103
- `--show-local-paths` only for local debugging.
106
+ `--show-local-paths` only for local debugging. Local Board discovery is
107
+ best-effort across common macOS and Linux listener tools; when a host restricts
108
+ listener inventory, remote PR/check status still reports normally.
104
109
 
105
110
  For the same redacted metadata in a local browser view, run
106
111
  `code-mower board serve --repo OWNER/REPO` and open the printed localhost URL.
@@ -164,10 +169,12 @@ after reinstalling, especially when switching between pipx and uv.
164
169
  | C. Builder experiment | You want to compare authoring loops before trusting them broadly. | Use a work order or experiment spec, run `code-mower builder-experiment run` around an explicit command, then review the source-free `authoringRun` artifact and normal audit evidence. | [Builder Experiments](docs/builder-experiments.md) |
165
170
 
166
171
  The current package-index announcement entry point is the tagged
167
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.0-beta.1/docs/try-in-10-minutes.md)
172
+ [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.1-beta.1/docs/try-in-10-minutes.md)
168
173
  guide. The v0.9 beta includes the completed native Board work plus the adoption
169
- and upgrade hardening from recent install rehearsals, so package-only users can
170
- start from the public package rather than a source checkout.
174
+ and upgrade hardening from recent install rehearsals; v0.9.1 adds a smaller
175
+ announcement-hardening pass on Board visibility, doctor guidance, and safer
176
+ setup docs. Package-only users can start from the public package rather than a
177
+ source checkout.
171
178
 
172
179
  ## What Calibration Does And Does Not Prove
173
180
 
@@ -190,13 +197,15 @@ review-request signals to propose known-clean and known-blocked cases. Review
190
197
  every disposition before using it for lane promotion or merge policy.
191
198
 
192
199
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
200
+ Existing-repo upgrade flow:
201
+ [docs/upgrade-existing-repo.md](docs/upgrade-existing-repo.md).
193
202
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
194
203
  Provider-contract baseline for the next release train:
195
204
  [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
196
205
 
197
206
  For release verification,
198
207
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
199
- the package-index procedure for `v0.9.0-beta.1` / `code-mower==0.9.0b1`. The
208
+ the package-index procedure for `v0.9.1-beta.1` / `code-mower==0.9.1b1`. The
200
209
  GitHub release records the workflow and rehearsal evidence for the exact tag.
201
210
 
202
211
  ## Optional: Plan Before Coding
@@ -382,8 +391,8 @@ measurement work.
382
391
 
383
392
  ## Installation Status
384
393
 
385
- The current package-index beta baseline is `v0.9.0-beta.1`, with pinned package
386
- install spec `code-mower==0.9.0b1`. Release evidence is recorded on the GitHub
394
+ The current package-index beta baseline is `v0.9.1-beta.1`, with pinned package
395
+ install spec `code-mower==0.9.1b1`. Release evidence is recorded on the GitHub
387
396
  release and in the first-user install rehearsal. The public repository is
388
397
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
389
398
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -424,6 +433,7 @@ first so local work exercises the same package entrypoint users install.
424
433
  ## Docs Map
425
434
 
426
435
  - [Install And Bootstrap](docs/install.md)
436
+ - [Upgrade An Existing Repository](docs/upgrade-existing-repo.md)
427
437
  - [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
428
438
  - [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
429
439
  - [Quickstart Reference](docs/quickstart.md)
@@ -78,12 +78,17 @@ wrappers, run `code-mower migration setup-drift --repo-path .` before copying a
78
78
  fresh `.code-mower.generated` tree. It is read-only and reports path-level
79
79
  classifications (`same`, `differs`, `new`, `repo-only`,
80
80
  `missing-from-output`) without file contents or diffs.
81
+ Use [Upgrade An Existing Repository](docs/upgrade-existing-repo.md) for the
82
+ reviewed PR flow, repo-only file handling, builder identity checks, and
83
+ wrapper/pin drift checks.
81
84
 
82
85
  After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
83
86
  see active builder/reviewer lanes, gate/check state, recent Code Mower
84
87
  workflows, local board/process hints when present, and the next operator
85
88
  action. Text and JSON output redact local cwd paths by default; use
86
- `--show-local-paths` only for local debugging.
89
+ `--show-local-paths` only for local debugging. Local Board discovery is
90
+ best-effort across common macOS and Linux listener tools; when a host restricts
91
+ listener inventory, remote PR/check status still reports normally.
87
92
 
88
93
  For the same redacted metadata in a local browser view, run
89
94
  `code-mower board serve --repo OWNER/REPO` and open the printed localhost URL.
@@ -147,10 +152,12 @@ after reinstalling, especially when switching between pipx and uv.
147
152
  | C. Builder experiment | You want to compare authoring loops before trusting them broadly. | Use a work order or experiment spec, run `code-mower builder-experiment run` around an explicit command, then review the source-free `authoringRun` artifact and normal audit evidence. | [Builder Experiments](docs/builder-experiments.md) |
148
153
 
149
154
  The current package-index announcement entry point is the tagged
150
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.0-beta.1/docs/try-in-10-minutes.md)
155
+ [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.1-beta.1/docs/try-in-10-minutes.md)
151
156
  guide. The v0.9 beta includes the completed native Board work plus the adoption
152
- and upgrade hardening from recent install rehearsals, so package-only users can
153
- start from the public package rather than a source checkout.
157
+ and upgrade hardening from recent install rehearsals; v0.9.1 adds a smaller
158
+ announcement-hardening pass on Board visibility, doctor guidance, and safer
159
+ setup docs. Package-only users can start from the public package rather than a
160
+ source checkout.
154
161
 
155
162
  ## What Calibration Does And Does Not Prove
156
163
 
@@ -173,13 +180,15 @@ review-request signals to propose known-clean and known-blocked cases. Review
173
180
  every disposition before using it for lane promotion or merge policy.
174
181
 
175
182
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
183
+ Existing-repo upgrade flow:
184
+ [docs/upgrade-existing-repo.md](docs/upgrade-existing-repo.md).
176
185
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
177
186
  Provider-contract baseline for the next release train:
178
187
  [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
179
188
 
180
189
  For release verification,
181
190
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
182
- the package-index procedure for `v0.9.0-beta.1` / `code-mower==0.9.0b1`. The
191
+ the package-index procedure for `v0.9.1-beta.1` / `code-mower==0.9.1b1`. The
183
192
  GitHub release records the workflow and rehearsal evidence for the exact tag.
184
193
 
185
194
  ## Optional: Plan Before Coding
@@ -365,8 +374,8 @@ measurement work.
365
374
 
366
375
  ## Installation Status
367
376
 
368
- The current package-index beta baseline is `v0.9.0-beta.1`, with pinned package
369
- install spec `code-mower==0.9.0b1`. Release evidence is recorded on the GitHub
377
+ The current package-index beta baseline is `v0.9.1-beta.1`, with pinned package
378
+ install spec `code-mower==0.9.1b1`. Release evidence is recorded on the GitHub
370
379
  release and in the first-user install rehearsal. The public repository is
371
380
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
372
381
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -407,6 +416,7 @@ first so local work exercises the same package entrypoint users install.
407
416
  ## Docs Map
408
417
 
409
418
  - [Install And Bootstrap](docs/install.md)
419
+ - [Upgrade An Existing Repository](docs/upgrade-existing-repo.md)
410
420
  - [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
411
421
  - [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
412
422
  - [Quickstart Reference](docs/quickstart.md)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.9.0b1"
7
+ version = "0.9.1b1"
8
8
  description = "Multi-reviewer AI code audit orchestration"
9
9
  requires-python = ">=3.12"
10
10
  readme = "README.md"
@@ -1,3 +1,3 @@
1
1
  """Code Mower package."""
2
2
 
3
- __version__ = "0.9.0b1"
3
+ __version__ = "0.9.1b1"
@@ -655,6 +655,14 @@ def render_board_html(config: BoardConfig) -> str:
655
655
  const stateClass = (value) => /fail|error|blocked/i.test(text(value)) ? "bad" : /warn|pending|waiting|queued|progress/i.test(text(value)) ? "warn" : "ok";
656
656
  const seconds = (value) => Number.isFinite(Number(value)) ? `${{Number(value).toFixed(1)}}s` : "n/a";
657
657
  const money = (value) => Number.isFinite(Number(value)) ? `$${{Number(value).toFixed(3)}}` : "n/a";
658
+ const localTime = (value) => {{
659
+ const raw = text(value);
660
+ if (!raw) return "";
661
+ const date = new Date(raw);
662
+ if (Number.isNaN(date.getTime())) return esc(raw);
663
+ const local = new Intl.DateTimeFormat(undefined, {{year:"numeric", month:"short", day:"numeric", hour:"numeric", minute:"2-digit", second:"2-digit", timeZoneName:"short"}}).format(date);
664
+ return `<time datetime="${{esc(raw)}}" title="UTC ${{esc(raw)}}">${{esc(local)}}</time>`;
665
+ }};
658
666
  function labels(groups) {{
659
667
  return Object.values(groups || {{}}).flat().map(pill).join(" ") || '<span class="muted">none</span>';
660
668
  }}
@@ -663,7 +671,7 @@ def render_board_html(config: BoardConfig) -> str:
663
671
  }}
664
672
  function render(data) {{
665
673
  document.getElementById("repo").textContent = REPO;
666
- document.getElementById("generated").textContent = `Generated ${{data.generated_at || ""}}`;
674
+ document.getElementById("generated").innerHTML = data.generated_at ? `Generated ${{localTime(data.generated_at)}}` : "Loading...";
667
675
  const prs = data.remote?.pull_requests || [];
668
676
  const runs = data.remote?.workflow_runs || [];
669
677
  const alerts = data.remote?.gate_health?.alerts || [];
@@ -681,18 +689,18 @@ def render_board_html(config: BoardConfig) -> str:
681
689
  `<div class="metric"><span class="muted">Agent cards</span><b>${{agentCards.length}}</b></div>`,
682
690
  `<div class="metric"><span class="muted">Gate alerts</span><b class="${{alerts.length ? "warn" : "ok"}}">${{alerts.length}}</b></div>`
683
691
  ].join(""));
684
- put("owner", ownerQueue.length ? ownerQueue.map(item => `<div class="row"><div class="line"><a href="${{esc(href(item.url))}}">#${{esc(item.pr_number)}} ${{esc(item.kind)}}</a>${{pill(item.next_action)}}${{pill(item.head_sha_prefix)}}</div><div class="muted">${{esc(item.branch)}} by ${{esc(item.author)}} updated ${{esc(item.updated_at)}}</div></div>`).join("") : empty(data.owner_queue?.message || "No owner queue items."));
685
- put("agents", agentCards.length ? agentCards.map(agent => `<div class="row"><div class="line"><b>${{esc(agent.provider)}}</b>${{pill(agent.role)}}${{pill(agent.status)}}${{agent.lane ? pill(agent.lane) : ""}}${{agent.pr_number ? pill(`#${{agent.pr_number}}`) : ""}}</div><div>${{esc(agent.title || agent.next_action || "local agent")}}</div><div class="muted">${{esc(agent.branch || agent.repo || "")}}${{agent.pid ? ` pid=${{esc(agent.pid)}}` : ""}}${{agent.cwd ? ` cwd=${{esc(agent.cwd)}}` : ""}}${{agent.updated_at ? ` updated ${{esc(agent.updated_at)}}` : ""}}</div></div>`).join("") : empty(data.agent_adapters?.message || "No local agent adapter cards."));
692
+ put("owner", ownerQueue.length ? ownerQueue.map(item => `<div class="row"><div class="line"><a href="${{esc(href(item.url))}}">#${{esc(item.pr_number)}} ${{esc(item.kind)}}</a>${{pill(item.next_action)}}${{pill(item.head_sha_prefix)}}</div><div class="muted">${{esc(item.branch)}} by ${{esc(item.author)}}${{item.updated_at ? ` updated ${{localTime(item.updated_at)}}` : ""}}</div></div>`).join("") : empty(data.owner_queue?.message || "No owner queue items."));
693
+ put("agents", agentCards.length ? agentCards.map(agent => `<div class="row"><div class="line"><b>${{esc(agent.provider)}}</b>${{pill(agent.role)}}${{pill(agent.status)}}${{agent.lane ? pill(agent.lane) : ""}}${{agent.pr_number ? pill(`#${{agent.pr_number}}`) : ""}}</div><div>${{esc(agent.title || agent.next_action || "local agent")}}</div><div class="muted">${{esc(agent.branch || agent.repo || "")}}${{agent.pid ? ` pid=${{esc(agent.pid)}}` : ""}}${{agent.cwd ? ` cwd=${{esc(agent.cwd)}}` : ""}}${{agent.updated_at ? ` updated ${{localTime(agent.updated_at)}}` : ""}}</div></div>`).join("") : empty(data.agent_adapters?.message || "No local agent adapter cards."));
686
694
  put("prs", prs.length ? prs.map(pr => `<div class="row">
687
695
  <div class="line"><a href="${{esc(href(pr.url))}}">#${{esc(pr.number)}} ${{esc(pr.title)}}</a>${{pill(pr.merge_state)}}${{pr.is_draft ? pill("draft") : ""}}${{pr.stale ? pill("stale") : ""}}</div>
688
- <div class="muted">${{esc(pr.branch)}} by ${{esc(pr.author)}} updated ${{esc(pr.updated_at)}}</div>
696
+ <div class="muted">${{esc(pr.branch)}} by ${{esc(pr.author)}}${{pr.updated_at ? ` updated ${{localTime(pr.updated_at)}}` : ""}}</div>
689
697
  <div>labels: ${{labels(pr.labels)}}</div>
690
698
  <div>checks: ${{checks(pr.checks)}}</div>
691
699
  <div>next: <b>${{esc(pr.next_action)}}</b></div>
692
700
  </div>`).join("") : empty("No open pull requests."));
693
701
  put("alerts", alerts.length ? alerts.map(a => `<div class="row"><b class="warn">${{esc(a.kind)}}</b> ${{esc(a.message)}}</div>`).join("") : empty("No gate alerts."));
694
- put("runs", runs.length ? runs.slice(0, 8).map(run => `<div class="row"><div class="line"><a href="${{esc(href(run.url))}}">${{esc(run.workflow || "workflow")}}</a>${{pill(run.conclusion || run.status || "unknown")}}</div><div class="muted">${{esc(run.branch)}} updated ${{esc(run.updated_at)}}</div></div>`).join("") : empty("No recent Code Mower workflow runs."));
695
- put("verdicts", verdicts.length ? verdicts.map(v => `<div class="row"><div class="line"><a href="${{esc(href(v.url))}}">#${{esc(v.pr_number)}} ${{esc(v.lane)}}</a>${{pill(v.verdict)}}${{pill(v.head_sha_prefix)}}</div><div class="muted">${{esc(v.created_at)}}</div></div>`).join("") : empty(timelines.verdicts?.message || "No local reviewer verdict history yet."));
702
+ put("runs", runs.length ? runs.slice(0, 8).map(run => `<div class="row"><div class="line"><a href="${{esc(href(run.url))}}">${{esc(run.workflow || "workflow")}}</a>${{pill(run.conclusion || run.status || "unknown")}}</div><div class="muted">${{esc(run.branch)}}${{run.updated_at ? ` updated ${{localTime(run.updated_at)}}` : ""}}</div></div>`).join("") : empty("No recent Code Mower workflow runs."));
703
+ put("verdicts", verdicts.length ? verdicts.map(v => `<div class="row"><div class="line"><a href="${{esc(href(v.url))}}">#${{esc(v.pr_number)}} ${{esc(v.lane)}}</a>${{pill(v.verdict)}}${{pill(v.head_sha_prefix)}}</div><div class="muted">${{localTime(v.created_at)}}</div></div>`).join("") : empty(timelines.verdicts?.message || "No local reviewer verdict history yet."));
696
704
  const spendRows = [
697
705
  ...spendGroups.map(g => `<div class="row"><div class="line"><b>${{esc(g.lane)}}</b>${{pill(g.verdict)}}${{pill(`${{g.runs}} runs`)}}</div><div class="muted">${{seconds(g.wall_seconds_total)}} total / ${{seconds(g.wall_seconds_avg)}} avg / ${{money(g.cost_usd_total)}} / ${{esc(g.total_tokens || 0)}} tokens</div></div>`),
698
706
  spend.skipped_rows ? `<div class="row muted">Skipped ${{esc(spend.skipped_rows)}} malformed spend row(s).</div>` : "",
@@ -708,7 +716,7 @@ def render_board_html(config: BoardConfig) -> str:
708
716
  put("history", events.length ? events.slice().reverse().map(event => {{
709
717
  const s = event.summary || {{}};
710
718
  const remote = s.remote_available ? "remote available" : "remote unavailable";
711
- return `<div class="row"><div class="line"><b>${{esc(event.created_at)}}</b>${{pill(remote)}}</div><div>next: <b>${{esc(s.next_action || "inspect")}}</b></div><div class="muted">PRs ${{esc(s.open_prs ?? 0)}} / alerts ${{esc(s.gate_alerts ?? 0)}} / local ${{esc((s.local_boards ?? 0) + (s.local_processes ?? 0))}}</div></div>`;
719
+ return `<div class="row"><div class="line"><b>${{localTime(event.created_at)}}</b>${{pill(remote)}}</div><div>next: <b>${{esc(s.next_action || "inspect")}}</b></div><div class="muted">PRs ${{esc(s.open_prs ?? 0)}} / alerts ${{esc(s.gate_alerts ?? 0)}} / local ${{esc((s.local_boards ?? 0) + (s.local_processes ?? 0))}}</div></div>`;
712
720
  }}).join("") : empty(history.message || "No local board events recorded yet."));
713
721
  }}
714
722
  async function load() {{
@@ -13,6 +13,7 @@ from .cloud import (
13
13
  token_file_mentions_cloud_token,
14
14
  )
15
15
  from .adoption import (
16
+ check_adoption_posture_guidance,
16
17
  check_adoption_setup,
17
18
  config_with_repository_target,
18
19
  detect_repo_slug,
@@ -31,6 +32,7 @@ from .github_human_token import (
31
32
  human_automation_token_config,
32
33
  human_automation_token_required,
33
34
  )
35
+ from .github_trusted_authors import trusted_author_variable_statuses
34
36
  from .groups import GROUP_LABELS, doctor_check_group_id
35
37
  from .models import (
36
38
  STATUS_FAIL,
@@ -105,11 +107,13 @@ __all__ = [
105
107
  "auth_probe_output_detail",
106
108
  "build_doctor_run_plan",
107
109
  "check_cloud_token_surface",
110
+ "check_adoption_posture_guidance",
108
111
  "check_adoption_setup",
109
112
  "check_github_auth_surface",
110
113
  "check_macos_runner_launchagent",
111
114
  "check_github_setup",
112
115
  "check_human_automation_token",
116
+ "trusted_author_variable_statuses",
113
117
  "check_repository_posture",
114
118
  "check_lane_runtime",
115
119
  "check_review_hygiene",
@@ -5,13 +5,25 @@ from __future__ import annotations
5
5
  import re
6
6
  import subprocess
7
7
  from pathlib import Path
8
- from typing import Any, Mapping
8
+ from typing import Any, Mapping, Sequence
9
9
 
10
10
  from .models import STATUS_PASS, STATUS_WARN, DoctorCheck
11
11
 
12
12
 
13
13
  OWNER_REPO_RE = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$")
14
14
  OWNER_LOGIN_PLACEHOLDER = "TODO_OWNER_LOGIN"
15
+ TRUSTED_AUDIT_AUTHOR_VARIABLES = (
16
+ "CLAUDE_AUDIT_BOT_AUTHORS",
17
+ "CODEX_BOT_AUTHORS",
18
+ )
19
+ GENERATED_SETUP_MARKERS = {
20
+ "generated_config": (".code-mower.generated/code-mower.yml",),
21
+ "installed_gate_workflow": (".github/workflows/code-mower-gate.yml",),
22
+ "installed_dispatch_workflow": (".github/workflows/dispatch-lanes.yml",),
23
+ "installed_agent_pr_labeler": (
24
+ ".github/workflows/code-mower-agent-pr-labeler.yml",
25
+ ),
26
+ }
15
27
 
16
28
 
17
29
  def normalize_repo_slug(value: str, *, option: str = "--repo") -> str:
@@ -103,6 +115,85 @@ def _configured_repositories(config: Mapping[str, Any] | None) -> list[str]:
103
115
  return slugs
104
116
 
105
117
 
118
+ def _generated_setup_marker_types(repo_root: Path | None) -> list[str]:
119
+ if repo_root is None:
120
+ return []
121
+ marker_types: list[str] = []
122
+ for marker_type, relative_paths in GENERATED_SETUP_MARKERS.items():
123
+ if any((repo_root / relative_path).exists() for relative_path in relative_paths):
124
+ marker_types.append(marker_type)
125
+ return marker_types
126
+
127
+
128
+ def _config_source_state(
129
+ *,
130
+ source: str,
131
+ using_packaged_example: bool,
132
+ generated_marker_types: Sequence[str],
133
+ ) -> str:
134
+ if not using_packaged_example:
135
+ return source or "repository_config"
136
+ if source == "source_tree_starter":
137
+ return "source_tree_starter"
138
+ if generated_marker_types:
139
+ return "generated_without_root_config"
140
+ return "cold_configless"
141
+
142
+
143
+ def check_adoption_posture_guidance(
144
+ checks: Sequence[DoctorCheck],
145
+ *,
146
+ adoption: bool,
147
+ adoption_posture: str,
148
+ ) -> tuple[DoctorCheck, ...]:
149
+ """Return first-run guidance when default posture may not match this host."""
150
+
151
+ if not adoption or adoption_posture != "reviewer-gate":
152
+ return ()
153
+ local_provider_gap_names = {"runtime.local_cli", "runtime.local_cli.probe"}
154
+ gap_lanes = sorted(
155
+ {
156
+ str(check.lane)
157
+ for check in checks
158
+ if check.lane
159
+ and (
160
+ check.name in local_provider_gap_names
161
+ or check.name.startswith("runtime.local_audit")
162
+ )
163
+ and check.status == STATUS_WARN
164
+ }
165
+ )
166
+ if not gap_lanes:
167
+ return ()
168
+ return (
169
+ DoctorCheck(
170
+ name="doctor.adoption.posture_hint",
171
+ status=STATUS_WARN,
172
+ message=(
173
+ "default reviewer-gate posture found local provider setup gaps"
174
+ ),
175
+ detail={
176
+ "adoption_posture": adoption_posture,
177
+ "local_provider_gap_lanes": gap_lanes,
178
+ "next_steps": [
179
+ "rerun_orchestrator_only_if_this_host_only_coordinates",
180
+ "rerun_hosted_builders_if_this_host_observes_hosted_lanes",
181
+ "finish_local_cli_setup_if_this_host_runs_reviewers",
182
+ ],
183
+ "commands": [
184
+ "code-mower doctor --adoption --orchestrator-only --repo OWNER/REPO",
185
+ "code-mower doctor --adoption --hosted-builders --repo OWNER/REPO",
186
+ ],
187
+ },
188
+ remediation=(
189
+ "If this host only coordinates or observes hosted builders, "
190
+ "rerun with `--orchestrator-only` or `--hosted-builders`; "
191
+ "otherwise finish the local CLI/token setup for the listed lanes."
192
+ ),
193
+ ),
194
+ )
195
+
196
+
106
197
  def check_adoption_setup(
107
198
  *,
108
199
  config: Mapping[str, Any] | None,
@@ -112,6 +203,8 @@ def check_adoption_setup(
112
203
  repo_source: str,
113
204
  using_packaged_example: bool,
114
205
  config_source: str = "",
206
+ repo_root: Path | None = None,
207
+ trusted_author_variables: Mapping[str, str] | None = None,
115
208
  ) -> tuple[DoctorCheck, ...]:
116
209
  """Return first-run adoption posture checks."""
117
210
 
@@ -148,27 +241,64 @@ def check_adoption_setup(
148
241
  source = config_source or (
149
242
  "packaged_starter" if using_packaged_example else "repository_config"
150
243
  )
244
+ generated_marker_types = _generated_setup_marker_types(repo_root)
245
+ source_state = _config_source_state(
246
+ source=source,
247
+ using_packaged_example=using_packaged_example,
248
+ generated_marker_types=generated_marker_types,
249
+ )
151
250
  source_messages = {
152
251
  "explicit_config": "using explicit Code Mower config",
252
+ "cold_configless": (
253
+ "using packaged starter config because no repository code-mower.yml was found"
254
+ ),
255
+ "generated_without_root_config": (
256
+ "using packaged starter config because generated Code Mower setup exists "
257
+ "but repository code-mower.yml is not installed"
258
+ ),
153
259
  "packaged_starter": "using packaged starter config for adoption checks",
154
260
  "repository_config": "using repository Code Mower config",
155
261
  "source_tree_starter": "using source-tree starter config for adoption checks",
156
262
  }
263
+ next_steps = (
264
+ [
265
+ "review_generated_setup",
266
+ "install_root_config",
267
+ "rerun_adoption_doctor",
268
+ ]
269
+ if source_state == "generated_without_root_config"
270
+ else [
271
+ "run_init_easy_apply",
272
+ "edit_generated_config",
273
+ "rerun_adoption_doctor",
274
+ ]
275
+ if source_state == "cold_configless"
276
+ else []
277
+ )
157
278
  detail = {
158
279
  "config_path": str(config_path),
159
280
  "config_source": source,
281
+ "config_source_state": source_state,
160
282
  "configured_repositories": repositories,
161
283
  "effective_repository": repo_slug,
284
+ "repository_config_present": not using_packaged_example,
285
+ "generated_setup_detected": bool(generated_marker_types),
286
+ "generated_setup_marker_types": generated_marker_types,
162
287
  }
288
+ if next_steps:
289
+ detail["next_steps"] = next_steps
163
290
  if using_packaged_example:
164
291
  checks.append(
165
292
  DoctorCheck(
166
293
  name="doctor.adoption.config_source",
167
294
  status=STATUS_WARN,
168
- message=source_messages.get(source, source_messages["packaged_starter"]),
295
+ message=source_messages.get(source_state, source_messages["packaged_starter"]),
169
296
  detail=detail,
170
297
  remediation=(
171
- "Run `code-mower init --easy --apply`, review the generated "
298
+ "Review the generated setup, commit an edited code-mower.yml "
299
+ "at the repository root, then rerun doctor."
300
+ if source_state == "generated_without_root_config"
301
+ else "Run `code-mower init --easy --apply`, review the generated "
172
302
  "setup, and commit an edited code-mower.yml before relying "
173
303
  "on recurring workflows."
174
304
  ),
@@ -236,17 +366,35 @@ def check_adoption_setup(
236
366
  )
237
367
  )
238
368
 
369
+ trusted_detail: dict[str, Any] = {
370
+ "variables": list(TRUSTED_AUDIT_AUTHOR_VARIABLES)
371
+ }
372
+ if trusted_author_variables is not None:
373
+ variable_status = {
374
+ name: str(trusted_author_variables.get(name) or "missing")
375
+ for name in TRUSTED_AUDIT_AUTHOR_VARIABLES
376
+ }
377
+ trusted_detail["variable_status"] = variable_status
378
+ all_present = all(
379
+ variable_status[name] == "present" for name in TRUSTED_AUDIT_AUTHOR_VARIABLES
380
+ )
381
+ if all_present:
382
+ checks.append(
383
+ DoctorCheck(
384
+ name="doctor.adoption.trusted_authors",
385
+ status=STATUS_PASS,
386
+ message="trusted audit-comment author variables are configured",
387
+ detail=trusted_detail,
388
+ )
389
+ )
390
+ return tuple(checks)
391
+
239
392
  checks.append(
240
393
  DoctorCheck(
241
394
  name="doctor.adoption.trusted_authors",
242
395
  status=STATUS_WARN,
243
396
  message="human-run audit comments must be listed as trusted lane authors",
244
- detail={
245
- "variables": [
246
- "CLAUDE_AUDIT_BOT_AUTHORS",
247
- "CODEX_BOT_AUTHORS",
248
- ]
249
- },
397
+ detail=trusted_detail,
250
398
  remediation=(
251
399
  "For manual pilot audits, set repository variables such as "
252
400
  "CLAUDE_AUDIT_BOT_AUTHORS and CODEX_BOT_AUTHORS to the "
@@ -0,0 +1,38 @@
1
+ """GitHub repository variable checks for trusted audit-comment authors."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+
7
+ from .github_api import _github_api_json
8
+
9
+
10
+ def trusted_author_variable_statuses(
11
+ *,
12
+ gh_path: str,
13
+ slug: str,
14
+ variables: Iterable[str],
15
+ http_timeout: int,
16
+ ) -> dict[str, str]:
17
+ """Return safe presence statuses for trusted-author repository variables."""
18
+
19
+ statuses: dict[str, str] = {}
20
+ for variable in variables:
21
+ name = str(variable).strip()
22
+ if not name:
23
+ continue
24
+ payload, _detail = _github_api_json(
25
+ gh_path,
26
+ f"repos/{slug}/actions/variables/{name}",
27
+ http_timeout=http_timeout,
28
+ )
29
+ if payload is None:
30
+ statuses[name] = "missing"
31
+ elif str(payload.get("value") or "").strip():
32
+ statuses[name] = "present"
33
+ else:
34
+ statuses[name] = "empty"
35
+ return statuses
36
+
37
+
38
+ __all__ = ("trusted_author_variable_statuses",)
@@ -3,16 +3,23 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from pathlib import Path
6
+ import shutil
6
7
  from typing import Any, Mapping
7
8
 
8
9
  from code_mower import config as code_mower_config
9
10
 
10
- from .adoption import check_adoption_setup, config_with_repository_target
11
+ from .adoption import (
12
+ TRUSTED_AUDIT_AUTHOR_VARIABLES,
13
+ check_adoption_posture_guidance,
14
+ check_adoption_setup,
15
+ config_with_repository_target,
16
+ )
11
17
  from .audit_limits import check_effective_audit_limits
12
18
  from .cloud import check_cloud_token_surface
13
19
  from .common import ACTIONS_COST_SAMPLE_DEFAULT, load_inputs
14
20
  from .github import check_github_setup
15
21
  from .github_config import check_repository_posture
22
+ from .github_trusted_authors import trusted_author_variable_statuses
16
23
  from .models import STATUS_FAIL, STATUS_PASS, DoctorCheck, DoctorReport
17
24
  from .providers import check_lane_runtime, effective_lane, provider_template_coverage, selected_lanes
18
25
  from .registry import DoctorCheckStage, build_doctor_run_plan
@@ -108,6 +115,22 @@ def run_doctor(
108
115
  repo_root = None if config_path.name == "code-mower.example.yml" else config_path.parent
109
116
  config, templates, checks = load_inputs(config_path, provider_templates_path)
110
117
  using_packaged_example = config_path.name == "code-mower.example.yml"
118
+ trusted_author_variables = None
119
+ trusted_author_repo_slug = repo_slug
120
+ if not trusted_author_repo_slug and isinstance(config, Mapping):
121
+ for repository in config.get("repositories") or []:
122
+ if isinstance(repository, Mapping) and repository.get("slug"):
123
+ trusted_author_repo_slug = str(repository.get("slug") or "")
124
+ break
125
+ if github and trusted_author_repo_slug:
126
+ gh_path = shutil.which("gh")
127
+ if gh_path:
128
+ trusted_author_variables = trusted_author_variable_statuses(
129
+ gh_path=gh_path,
130
+ slug=trusted_author_repo_slug,
131
+ variables=TRUSTED_AUDIT_AUTHOR_VARIABLES,
132
+ http_timeout=http_timeout,
133
+ )
111
134
  checks.extend(
112
135
  check_adoption_setup(
113
136
  config=config,
@@ -117,6 +140,8 @@ def run_doctor(
117
140
  repo_source=repo_source,
118
141
  config_source=config_source,
119
142
  using_packaged_example=using_packaged_example,
143
+ repo_root=Path.cwd() if using_packaged_example else config_path.parent,
144
+ trusted_author_variables=trusted_author_variables,
120
145
  )
121
146
  )
122
147
  if config is not None and repo_slug:
@@ -217,6 +242,13 @@ def run_doctor(
217
242
  http_timeout=http_timeout,
218
243
  )
219
244
  )
245
+ checks.extend(
246
+ check_adoption_posture_guidance(
247
+ checks,
248
+ adoption=adoption,
249
+ adoption_posture=adoption_posture,
250
+ )
251
+ )
220
252
 
221
253
  if "github" in enabled_stages:
222
254
  checks.extend(