code-mower 0.9.0b1__tar.gz → 0.9.2b1__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.2b1}/PKG-INFO +19 -8
  2. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/README.md +18 -7
  3. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/pyproject.toml +1 -1
  4. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/board.py +17 -8
  6. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/board_store.py +4 -2
  7. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cli.py +0 -3
  8. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/__init__.py +4 -0
  9. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/adoption.py +157 -9
  10. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_human_token.py +4 -6
  11. code_mower-0.9.2b1/src/code_mower/doctor_checks/github_trusted_authors.py +38 -0
  12. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/runner.py +33 -1
  13. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_status.py +117 -18
  14. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/migration.py +1 -1
  15. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package_manifest.py +5 -1
  16. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
  17. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/PKG-INFO +19 -8
  18. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/SOURCES.txt +1 -2
  19. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/builder-provenance.yml.j2 +1 -1
  20. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_board.py +5 -2
  21. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_github_checks.py +71 -4
  22. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_registry.py +208 -0
  23. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_lane_status.py +133 -8
  24. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_release_hygiene.py +91 -38
  25. code_mower-0.9.0b1/src/code_mower/observe.py +0 -324
  26. code_mower-0.9.0b1/tests/test_observe.py +0 -111
  27. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/CODE_OF_CONDUCT.md +0 -0
  28. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/LICENSE +0 -0
  29. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/MANIFEST.in +0 -0
  30. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/NOTICE +0 -0
  31. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/SUPPORT.md +0 -0
  32. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/requirements/requirements.txt +0 -0
  33. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/setup.cfg +0 -0
  34. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/__init__.py +0 -0
  35. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/_base.py +0 -0
  36. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  37. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/gitar.py +0 -0
  38. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/greptile.py +0 -0
  39. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/adapters/qodo.py +0 -0
  40. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  41. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/antigravity_sdk_probe.py +0 -0
  42. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/audit_handoff_log.py +0 -0
  43. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/audit_labeler_lib.py +0 -0
  44. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/audit_limits.py +0 -0
  45. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/audit_progress.py +0 -0
  46. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/blind_review_artifacts.py +0 -0
  47. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/blind_review_coordinator.py +0 -0
  48. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/bootstrap.py +0 -0
  49. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/builder_experiment.py +0 -0
  50. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/builder_runs.py +0 -0
  51. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/__init__.py +0 -0
  52. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/arms.py +0 -0
  53. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/auto_discovery.py +0 -0
  54. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/commands.py +0 -0
  55. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/context_inputs.py +0 -0
  56. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/corpus.py +0 -0
  57. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/effect_report.py +0 -0
  58. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/evidence.py +0 -0
  59. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/evidence_report.py +0 -0
  60. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/identity.py +0 -0
  61. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/metrics.py +0 -0
  62. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/overlap.py +0 -0
  63. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/planning.py +0 -0
  64. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/policy.py +0 -0
  65. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/results.py +0 -0
  66. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/run_results.py +0 -0
  67. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/run_status.py +0 -0
  68. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/runner.py +0 -0
  69. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/truth.py +0 -0
  70. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/calibration/value_report.py +0 -0
  71. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/checks.py +0 -0
  72. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/claude_audit_pr.py +0 -0
  73. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/claude_cli_bounce.py +0 -0
  74. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/claude_cli_environment.py +0 -0
  75. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/clear_stale.py +0 -0
  76. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud.py +0 -0
  77. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/__init__.py +0 -0
  78. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/bundle.py +0 -0
  79. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/doctor.py +0 -0
  80. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/dogfood.py +0 -0
  81. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/endpoints.py +0 -0
  82. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/errors.py +0 -0
  83. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/events.py +0 -0
  84. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/export.py +0 -0
  85. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/git_metadata.py +0 -0
  86. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/manifest.py +0 -0
  87. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/operations.py +0 -0
  88. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/reports.py +0 -0
  89. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/setup.py +0 -0
  90. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/tokens.py +0 -0
  91. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/cloud_client/upload.py +0 -0
  92. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/code_mower_calibration.py +0 -0
  93. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/code_mower_context_packs.py +0 -0
  94. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/code_mower_merge.py +0 -0
  95. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/code_mower_telemetry.py +0 -0
  96. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  97. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/codex_audit_env_preflight.py +0 -0
  98. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/codex_audit_pr.py +0 -0
  99. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  100. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  101. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/config.py +0 -0
  102. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/decisions.py +0 -0
  103. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor.py +0 -0
  104. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/audit_limits.py +0 -0
  105. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/cloud.py +0 -0
  106. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/common.py +0 -0
  107. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github.py +0 -0
  108. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions.py +0 -0
  109. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  110. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  111. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  112. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  113. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  114. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  115. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  116. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  117. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_api.py +0 -0
  118. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_branch.py +0 -0
  119. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_config.py +0 -0
  120. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_provider.py +0 -0
  121. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/github_repo.py +0 -0
  122. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/groups.py +0 -0
  123. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/models.py +0 -0
  124. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/output.py +0 -0
  125. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/presets.py +0 -0
  126. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/privacy.py +0 -0
  127. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  128. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  129. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  130. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_env.py +0 -0
  131. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  132. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  133. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
  134. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  135. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  136. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  137. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  138. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  139. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  140. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  141. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  142. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  143. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/providers.py +0 -0
  144. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/registry.py +0 -0
  145. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/runtime.py +0 -0
  146. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  147. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -0
  148. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/gate_health.py +0 -0
  149. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  150. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/git_identity.py +0 -0
  151. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/grok_build_audit_pr.py +0 -0
  152. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  153. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/init.py +0 -0
  154. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/__init__.py +0 -0
  155. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/aider.py +0 -0
  156. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  157. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/claude.py +0 -0
  158. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/codex.py +0 -0
  159. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/devin.py +0 -0
  160. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  161. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/grok_build.py +0 -0
  162. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  163. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/lane_configs/local_llm.py +0 -0
  164. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/local_llm_audit_pr.py +0 -0
  165. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/local_llm_bakeoff.py +0 -0
  166. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/local_llm_calibration.py +0 -0
  167. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/local_llm_profiles.py +0 -0
  168. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/migration_install.py +0 -0
  169. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/migration_mirror.py +0 -0
  170. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/migration_readiness.py +0 -0
  171. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/migration_rehearsal.py +0 -0
  172. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/next_steps.py +0 -0
  173. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package.py +0 -0
  174. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package_content.py +0 -0
  175. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package_paths.py +0 -0
  176. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package_rendering.py +0 -0
  177. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/package_static.py +0 -0
  178. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/plan_context.py +0 -0
  179. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/prompts.py +0 -0
  180. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_registry.py +0 -0
  181. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/__init__.py +0 -0
  182. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/comments.py +0 -0
  183. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/exit_codes.py +0 -0
  184. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/git.py +0 -0
  185. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/github_auth.py +0 -0
  186. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/github_pr.py +0 -0
  187. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  188. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/process.py +0 -0
  189. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/repo_paths.py +0 -0
  190. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/text_schema.py +0 -0
  191. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  192. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/provider_runners/workspace.py +0 -0
  193. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/providers/__init__.py +0 -0
  194. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/providers/local_cli.py +0 -0
  195. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/providers/provenance.py +0 -0
  196. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/release_readiness.py +0 -0
  197. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/reviewer_metrics.py +0 -0
  198. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/reviewer_spend.py +0 -0
  199. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/saas_reviewer_labeler.py +0 -0
  200. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/secrets.py +0 -0
  201. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/builder-experiment.example.json +0 -0
  202. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  203. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/calibration-corpus.json +0 -0
  204. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/code-mower.example.yml +0 -0
  205. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/context-packs.example.json +0 -0
  206. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  207. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  208. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  209. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  210. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  211. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  212. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  213. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
  214. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  215. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/README.md +0 -0
  216. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/claude.md +0 -0
  217. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/codex.md +0 -0
  218. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/cursor.md +0 -0
  219. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/generic.md +0 -0
  220. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/lanes/run_mac_lane.sh +0 -0
  221. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/code_mower +0 -0
  222. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  223. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  224. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  225. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  226. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  227. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/product-support/status_report.py +0 -0
  228. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/providers.yml +0 -0
  229. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  230. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  231. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  232. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  233. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  234. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  235. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +0 -0
  236. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  237. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  238. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  239. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  240. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
  241. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  242. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  243. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  244. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  245. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  246. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
  247. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/trailer_comment_labeler.py +0 -0
  248. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/versioning.py +0 -0
  249. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/work_orders.py +0 -0
  250. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower/workflow_actionlint.py +0 -0
  251. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/dependency_links.txt +0 -0
  252. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/entry_points.txt +0 -0
  253. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/requires.txt +0 -0
  254. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/src/code_mower.egg-info/top_level.txt +0 -0
  255. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/builder-experiment.example.json +0 -0
  256. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/calibration-corpus.example.json +0 -0
  257. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/calibration-corpus.json +0 -0
  258. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/code-mower.yml.j2 +0 -0
  259. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/context-packs.example.json +0 -0
  260. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/cursor/BUGBOT.md +0 -0
  261. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/README.md +0 -0
  262. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/claude.md +0 -0
  263. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/codex.md +0 -0
  264. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/cursor.md +0 -0
  265. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/generic.md +0 -0
  266. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/lanes/run_mac_lane.sh +0 -0
  267. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/acp_bridge.yml +0 -0
  268. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/aider.yml +0 -0
  269. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/antigravity_cli.yml +0 -0
  270. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/claude_audit.yml +0 -0
  271. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/claude_review.yml +0 -0
  272. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/coderabbit_cli.yml +0 -0
  273. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/codex.yml +0 -0
  274. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/cursor_bugbot.yml +0 -0
  275. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/devin.yml +0 -0
  276. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/gemini_cli.yml +0 -0
  277. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/gitar.yml +0 -0
  278. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/greptile.yml +0 -0
  279. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/hermes_cli.yml +0 -0
  280. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/local_llm.yml +0 -0
  281. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers/qodo.yml +0 -0
  282. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/providers.yml +0 -0
  283. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/reviewer-spend.example.json +0 -0
  284. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/reviewer-value-report.example.md +0 -0
  285. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  286. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  287. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  288. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  289. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  290. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/code-mower-gate.yml.j2 +0 -0
  291. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  292. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  293. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  294. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  295. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  296. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  297. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  298. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  299. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  300. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_antigravity_sdk_probe.py +0 -0
  301. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_audit_comment_posture.py +0 -0
  302. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_audit_limits.py +0 -0
  303. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_builder_experiment.py +0 -0
  304. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_builder_identity.py +0 -0
  305. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_builder_runs.py +0 -0
  306. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_calibration_effect_report.py +0 -0
  307. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_calibration_truth.py +0 -0
  308. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_checks.py +0 -0
  309. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_claude_audit_pr.py +0 -0
  310. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_claude_cli_bounce.py +0 -0
  311. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_clear_stale.py +0 -0
  312. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_cloud_client.py +0 -0
  313. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_cloud_git_metadata.py +0 -0
  314. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_cloud_manifest.py +0 -0
  315. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_cloud_reports.py +0 -0
  316. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  317. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_codex_audit_env_preflight.py +0 -0
  318. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_codex_audit_pr.py +0 -0
  319. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_decision_audit_integration.py +0 -0
  320. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_decisions.py +0 -0
  321. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_actions_cost_summary.py +0 -0
  322. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_actions_failure_selection.py +0 -0
  323. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_boundaries.py +0 -0
  324. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_output.py +0 -0
  325. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_privacy.py +0 -0
  326. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_provider_env_required.py +0 -0
  327. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_provider_env_tokens.py +0 -0
  328. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_provider_local_audit_setup.py +0 -0
  329. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_provider_probe.py +0 -0
  330. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_provider_review_hygiene.py +0 -0
  331. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_runtime.py +0 -0
  332. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_doctor_self_hosted_runner.py +0 -0
  333. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_gate_health.py +0 -0
  334. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_init_actionlint.py +0 -0
  335. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_init_build_loop.py +0 -0
  336. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_local_llm_github_helpers.py +0 -0
  337. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_migration_setup_drift.py +0 -0
  338. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_plan_context.py +0 -0
  339. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_prompts.py +0 -0
  340. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_fixture_contracts.py +0 -0
  341. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_local_cli.py +0 -0
  342. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_comments.py +0 -0
  343. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_git.py +0 -0
  344. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_github_pr.py +0 -0
  345. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_pr_worktree.py +0 -0
  346. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_process.py +0 -0
  347. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_repo_paths.py +0 -0
  348. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_text_schema.py +0 -0
  349. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_provider_runners_workspace.py +0 -0
  350. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_reviewer_metrics_core.py +0 -0
  351. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_reviewer_spend.py +0 -0
  352. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/tests/test_trailer_comment_labeler.py +0 -0
  353. {code_mower-0.9.0b1 → code_mower-0.9.2b1}/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.2b1
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,13 @@ 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.2-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.2 keeps the path
175
+ simple by removing the retired third-party observe bridge, softening
176
+ dispatch-token expiry metadata when the secret is present, and making
177
+ stale-audit waits name the runner/dispatcher requeue path. Package-only users
178
+ can start from the public package rather than a source checkout.
171
179
 
