code-mower 0.8.0b1__tar.gz → 0.9.0b1__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 (352) hide show
  1. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/PKG-INFO +24 -11
  2. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/README.md +23 -10
  3. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/pyproject.toml +1 -1
  4. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/__init__.py +1 -1
  5. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/board.py +79 -19
  6. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cli.py +2 -1
  7. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor.py +41 -1
  8. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/adoption.py +20 -12
  9. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/common.py +2 -0
  10. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github.py +2 -0
  11. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_human_token.py +39 -7
  12. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_review_hygiene.py +53 -30
  13. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/providers.py +9 -4
  14. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/runner.py +3 -0
  15. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -3
  16. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_status.py +21 -5
  17. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/migration.py +351 -1
  18. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/migration_install.py +22 -0
  19. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/migration_rehearsal.py +30 -7
  20. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/next_steps.py +4 -4
  21. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package_content.py +1 -1
  22. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/release_readiness.py +3 -0
  23. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
  24. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/PKG-INFO +24 -11
  25. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/SOURCES.txt +1 -0
  26. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/builder-provenance.yml.j2 +1 -1
  27. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_board.py +80 -0
  28. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_github_checks.py +30 -0
  29. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_provider_review_hygiene.py +4 -6
  30. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_registry.py +45 -0
  31. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_self_hosted_runner.py +31 -0
  32. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_lane_status.py +22 -0
  33. code_mower-0.9.0b1/tests/test_migration_setup_drift.py +82 -0
  34. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_release_hygiene.py +199 -39
  35. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/CODE_OF_CONDUCT.md +0 -0
  36. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/LICENSE +0 -0
  37. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/MANIFEST.in +0 -0
  38. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/NOTICE +0 -0
  39. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/SUPPORT.md +0 -0
  40. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/requirements/requirements.txt +0 -0
  41. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/setup.cfg +0 -0
  42. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/__init__.py +0 -0
  43. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/_base.py +0 -0
  44. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  45. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/gitar.py +0 -0
  46. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/greptile.py +0 -0
  47. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/adapters/qodo.py +0 -0
  48. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  49. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/antigravity_sdk_probe.py +0 -0
  50. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/audit_handoff_log.py +0 -0
  51. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/audit_labeler_lib.py +0 -0
  52. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/audit_limits.py +0 -0
  53. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/audit_progress.py +0 -0
  54. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/blind_review_artifacts.py +0 -0
  55. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/blind_review_coordinator.py +0 -0
  56. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/board_store.py +0 -0
  57. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/bootstrap.py +0 -0
  58. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/builder_experiment.py +0 -0
  59. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/builder_runs.py +0 -0
  60. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/__init__.py +0 -0
  61. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/arms.py +0 -0
  62. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/auto_discovery.py +0 -0
  63. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/commands.py +0 -0
  64. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/context_inputs.py +0 -0
  65. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/corpus.py +0 -0
  66. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/effect_report.py +0 -0
  67. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/evidence.py +0 -0
  68. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/evidence_report.py +0 -0
  69. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/identity.py +0 -0
  70. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/metrics.py +0 -0
  71. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/overlap.py +0 -0
  72. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/planning.py +0 -0
  73. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/policy.py +0 -0
  74. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/results.py +0 -0
  75. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/run_results.py +0 -0
  76. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/run_status.py +0 -0
  77. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/runner.py +0 -0
  78. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/truth.py +0 -0
  79. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/calibration/value_report.py +0 -0
  80. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/checks.py +0 -0
  81. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/claude_audit_pr.py +0 -0
  82. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/claude_cli_bounce.py +0 -0
  83. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/claude_cli_environment.py +0 -0
  84. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/clear_stale.py +0 -0
  85. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud.py +0 -0
  86. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/__init__.py +0 -0
  87. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/bundle.py +0 -0
  88. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/doctor.py +0 -0
  89. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/dogfood.py +0 -0
  90. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/endpoints.py +0 -0
  91. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/errors.py +0 -0
  92. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/events.py +0 -0
  93. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/export.py +0 -0
  94. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/git_metadata.py +0 -0
  95. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/manifest.py +0 -0
  96. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/operations.py +0 -0
  97. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/reports.py +0 -0
  98. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/setup.py +0 -0
  99. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/tokens.py +0 -0
  100. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/cloud_client/upload.py +0 -0
  101. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/code_mower_calibration.py +0 -0
  102. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/code_mower_context_packs.py +0 -0
  103. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/code_mower_merge.py +0 -0
  104. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/code_mower_telemetry.py +0 -0
  105. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  106. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/codex_audit_env_preflight.py +0 -0
  107. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/codex_audit_pr.py +0 -0
  108. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  109. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  110. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/config.py +0 -0
  111. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/decisions.py +0 -0
  112. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/__init__.py +0 -0
  113. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/audit_limits.py +0 -0
  114. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/cloud.py +0 -0
  115. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions.py +0 -0
  116. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  117. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  118. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  119. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  120. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  121. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  122. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  123. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  124. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_api.py +0 -0
  125. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_branch.py +0 -0
  126. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_config.py +0 -0
  127. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_provider.py +0 -0
  128. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/github_repo.py +0 -0
  129. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/groups.py +0 -0
  130. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/models.py +0 -0
  131. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/output.py +0 -0
  132. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/presets.py +0 -0
  133. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/privacy.py +0 -0
  134. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  135. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  136. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  137. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_env.py +0 -0
  138. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  139. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  140. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
  141. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  142. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  143. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  144. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  145. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  146. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  147. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  148. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  149. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/registry.py +0 -0
  150. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/runtime.py +0 -0
  151. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  152. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/gate_health.py +0 -0
  153. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/gemini_cli_audit_pr.py +0 -0
  154. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/git_identity.py +0 -0
  155. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/grok_build_audit_pr.py +0 -0
  156. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  157. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/init.py +0 -0
  158. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/__init__.py +0 -0
  159. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/aider.py +0 -0
  160. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  161. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/claude.py +0 -0
  162. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/codex.py +0 -0
  163. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/devin.py +0 -0
  164. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  165. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/grok_build.py +0 -0
  166. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  167. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/lane_configs/local_llm.py +0 -0
  168. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/local_llm_audit_pr.py +0 -0
  169. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/local_llm_bakeoff.py +0 -0
  170. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/local_llm_calibration.py +0 -0
  171. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/local_llm_profiles.py +0 -0
  172. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/migration_mirror.py +0 -0
  173. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/migration_readiness.py +0 -0
  174. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/observe.py +0 -0
  175. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package.py +0 -0
  176. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package_manifest.py +0 -0
  177. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package_paths.py +0 -0
  178. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package_rendering.py +0 -0
  179. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/package_static.py +0 -0
  180. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/plan_context.py +0 -0
  181. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/prompts.py +0 -0
  182. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_registry.py +0 -0
  183. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/__init__.py +0 -0
  184. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/comments.py +0 -0
  185. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/exit_codes.py +0 -0
  186. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/git.py +0 -0
  187. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/github_auth.py +0 -0
  188. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/github_pr.py +0 -0
  189. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  190. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/process.py +0 -0
  191. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/repo_paths.py +0 -0
  192. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/text_schema.py +0 -0
  193. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
  194. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/provider_runners/workspace.py +0 -0
  195. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/providers/__init__.py +0 -0
  196. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/providers/local_cli.py +0 -0
  197. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/providers/provenance.py +0 -0
  198. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/reviewer_metrics.py +0 -0
  199. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/reviewer_spend.py +0 -0
  200. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/saas_reviewer_labeler.py +0 -0
  201. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/secrets.py +0 -0
  202. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/builder-experiment.example.json +0 -0
  203. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  204. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/calibration-corpus.json +0 -0
  205. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/code-mower.example.yml +0 -0
  206. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/context-packs.example.json +0 -0
  207. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  208. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  209. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  210. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  211. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  212. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  213. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  214. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
  215. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  216. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/README.md +0 -0
  217. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/claude.md +0 -0
  218. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/codex.md +0 -0
  219. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/cursor.md +0 -0
  220. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/generic.md +0 -0
  221. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/lanes/run_mac_lane.sh +0 -0
  222. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/code_mower +0 -0
  223. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  224. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  225. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  226. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  227. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  228. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/product-support/status_report.py +0 -0
  229. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/providers.yml +0 -0
  230. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  231. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  232. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  233. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  234. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  235. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  236. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +0 -0
  237. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  238. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  239. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  240. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  241. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
  242. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  243. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  244. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  245. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  246. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  247. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
  248. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/trailer_comment_labeler.py +0 -0
  249. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/versioning.py +0 -0
  250. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/work_orders.py +0 -0
  251. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower/workflow_actionlint.py +0 -0
  252. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/dependency_links.txt +0 -0
  253. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/entry_points.txt +0 -0
  254. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/requires.txt +0 -0
  255. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/src/code_mower.egg-info/top_level.txt +0 -0
  256. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/builder-experiment.example.json +0 -0
  257. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/calibration-corpus.example.json +0 -0
  258. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/calibration-corpus.json +0 -0
  259. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/code-mower.yml.j2 +0 -0
  260. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/context-packs.example.json +0 -0
  261. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/cursor/BUGBOT.md +0 -0
  262. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/README.md +0 -0
  263. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/claude.md +0 -0
  264. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/codex.md +0 -0
  265. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/cursor.md +0 -0
  266. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/generic.md +0 -0
  267. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/lanes/run_mac_lane.sh +0 -0
  268. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/acp_bridge.yml +0 -0
  269. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/aider.yml +0 -0
  270. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/antigravity_cli.yml +0 -0
  271. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/claude_audit.yml +0 -0
  272. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/claude_review.yml +0 -0
  273. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/coderabbit_cli.yml +0 -0
  274. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/codex.yml +0 -0
  275. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/cursor_bugbot.yml +0 -0
  276. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/devin.yml +0 -0
  277. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/gemini_cli.yml +0 -0
  278. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/gitar.yml +0 -0
  279. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/greptile.yml +0 -0
  280. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/hermes_cli.yml +0 -0
  281. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/local_llm.yml +0 -0
  282. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers/qodo.yml +0 -0
  283. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/providers.yml +0 -0
  284. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/reviewer-spend.example.json +0 -0
  285. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/reviewer-value-report.example.md +0 -0
  286. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  287. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  288. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  289. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
  290. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  291. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/code-mower-gate.yml.j2 +0 -0
  292. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/dispatch-lanes.yml.j2 +0 -0
  293. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  294. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  295. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  296. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  297. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  298. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  299. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
  300. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  301. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_antigravity_sdk_probe.py +0 -0
  302. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_audit_comment_posture.py +0 -0
  303. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_audit_limits.py +0 -0
  304. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_builder_experiment.py +0 -0
  305. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_builder_identity.py +0 -0
  306. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_builder_runs.py +0 -0
  307. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_calibration_effect_report.py +0 -0
  308. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_calibration_truth.py +0 -0
  309. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_checks.py +0 -0
  310. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_claude_audit_pr.py +0 -0
  311. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_claude_cli_bounce.py +0 -0
  312. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_clear_stale.py +0 -0
  313. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_cloud_client.py +0 -0
  314. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_cloud_git_metadata.py +0 -0
  315. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_cloud_manifest.py +0 -0
  316. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_cloud_reports.py +0 -0
  317. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  318. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_codex_audit_env_preflight.py +0 -0
  319. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_codex_audit_pr.py +0 -0
  320. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_decision_audit_integration.py +0 -0
  321. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_decisions.py +0 -0
  322. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_actions_cost_summary.py +0 -0
  323. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_actions_failure_selection.py +0 -0
  324. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_boundaries.py +0 -0
  325. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_output.py +0 -0
  326. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_privacy.py +0 -0
  327. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_provider_env_required.py +0 -0
  328. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_provider_env_tokens.py +0 -0
  329. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_provider_local_audit_setup.py +0 -0
  330. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_provider_probe.py +0 -0
  331. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_doctor_runtime.py +0 -0
  332. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_gate_health.py +0 -0
  333. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_init_actionlint.py +0 -0
  334. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_init_build_loop.py +0 -0
  335. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_local_llm_github_helpers.py +0 -0
  336. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_observe.py +0 -0
  337. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_plan_context.py +0 -0
  338. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_prompts.py +0 -0
  339. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_fixture_contracts.py +0 -0
  340. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_local_cli.py +0 -0
  341. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_comments.py +0 -0
  342. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_git.py +0 -0
  343. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_github_pr.py +0 -0
  344. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_pr_worktree.py +0 -0
  345. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_process.py +0 -0
  346. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_repo_paths.py +0 -0
  347. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_text_schema.py +0 -0
  348. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_provider_runners_workspace.py +0 -0
  349. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_reviewer_metrics_core.py +0 -0
  350. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_reviewer_spend.py +0 -0
  351. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/tests/test_trailer_comment_labeler.py +0 -0
  352. {code_mower-0.8.0b1 → code_mower-0.9.0b1}/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.8.0b1
