code-mower 0.5.0b52__tar.gz → 0.6.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 (346) hide show
  1. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/PKG-INFO +41 -16
  2. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/README.md +40 -15
  3. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/pyproject.toml +8 -3
  4. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/__init__.py +1 -1
  5. code_mower-0.6.0b1/src/code_mower/antigravity_sdk_probe.py +129 -0
  6. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/bootstrap.py +1 -1
  7. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/builder_experiment.py +165 -3
  8. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/auto_discovery.py +11 -4
  9. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/claude_audit_pr.py +20 -20
  10. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cli.py +51 -2
  11. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud.py +9 -0
  12. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/__init__.py +2 -0
  13. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/events.py +146 -4
  14. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/operations.py +14 -1
  15. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/code_mower_telemetry.py +27 -10
  16. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/codex_audit_pr.py +21 -26
  17. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/config.py +1 -0
  18. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/gemini_cli_audit_pr.py +10 -6
  19. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/init.py +127 -32
  20. code_mower-0.6.0b1/src/code_mower/lane_status.py +457 -0
  21. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/next_steps.py +1 -1
  22. code_mower-0.6.0b1/src/code_mower/observe.py +324 -0
  23. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package_content.py +1 -0
  24. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package_manifest.py +10 -2
  25. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_registry.py +1 -4
  26. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/__init__.py +16 -0
  27. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/comments.py +36 -0
  28. code_mower-0.6.0b1/src/code_mower/provider_runners/exit_codes.py +13 -0
  29. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/verdict_artifacts.py +81 -10
  30. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/release_readiness.py +5 -2
  31. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/code-mower.example.yml +9 -5
  32. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lanes/run_mac_lane.sh +4 -1
  33. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
  34. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +8 -2
  35. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +5 -3
  36. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +124 -123
  37. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +1 -0
  38. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/trailer_comment_labeler.py +15 -1
  39. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/versioning.py +5 -2
  40. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/PKG-INFO +41 -16
  41. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/SOURCES.txt +11 -2
  42. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/lanes/run_mac_lane.sh +4 -1
  43. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/builder-provenance.yml.j2 +1 -1
  44. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +8 -2
  45. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/code-mower-gate.yml.j2 +5 -3
  46. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/dispatch-lanes.yml.j2 +124 -123
  47. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/self-hosted-local-audit.yml.j2 +1 -0
  48. code_mower-0.6.0b1/tests/test_antigravity_sdk_probe.py +120 -0
  49. code_mower-0.6.0b1/tests/test_builder_experiment.py +131 -0
  50. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_builder_identity.py +32 -2
  51. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_cloud_client.py +37 -0
  52. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_gate_health.py +1 -1
  53. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_init_build_loop.py +28 -7
  54. code_mower-0.6.0b1/tests/test_lane_status.py +128 -0
  55. code_mower-0.6.0b1/tests/test_observe.py +111 -0
  56. code_mower-0.6.0b1/tests/test_provider_fixture_contracts.py +134 -0
  57. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_local_cli.py +104 -0
  58. code_mower-0.6.0b1/tests/test_provider_runners_comments.py +77 -0
  59. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_release_hygiene.py +358 -50
  60. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_reviewer_metrics_core.py +120 -2
  61. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_trailer_comment_labeler.py +35 -0
  62. code_mower-0.5.0b52/tests/test_provider_runners_comments.py +0 -42
  63. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/CODE_OF_CONDUCT.md +0 -0
  64. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/LICENSE +0 -0
  65. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/MANIFEST.in +0 -0
  66. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/NOTICE +0 -0
  67. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/SUPPORT.md +0 -0
  68. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/requirements/requirements.txt +0 -0
  69. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/setup.cfg +0 -0
  70. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/__init__.py +0 -0
  71. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/_base.py +0 -0
  72. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/cursor_bugbot.py +0 -0
  73. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/gitar.py +0 -0
  74. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/greptile.py +0 -0
  75. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/adapters/qodo.py +0 -0
  76. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
  77. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/audit_handoff_log.py +0 -0
  78. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/audit_labeler_lib.py +0 -0
  79. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/audit_limits.py +0 -0
  80. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/audit_progress.py +0 -0
  81. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/blind_review_artifacts.py +0 -0
  82. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/blind_review_coordinator.py +0 -0
  83. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/builder_runs.py +0 -0
  84. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/__init__.py +0 -0
  85. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/arms.py +0 -0
  86. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/commands.py +0 -0
  87. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/context_inputs.py +0 -0
  88. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/corpus.py +0 -0
  89. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/effect_report.py +0 -0
  90. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/evidence.py +0 -0
  91. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/evidence_report.py +0 -0
  92. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/identity.py +0 -0
  93. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/metrics.py +0 -0
  94. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/overlap.py +0 -0
  95. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/planning.py +0 -0
  96. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/policy.py +0 -0
  97. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/results.py +0 -0
  98. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/run_results.py +0 -0
  99. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/run_status.py +0 -0
  100. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/runner.py +0 -0
  101. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/truth.py +0 -0
  102. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/calibration/value_report.py +0 -0
  103. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/checks.py +0 -0
  104. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/claude_cli_bounce.py +0 -0
  105. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/claude_cli_environment.py +0 -0
  106. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/clear_stale.py +0 -0
  107. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/bundle.py +0 -0
  108. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/doctor.py +0 -0
  109. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/dogfood.py +0 -0
  110. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/endpoints.py +0 -0
  111. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/errors.py +0 -0
  112. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/export.py +0 -0
  113. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/git_metadata.py +0 -0
  114. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/manifest.py +0 -0
  115. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/reports.py +0 -0
  116. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/setup.py +0 -0
  117. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/cloud_client/upload.py +0 -0
  118. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/code_mower_calibration.py +0 -0
  119. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/code_mower_context_packs.py +0 -0
  120. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/code_mower_merge.py +0 -0
  121. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
  122. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/codex_audit_env_preflight.py +0 -0
  123. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/codex_audit_schema_smoke.py +0 -0
  124. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/codex_audit_verdict.schema.json +0 -0
  125. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/decisions.py +0 -0
  126. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor.py +0 -0
  127. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/__init__.py +0 -0
  128. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/audit_limits.py +0 -0
  129. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/cloud.py +0 -0
  130. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/common.py +0 -0
  131. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github.py +0 -0
  132. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions.py +0 -0
  133. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
  134. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
  135. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
  136. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
  137. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
  138. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
  139. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
  140. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
  141. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_api.py +0 -0
  142. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_branch.py +0 -0
  143. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_config.py +0 -0
  144. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_human_token.py +0 -0
  145. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_provider.py +0 -0
  146. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/github_repo.py +0 -0
  147. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/groups.py +0 -0
  148. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/models.py +0 -0
  149. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/output.py +0 -0
  150. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/presets.py +0 -0
  151. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/privacy.py +0 -0
  152. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
  153. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
  154. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
  155. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_env.py +0 -0
  156. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
  157. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
  158. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
  159. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
  160. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
  161. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
  162. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_probe.py +0 -0
  163. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
  164. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
  165. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
  166. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
  167. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
  168. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/providers.py +0 -0
  169. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/registry.py +0 -0
  170. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/runner.py +0 -0
  171. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/runtime.py +0 -0
  172. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
  173. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -0
  174. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/gate_health.py +0 -0
  175. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/grok_build_audit_pr.py +0 -0
  176. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/hermes_cli_audit_pr.py +0 -0
  177. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/__init__.py +0 -0
  178. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/aider.py +0 -0
  179. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
  180. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/claude.py +0 -0
  181. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/codex.py +0 -0
  182. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/devin.py +0 -0
  183. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/gemini_cli.py +0 -0
  184. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/grok_build.py +0 -0
  185. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/hermes_cli.py +0 -0
  186. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/lane_configs/local_llm.py +0 -0
  187. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/local_llm_audit_pr.py +0 -0
  188. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/local_llm_bakeoff.py +0 -0
  189. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/local_llm_calibration.py +0 -0
  190. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/local_llm_profiles.py +0 -0
  191. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/migration.py +0 -0
  192. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/migration_install.py +0 -0
  193. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/migration_mirror.py +0 -0
  194. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/migration_readiness.py +0 -0
  195. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/migration_rehearsal.py +0 -0
  196. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package.py +0 -0
  197. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package_paths.py +0 -0
  198. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package_rendering.py +0 -0
  199. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/package_static.py +0 -0
  200. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/plan_context.py +0 -0
  201. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/prompts.py +0 -0
  202. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/git.py +0 -0
  203. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/github_auth.py +0 -0
  204. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/github_pr.py +0 -0
  205. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/pr_worktree.py +0 -0
  206. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/process.py +0 -0
  207. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/repo_paths.py +0 -0
  208. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/text_schema.py +0 -0
  209. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/provider_runners/workspace.py +0 -0
  210. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/providers/__init__.py +0 -0
  211. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/providers/local_cli.py +0 -0
  212. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/providers/provenance.py +0 -0
  213. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/reviewer_metrics.py +0 -0
  214. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/reviewer_spend.py +0 -0
  215. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/saas_reviewer_labeler.py +0 -0
  216. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/secrets.py +0 -0
  217. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/builder-experiment.example.json +0 -0
  218. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/calibration-corpus.example.json +0 -0
  219. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/calibration-corpus.json +0 -0
  220. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/context-packs.example.json +0 -0
  221. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
  222. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
  223. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
  224. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
  225. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
  226. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/operability.md +0 -0
  227. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
  228. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
  229. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
  230. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lanes/README.md +0 -0
  231. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lanes/claude.md +0 -0
  232. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lanes/codex.md +0 -0
  233. /code_mower-0.5.0b52/src/code_mower/templates/lanes/grok.md → /code_mower-0.6.0b1/src/code_mower/templates/lanes/cursor.md +0 -0
  234. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/lanes/generic.md +0 -0
  235. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/code_mower +0 -0
  236. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
  237. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
  238. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
  239. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
  240. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
  241. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/product-support/status_report.py +0 -0
  242. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/providers.yml +0 -0
  243. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/reviewer-spend.example.json +0 -0
  244. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
  245. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  246. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  247. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  248. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
  249. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  250. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
  251. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
  252. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  253. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
  254. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  255. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  256. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
  257. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/work_orders.py +0 -0
  258. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower/workflow_actionlint.py +0 -0
  259. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/dependency_links.txt +0 -0
  260. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/entry_points.txt +0 -0
  261. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/requires.txt +0 -0
  262. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/src/code_mower.egg-info/top_level.txt +0 -0
  263. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/builder-experiment.example.json +0 -0
  264. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/calibration-corpus.example.json +0 -0
  265. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/calibration-corpus.json +0 -0
  266. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/code-mower.yml.j2 +0 -0
  267. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/context-packs.example.json +0 -0
  268. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/cursor/BUGBOT.md +0 -0
  269. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/lanes/README.md +0 -0
  270. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/lanes/claude.md +0 -0
  271. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/lanes/codex.md +0 -0
  272. /code_mower-0.5.0b52/templates/lanes/grok.md → /code_mower-0.6.0b1/templates/lanes/cursor.md +0 -0
  273. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/lanes/generic.md +0 -0
  274. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/acp_bridge.yml +0 -0
  275. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/aider.yml +0 -0
  276. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/antigravity_cli.yml +0 -0
  277. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/claude_audit.yml +0 -0
  278. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/claude_review.yml +0 -0
  279. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/coderabbit_cli.yml +0 -0
  280. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/codex.yml +0 -0
  281. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/cursor_bugbot.yml +0 -0
  282. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/devin.yml +0 -0
  283. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/gemini_cli.yml +0 -0
  284. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/gitar.yml +0 -0
  285. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/greptile.yml +0 -0
  286. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/hermes_cli.yml +0 -0
  287. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/local_llm.yml +0 -0
  288. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers/qodo.yml +0 -0
  289. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/providers.yml +0 -0
  290. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/reviewer-spend.example.json +0 -0
  291. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/reviewer-value-report.example.md +0 -0
  292. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
  293. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
  294. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
  295. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
  296. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/hosted-bridge.yml.j2 +0 -0
  297. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
  298. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/local-cli-audit.yml.j2 +0 -0
  299. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
  300. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/review-clear-stale.yml.j2 +0 -0
  301. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
  302. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
  303. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_audit_comment_posture.py +0 -0
  304. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_audit_limits.py +0 -0
  305. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_builder_runs.py +0 -0
  306. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_calibration_effect_report.py +0 -0
  307. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_calibration_truth.py +0 -0
  308. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_checks.py +0 -0
  309. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_claude_audit_pr.py +0 -0
  310. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_claude_cli_bounce.py +0 -0
  311. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_clear_stale.py +0 -0
  312. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_cloud_git_metadata.py +0 -0
  313. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_cloud_manifest.py +0 -0
  314. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_cloud_reports.py +0 -0
  315. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_coderabbit_cli_audit_pr.py +0 -0
  316. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_codex_audit_env_preflight.py +0 -0
  317. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_codex_audit_pr.py +0 -0
  318. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_decision_audit_integration.py +0 -0
  319. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_decisions.py +0 -0
  320. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_actions_cost_summary.py +0 -0
  321. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_actions_failure_selection.py +0 -0
  322. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_boundaries.py +0 -0
  323. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_github_checks.py +0 -0
  324. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_output.py +0 -0
  325. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_privacy.py +0 -0
  326. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_provider_env_required.py +0 -0
  327. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_provider_env_tokens.py +0 -0
  328. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_provider_local_audit_setup.py +0 -0
  329. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_provider_probe.py +0 -0
  330. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_provider_review_hygiene.py +0 -0
  331. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_registry.py +0 -0
  332. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_runtime.py +0 -0
  333. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_doctor_self_hosted_runner.py +0 -0
  334. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_init_actionlint.py +0 -0
  335. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_local_llm_github_helpers.py +0 -0
  336. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_plan_context.py +0 -0
  337. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_prompts.py +0 -0
  338. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_git.py +0 -0
  339. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_github_pr.py +0 -0
  340. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_pr_worktree.py +0 -0
  341. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_process.py +0 -0
  342. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_repo_paths.py +0 -0
  343. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_text_schema.py +0 -0
  344. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_provider_runners_workspace.py +0 -0
  345. {code_mower-0.5.0b52 → code_mower-0.6.0b1}/tests/test_reviewer_spend.py +0 -0
  346. {code_mower-0.5.0b52 → code_mower-0.6.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.5.0b52
3
+ Version: 0.6.0b1
4
4
  Summary: Multi-reviewer AI code audit orchestration
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.11
@@ -59,9 +59,8 @@ Code Mower should feel like an engineering tool, not a demo harness:
59
59
 
60
60
  `code-mower doctor --preflight` is the first useful command. It checks your
61
61
  runtime, GitHub setup, provider CLIs, token posture, optional cloud setup, and
62
- private-repo Actions cost traps. `--preflight` is the friendly name for the
63
- versioned v0.5 first-run preset, so `doctor --v05` remains equivalent for
64
- scripts.
62
+ private-repo Actions cost traps. `--preflight` is the friendly first-run preset;
63
+ `doctor --v05` remains an equivalent compatibility alias for older scripts.
65
64
 
66
65
  Example, shortened:
67
66
 
@@ -86,6 +85,10 @@ boundaries visible before you promote any reviewer lane.
86
85
 
87
86
  See a fuller static transcript: [docs/first-run-transcript.md](docs/first-run-transcript.md).
88
87
 
88
+ After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
89
+ see active builder/reviewer lanes, gate/check state, recent Code Mower
90
+ workflows, local AgentTrail boards when present, and the next operator action.
91
+
89
92
  ## See The Value Shape First
90
93
 
91
94
  If you want to understand the product before installing anything, start with
@@ -103,14 +106,18 @@ fast, or eligible for stronger merge policy on your actual codebase.
103
106
  ## Start Here
104
107
 
105
108
  Choose one path. Each path has one guide and gets to one visible outcome.
109
+ Cold adopters should start with the reviewer gate, then add builders, then
110
+ measure builder experiments; provider experiments come after that base loop is
111
+ observable.
106
112
 
107
113
  | Path | Use When | Route | Guide |
108
114
  | --- | --- | --- | --- |
109
115
  | A. Reviewer gate in 10 minutes | You want one audited PR before recurring workflows or builder dispatch. | Install, run `init --easy`, run `doctor --preflight`, open a small setup PR, run Codex and Claude audits, then merge manually when the audit evidence is clean. | [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md) |
110
116
  | B. Build loop in 30 minutes | You want builders plus an orchestrator pattern after the reviewer gate works. | Complete path A, then add the automation token, require `code-mower/gate` from Any source, enable repository auto-merge, prove the self-hosted Mac lane runner with `doctor --runner`, run `init --builders`, and dispatch the first issue. | [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md) |
117
+ | 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) |
111
118
 