172
180
  ## What Calibration Does And Does Not Prove
173
181
 
@@ -190,13 +198,15 @@ review-request signals to propose known-clean and known-blocked cases. Review
190
198
  every disposition before using it for lane promotion or merge policy.
191
199
 
192
200
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
201
+ Existing-repo upgrade flow:
202
+ [docs/upgrade-existing-repo.md](docs/upgrade-existing-repo.md).
193
203
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
194
204
  Provider-contract baseline for the next release train:
195
205
  [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
196
206
 
197
207
  For release verification,
198
208
  [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
209
+ the package-index procedure for `v0.9.2-beta.1` / `code-mower==0.9.2b1`. The
200
210
  GitHub release records the workflow and rehearsal evidence for the exact tag.
201
211
 
202
212
  ## Optional: Plan Before Coding
@@ -382,8 +392,8 @@ measurement work.
382
392
 
383
393
  ## Installation Status
384
394
 
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
395
+ The current package-index beta baseline is `v0.9.2-beta.1`, with pinned package
396
+ install spec `code-mower==0.9.2b1`. Release evidence is recorded on the GitHub
387
397
  release and in the first-user install rehearsal. The public repository is
388
398
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
389
399
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -424,6 +434,7 @@ first so local work exercises the same package entrypoint users install.
424
434
  ## Docs Map
425
435
 
426
436
  - [Install And Bootstrap](docs/install.md)
437
+ - [Upgrade An Existing Repository](docs/upgrade-existing-repo.md)
427
438
  - [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
428
439
  - [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
429
440
  - [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,13 @@ 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.2-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.2 keeps the path
158
+ simple by removing the retired third-party observe bridge, softening
159
+ dispatch-token expiry metadata when the secret is present, and making
160
+ stale-audit waits name the runner/dispatcher requeue path. Package-only users
161
+ can start from the public package rather than a source checkout.
154
162
 
155
163
  ## What Calibration Does And Does Not Prove
156
164
 
@@ -173,13 +181,15 @@ review-request signals to propose known-clean and known-blocked cases. Review
173
181
  every disposition before using it for lane promotion or merge policy.
174
182
 
175
183
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
184
+ Existing-repo upgrade flow:
185
+ [docs/upgrade-existing-repo.md](docs/upgrade-existing-repo.md).
176
186
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
177
187
  Provider-contract baseline for the next release train:
178
188
  [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
179
189
 
180
190
  For release verification,
181
191
  [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
192
+ the package-index procedure for `v0.9.2-beta.1` / `code-mower==0.9.2b1`. The
183
193
  GitHub release records the workflow and rehearsal evidence for the exact tag.
184
194
 
185
195
  ## Optional: Plan Before Coding
@@ -365,8 +375,8 @@ measurement work.
365
375
 
366
376
  ## Installation Status
367
377
 
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
378
+ The current package-index beta baseline is `v0.9.2-beta.1`, with pinned package
379
+ install spec `code-mower==0.9.2b1`. Release evidence is recorded on the GitHub
370
380
  release and in the first-user install rehearsal. The public repository is
371
381
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
372
382
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -407,6 +417,7 @@ first so local work exercises the same package entrypoint users install.
407
417
  ## Docs Map
408
418
 
409
419
  - [Install And Bootstrap](docs/install.md)
420
+ - [Upgrade An Existing Repository](docs/upgrade-existing-repo.md)
410
421
  - [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
411
422
  - [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
412
423
  - [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.2b1"
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.2b1"
@@ -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,25 +689,26 @@ 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>
700
+ ${{pr.next_detail ? `<div class="muted">${{esc(pr.next_detail)}}</div>` : ""}}
692
701
  </div>`).join("") : empty("No open pull requests."));
693
702
  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."));
703
+ 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."));
704
+ 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
705
  const spendRows = [
697
706
  ...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
707
  spend.skipped_rows ? `<div class="row muted">Skipped ${{esc(spend.skipped_rows)}} malformed spend row(s).</div>` : "",
699
708
  spend.filtered_rows ? `<div class="row muted">Filtered ${{esc(spend.filtered_rows)}} spend row(s) from other repos.</div>` : ""
700
709
  ].filter(Boolean);
701
710
  put("spend", spendRows.length ? spendRows.join("") : empty(spend.message || "No reviewer spend rows for this repo yet."));
702
- const boards = data.agenttrail?.boards || [];
711
+ const boards = data.local_boards?.boards || [];
703
712
  const procs = data.local_processes?.processes || [];
704
713
  put("local", [...boards.map(b => `<div class="row">board localhost:${{esc(b.port)}} pid=${{esc(b.pid)}} cwd=<code>${{esc(b.cwd || "")}}</code></div>`), ...procs.slice(0, 8).map(p => `<div class="row">${{esc(p.provider)}} pid=${{esc(p.pid)}} cwd=<code>${{esc(p.cwd || "")}}</code></div>`)].join("") || empty("No local boards or lane processes visible."));
705
714
  }}
@@ -708,7 +717,7 @@ def render_board_html(config: BoardConfig) -> str:
708
717
  put("history", events.length ? events.slice().reverse().map(event => {{
709
718
  const s = event.summary || {{}};
710
719
  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>`;
720
+ 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
721
  }}).join("") : empty(history.message || "No local board events recorded yet."));
713
722
  }}
714
723
  async function load() {{
@@ -83,14 +83,16 @@ def _redact_local_paths(value: Any) -> Any:
83
83
 
84
84
  def _snapshot_summary(snapshot: Mapping[str, Any]) -> dict[str, Any]:
85
85
  remote = snapshot.get("remote") if isinstance(snapshot.get("remote"), dict) else {}
86
- agenttrail = snapshot.get("agenttrail") if isinstance(snapshot.get("agenttrail"), dict) else {}
86
+ local_boards = (
87
+ snapshot.get("local_boards") if isinstance(snapshot.get("local_boards"), dict) else {}
88
+ )
87
89
  local_processes = (
88
90
  snapshot.get("local_processes") if isinstance(snapshot.get("local_processes"), dict) else {}
89
91
  )
90
92
  pull_requests = remote.get("pull_requests") if isinstance(remote.get("pull_requests"), list) else []
91
93
  gate_health = remote.get("gate_health") if isinstance(remote.get("gate_health"), dict) else {}
92
94
  gate_alerts = gate_health.get("alerts") if isinstance(gate_health.get("alerts"), list) else []
93
- boards = agenttrail.get("boards") if isinstance(agenttrail.get("boards"), list) else []
95
+ boards = local_boards.get("boards") if isinstance(local_boards.get("boards"), list) else []
94
96
  processes = (
95
97
  local_processes.get("processes")
96
98
  if isinstance(local_processes.get("processes"), list)
@@ -71,7 +71,6 @@ from . import local_llm_calibration
71
71
  from . import local_llm_profiles
72
72
  from . import migration as code_mower_migration
73
73
  from . import next_steps as code_mower_next_steps
74
- from . import observe as code_mower_observe
75
74
  from . import package as code_mower_package
76
75
  from . import prompts as code_mower_prompts
77
76
  from . import reviewer_metrics
@@ -456,7 +455,6 @@ COMMAND_DESCRIPTIONS: dict[str, str] = {
456
455
  "migration": "Rehearse standalone package and wrapper migration paths.",
457
456
  "merge-plan": "Inspect merge-readiness signals and lane labels.",
458
457
  "next-steps": "Print the recommended next actions after setup.",
459
- "observe": "Run legacy optional local observability companions.",
460
458
  "package": "Build or inspect package extraction artifacts.",
461
459
  "plan": "Create local issue-derived planning artifacts.",
462
460
  "project-context": "Create editable local project-context doctrine docs.",
@@ -596,7 +594,6 @@ COMMAND_HANDLERS: dict[str, CommandHandler] = {
596
594
  "migration": code_mower_migration.main,
597
595
  "merge-plan": code_mower_merge.main,
598
596
  "next-steps": code_mower_next_steps.main,
599
- "observe": code_mower_observe.main,
600
597
  "package": _package_main,
601
598
  "plan": code_mower_work_orders.plan_main,
602
599
  "project-context": code_mower_work_orders.project_context_main,
@@ -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 "
@@ -173,11 +173,10 @@ def check_human_automation_token(
173
173
  http_timeout=http_timeout,
174
174
  )
175
175
  if variable_payload is None:
176
- status = _blocking_status_for_posture(adoption_posture)
177
176
  return DoctorCheck(
178
177
  name="github.human_automation_token",
179
- status=status,
180
- message=f"{slug} is missing the {expires_var} human token expiry variable",
178
+ status=STATUS_WARN,
179
+ message=f"{slug} is missing the {expires_var} human token expiry metadata",
181
180
  detail={
182
181
  **detail,
183
182
  "created_at": str(secret_payload.get("created_at") or ""),
@@ -219,10 +218,9 @@ def check_human_automation_token(
219
218
  )
220
219
  expiry = _parse_expiry(expiry_text)
221
220
  if expiry is None:
222
- status = _blocking_status_for_posture(adoption_posture)
223
221
  return DoctorCheck(
224
222
  name="github.human_automation_token",
225
- status=status,
223
+ status=STATUS_WARN,
226
224
  message=f"{slug} has an invalid {expires_var} value",
227
225
  detail={**detail, "expires_at": expiry_text},
228
226
  remediation=(
@@ -235,7 +233,7 @@ def check_human_automation_token(
235
233
  days_remaining = (expiry - today).days
236
234
  status = STATUS_PASS
237
235
  if days_remaining < 0:
238
- status = _blocking_status_for_posture(adoption_posture)
236
+ status = STATUS_WARN
239
237
  elif days_remaining <= EXPIRY_WARNING_DAYS:
240
238
  status = STATUS_WARN
241
239
 
@@ -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",)