3
+ Version: 0.9.0b1
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.12
@@ -64,6 +64,8 @@ for a real repository. It checks your runtime, GitHub setup, provider CLIs,
64
64
  token posture, optional cloud setup, private-repo Actions cost traps, and
65
65
  first-run adoption gaps. `--preflight` remains the compatibility preset for
66
66
  older scripts; `--adoption` adds explicit repo targeting and setup guidance.
67
+ Use `--hosted-builders` or `--orchestrator-only` when the current machine is
68
+ observing/coordinating lanes and will not run local Codex or Claude wrappers.
67
69
 
68
70
  Example, shortened:
69
71
 
@@ -88,6 +90,12 @@ boundaries visible before you promote any reviewer lane.
88
90
 
89
91
  See a fuller static transcript: [docs/first-run-transcript.md](docs/first-run-transcript.md).
90
92
 
93
+ For an existing repository that already has Code Mower generated workflows or
94
+ wrappers, run `code-mower migration setup-drift --repo-path .` before copying a
95
+ fresh `.code-mower.generated` tree. It is read-only and reports path-level
96
+ classifications (`same`, `differs`, `new`, `repo-only`,
97
+ `missing-from-output`) without file contents or diffs.
98
+
91
99
  After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
92
100
  see active builder/reviewer lanes, gate/check state, recent Code Mower
93
101
  workflows, local board/process hints when present, and the next operator
@@ -96,8 +104,10 @@ action. Text and JSON output redact local cwd paths by default; use
96
104
 
97
105
  For the same redacted metadata in a local browser view, run
98
106
  `code-mower board serve --repo OWNER/REPO` and open the printed localhost URL.
99
- Plain `board serve` is read-only. To build local history while the browser view
100
- is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
107
+ Plain `board serve` is read-only. If the default Board port is busy, the CLI
108
+ uses a nearby free loopback port and prints the URL; an explicit `--port` stays
109
+ strict and reports a friendly conflict. To build local history while the browser
110
+ view is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
101
111
  records at most one snapshot every 60 seconds by default. To append one snapshot
102
112
  without serving the browser view, run
103
113
  `code-mower board record --repo OWNER/REPO` from the repository checkout; it
@@ -143,7 +153,9 @@ observable.
143
153
 
144
154
  Install first from the [Install And Bootstrap](docs/install.md) matrix: pipx for
145
155
  laptops, uv tool installs for hosted agents or CI boxes, and an editable venv
146
- for Code Mower contributors. All paths require Python 3.12 or newer.
156
+ for Code Mower contributors. All paths require Python 3.12 or newer. For
157
+ upgrades, record `command -v code-mower` and `code-mower --version` before and
158
+ after reinstalling, especially when switching between pipx and uv.
147
159
 
148
160
  | Path | Use When | Route | Guide |
149
161
  | --- | --- | --- | --- |
@@ -152,10 +164,10 @@ for Code Mower contributors. All paths require Python 3.12 or newer.
152
164
  | 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) |
153
165
 
154
166
  The current package-index announcement entry point is the tagged
155
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.8.0-beta.1/docs/try-in-10-minutes.md)
156
- guide. The v0.8 beta includes the completed adoption-polish and native Board
157
- work, so package-only users can start from the public package rather than a
158
- source checkout.
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)
168
+ 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.
159
171
 
160
172
  ## What Calibration Does And Does Not Prove
161
173
 
@@ -184,7 +196,7 @@ Provider-contract baseline for the next release train:
184
196
 
185
197
  For release verification,
186
198
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
187
- the package-index procedure for `v0.8.0-beta.1` / `code-mower==0.8.0b1`. The
199
+ the package-index procedure for `v0.9.0-beta.1` / `code-mower==0.9.0b1`. The
188
200
  GitHub release records the workflow and rehearsal evidence for the exact tag.
189
201
 
190
202
  ## Optional: Plan Before Coding
@@ -370,8 +382,8 @@ measurement work.
370
382
 
371
383
  ## Installation Status
372
384
 
373
- The current package-index beta baseline is `v0.8.0-beta.1`, with pinned package
374
- install spec `code-mower==0.8.0b1`. Release evidence is recorded on the GitHub
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
375
387
  release and in the first-user install rehearsal. The public repository is
376
388
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
377
389
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -434,6 +446,7 @@ first so local work exercises the same package entrypoint users install.
434
446
  - [v0.6 Truth Baseline](docs/v06-truth-baseline.md)
435
447
  - [v0.6 Release Notes](docs/v06-release-notes.md)
436
448
  - [v0.8 Release Notes](docs/v08-release-notes.md)
449
+ - [v0.9 Release Notes](docs/v09-release-notes.md)
437
450
  - [Post-v0.8 Effectiveness Assessment](docs/post-v08-effectiveness-assessment.md)
438
451
  - [Demo Calibration Example](examples/demo-calibration/README.md)
439
452
  - [Board Demo Rehearsal](examples/board-demo/README.md)
@@ -47,6 +47,8 @@ for a real repository. It checks your runtime, GitHub setup, provider CLIs,
47
47
  token posture, optional cloud setup, private-repo Actions cost traps, and
48
48
  first-run adoption gaps. `--preflight` remains the compatibility preset for
49
49
  older scripts; `--adoption` adds explicit repo targeting and setup guidance.
50
+ Use `--hosted-builders` or `--orchestrator-only` when the current machine is
51
+ observing/coordinating lanes and will not run local Codex or Claude wrappers.
50
52
 
51
53
  Example, shortened:
52
54
 
@@ -71,6 +73,12 @@ boundaries visible before you promote any reviewer lane.
71
73
 
72
74
  See a fuller static transcript: [docs/first-run-transcript.md](docs/first-run-transcript.md).
73
75
 
76
+ For an existing repository that already has Code Mower generated workflows or
77
+ wrappers, run `code-mower migration setup-drift --repo-path .` before copying a
78
+ fresh `.code-mower.generated` tree. It is read-only and reports path-level
79
+ classifications (`same`, `differs`, `new`, `repo-only`,
80
+ `missing-from-output`) without file contents or diffs.
81
+
74
82
  After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
75
83
  see active builder/reviewer lanes, gate/check state, recent Code Mower
76
84
  workflows, local board/process hints when present, and the next operator
@@ -79,8 +87,10 @@ action. Text and JSON output redact local cwd paths by default; use
79
87
 
80
88
  For the same redacted metadata in a local browser view, run
81
89
  `code-mower board serve --repo OWNER/REPO` and open the printed localhost URL.
82
- Plain `board serve` is read-only. To build local history while the browser view
83
- is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
90
+ Plain `board serve` is read-only. If the default Board port is busy, the CLI
91
+ uses a nearby free loopback port and prints the URL; an explicit `--port` stays
92
+ strict and reports a friendly conflict. To build local history while the browser
93
+ view is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
84
94
  records at most one snapshot every 60 seconds by default. To append one snapshot
85
95
  without serving the browser view, run
86
96
  `code-mower board record --repo OWNER/REPO` from the repository checkout; it
@@ -126,7 +136,9 @@ observable.
126
136
 
127
137
  Install first from the [Install And Bootstrap](docs/install.md) matrix: pipx for
128
138
  laptops, uv tool installs for hosted agents or CI boxes, and an editable venv
129
- for Code Mower contributors. All paths require Python 3.12 or newer.
139
+ for Code Mower contributors. All paths require Python 3.12 or newer. For
140
+ upgrades, record `command -v code-mower` and `code-mower --version` before and
141
+ after reinstalling, especially when switching between pipx and uv.
130
142
 
131
143
  | Path | Use When | Route | Guide |
132
144
  | --- | --- | --- | --- |
@@ -135,10 +147,10 @@ for Code Mower contributors. All paths require Python 3.12 or newer.
135
147
  | 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) |
136
148
 
137
149
  The current package-index announcement entry point is the tagged
138
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.8.0-beta.1/docs/try-in-10-minutes.md)
139
- guide. The v0.8 beta includes the completed adoption-polish and native Board
140
- work, so package-only users can start from the public package rather than a
141
- source checkout.
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)
151
+ 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.
142
154
 
143
155
  ## What Calibration Does And Does Not Prove
144
156
 
@@ -167,7 +179,7 @@ Provider-contract baseline for the next release train:
167
179
 
168
180
  For release verification,
169
181
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
170
- the package-index procedure for `v0.8.0-beta.1` / `code-mower==0.8.0b1`. The
182
+ the package-index procedure for `v0.9.0-beta.1` / `code-mower==0.9.0b1`. The
171
183
  GitHub release records the workflow and rehearsal evidence for the exact tag.
172
184
 
173
185
  ## Optional: Plan Before Coding
@@ -353,8 +365,8 @@ measurement work.
353
365
 
354
366
  ## Installation Status
355
367
 
356
- The current package-index beta baseline is `v0.8.0-beta.1`, with pinned package
357
- install spec `code-mower==0.8.0b1`. Release evidence is recorded on the GitHub
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
358
370
  release and in the first-user install rehearsal. The public repository is
359
371
  [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
360
372
  GitHub releases remain the auditable source for tags, build artifacts, and
@@ -417,6 +429,7 @@ first so local work exercises the same package entrypoint users install.
417
429
  - [v0.6 Truth Baseline](docs/v06-truth-baseline.md)
418
430
  - [v0.6 Release Notes](docs/v06-release-notes.md)
419
431
  - [v0.8 Release Notes](docs/v08-release-notes.md)
432
+ - [v0.9 Release Notes](docs/v09-release-notes.md)
420
433
  - [Post-v0.8 Effectiveness Assessment](docs/post-v08-effectiveness-assessment.md)
421
434
  - [Demo Calibration Example](examples/demo-calibration/README.md)
422
435
  - [Board Demo Rehearsal](examples/board-demo/README.md)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.8.0b1"
7
+ version = "0.9.0b1"
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.8.0b1"
3
+ __version__ = "0.9.0b1"
@@ -4,6 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import argparse
7
+ import errno
7
8
  import json
8
9
  import re
9
10
  import socket
@@ -41,6 +42,7 @@ class BoardConfig:
41
42
  repo: str
42
43
  host: str = DEFAULT_HOST
43
44
  port: int = DEFAULT_PORT
45
+ port_was_default: bool = True
44
46
  pr_limit: int = 50
45
47
  workflow_limit: int = 20
46
48
  stale_minutes: int = 30
@@ -111,6 +113,46 @@ def _server_url(host: str, port: int) -> str:
111
113
  return f"http://{display_host}:{port}/"
112
114
 
113
115
 
116
+ def _candidate_ports(config: BoardConfig) -> list[int]:
117
+ if not config.port_was_default:
118
+ return [config.port]
119
+ last_port = min(65535, config.port + 9)
120
+ return list(range(config.port, last_port + 1))
121
+
122
+
123
+ def _explicit_port_conflict_message(host: str, port: int) -> str:
124
+ suggestions = list(range(port + 1, min(65535, port + 3) + 1))
125
+ suggestion_text = f" such as {', '.join(str(candidate) for candidate in suggestions)}" if suggestions else ""
126
+ return (
127
+ f"error: Code Mower Board port {port} is already in use on {host}. "
128
+ f"Pass --port with a free loopback port{suggestion_text}."
129
+ )
130
+
131
+
132
+ def _bind_board_server(
133
+ config: BoardConfig,
134
+ handler: type[BaseHTTPRequestHandler],
135
+ ) -> ThreadingHTTPServer | None:
136
+ server_type = _server_class(config.host)
137
+ tried: list[int] = []
138
+ for port in _candidate_ports(config):
139
+ tried.append(port)
140
+ try:
141
+ return server_type((config.host, port), handler)
142
+ except OSError as exc:
143
+ if exc.errno != errno.EADDRINUSE:
144
+ raise
145
+ if not config.port_was_default:
146
+ print(_explicit_port_conflict_message(config.host, port), file=sys.stderr)
147
+ return None
148
+ print(
149
+ "error: Code Mower Board could not find a free loopback port in "
150
+ f"{tried[0]}-{tried[-1]}; pass --port with a free port.",
151
+ file=sys.stderr,
152
+ )
153
+ return None
154
+
155
+
114
156
  def status_payload(
115
157
  config: BoardConfig,
116
158
  *,
@@ -781,6 +823,9 @@ def serve(config: BoardConfig, *, open_browser: bool = False) -> int:
781
823
  if not _is_loopback(config.host):
782
824
  print("error: board host must be loopback; use 127.0.0.1 or localhost", file=sys.stderr)
783
825
  return 2
826
+ if not 0 <= config.port <= 65535:
827
+ print("error: --port must be between 0 and 65535", file=sys.stderr)
828
+ return 2
784
829
  if config.record_interval_seconds < 0:
785
830
  print("error: --record-interval-seconds must be non-negative", file=sys.stderr)
786
831
  return 2
@@ -791,10 +836,14 @@ def serve(config: BoardConfig, *, open_browser: bool = False) -> int:
791
836
  print("error: --max-events must be at least 1", file=sys.stderr)
792
837
  return 2
793
838
  handler = make_handler(config)
794
- server_type = _server_class(config.host)
795
- with server_type((config.host, config.port), handler) as server:
839
+ server = _bind_board_server(config, handler)
840
+ if server is None:
841
+ return 2
842
+ with server:
796
843
  port = int(server.server_address[1])
797
844
  url = _server_url(config.host, port)
845
+ if config.port_was_default and port != config.port:
846
+ print(f"Code Mower Board: default port {config.port} was busy; using {port}", file=sys.stderr)
798
847
  print(f"Code Mower Board: {url}", flush=True)
799
848
  if open_browser:
800
849
  webbrowser.open(url)
@@ -1057,22 +1106,32 @@ def main(argv: list[str] | None = None) -> int:
1057
1106
  subparsers = parser.add_subparsers(dest="command", required=True)
1058
1107
  serve_parser = subparsers.add_parser("serve")
1059
1108
  serve_parser.add_argument("--repo", required=True)
1060
- serve_parser.add_argument("--host", default=DEFAULT_HOST)
1061
- serve_parser.add_argument("--port", type=int, default=DEFAULT_PORT)
1062
- serve_parser.add_argument("--pr-limit", type=int, default=50)
1063
- serve_parser.add_argument("--workflow-limit", type=int, default=20)
1064
- serve_parser.add_argument("--stale-minutes", type=int, default=30)
1065
- serve_parser.add_argument("--refresh-seconds", type=int, default=15)
1066
- serve_parser.add_argument("--show-local-paths", action="store_true")
1067
- serve_parser.add_argument("--repo-path", default=".")
1068
- serve_parser.add_argument("--store-path")
1069
- serve_parser.add_argument("--spend-path")
1070
- serve_parser.add_argument("--agent-adapters-path")
1071
- serve_parser.add_argument("--event-limit", type=int, default=20)
1072
- serve_parser.add_argument("--record-events", action="store_true")
1073
- serve_parser.add_argument("--record-interval-seconds", type=int, default=60)
1074
- serve_parser.add_argument("--retention-days", type=int, default=board_store.DEFAULT_RETENTION_DAYS)
1075
- serve_parser.add_argument("--max-events", type=int, default=board_store.DEFAULT_MAX_EVENTS)
1109
+ serve_parser.add_argument("--host", default=DEFAULT_HOST, help="loopback host to bind; default: 127.0.0.1")
1110
+ serve_parser.add_argument(
1111
+ "--port",
1112
+ type=int,
1113
+ default=None,
1114
+ help="loopback port; the default auto-falls forward when busy",
1115
+ )
1116
+ serve_parser.add_argument("--pr-limit", type=int, default=50, help="open PRs to show")
1117
+ serve_parser.add_argument("--workflow-limit", type=int, default=20, help="recent Code Mower workflow runs to show")
1118
+ serve_parser.add_argument("--stale-minutes", type=int, default=30, help="minutes before gate evidence is stale")
1119
+ serve_parser.add_argument("--refresh-seconds", type=int, default=15, help="browser refresh interval")
1120
+ serve_parser.add_argument("--show-local-paths", action="store_true", help="show local cwd paths for debugging")
1121
+ serve_parser.add_argument("--repo-path", default=".", help="repository checkout used for local Board files")
1122
+ serve_parser.add_argument("--store-path", help="custom local Board event store path")
1123
+ serve_parser.add_argument("--spend-path", help="custom reviewer spend ledger path")
1124
+ serve_parser.add_argument("--agent-adapters-path", help="custom local agent card directory")
1125
+ serve_parser.add_argument("--event-limit", type=int, default=20, help="local history events to show")
1126
+ serve_parser.add_argument("--record-events", action="store_true", help="append local history while the Board is open")
1127
+ serve_parser.add_argument("--record-interval-seconds", type=int, default=60, help="minimum seconds between records")
1128
+ serve_parser.add_argument(
1129
+ "--retention-days",
1130
+ type=int,
1131
+ default=board_store.DEFAULT_RETENTION_DAYS,
1132
+ help="local history retention window",
1133
+ )
1134
+ serve_parser.add_argument("--max-events", type=int, default=board_store.DEFAULT_MAX_EVENTS, help="maximum local events")
1076
1135
  serve_parser.add_argument("--open", action="store_true", help="open the local board in a browser")
1077
1136
  record_parser = subparsers.add_parser("record")
1078
1137
  record_parser.add_argument("--repo", required=True)
@@ -1115,7 +1174,8 @@ def main(argv: list[str] | None = None) -> int:
1115
1174
  BoardConfig(
1116
1175
  repo=args.repo,
1117
1176
  host=args.host,
1118
- port=args.port,
1177
+ port=DEFAULT_PORT if args.port is None else args.port,
1178
+ port_was_default=args.port is None,
1119
1179
  pr_limit=args.pr_limit,
1120
1180
  workflow_limit=args.workflow_limit,
1121
1181
  stale_minutes=args.stale_minutes,
@@ -556,7 +556,8 @@ def _top_level_help(show_all: bool) -> str:
556
556
  " code-mower board serve --repo OWNER/REPO",
557
557
  (
558
558
  " code-mower migration package-install-rehearsal "
559
- f"--package-spec {code_mower_next_steps.current_alpha_package_spec()} --json"
559
+ f"--package-spec {code_mower_next_steps.current_alpha_package_spec()} "
560
+ "--allow-package-index --json"
560
561
  ),
561
562
  ]
562
563
  )
@@ -51,6 +51,39 @@ detect_repo_slug = _doctor_checks.detect_repo_slug
51
51
  normalize_repo_slug = _doctor_checks.normalize_repo_slug
52
52
 
53
53
 
54
+ def _source_repo_uses_starter_config(cwd: Path, config_path: Path) -> bool:
55
+ """Return true when doctor is running from Code Mower's source tree."""
56
+
57
+ try:
58
+ config_path.resolve().relative_to(cwd.resolve())
59
+ except ValueError:
60
+ return False
61
+ return (
62
+ config_path.name == "code-mower.example.yml"
63
+ and (cwd / "pyproject.toml").is_file()
64
+ and (cwd / "src" / "code_mower" / "templates" / "code-mower.example.yml").is_file()
65
+ )
66
+
67
+
68
+ def _doctor_config_source_label(
69
+ *,
70
+ config_arg: str,
71
+ config_path: Path,
72
+ easy: bool,
73
+ cwd: Path | None = None,
74
+ ) -> str:
75
+ """Classify the config source for adoption-facing doctor output."""
76
+
77
+ cwd = cwd or Path.cwd()
78
+ if config_arg != "code-mower.yml":
79
+ return "explicit_config"
80
+ if config_path.name == "code-mower.example.yml" and easy:
81
+ if _source_repo_uses_starter_config(cwd, config_path):
82
+ return "source_tree_starter"
83
+ return "packaged_starter"
84
+ return "repository_config"
85
+
86
+
54
87
  _DOCTOR_COMPAT_EXPORTS = (
55
88
  DEFAULT_CLOUD_TOKEN_DIR,
56
89
  DEFAULT_CLOUD_TOKEN_ENV,
@@ -68,6 +101,7 @@ _DOCTOR_COMPAT_EXPORTS = (
68
101
  resolve_doctor_config_path_for_script,
69
102
  resolve_doctor_provider_templates_path,
70
103
  _token_file_mentions_cloud_token,
104
+ _doctor_config_source_label,
71
105
  )
72
106
 
73
107
 
@@ -202,12 +236,18 @@ def main(argv: Sequence[str] | None = None) -> int:
202
236
  repo_slug = detect_repo_slug(Path.cwd())
203
237
  repo_source = "git_remote" if repo_slug else ""
204
238
  provider_templates_path = resolve_doctor_provider_templates_path(args.provider_templates)
239
+ config_path = resolve_doctor_config_path(args.config, easy=args.easy)
205
240
  report = run_doctor(
206
- config_path=resolve_doctor_config_path(args.config, easy=args.easy),
241
+ config_path=config_path,
207
242
  provider_templates_path=provider_templates_path,
208
243
  profile=args.profile,
209
244
  repo_slug=repo_slug,
210
245
  repo_source=repo_source,
246
+ config_source=_doctor_config_source_label(
247
+ config_arg=args.config,
248
+ config_path=config_path,
249
+ easy=args.easy,
250
+ ),
211
251
  adoption=args.adoption,
212
252
  adoption_posture=args.adoption_posture,
213
253
  probe_runtime=args.probe_runtime,
@@ -111,6 +111,7 @@ def check_adoption_setup(
111
111
  repo_slug: str,
112
112
  repo_source: str,
113
113
  using_packaged_example: bool,
114
+ config_source: str = "",
114
115
  ) -> tuple[DoctorCheck, ...]:
115
116
  """Return first-run adoption posture checks."""
116
117
 
@@ -144,17 +145,28 @@ def check_adoption_setup(
144
145
  )
145
146
 
146
147
  repositories = _configured_repositories(config)
148
+ source = config_source or (
149
+ "packaged_starter" if using_packaged_example else "repository_config"
150
+ )
151
+ source_messages = {
152
+ "explicit_config": "using explicit Code Mower config",
153
+ "packaged_starter": "using packaged starter config for adoption checks",
154
+ "repository_config": "using repository Code Mower config",
155
+ "source_tree_starter": "using source-tree starter config for adoption checks",
156
+ }
157
+ detail = {
158
+ "config_path": str(config_path),
159
+ "config_source": source,
160
+ "configured_repositories": repositories,
161
+ "effective_repository": repo_slug,
162
+ }
147
163
  if using_packaged_example:
148
164
  checks.append(
149
165
  DoctorCheck(
150
166
  name="doctor.adoption.config_source",
151
167
  status=STATUS_WARN,
152
- message="using packaged starter config for adoption checks",
153
- detail={
154
- "config_path": str(config_path),
155
- "configured_repositories": repositories,
156
- "effective_repository": repo_slug,
157
- },
168
+ message=source_messages.get(source, source_messages["packaged_starter"]),
169
+ detail=detail,
158
170
  remediation=(
159
171
  "Run `code-mower init --easy --apply`, review the generated "
160
172
  "setup, and commit an edited code-mower.yml before relying "
@@ -167,12 +179,8 @@ def check_adoption_setup(
167
179
  DoctorCheck(
168
180
  name="doctor.adoption.config_source",
169
181
  status=STATUS_PASS,
170
- message="using repository Code Mower config",
171
- detail={
172
- "config_path": str(config_path),
173
- "configured_repositories": repositories,
174
- "effective_repository": repo_slug,
175
- },
182
+ message=source_messages.get(source, source_messages["repository_config"]),
183
+ detail=detail,
176
184
  )
177
185
  )
178
186
 
@@ -66,6 +66,7 @@ ACTIONS_METADATA_WORKFLOW_MARKERS = (
66
66
  "audit-label-cleanup",
67
67
  "devin-audit-bridge",
68
68
  )
69
+ OBSERVER_ADOPTION_POSTURES = frozenset({"hosted-builders", "orchestrator-only"})
69
70
 
70
71
  __all__ = [
71
72
  "ACTIONS_BILLING_BLOCK_PATTERNS",
@@ -76,6 +77,7 @@ __all__ = [
76
77
  "DoctorCheck",
77
78
  "MAX_ACTIONS_FAILED_JOBS_TO_INSPECT",
78
79
  "MAX_ACTIONS_FAILED_RUNS_TO_INSPECT",
80
+ "OBSERVER_ADOPTION_POSTURES",
79
81
  "STATUS_FAIL",
80
82
  "STATUS_PASS",
81
83
  "STATUS_SKIP",
@@ -36,6 +36,7 @@ def check_github_setup(
36
36
  lanes: Sequence[tuple[str, Mapping[str, Any]]],
37
37
  http_timeout: int,
38
38
  actions_cost_sample: int = ACTIONS_COST_SAMPLE_DEFAULT,
39
+ adoption_posture: str = "reviewer-gate",
39
40
  ) -> list[DoctorCheck]:
40
41
  checks: list[DoctorCheck] = []
41
42
  gh_path = shutil.which("gh")
@@ -142,6 +143,7 @@ def check_github_setup(
142
143
  config=config,
143
144
  lanes=lanes,
144
145
  http_timeout=http_timeout,
146
+ adoption_posture=adoption_posture,
145
147
  )
146
148
  )
147
149
  if has_merge_authority:
@@ -5,7 +5,14 @@ from __future__ import annotations
5
5
  from datetime import UTC, date, datetime
6
6
  from typing import Any, Mapping, Sequence
7
7
 
8
- from .common import DoctorCheck, STATUS_FAIL, STATUS_PASS, STATUS_SKIP, STATUS_WARN
8
+ from .common import (
9
+ OBSERVER_ADOPTION_POSTURES,
10
+ DoctorCheck,
11
+ STATUS_FAIL,
12
+ STATUS_PASS,
13
+ STATUS_SKIP,
14
+ STATUS_WARN,
15
+ )
9
16
  from .github_api import _github_api_json
10
17
 
11
18
  DEFAULT_HUMAN_TOKEN_SECRET = "DISPATCH_TOKEN"
@@ -93,6 +100,18 @@ def _is_expiry_placeholder(value: str) -> bool:
93
100
  return value.strip().upper() in EXPIRY_PLACEHOLDER_VALUES
94
101
 
95
102
 
103
+ def _blocking_status_for_posture(adoption_posture: str) -> str:
104
+ return STATUS_WARN if adoption_posture in OBSERVER_ADOPTION_POSTURES else STATUS_FAIL
105
+
106
+
107
+ def _token_readiness_context(adoption_posture: str) -> str:
108
+ if adoption_posture == "hosted-builders":
109
+ return "hosted-builder observer posture"
110
+ if adoption_posture == "orchestrator-only":
111
+ return "orchestrator-only posture"
112
+ return "reviewer-gate posture"
113
+
114
+
96
115
  def check_human_automation_token(
97
116
  *,
98
117
  gh_path: str,
@@ -100,6 +119,7 @@ def check_human_automation_token(
100
119
  config: Mapping[str, Any],
101
120
  lanes: Sequence[tuple[str, Mapping[str, Any]]],
102
121
  http_timeout: int,
122
+ adoption_posture: str = "reviewer-gate",
103
123
  now: datetime | None = None,
104
124
  ) -> DoctorCheck:
105
125
  token = human_automation_token_config(config)
@@ -110,6 +130,7 @@ def check_human_automation_token(
110
130
  "secret": secret_name,
111
131
  "expires_var": expires_var,
112
132
  "required": human_automation_token_required(config, lanes),
133
+ "adoption_posture": adoption_posture,
113
134
  }
114
135
  if not detail["required"]:
115
136
  return DoctorCheck(
@@ -125,15 +146,24 @@ def check_human_automation_token(
125
146
  http_timeout=http_timeout,
126
147
  )
127
148
  if secret_payload is None:
149
+ status = _blocking_status_for_posture(adoption_posture)
128
150
  return DoctorCheck(
129
151
  name="github.human_automation_token",
130
- status=STATUS_FAIL,
131
- message=f"{slug} is missing the {secret_name} human automation token secret",
152
+ status=status,
153
+ message=(
154
+ f"{slug} is missing the {secret_name} human automation token secret"
155
+ + (
156
+ f" for {_token_readiness_context(adoption_posture)}"
157
+ if status == STATUS_WARN
158
+ else ""
159
+ )
160
+ ),
132
161
  detail={**detail, "secret_check": secret_detail},
133
162
  remediation=(
134
163
  f"Create one human-owned fine-grained PAT secret with "
135
164
  f"`gh secret set {secret_name}`. Grant repository Contents read, "
136
- "Issues read/write, and Pull requests read/write."
165
+ "Issues read/write, and Pull requests read/write before relying "
166
+ "on unattended dispatch, labels, or fix-round mentions."
137
167
  ),
138
168
  )
139
169
 
@@ -143,9 +173,10 @@ def check_human_automation_token(
143
173
  http_timeout=http_timeout,
144
174
  )
145
175
  if variable_payload is None:
176
+ status = _blocking_status_for_posture(adoption_posture)
146
177
  return DoctorCheck(
147
178
  name="github.human_automation_token",
148
- status=STATUS_FAIL,
179
+ status=status,
149
180
  message=f"{slug} is missing the {expires_var} human token expiry variable",
150
181
  detail={
151
182
  **detail,
@@ -188,9 +219,10 @@ def check_human_automation_token(
188
219
  )
189
220
  expiry = _parse_expiry(expiry_text)
190
221
  if expiry is None:
222
+ status = _blocking_status_for_posture(adoption_posture)
191
223
  return DoctorCheck(
192
224
  name="github.human_automation_token",
193
- status=STATUS_FAIL,
225
+ status=status,
194
226
  message=f"{slug} has an invalid {expires_var} value",
195
227
  detail={**detail, "expires_at": expiry_text},
196
228
  remediation=(
@@ -203,7 +235,7 @@ def check_human_automation_token(
203
235
  days_remaining = (expiry - today).days
204
236
  status = STATUS_PASS
205
237
  if days_remaining < 0:
206
- status = STATUS_FAIL
238
+ status = _blocking_status_for_posture(adoption_posture)
207
239
  elif days_remaining <= EXPIRY_WARNING_DAYS:
208
240
  status = STATUS_WARN
209
241