112
- The beta.52 announcement entry point remains the tagged
113
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.5.0-beta.52/docs/try-in-10-minutes.md)
119
+ The v0.6 beta announcement entry point is the tagged
120
+ [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.6.0-beta.1/docs/try-in-10-minutes.md)
114
121
  guide.
115
122
 
116
123
  ## What Calibration Does And Does Not Prove
@@ -135,10 +142,13 @@ every disposition before using it for lane promotion or merge policy.
135
142
 
136
143
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
137
144
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
145
+ Provider-contract baseline for the next release train:
146
+ [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
138
147
 
139
- The current PyPI beta has been rehearsed end-to-end from a clean install:
148
+ For release verification,
140
149
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
141
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b52`.
150
+ the package-index procedure for `v0.6.0-beta.1` / `code-mower==0.6.0b1`. The
151
+ GitHub release records the workflow and rehearsal evidence for the exact tag.
142
152
 
143
153
  ## Optional: Plan Before Coding
144
154
 
@@ -197,6 +207,11 @@ optional work order, single-writer branch, reviewer lanes, and fix rounds. Code
197
207
  Mower's templates now support that loop end to end; humans still own
198
208
  credentials, branch protection, calibration, and owner decisions.
199
209
 
210
+ The reference adoption shape is Claude Code as orchestrator; Claude Code,
211
+ Codex, and Cursor as builder lanes; Claude Code and Codex as reviewer lanes;
212
+ and Gitar or Antigravity as informational reviewer signal until local
213
+ calibration says otherwise.
214
+
200
215
  ## Why Not Just Run Codex Or Claude Yourself?
201
216
 
202
217
  You should, at first. Code Mower is not a replacement for a good local agent or
@@ -274,6 +289,10 @@ Everything else starts manual or informational until your own calibration data
274
289
  proves it is useful: Antigravity/Gemini, Hermes, CodeRabbit CLI, Cursor BugBot,
275
290
  Qodo, Greptile, Devin, local LLMs, and future ACP bridges.
276
291
 
292
+ Gemini CLI and Antigravity are distinct lane ids even though both are Google
293
+ surfaces and may use Gemini model infrastructure. Keep their auth, model
294
+ provenance, calibration evidence, and release notes separate.
295
+
277
296
  Provider details: [docs/provider-matrix.md](docs/provider-matrix.md).
278
297
  Setup/auth fixes: [docs/troubleshooting.md](docs/troubleshooting.md).
279
298
 
@@ -285,12 +304,13 @@ engineer can:
285
304
  1. install Code Mower in a clean repo;
286
305
  2. understand the local/cloud trust boundary;
287
306
  3. run `init --easy` and `doctor --preflight`;
288
- 4. detect and run the repo's native lint/test/build surface instead of assuming
307
+ 4. run `lanes status --repo OWNER/REPO` to see active lanes and gate state;
308
+ 5. detect and run the repo's native lint/test/build surface instead of assuming
289
309
  every project uses the same tools;
290
- 5. produce a local value report from known PR outcomes;
291
- 6. decide which lanes should stay informational, selective, or merge-gating;
310
+ 6. produce a local value report from known PR outcomes;
311
+ 7. decide which lanes should stay informational, selective, or merge-gating;
292
312
  and
293
- 7. optionally upload sanitized metadata to CodeMower.com and see useful team
313
+ 8. optionally upload sanitized metadata to CodeMower.com and see useful team
294
314
  dashboard signal.
295
315
 
296
316
  Build-loop templates extend the same loop from "who reviews best?" to "which AI
@@ -302,9 +322,10 @@ measurement work.
302
322
 
303
323
  ## Installation Status
304
324
 
305
- The current public beta is `v0.5.0-beta.52` from
306
- [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
307
- as `code-mower==0.5.0b52` on [PyPI](https://pypi.org/project/code-mower/).
325
+ The current public beta baseline is `v0.6.0-beta.1`, with pinned package-index
326
+ install spec `code-mower==0.6.0b1`. Release evidence is recorded on the GitHub
327
+ release and in the first-user install rehearsal. The public repository is
328
+ [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
308
329
  GitHub releases remain the auditable source for tags, build artifacts, and
309
330
  release notes.
310
331
 
@@ -317,6 +338,8 @@ scripts/dev-python -m venv .venv
317
338
  ```
318
339
 
319
340
  The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
341
+ Do not run the CLI by hand-wiring source import paths; install the editable venv
342
+ first so local work exercises the same package entrypoint users install.
320
343
 
321
344
  ## Known Limitations
322
345
 
@@ -351,13 +374,15 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
351
374
  - [Lane Standing Instructions](docs/lanes/README.md)
352
375
  - [Codex Lane Standing Instructions](docs/lanes/codex.md)
353
376
  - [Claude Lane Standing Instructions](docs/lanes/claude.md)
354
- - [Cursor Hosted Lane Standing Instructions](docs/lanes/grok.md)
377
+ - [Cursor Hosted Lane Standing Instructions](docs/lanes/cursor.md)
355
378
  - [Provider Matrix](docs/provider-matrix.md)
356
379
  - [GitHub Setup](docs/github-setup.md)
357
380
  - [First Run Transcript](docs/first-run-transcript.md)
358
381
  - [First-User Demo Transcript](docs/first-user-demo-transcript.md)
359
382
  - [First-User Install Rehearsal](docs/first-user-install-rehearsal.md)
360
383
  - [Launch Command Surface](docs/launch-command-surface.md)
384
+ - [v0.6 Truth Baseline](docs/v06-truth-baseline.md)
385
+ - [v0.6 Release Notes](docs/v06-release-notes.md)
361
386
  - [Demo Calibration Example](examples/demo-calibration/README.md)
362
387
  - [PyPI Release Runbook](docs/pypi-release.md)
363
388
  - [Sample Doctor Output](docs/sample-doctor-output.md)
@@ -44,9 +44,8 @@ Code Mower should feel like an engineering tool, not a demo harness:
44
44
 
45
45
  `code-mower doctor --preflight` is the first useful command. It checks your
46
46
  runtime, GitHub setup, provider CLIs, token posture, optional cloud setup, and
47
- private-repo Actions cost traps. `--preflight` is the friendly name for the
48
- versioned v0.5 first-run preset, so `doctor --v05` remains equivalent for
49
- scripts.
47
+ private-repo Actions cost traps. `--preflight` is the friendly first-run preset;
48
+ `doctor --v05` remains an equivalent compatibility alias for older scripts.
50
49
 
51
50
  Example, shortened:
52
51
 
@@ -71,6 +70,10 @@ boundaries visible before you promote any reviewer lane.
71
70
 
72
71
  See a fuller static transcript: [docs/first-run-transcript.md](docs/first-run-transcript.md).
73
72
 
73
+ After `init` and `doctor`, use `code-mower lanes status --repo OWNER/REPO` to
74
+ see active builder/reviewer lanes, gate/check state, recent Code Mower
75
+ workflows, local AgentTrail boards when present, and the next operator action.
76
+
74
77
  ## See The Value Shape First
75
78
 
76
79
  If you want to understand the product before installing anything, start with
@@ -88,14 +91,18 @@ fast, or eligible for stronger merge policy on your actual codebase.
88
91
  ## Start Here
89
92
 
90
93
  Choose one path. Each path has one guide and gets to one visible outcome.
94
+ Cold adopters should start with the reviewer gate, then add builders, then
95
+ measure builder experiments; provider experiments come after that base loop is
96
+ observable.
91
97
 
92
98
  | Path | Use When | Route | Guide |
93
99
  | --- | --- | --- | --- |
94
100
  | A. Reviewer gate in 10 minutes | You want one audited PR before recurring workflows or builder dispatch. | Install, run `init --easy`, run `doctor --preflight`, open a small setup PR, run Codex and Claude audits, then merge manually when the audit evidence is clean. | [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md) |
95
101
  | B. Build loop in 30 minutes | You want builders plus an orchestrator pattern after the reviewer gate works. | Complete path A, then add the automation token, require `code-mower/gate` from Any source, enable repository auto-merge, prove the self-hosted Mac lane runner with `doctor --runner`, run `init --builders`, and dispatch the first issue. | [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md) |
102
+ | 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) |
96
103
 
97
- The beta.52 announcement entry point remains the tagged
98
- [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.5.0-beta.52/docs/try-in-10-minutes.md)
104
+ The v0.6 beta announcement entry point is the tagged
105
+ [Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.6.0-beta.1/docs/try-in-10-minutes.md)
99
106
  guide.
100
107
 
101
108
  ## What Calibration Does And Does Not Prove
@@ -120,10 +127,13 @@ every disposition before using it for lane promotion or merge policy.
120
127
 
121
128
  Full walkthrough: [docs/try-in-10-minutes.md](docs/try-in-10-minutes.md).
122
129
  First-time command map: [docs/launch-command-surface.md](docs/launch-command-surface.md).
130
+ Provider-contract baseline for the next release train:
131
+ [docs/v06-truth-baseline.md](docs/v06-truth-baseline.md).
123
132
 
124
- The current PyPI beta has been rehearsed end-to-end from a clean install:
133
+ For release verification,
125
134
  [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
126
- the latest 10/10 public-package readiness proof for `code-mower==0.5.0b52`.
135
+ the package-index procedure for `v0.6.0-beta.1` / `code-mower==0.6.0b1`. The
136
+ GitHub release records the workflow and rehearsal evidence for the exact tag.
127
137
 
128
138
  ## Optional: Plan Before Coding
129
139
 
@@ -182,6 +192,11 @@ optional work order, single-writer branch, reviewer lanes, and fix rounds. Code
182
192
  Mower's templates now support that loop end to end; humans still own
183
193
  credentials, branch protection, calibration, and owner decisions.
184
194
 
195
+ The reference adoption shape is Claude Code as orchestrator; Claude Code,
196
+ Codex, and Cursor as builder lanes; Claude Code and Codex as reviewer lanes;
197
+ and Gitar or Antigravity as informational reviewer signal until local
198
+ calibration says otherwise.
199
+
185
200
  ## Why Not Just Run Codex Or Claude Yourself?
186
201
 
187
202
  You should, at first. Code Mower is not a replacement for a good local agent or
@@ -259,6 +274,10 @@ Everything else starts manual or informational until your own calibration data
259
274
  proves it is useful: Antigravity/Gemini, Hermes, CodeRabbit CLI, Cursor BugBot,
260
275
  Qodo, Greptile, Devin, local LLMs, and future ACP bridges.
261
276
 
277
+ Gemini CLI and Antigravity are distinct lane ids even though both are Google
278
+ surfaces and may use Gemini model infrastructure. Keep their auth, model
279
+ provenance, calibration evidence, and release notes separate.
280
+
262
281
  Provider details: [docs/provider-matrix.md](docs/provider-matrix.md).
263
282
  Setup/auth fixes: [docs/troubleshooting.md](docs/troubleshooting.md).
264
283
 
@@ -270,12 +289,13 @@ engineer can:
270
289
  1. install Code Mower in a clean repo;
271
290
  2. understand the local/cloud trust boundary;
272
291
  3. run `init --easy` and `doctor --preflight`;
273
- 4. detect and run the repo's native lint/test/build surface instead of assuming
292
+ 4. run `lanes status --repo OWNER/REPO` to see active lanes and gate state;
293
+ 5. detect and run the repo's native lint/test/build surface instead of assuming
274
294
  every project uses the same tools;
275
- 5. produce a local value report from known PR outcomes;
276
- 6. decide which lanes should stay informational, selective, or merge-gating;
295
+ 6. produce a local value report from known PR outcomes;
296
+ 7. decide which lanes should stay informational, selective, or merge-gating;
277
297
  and
278
- 7. optionally upload sanitized metadata to CodeMower.com and see useful team
298
+ 8. optionally upload sanitized metadata to CodeMower.com and see useful team
279
299
  dashboard signal.
280
300
 
281
301
  Build-loop templates extend the same loop from "who reviews best?" to "which AI
@@ -287,9 +307,10 @@ measurement work.
287
307
 
288
308
  ## Installation Status
289
309
 
290
- The current public beta is `v0.5.0-beta.52` from
291
- [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
292
- as `code-mower==0.5.0b52` on [PyPI](https://pypi.org/project/code-mower/).
310
+ The current public beta baseline is `v0.6.0-beta.1`, with pinned package-index
311
+ install spec `code-mower==0.6.0b1`. Release evidence is recorded on the GitHub
312
+ release and in the first-user install rehearsal. The public repository is
313
+ [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
293
314
  GitHub releases remain the auditable source for tags, build artifacts, and
294
315
  release notes.
295
316
 
@@ -302,6 +323,8 @@ scripts/dev-python -m venv .venv
302
323
  ```
303
324
 
304
325
  The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
326
+ Do not run the CLI by hand-wiring source import paths; install the editable venv
327
+ first so local work exercises the same package entrypoint users install.
305
328
 
306
329
  ## Known Limitations
307
330
 
@@ -336,13 +359,15 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
336
359
  - [Lane Standing Instructions](docs/lanes/README.md)
337
360
  - [Codex Lane Standing Instructions](docs/lanes/codex.md)
338
361
  - [Claude Lane Standing Instructions](docs/lanes/claude.md)
339
- - [Cursor Hosted Lane Standing Instructions](docs/lanes/grok.md)
362
+ - [Cursor Hosted Lane Standing Instructions](docs/lanes/cursor.md)
340
363
  - [Provider Matrix](docs/provider-matrix.md)
341
364
  - [GitHub Setup](docs/github-setup.md)
342
365
  - [First Run Transcript](docs/first-run-transcript.md)
343
366
  - [First-User Demo Transcript](docs/first-user-demo-transcript.md)
344
367
  - [First-User Install Rehearsal](docs/first-user-install-rehearsal.md)
345
368
  - [Launch Command Surface](docs/launch-command-surface.md)
369
+ - [v0.6 Truth Baseline](docs/v06-truth-baseline.md)
370
+ - [v0.6 Release Notes](docs/v06-release-notes.md)
346
371
  - [Demo Calibration Example](examples/demo-calibration/README.md)
347
372
  - [PyPI Release Runbook](docs/pypi-release.md)
348
373
  - [Sample Doctor Output](docs/sample-doctor-output.md)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-mower"
7
- version = "0.5.0b52"
7
+ version = "0.6.0b1"
8
8
  description = "Multi-reviewer AI code audit orchestration"
9
9
  requires-python = ">=3.11"
10
10
  readme = "README.md"
@@ -47,8 +47,13 @@ target-version = "py311"
47
47
  line-length = 100
48
48
 
49
49
  [tool.ruff.lint]
50
- select = ["E", "F"]
51
- ignore = ["E501"]
50
+ select = ["E", "F", "W", "B"]
51
+ ignore = [
52
+ "E501",
53
+ # LaneConfig instances are finite config objects; keep the callable helper
54
+ # shape stable instead of churning call sites for cached_property.
55
+ "B019",
56
+ ]
52
57
 
53
58
  [tool.ruff.lint.per-file-ignores]
54
59
  "tests/*.py" = ["E402"]
@@ -1,3 +1,3 @@
1
1
  """Code Mower package."""
2
2
 
3
- __version__ = "0.5.0b52"
3
+ __version__ = "0.6.0b1"
@@ -0,0 +1,129 @@
1
+ """Optional Antigravity SDK probe helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib
6
+ import importlib.util
7
+ from importlib import metadata
8
+ from typing import Any
9
+
10
+ PACKAGE_NAME = "google-antigravity"
11
+ IMPORT_NAME = "google.antigravity"
12
+ EXPECTED_EXPORTS = (
13
+ "Agent",
14
+ "LocalAgentConfig",
15
+ "CapabilitiesConfig",
16
+ "UsageMetadata",
17
+ "GeminiAPIEndpoint",
18
+ "VertexEndpoint",
19
+ )
20
+ LOCAL_HARNESS_PATH = "google/antigravity/bin/localharness"
21
+
22
+
23
+ def _dependency_name(requirement: str) -> str:
24
+ text = requirement.split(";", 1)[0].strip()
25
+ for separator in ("<", ">", "=", "!", "~", " "):
26
+ if separator in text:
27
+ text = text.split(separator, 1)[0].strip()
28
+ return text
29
+
30
+
31
+ def _dependency_names(requirements: list[str] | None) -> tuple[list[str], list[str]]:
32
+ required: set[str] = set()
33
+ optional: set[str] = set()
34
+ for requirement in requirements or []:
35
+ name = _dependency_name(requirement)
36
+ if not name:
37
+ continue
38
+ if "extra ==" in requirement:
39
+ optional.add(name)
40
+ else:
41
+ required.add(name)
42
+ return sorted(required), sorted(optional)
43
+
44
+
45
+ def _distribution_details(package_name: str) -> dict[str, Any]:
46
+ try:
47
+ distribution = metadata.distribution(package_name)
48
+ except metadata.PackageNotFoundError:
49
+ return {
50
+ "installed": False,
51
+ "package_version": "",
52
+ "dependencies": [],
53
+ "optional_dependencies": [],
54
+ "has_local_harness_binary": False,
55
+ }
56
+ files = distribution.files or []
57
+ dependencies, optional_dependencies = _dependency_names(distribution.requires)
58
+ return {
59
+ "installed": True,
60
+ "package_version": metadata.version(package_name),
61
+ "dependencies": dependencies,
62
+ "optional_dependencies": optional_dependencies,
63
+ "has_local_harness_binary": any(
64
+ str(path).replace("\\", "/") == LOCAL_HARNESS_PATH for path in files
65
+ ),
66
+ }
67
+
68
+
69
+ def _is_importable(import_name: str) -> bool:
70
+ try:
71
+ return importlib.util.find_spec(import_name) is not None
72
+ except (ImportError, ValueError):
73
+ return False
74
+
75
+
76
+ def probe_antigravity_sdk(*, import_api: bool = False) -> dict[str, Any]:
77
+ """Return metadata-only facts about the optional Antigravity SDK surface."""
78
+
79
+ details = _distribution_details(PACKAGE_NAME)
80
+ importable = _is_importable(IMPORT_NAME)
81
+ report: dict[str, Any] = {
82
+ "mode": "antigravity-sdk-probe",
83
+ "package": PACKAGE_NAME,
84
+ "import_name": IMPORT_NAME,
85
+ "installed": details["installed"],
86
+ "package_version": details["package_version"],
87
+ "dependencies": details["dependencies"],
88
+ "optional_dependencies": details["optional_dependencies"],
89
+ "has_local_harness_binary": details["has_local_harness_binary"],
90
+ "importable": importable,
91
+ "import_api": import_api,
92
+ "api_exports": {},
93
+ "research_posture": "optional_research",
94
+ "privacy": {
95
+ "model_call": False,
96
+ "auth_probe": False,
97
+ "source_or_diff": False,
98
+ "raw_output": False,
99
+ },
100
+ }
101
+ if import_api and importable:
102
+ module = importlib.import_module(IMPORT_NAME)
103
+ report["api_exports"] = {
104
+ name: hasattr(module, name) for name in EXPECTED_EXPORTS
105
+ }
106
+
107
+ missing_exports = [
108
+ name for name, present in report["api_exports"].items() if not present
109
+ ]
110
+ if not report["installed"]:
111
+ report["status"] = "warn"
112
+ report["message"] = (
113
+ "optional Antigravity SDK package is not installed; install "
114
+ "google-antigravity in a disposable venv before SDK lane research"
115
+ )
116
+ elif not report["importable"]:
117
+ report["status"] = "warn"
118
+ report["message"] = "optional Antigravity SDK package is installed but not importable"
119
+ elif import_api and missing_exports:
120
+ report["status"] = "warn"
121
+ report["message"] = (
122
+ "optional Antigravity SDK import succeeded but expected API exports "
123
+ "are missing"
124
+ )
125
+ report["missing_exports"] = missing_exports
126
+ else:
127
+ report["status"] = "pass"
128
+ report["message"] = "optional Antigravity SDK probe completed without model calls"
129
+ return report
@@ -235,7 +235,7 @@ def _acquire_venv_lock(
235
235
  raise RuntimeError(
236
236
  "timed out waiting for Code Mower venv lock: "
237
237
  f"{lock_dir}"
238
- )
238
+ ) from None
239
239
  time.sleep(poll_seconds)
240
240
  continue
241
241
  owner_id = f"{os.getpid()}-{uuid.uuid4().hex}"
@@ -7,8 +7,11 @@ import argparse
7
7
  import hashlib
8
8
  import json
9
9
  import re
10
+ import subprocess
10
11
  import sys
12
+ import time
11
13
  import uuid
14
+ from datetime import datetime, timezone
12
15
  from pathlib import Path
13
16
  from typing import Any, Iterable, Mapping, Sequence
14
17
 
@@ -16,6 +19,7 @@ BUILDER_PLAN_MODE = "code-mower-builder-experiment-plan"
16
19
  BUILDER_PLAN_SCHEMA = "code_mower.builderExperimentPlan.v1"
17
20
  BUILDER_REPORT_MODE = "code-mower-builder-experiment-report"
18
21
  BUILDER_REPORT_SCHEMA = "code_mower.builderExperimentReport.v1"
22
+ AUTHORING_RUN_SCHEMA = "code_mower.authoringRun.v1"
19
23
  SAFE_SLUG_RE = re.compile(r"[^A-Za-z0-9_.-]+")
20
24
  DEFAULT_METRICS = (
21
25
  "elapsed_seconds",
@@ -39,6 +43,16 @@ def _stable_suffix(value: Any, length: int = 8) -> str:
39
43
  return hashlib.sha256(str(value or "").encode("utf-8")).hexdigest()[:length]
40
44
 
41
45
 
46
+ def _sha256_text(value: Any) -> str:
47
+ return "sha256:" + hashlib.sha256(
48
+ json.dumps(value, sort_keys=True).encode("utf-8")
49
+ ).hexdigest()
50
+
51
+
52
+ def _utc_now() -> str:
53
+ return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
54
+
55
+
42
56
  def _identity_slug(value: Any, fallback: str) -> str:
43
57
  return f"{_safe_slug(value, fallback)}-{_stable_suffix(value)}"
44
58
 
@@ -494,6 +508,111 @@ def render_report_text(report: Mapping[str, Any]) -> str:
494
508
  return "\n".join(lines) + "\n"
495
509
 
496
510
 
511
+ def _load_plan_or_spec(
512
+ path: Path,
513
+ *,
514
+ output_dir: Path = Path(".code-mower/builder-experiments"),
515
+ replicates: int = 1,
516
+ ) -> dict[str, Any]:
517
+ payload = dict(_load_json(path))
518
+ if payload.get("schema") == BUILDER_PLAN_SCHEMA or payload.get("runs"):
519
+ return payload
520
+ return build_plan(normalize_spec(payload), output_dir=output_dir, replicates=replicates)
521
+
522
+
523
+ def _planned_run(plan: Mapping[str, Any], run_id: str) -> Mapping[str, Any]:
524
+ for run in plan.get("runs", []) or []:
525
+ if isinstance(run, Mapping) and str(run.get("run_id") or "") == run_id:
526
+ return run
527
+ raise ValueError(f"run_id not found in builder experiment plan: {run_id}")
528
+
529
+
530
+ def _safe_command_metadata(command: Sequence[str]) -> dict[str, Any]:
531
+ executable = Path(str(command[0])).name if command else ""
532
+ return {
533
+ "executable": executable,
534
+ "arg_count": len(command),
535
+ "argv_sha256": _sha256_text(list(command)),
536
+ "stdout_stderr": "not_captured",
537
+ }
538
+
539
+
540
+ def run_authoring_subprocess(
541
+ planned_run: Mapping[str, Any],
542
+ *,
543
+ command: Sequence[str],
544
+ dry_run: bool = False,
545
+ cwd: Path | None = None,
546
+ timeout: float | None = None,
547
+ branch: str = "",
548
+ pull_request: str = "",
549
+ ) -> dict[str, Any]:
550
+ if not command:
551
+ raise ValueError("builder-experiment run requires an explicit command after --")
552
+ if cwd is not None and not cwd.is_dir():
553
+ raise ValueError(f"--cwd must be an existing directory: {cwd}")
554
+ started_at = _utc_now()
555
+ ended_at = started_at
556
+ elapsed_seconds = 0.0
557
+ status = "planned"
558
+ exit_code: int | None = None
559
+ if not dry_run:
560
+ started = time.monotonic()
561
+ try:
562
+ result = subprocess.run(
563
+ list(command),
564
+ cwd=str(cwd) if cwd is not None else None,
565
+ stdout=subprocess.DEVNULL,
566
+ stderr=subprocess.DEVNULL,
567
+ timeout=timeout,
568
+ check=False,
569
+ )
570
+ exit_code = result.returncode
571
+ status = "completed" if exit_code == 0 else "failed"
572
+ except subprocess.TimeoutExpired:
573
+ status = "timeout"
574
+ except OSError as exc:
575
+ raise ValueError(
576
+ f"unable to start builder command {Path(str(command[0])).name!r}: "
577
+ f"{getattr(exc, 'strerror', '') or exc}"
578
+ ) from None
579
+ elapsed_seconds = round(time.monotonic() - started, 3)
580
+ ended_at = _utc_now()
581
+
582
+ return {
583
+ "schema": AUTHORING_RUN_SCHEMA,
584
+ "run_id": str(planned_run.get("run_id") or ""),
585
+ "experiment_id": str(planned_run.get("experiment_id") or ""),
586
+ "repo": str(planned_run.get("repo") or ""),
587
+ "task_id": str(planned_run.get("task_id") or ""),
588
+ "task_class": str(planned_run.get("task_class") or ""),
589
+ "builder": {
590
+ "provider": str(planned_run.get("provider") or ""),
591
+ "tool": str(planned_run.get("tool") or ""),
592
+ "model": str(planned_run.get("model") or ""),
593
+ },
594
+ "started_at": started_at,
595
+ "ended_at": ended_at,
596
+ "elapsed_seconds": elapsed_seconds,
597
+ "status": status,
598
+ "branch": branch,
599
+ "pull_request": pull_request,
600
+ "executor": {
601
+ "type": "subprocess",
602
+ "dry_run": dry_run,
603
+ "exit_code": exit_code,
604
+ "command": _safe_command_metadata(command),
605
+ },
606
+ "privacy": {
607
+ "source_or_diff": False,
608
+ "transcript": False,
609
+ "raw_stdout_stderr": False,
610
+ "auth_output": False,
611
+ "secrets": False,
612
+ },
613
+ }
614
+
615
+
497
616
  def main(argv: list[str] | None = None) -> int:
498
617
  parser = argparse.ArgumentParser(prog="code-mower builder-experiment")
499
618
  subparsers = parser.add_subparsers(dest="command", required=True)
@@ -510,16 +629,59 @@ def main(argv: list[str] | None = None) -> int:
510
629
  report_parser.add_argument("--replicates", type=int, default=1)
511
630
  report_parser.add_argument("--output", type=Path)
512
631
  report_parser.add_argument("--json", action="store_true")
513
- args = parser.parse_args(argv)
632
+ run_parser = subparsers.add_parser("run")
633
+ run_parser.add_argument("spec", type=Path)
634
+ run_parser.add_argument("--run-id", required=True)
635
+ run_parser.add_argument("--output-dir", type=Path, default=Path(".code-mower/builder-experiments"))
636
+ run_parser.add_argument("--replicates", type=int, default=1)
637
+ run_parser.add_argument("--output", type=Path)
638
+ run_parser.add_argument("--cwd", type=Path)
639
+ run_parser.add_argument("--timeout", type=float)
640
+ run_parser.add_argument("--dry-run", action="store_true")
641
+ run_parser.add_argument("--branch", default="")
642
+ run_parser.add_argument("--pull-request", default="")
643
+ run_parser.add_argument("--json", action="store_true")
644
+ raw_argv = list(sys.argv[1:] if argv is None else argv)
645
+ builder_command: list[str] = []
646
+ parse_argv = raw_argv
647
+ if raw_argv[:1] == ["run"] and "--" in raw_argv:
648
+ command_index = raw_argv.index("--")
649
+ builder_command = raw_argv[command_index + 1 :]
650
+ parse_argv = raw_argv[:command_index]
651
+ args = parser.parse_args(parse_argv)
514
652
 
515
653
  try:
516
- spec = load_spec(args.spec)
517
- plan = build_plan(spec, output_dir=args.output_dir, replicates=args.replicates)
518
654
  if args.command == "plan":
655
+ spec = load_spec(args.spec)
656
+ plan = build_plan(spec, output_dir=args.output_dir, replicates=args.replicates)
519
657
  if args.output:
520
658
  _write_json(args.output, plan)
521
659
  print(json.dumps(plan, indent=2, sort_keys=True) if args.json else render_plan_text(plan))
522
660
  return 0
661
+ if args.command == "run":
662
+ plan = _load_plan_or_spec(
663
+ args.spec,
664
+ output_dir=args.output_dir,
665
+ replicates=args.replicates,
666
+ )
667
+ command = builder_command
668
+ planned = _planned_run(plan, args.run_id)
669
+ artifact = run_authoring_subprocess(
670
+ planned,
671
+ command=command,
672
+ dry_run=args.dry_run,
673
+ cwd=args.cwd,
674
+ timeout=args.timeout,
675
+ branch=args.branch,
676
+ pull_request=args.pull_request,
677
+ )
678
+ run_dir = Path(str(planned.get("output_dir") or ".code-mower/authoring-runs"))
679
+ output = args.output or run_dir / f"{_safe_slug(args.run_id)}.json"
680
+ _write_json(output, artifact)
681
+ print(json.dumps(artifact, indent=2, sort_keys=True) if args.json else f"wrote {output}")
682
+ return 0
683
+ spec = load_spec(args.spec)
684
+ plan = build_plan(spec, output_dir=args.output_dir, replicates=args.replicates)
523
685
  run_results = load_run_results(args.runs)
524
686
  report = build_report(plan, run_results)
525
687
  if args.output: