code-mower 0.5.0b51__tar.gz → 0.5.0b52__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.
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/MANIFEST.in +2 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/PKG-INFO +49 -46
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/README.md +48 -45
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/pyproject.toml +2 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/__init__.py +1 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/audit_labeler_lib.py +222 -17
- code_mower-0.5.0b52/src/code_mower/audit_limits.py +141 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/claude_audit_pr.py +386 -86
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cli.py +4 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/codex_audit_pr.py +640 -76
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/config.py +270 -3
- code_mower-0.5.0b52/src/code_mower/decisions.py +717 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor.py +12 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/__init__.py +18 -0
- code_mower-0.5.0b52/src/code_mower/doctor_checks/audit_limits.py +186 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github.py +10 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_branch.py +17 -5
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_human_token.py +10 -7
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_repo.py +2 -2
- code_mower-0.5.0b52/src/code_mower/doctor_checks/provider_local_audit_setup.py +162 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/providers.py +8 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/registry.py +13 -2
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/runner.py +27 -1
- code_mower-0.5.0b52/src/code_mower/doctor_checks/self_hosted_runner.py +964 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/init.py +1063 -57
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/claude.py +1 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/codex.py +1 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/migration_mirror.py +1 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package.py +5 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package_content.py +24 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package_manifest.py +31 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/__init__.py +9 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/github_pr.py +31 -1
- code_mower-0.5.0b52/src/code_mower/provider_runners/repo_paths.py +87 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/code-mower.example.yml +20 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/base-audit.md +10 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/README.md +39 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/claude.md +22 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/codex.md +22 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/generic.md +20 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/grok.md +22 -0
- code_mower-0.5.0b52/src/code_mower/templates/lanes/run_mac_lane.sh +529 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +81 -27
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +3 -5
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/code-mower-gate-health.yml.j2 +6 -7
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +44 -17
- code_mower-0.5.0b52/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +549 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +1 -1
- code_mower-0.5.0b52/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +125 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +5 -5
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/saas-reviewer-labeler.yml.j2 +1 -2
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/self-hosted-local-audit.yml.j2 +6 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52/src/code_mower}/templates/workflows/trailer-comment-labeler.yml.j2 +2 -2
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/weekly-status.yml.j2 +9 -9
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/trailer_comment_labeler.py +40 -3
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/versioning.py +20 -0
- code_mower-0.5.0b52/src/code_mower/workflow_actionlint.py +231 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/PKG-INFO +49 -46
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/SOURCES.txt +29 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/code-mower.yml.j2 +6 -0
- code_mower-0.5.0b52/templates/lanes/README.md +39 -0
- code_mower-0.5.0b52/templates/lanes/claude.md +22 -0
- code_mower-0.5.0b52/templates/lanes/codex.md +22 -0
- code_mower-0.5.0b52/templates/lanes/generic.md +20 -0
- code_mower-0.5.0b52/templates/lanes/grok.md +22 -0
- code_mower-0.5.0b52/templates/lanes/run_mac_lane.sh +529 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +81 -27
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +3 -5
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/code-mower-gate-health.yml.j2 +6 -7
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/code-mower-gate.yml.j2 +44 -17
- code_mower-0.5.0b52/templates/workflows/dispatch-lanes.yml.j2 +549 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/hosted-bridge.yml.j2 +1 -1
- code_mower-0.5.0b52/templates/workflows/lane-mac-runner.yml.j2 +125 -0
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/saas-reviewer-labeler.yml.j2 +1 -2
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/self-hosted-local-audit.yml.j2 +6 -0
- {code_mower-0.5.0b51/src/code_mower → code_mower-0.5.0b52}/templates/workflows/trailer-comment-labeler.yml.j2 +2 -2
- code_mower-0.5.0b52/tests/test_audit_limits.py +71 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_builder_identity.py +22 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_claude_audit_pr.py +339 -0
- code_mower-0.5.0b52/tests/test_codex_audit_pr.py +715 -0
- code_mower-0.5.0b52/tests/test_decision_audit_integration.py +218 -0
- code_mower-0.5.0b52/tests/test_decisions.py +478 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_github_checks.py +95 -4
- code_mower-0.5.0b52/tests/test_doctor_provider_local_audit_setup.py +90 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_registry.py +35 -0
- code_mower-0.5.0b52/tests/test_doctor_self_hosted_runner.py +302 -0
- code_mower-0.5.0b52/tests/test_init_actionlint.py +134 -0
- code_mower-0.5.0b52/tests/test_init_build_loop.py +1713 -0
- code_mower-0.5.0b52/tests/test_plan_context.py +448 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_prompts.py +3 -0
- code_mower-0.5.0b52/tests/test_provider_runners_github_pr.py +166 -0
- code_mower-0.5.0b52/tests/test_provider_runners_repo_paths.py +59 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_release_hygiene.py +1066 -83
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_trailer_comment_labeler.py +133 -1
- code_mower-0.5.0b51/src/code_mower/provider_runners/repo_paths.py +0 -23
- code_mower-0.5.0b51/tests/test_codex_audit_pr.py +0 -243
- code_mower-0.5.0b51/tests/test_plan_context.py +0 -241
- code_mower-0.5.0b51/tests/test_provider_runners_github_pr.py +0 -65
- code_mower-0.5.0b51/tests/test_provider_runners_repo_paths.py +0 -26
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/CODE_OF_CONDUCT.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/LICENSE +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/NOTICE +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/SUPPORT.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/requirements/requirements.txt +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/setup.cfg +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/__init__.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/_base.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/cursor_bugbot.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/gitar.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/greptile.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/adapters/qodo.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/audit_handoff_log.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/audit_progress.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/blind_review_artifacts.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/blind_review_coordinator.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/bootstrap.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/builder_experiment.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/builder_runs.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/__init__.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/arms.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/auto_discovery.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/commands.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/context_inputs.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/corpus.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/effect_report.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/evidence.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/evidence_report.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/identity.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/metrics.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/overlap.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/planning.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/policy.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/results.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/run_results.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/run_status.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/runner.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/truth.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/calibration/value_report.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/checks.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/claude_cli_environment.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/clear_stale.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/__init__.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/bundle.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/doctor.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/dogfood.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/endpoints.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/errors.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/events.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/export.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/git_metadata.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/manifest.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/operations.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/reports.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/setup.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/cloud_client/upload.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/code_mower_calibration.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/code_mower_context_packs.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/code_mower_merge.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/code_mower_telemetry.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/codex_audit_env_preflight.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/codex_audit_schema_smoke.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/codex_audit_verdict.schema.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/cloud.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/common.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_api.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_config.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/github_provider.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/groups.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/models.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/output.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/presets.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/privacy.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_env.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_probe.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/runtime.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/gate_health.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/gemini_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/grok_build_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/hermes_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/__init__.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/aider.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/devin.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/gemini_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/grok_build.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/hermes_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/lane_configs/local_llm.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/local_llm_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/local_llm_bakeoff.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/local_llm_calibration.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/local_llm_profiles.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/migration.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/migration_install.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/migration_readiness.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/migration_rehearsal.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/next_steps.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package_paths.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package_rendering.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/package_static.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/plan_context.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/prompts.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_registry.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/comments.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/git.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/github_auth.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/pr_worktree.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/process.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/text_schema.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/provider_runners/workspace.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/providers/__init__.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/providers/local_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/providers/provenance.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/release_readiness.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/reviewer_metrics.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/reviewer_spend.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/saas_reviewer_labeler.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/secrets.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/operability.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/code_mower +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/product-support/status_report.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/providers.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower/work_orders.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/dependency_links.txt +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/entry_points.txt +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/requires.txt +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/src/code_mower.egg-info/top_level.txt +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/cursor/BUGBOT.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/acp_bridge.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/aider.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/antigravity_cli.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/claude_audit.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/claude_review.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/coderabbit_cli.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/codex.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/cursor_bugbot.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/devin.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/gemini_cli.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/gitar.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/greptile.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/hermes_cli.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/local_llm.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers/qodo.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/providers.yml +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_audit_comment_posture.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_builder_runs.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_calibration_effect_report.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_calibration_truth.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_checks.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_clear_stale.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_cloud_client.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_cloud_git_metadata.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_cloud_manifest.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_cloud_reports.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_codex_audit_env_preflight.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_boundaries.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_output.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_privacy.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_provider_env_required.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_provider_env_tokens.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_provider_probe.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_provider_review_hygiene.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_doctor_runtime.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_gate_health.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_local_llm_github_helpers.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_local_cli.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_comments.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_git.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_pr_worktree.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_process.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_text_schema.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_provider_runners_workspace.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_reviewer_metrics_core.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_reviewer_spend.py +0 -0
- {code_mower-0.5.0b51 → code_mower-0.5.0b52}/tests/test_work_orders.py +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
recursive-include src/code_mower/templates *.yml *.yaml *.json
|
|
2
2
|
recursive-include src/code_mower/templates *.md
|
|
3
3
|
recursive-include src/code_mower/templates *.j2
|
|
4
|
+
recursive-include src/code_mower/templates/lanes *
|
|
4
5
|
recursive-include src/code_mower/templates/product-support *
|
|
5
6
|
include src/code_mower/*.json
|
|
6
7
|
recursive-include templates *.j2 *.json *.md *.yml *.yaml
|
|
8
|
+
recursive-include templates/lanes *
|
|
7
9
|
include requirements/*.txt
|
|
8
10
|
include LICENSE
|
|
9
11
|
include NOTICE
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-mower
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0b52
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -19,6 +19,9 @@ Code Mower helps teams set up AI peer-programmer and reviewer lanes on real
|
|
|
19
19
|
GitHub pull requests, then measure which builders and reviewers are useful on
|
|
20
20
|
their actual codebase.
|
|
21
21
|
|
|
22
|
+
Code Mower is beta, bring-your-own-agent-loop software for teams willing to
|
|
23
|
+
calibrate reviewers. It is not a drop-in autonomous merge gate.
|
|
24
|
+
|
|
22
25
|
The short version:
|
|
23
26
|
|
|
24
27
|
- create safe, manual-first reviewer lanes for Codex, Claude, Gitar, and other
|
|
@@ -97,46 +100,26 @@ known-blocked control, and three reviewer lanes. It shows the decision Code
|
|
|
97
100
|
Mower is built to support: which AI reviewers are useful, noisy, expensive,
|
|
98
101
|
fast, or eligible for stronger merge policy on your actual codebase.
|
|
99
102
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
python3.12 --version
|
|
106
|
-
pipx install --python python3.12 code-mower==0.5.0b51
|
|
107
|
-
code-mower --version
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
`0.5.0b51` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
111
|
-
line, use the explicit beta version above or allow prereleases with:
|
|
103
|
+
## Start Here
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
pipx install --python python3.12 --pip-args="--pre" code-mower
|
|
115
|
-
```
|
|
105
|
+
Choose one path. Each path has one guide and gets to one visible outcome.
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
code-mower init --
|
|
121
|
-
code-mower doctor --preflight
|
|
122
|
-
code-mower checks detect --json
|
|
123
|
-
```
|
|
107
|
+
| Path | Use When | Route | Guide |
|
|
108
|
+
| --- | --- | --- | --- |
|
|
109
|
+
| 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
|
+
| 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) |
|
|
124
111
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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)
|
|
114
|
+
guide.
|
|
128
115
|
|
|
129
|
-
|
|
130
|
-
produce the starter local report:
|
|
116
|
+
## What Calibration Does And Does Not Prove
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```
|
|
118
|
+
The generated starter corpus proves that the commands run and the report path
|
|
119
|
+
works. It does not prove that a reviewer should gate merges. Promote reviewer
|
|
120
|
+
lanes only after repository-specific known-clean and known-blocked evidence
|
|
121
|
+
meets the [lane promotion policy](docs/lane-promotion-policy.md).
|
|
137
122
|
|
|
138
|
-
The generated setup also includes the configurable owner escalation and weekly
|
|
139
|
-
status digest templates. The generated starter corpus proves the command path.
|
|
140
123
|
To bootstrap a draft from your repository history:
|
|
141
124
|
|
|
142
125
|
```bash
|
|
@@ -155,7 +138,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
155
138
|
|
|
156
139
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
157
140
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
158
|
-
the latest 10/10 public-package readiness proof for `code-mower==0.5.
|
|
141
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b52`.
|
|
159
142
|
|
|
160
143
|
## Optional: Plan Before Coding
|
|
161
144
|
|
|
@@ -205,6 +188,15 @@ That lets CodeMower.com show `issue -> plan -> work order -> builder run -> PR
|
|
|
205
188
|
transcripts, prompts, or issue body text. See
|
|
206
189
|
[docs/builders-grok-cursor.md](docs/builders-grok-cursor.md).
|
|
207
190
|
|
|
191
|
+
## Roles
|
|
192
|
+
|
|
193
|
+
Code Mower records builder provenance for Claude Code, Codex, Cursor-style
|
|
194
|
+
hosted builders, and similar authoring lanes, then runs reviewer lanes against
|
|
195
|
+
the resulting pull requests. The orchestrator is a workflow convention: issue,
|
|
196
|
+
optional work order, single-writer branch, reviewer lanes, and fix rounds. Code
|
|
197
|
+
Mower's templates now support that loop end to end; humans still own
|
|
198
|
+
credentials, branch protection, calibration, and owner decisions.
|
|
199
|
+
|
|
208
200
|
## Why Not Just Run Codex Or Claude Yourself?
|
|
209
201
|
|
|
210
202
|
You should, at first. Code Mower is not a replacement for a good local agent or
|
|
@@ -301,18 +293,18 @@ engineer can:
|
|
|
301
293
|
7. optionally upload sanitized metadata to CodeMower.com and see useful team
|
|
302
294
|
dashboard signal.
|
|
303
295
|
|
|
304
|
-
|
|
305
|
-
|
|
296
|
+
Build-loop templates extend the same loop from "who reviews best?" to "which AI
|
|
297
|
+
builder plus reviewer loop ships best on this product?" Start with
|
|
298
|
+
[docs/build-loop-in-30-minutes.md](docs/build-loop-in-30-minutes.md), then use
|
|
306
299
|
[docs/builder-experiments.md](docs/builder-experiments.md) and
|
|
307
|
-
[docs/authoring-intelligence.md](docs/authoring-intelligence.md)
|
|
308
|
-
|
|
309
|
-
[docs/builders-grok-cursor.md](docs/builders-grok-cursor.md).
|
|
300
|
+
[docs/authoring-intelligence.md](docs/authoring-intelligence.md) for deeper
|
|
301
|
+
measurement work.
|
|
310
302
|
|
|
311
303
|
## Installation Status
|
|
312
304
|
|
|
313
|
-
The current public beta is `v0.5.0-beta.
|
|
305
|
+
The current public beta is `v0.5.0-beta.52` from
|
|
314
306
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
315
|
-
as `code-mower==0.5.
|
|
307
|
+
as `code-mower==0.5.0b52` on [PyPI](https://pypi.org/project/code-mower/).
|
|
316
308
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
317
309
|
release notes.
|
|
318
310
|
|
|
@@ -349,7 +341,19 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
|
|
|
349
341
|
## Docs Map
|
|
350
342
|
|
|
351
343
|
- [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
|
|
352
|
-
- [
|
|
344
|
+
- [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
|
|
345
|
+
- [Quickstart Reference](docs/quickstart.md)
|
|
346
|
+
- [Planning And Work Orders](docs/planning-work-orders.md)
|
|
347
|
+
- [Builder Providers: Grok And Cursor](docs/builders-grok-cursor.md)
|
|
348
|
+
- [Build Loop Operations](docs/build-loop.md)
|
|
349
|
+
- [Self-Hosted Mac Runner](docs/self-hosted-mac-runner.md)
|
|
350
|
+
- [Local Audit Runner](docs/local-audit-runner.md)
|
|
351
|
+
- [Lane Standing Instructions](docs/lanes/README.md)
|
|
352
|
+
- [Codex Lane Standing Instructions](docs/lanes/codex.md)
|
|
353
|
+
- [Claude Lane Standing Instructions](docs/lanes/claude.md)
|
|
354
|
+
- [Cursor Hosted Lane Standing Instructions](docs/lanes/grok.md)
|
|
355
|
+
- [Provider Matrix](docs/provider-matrix.md)
|
|
356
|
+
- [GitHub Setup](docs/github-setup.md)
|
|
353
357
|
- [First Run Transcript](docs/first-run-transcript.md)
|
|
354
358
|
- [First-User Demo Transcript](docs/first-user-demo-transcript.md)
|
|
355
359
|
- [First-User Install Rehearsal](docs/first-user-install-rehearsal.md)
|
|
@@ -358,8 +362,7 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
|
|
|
358
362
|
- [PyPI Release Runbook](docs/pypi-release.md)
|
|
359
363
|
- [Sample Doctor Output](docs/sample-doctor-output.md)
|
|
360
364
|
- [Architecture](docs/architecture.md)
|
|
361
|
-
- [
|
|
362
|
-
- [GitHub Setup](docs/github-setup.md)
|
|
365
|
+
- [Lane Promotion Policy](docs/lane-promotion-policy.md)
|
|
363
366
|
- [Cloud Sharing](docs/cloud-sharing.md)
|
|
364
367
|
- [Cloud Data Contract](docs/cloud-data-contract.md)
|
|
365
368
|
- [Privacy And Threat Model](docs/privacy-threat-model.md)
|
|
@@ -4,6 +4,9 @@ Code Mower helps teams set up AI peer-programmer and reviewer lanes on real
|
|
|
4
4
|
GitHub pull requests, then measure which builders and reviewers are useful on
|
|
5
5
|
their actual codebase.
|
|
6
6
|
|
|
7
|
+
Code Mower is beta, bring-your-own-agent-loop software for teams willing to
|
|
8
|
+
calibrate reviewers. It is not a drop-in autonomous merge gate.
|
|
9
|
+
|
|
7
10
|
The short version:
|
|
8
11
|
|
|
9
12
|
- create safe, manual-first reviewer lanes for Codex, Claude, Gitar, and other
|
|
@@ -82,46 +85,26 @@ known-blocked control, and three reviewer lanes. It shows the decision Code
|
|
|
82
85
|
Mower is built to support: which AI reviewers are useful, noisy, expensive,
|
|
83
86
|
fast, or eligible for stronger merge policy on your actual codebase.
|
|
84
87
|
|
|
85
|
-
##
|
|
86
|
-
|
|
87
|
-
Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
python3.12 --version
|
|
91
|
-
pipx install --python python3.12 code-mower==0.5.0b51
|
|
92
|
-
code-mower --version
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`0.5.0b51` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
96
|
-
line, use the explicit beta version above or allow prereleases with:
|
|
88
|
+
## Start Here
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
pipx install --python python3.12 --pip-args="--pre" code-mower
|
|
100
|
-
```
|
|
90
|
+
Choose one path. Each path has one guide and gets to one visible outcome.
|
|
101
91
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
code-mower init --
|
|
106
|
-
code-mower doctor --preflight
|
|
107
|
-
code-mower checks detect --json
|
|
108
|
-
```
|
|
92
|
+
| Path | Use When | Route | Guide |
|
|
93
|
+
| --- | --- | --- | --- |
|
|
94
|
+
| 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
|
+
| 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) |
|
|
109
96
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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)
|
|
99
|
+
guide.
|
|
113
100
|
|
|
114
|
-
|
|
115
|
-
produce the starter local report:
|
|
101
|
+
## What Calibration Does And Does Not Prove
|
|
116
102
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
```
|
|
103
|
+
The generated starter corpus proves that the commands run and the report path
|
|
104
|
+
works. It does not prove that a reviewer should gate merges. Promote reviewer
|
|
105
|
+
lanes only after repository-specific known-clean and known-blocked evidence
|
|
106
|
+
meets the [lane promotion policy](docs/lane-promotion-policy.md).
|
|
122
107
|
|
|
123
|
-
The generated setup also includes the configurable owner escalation and weekly
|
|
124
|
-
status digest templates. The generated starter corpus proves the command path.
|
|
125
108
|
To bootstrap a draft from your repository history:
|
|
126
109
|
|
|
127
110
|
```bash
|
|
@@ -140,7 +123,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
140
123
|
|
|
141
124
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
142
125
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
143
|
-
the latest 10/10 public-package readiness proof for `code-mower==0.5.
|
|
126
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b52`.
|
|
144
127
|
|
|
145
128
|
## Optional: Plan Before Coding
|
|
146
129
|
|
|
@@ -190,6 +173,15 @@ That lets CodeMower.com show `issue -> plan -> work order -> builder run -> PR
|
|
|
190
173
|
transcripts, prompts, or issue body text. See
|
|
191
174
|
[docs/builders-grok-cursor.md](docs/builders-grok-cursor.md).
|
|
192
175
|
|
|
176
|
+
## Roles
|
|
177
|
+
|
|
178
|
+
Code Mower records builder provenance for Claude Code, Codex, Cursor-style
|
|
179
|
+
hosted builders, and similar authoring lanes, then runs reviewer lanes against
|
|
180
|
+
the resulting pull requests. The orchestrator is a workflow convention: issue,
|
|
181
|
+
optional work order, single-writer branch, reviewer lanes, and fix rounds. Code
|
|
182
|
+
Mower's templates now support that loop end to end; humans still own
|
|
183
|
+
credentials, branch protection, calibration, and owner decisions.
|
|
184
|
+
|
|
193
185
|
## Why Not Just Run Codex Or Claude Yourself?
|
|
194
186
|
|
|
195
187
|
You should, at first. Code Mower is not a replacement for a good local agent or
|
|
@@ -286,18 +278,18 @@ engineer can:
|
|
|
286
278
|
7. optionally upload sanitized metadata to CodeMower.com and see useful team
|
|
287
279
|
dashboard signal.
|
|
288
280
|
|
|
289
|
-
|
|
290
|
-
|
|
281
|
+
Build-loop templates extend the same loop from "who reviews best?" to "which AI
|
|
282
|
+
builder plus reviewer loop ships best on this product?" Start with
|
|
283
|
+
[docs/build-loop-in-30-minutes.md](docs/build-loop-in-30-minutes.md), then use
|
|
291
284
|
[docs/builder-experiments.md](docs/builder-experiments.md) and
|
|
292
|
-
[docs/authoring-intelligence.md](docs/authoring-intelligence.md)
|
|
293
|
-
|
|
294
|
-
[docs/builders-grok-cursor.md](docs/builders-grok-cursor.md).
|
|
285
|
+
[docs/authoring-intelligence.md](docs/authoring-intelligence.md) for deeper
|
|
286
|
+
measurement work.
|
|
295
287
|
|
|
296
288
|
## Installation Status
|
|
297
289
|
|
|
298
|
-
The current public beta is `v0.5.0-beta.
|
|
290
|
+
The current public beta is `v0.5.0-beta.52` from
|
|
299
291
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
300
|
-
as `code-mower==0.5.
|
|
292
|
+
as `code-mower==0.5.0b52` on [PyPI](https://pypi.org/project/code-mower/).
|
|
301
293
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
302
294
|
release notes.
|
|
303
295
|
|
|
@@ -334,7 +326,19 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
|
|
|
334
326
|
## Docs Map
|
|
335
327
|
|
|
336
328
|
- [Try Code Mower In 10 Minutes](docs/try-in-10-minutes.md)
|
|
337
|
-
- [
|
|
329
|
+
- [Build Loop In 30 Minutes](docs/build-loop-in-30-minutes.md)
|
|
330
|
+
- [Quickstart Reference](docs/quickstart.md)
|
|
331
|
+
- [Planning And Work Orders](docs/planning-work-orders.md)
|
|
332
|
+
- [Builder Providers: Grok And Cursor](docs/builders-grok-cursor.md)
|
|
333
|
+
- [Build Loop Operations](docs/build-loop.md)
|
|
334
|
+
- [Self-Hosted Mac Runner](docs/self-hosted-mac-runner.md)
|
|
335
|
+
- [Local Audit Runner](docs/local-audit-runner.md)
|
|
336
|
+
- [Lane Standing Instructions](docs/lanes/README.md)
|
|
337
|
+
- [Codex Lane Standing Instructions](docs/lanes/codex.md)
|
|
338
|
+
- [Claude Lane Standing Instructions](docs/lanes/claude.md)
|
|
339
|
+
- [Cursor Hosted Lane Standing Instructions](docs/lanes/grok.md)
|
|
340
|
+
- [Provider Matrix](docs/provider-matrix.md)
|
|
341
|
+
- [GitHub Setup](docs/github-setup.md)
|
|
338
342
|
- [First Run Transcript](docs/first-run-transcript.md)
|
|
339
343
|
- [First-User Demo Transcript](docs/first-user-demo-transcript.md)
|
|
340
344
|
- [First-User Install Rehearsal](docs/first-user-install-rehearsal.md)
|
|
@@ -343,8 +347,7 @@ The wrapper resolves Python 3.12+ and refuses stale or old system Python shims.
|
|
|
343
347
|
- [PyPI Release Runbook](docs/pypi-release.md)
|
|
344
348
|
- [Sample Doctor Output](docs/sample-doctor-output.md)
|
|
345
349
|
- [Architecture](docs/architecture.md)
|
|
346
|
-
- [
|
|
347
|
-
- [GitHub Setup](docs/github-setup.md)
|
|
350
|
+
- [Lane Promotion Policy](docs/lane-promotion-policy.md)
|
|
348
351
|
- [Cloud Sharing](docs/cloud-sharing.md)
|
|
349
352
|
- [Cloud Data Contract](docs/cloud-data-contract.md)
|
|
350
353
|
- [Privacy And Threat Model](docs/privacy-threat-model.md)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-mower"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.0b52"
|
|
8
8
|
description = "Multi-reviewer AI code audit orchestration"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
readme = "README.md"
|
|
@@ -31,6 +31,7 @@ code_mower = [
|
|
|
31
31
|
"templates/**/*.yml",
|
|
32
32
|
"templates/**/*.yaml",
|
|
33
33
|
"templates/**/*.j2",
|
|
34
|
+
"templates/lanes/*",
|
|
34
35
|
"templates/product-support/*",
|
|
35
36
|
]
|
|
36
37
|
|
|
@@ -22,6 +22,14 @@ from typing import Any, Callable, Dict, Mapping, Optional, Pattern, Sequence
|
|
|
22
22
|
from urllib.parse import quote
|
|
23
23
|
import re
|
|
24
24
|
|
|
25
|
+
if __package__:
|
|
26
|
+
try:
|
|
27
|
+
from . import decisions as code_mower_decisions
|
|
28
|
+
except ImportError: # pragma: no cover - copied tools fallback
|
|
29
|
+
import decisions as code_mower_decisions # type: ignore
|
|
30
|
+
else: # pragma: no cover - direct helper execution
|
|
31
|
+
import decisions as code_mower_decisions # type: ignore
|
|
32
|
+
|
|
25
33
|
MIN_ABBREVIATED_SHA_LENGTH = 7
|
|
26
34
|
AUTHOR_EXCLUSION_ENV = "CODE_MOWER_AUTHOR_EXCLUSION_JSON"
|
|
27
35
|
ACTIONS_RUN_MARKER_RE = re.compile(
|
|
@@ -58,6 +66,35 @@ class ActionsRunMarker:
|
|
|
58
66
|
body_sha256: str
|
|
59
67
|
|
|
60
68
|
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class AuditVerdict:
|
|
71
|
+
verdict: str
|
|
72
|
+
updated_at: str
|
|
73
|
+
created_at: str
|
|
74
|
+
comment_id: int
|
|
75
|
+
comment_index: int
|
|
76
|
+
run_id: str
|
|
77
|
+
|
|
78
|
+
def sort_key(self) -> tuple[str, str, int, int]:
|
|
79
|
+
return (self.updated_at, self.created_at, self.comment_id, self.comment_index)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class AuditRunInFlight:
|
|
84
|
+
run_id: str
|
|
85
|
+
job_name: str
|
|
86
|
+
queued_since: str
|
|
87
|
+
run_status: str
|
|
88
|
+
job_status: str
|
|
89
|
+
job_conclusion: str
|
|
90
|
+
|
|
91
|
+
def description(self) -> str:
|
|
92
|
+
run_id = self.run_id or "unknown"
|
|
93
|
+
job_name = self.job_name or "unknown"
|
|
94
|
+
queued_since = self.queued_since or "unknown"
|
|
95
|
+
return f"run {run_id} job {job_name!r} queued since {queued_since}"
|
|
96
|
+
|
|
97
|
+
|
|
61
98
|
@dataclass(frozen=True)
|
|
62
99
|
class LaneConfig:
|
|
63
100
|
name: str
|
|
@@ -71,6 +108,7 @@ class LaneConfig:
|
|
|
71
108
|
pass_patterns: tuple[Pattern[str], ...]
|
|
72
109
|
blocked_patterns: tuple[Pattern[str], ...]
|
|
73
110
|
label_state_fallbacks: bool = False
|
|
111
|
+
decision_coverage: bool = False
|
|
74
112
|
token_env_vars: tuple[str, ...] = ("GITHUB_TOKEN",)
|
|
75
113
|
|
|
76
114
|
@functools.lru_cache(maxsize=1)
|
|
@@ -364,7 +402,12 @@ def audit_comment_head_sha(body: str) -> str:
|
|
|
364
402
|
return match.group(1) if match else ""
|
|
365
403
|
|
|
366
404
|
|
|
367
|
-
def terminal_audit_trailer_verdict(
|
|
405
|
+
def terminal_audit_trailer_verdict(
|
|
406
|
+
lane: Mapping[str, Any],
|
|
407
|
+
body: str,
|
|
408
|
+
*,
|
|
409
|
+
decisions: Sequence[code_mower_decisions.DecisionRecord] = (),
|
|
410
|
+
) -> str:
|
|
368
411
|
candidates: list[tuple[int, str]] = []
|
|
369
412
|
for label_key, verdict in (("done", "done"), ("blocked", "blocked")):
|
|
370
413
|
label = str(lane.get(label_key) or "")
|
|
@@ -375,7 +418,18 @@ def terminal_audit_trailer_verdict(lane: Mapping[str, Any], body: str) -> str:
|
|
|
375
418
|
candidates.append((index, verdict))
|
|
376
419
|
if not candidates:
|
|
377
420
|
return ""
|
|
378
|
-
|
|
421
|
+
verdict = max(candidates, key=lambda item: item[0])[1]
|
|
422
|
+
if (
|
|
423
|
+
verdict == "blocked"
|
|
424
|
+
and lane.get("decision_coverage") is True
|
|
425
|
+
and code_mower_decisions.audit_blockers_are_decision_covered(
|
|
426
|
+
body,
|
|
427
|
+
decisions,
|
|
428
|
+
lane=str(lane.get("author_lane") or lane.get("id") or ""),
|
|
429
|
+
)
|
|
430
|
+
):
|
|
431
|
+
return "done"
|
|
432
|
+
return verdict
|
|
379
433
|
|
|
380
434
|
|
|
381
435
|
def current_audit_trailer_verdict(
|
|
@@ -383,10 +437,11 @@ def current_audit_trailer_verdict(
|
|
|
383
437
|
body: str,
|
|
384
438
|
*,
|
|
385
439
|
head_sha: str,
|
|
440
|
+
decisions: Sequence[code_mower_decisions.DecisionRecord] = (),
|
|
386
441
|
) -> str:
|
|
387
442
|
if "Head SHA: `" + head_sha + "`" not in body:
|
|
388
443
|
return ""
|
|
389
|
-
return terminal_audit_trailer_verdict(lane, body)
|
|
444
|
+
return terminal_audit_trailer_verdict(lane, body, decisions=decisions)
|
|
390
445
|
|
|
391
446
|
|
|
392
447
|
def latest_current_audit_verdict(
|
|
@@ -398,14 +453,45 @@ def latest_current_audit_verdict(
|
|
|
398
453
|
[Mapping[str, Any], str, str, object, str | None],
|
|
399
454
|
bool,
|
|
400
455
|
],
|
|
456
|
+
decision_authorities: Sequence[str] = (),
|
|
401
457
|
) -> str:
|
|
402
|
-
|
|
458
|
+
verdict = latest_current_audit_verdict_detail(
|
|
459
|
+
lane,
|
|
460
|
+
comments,
|
|
461
|
+
head_sha=head_sha,
|
|
462
|
+
trusted_comment_author=trusted_comment_author,
|
|
463
|
+
decision_authorities=decision_authorities,
|
|
464
|
+
)
|
|
465
|
+
return verdict.verdict if verdict else ""
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def latest_current_audit_verdict_detail(
|
|
469
|
+
lane: Mapping[str, Any],
|
|
470
|
+
comments: Sequence[Mapping[str, Any]],
|
|
471
|
+
*,
|
|
472
|
+
head_sha: str,
|
|
473
|
+
trusted_comment_author: Callable[
|
|
474
|
+
[Mapping[str, Any], str, str, object, str | None],
|
|
475
|
+
bool,
|
|
476
|
+
],
|
|
477
|
+
decision_authorities: Sequence[str] = (),
|
|
478
|
+
) -> AuditVerdict | None:
|
|
479
|
+
verdicts: list[AuditVerdict] = []
|
|
480
|
+
decisions = code_mower_decisions.collect_decision_records_from_comments(
|
|
481
|
+
comments,
|
|
482
|
+
authorities=decision_authorities,
|
|
483
|
+
)
|
|
403
484
|
for index, comment in enumerate(comments):
|
|
404
485
|
author = str(((comment.get("user") or {}).get("login")) or "")
|
|
405
486
|
body = str(comment.get("body") or "")
|
|
406
487
|
if not trusted_comment_author(lane, author, body, comment.get("id"), None):
|
|
407
488
|
continue
|
|
408
|
-
verdict = current_audit_trailer_verdict(
|
|
489
|
+
verdict = current_audit_trailer_verdict(
|
|
490
|
+
lane,
|
|
491
|
+
body,
|
|
492
|
+
head_sha=head_sha,
|
|
493
|
+
decisions=decisions,
|
|
494
|
+
)
|
|
409
495
|
if verdict:
|
|
410
496
|
try:
|
|
411
497
|
comment_id = int(comment.get("id") or 0)
|
|
@@ -419,10 +505,46 @@ def latest_current_audit_verdict(
|
|
|
419
505
|
or ""
|
|
420
506
|
)
|
|
421
507
|
created = str(comment.get("created_at") or comment.get("createdAt") or "")
|
|
422
|
-
verdicts.append(
|
|
508
|
+
verdicts.append(
|
|
509
|
+
AuditVerdict(
|
|
510
|
+
verdict=verdict,
|
|
511
|
+
updated_at=updated,
|
|
512
|
+
created_at=created,
|
|
513
|
+
comment_id=comment_id,
|
|
514
|
+
comment_index=index,
|
|
515
|
+
run_id=parse_audit_run_id(body),
|
|
516
|
+
)
|
|
517
|
+
)
|
|
423
518
|
if verdicts:
|
|
424
|
-
return max(verdicts, key=lambda item: item
|
|
425
|
-
return
|
|
519
|
+
return max(verdicts, key=lambda item: item.sort_key())
|
|
520
|
+
return None
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def audit_verdict_newer_than_in_flight(
|
|
524
|
+
verdict: AuditVerdict | None,
|
|
525
|
+
detail: AuditRunInFlight,
|
|
526
|
+
) -> bool:
|
|
527
|
+
if (
|
|
528
|
+
verdict is None
|
|
529
|
+
or verdict.verdict != "done"
|
|
530
|
+
or not verdict.updated_at
|
|
531
|
+
or not detail.queued_since
|
|
532
|
+
):
|
|
533
|
+
return False
|
|
534
|
+
try:
|
|
535
|
+
verdict_run_id = int(verdict.run_id)
|
|
536
|
+
detail_run_id = int(detail.run_id)
|
|
537
|
+
except (TypeError, ValueError):
|
|
538
|
+
verdict_run_id = None
|
|
539
|
+
detail_run_id = None
|
|
540
|
+
if verdict_run_id is not None and detail_run_id is not None:
|
|
541
|
+
if verdict_run_id != detail_run_id:
|
|
542
|
+
return verdict_run_id > detail_run_id
|
|
543
|
+
if verdict.updated_at > detail.queued_since:
|
|
544
|
+
return True
|
|
545
|
+
if verdict.updated_at != detail.queued_since:
|
|
546
|
+
return False
|
|
547
|
+
return False
|
|
426
548
|
|
|
427
549
|
|
|
428
550
|
def attested_non_current_audit_heads(
|
|
@@ -502,23 +624,69 @@ def audit_job_matches_lane(job: Mapping[str, Any], lane: Mapping[str, Any]) -> b
|
|
|
502
624
|
return any(token in name for token in _audit_lane_match_tokens(lane))
|
|
503
625
|
|
|
504
626
|
|
|
505
|
-
def
|
|
627
|
+
def _audit_mapping_timestamp(item: Mapping[str, Any], keys: Sequence[str]) -> str:
|
|
628
|
+
for key in keys:
|
|
629
|
+
value = str(item.get(key) or "")
|
|
630
|
+
if value:
|
|
631
|
+
return value
|
|
632
|
+
return ""
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
def audit_run_queued_since(
|
|
636
|
+
run: Mapping[str, Any],
|
|
637
|
+
job: Mapping[str, Any] | None = None,
|
|
638
|
+
) -> str:
|
|
639
|
+
if job is not None:
|
|
640
|
+
job_time = _audit_mapping_timestamp(
|
|
641
|
+
job,
|
|
642
|
+
(
|
|
643
|
+
"queued_at",
|
|
644
|
+
"queuedAt",
|
|
645
|
+
"started_at",
|
|
646
|
+
"startedAt",
|
|
647
|
+
"created_at",
|
|
648
|
+
"createdAt",
|
|
649
|
+
"completed_at",
|
|
650
|
+
"completedAt",
|
|
651
|
+
),
|
|
652
|
+
)
|
|
653
|
+
if job_time:
|
|
654
|
+
return job_time
|
|
655
|
+
return _audit_mapping_timestamp(
|
|
656
|
+
run,
|
|
657
|
+
(
|
|
658
|
+
"created_at",
|
|
659
|
+
"createdAt",
|
|
660
|
+
"queued_at",
|
|
661
|
+
"queuedAt",
|
|
662
|
+
"run_started_at",
|
|
663
|
+
"runStartedAt",
|
|
664
|
+
"started_at",
|
|
665
|
+
"startedAt",
|
|
666
|
+
"updated_at",
|
|
667
|
+
"updatedAt",
|
|
668
|
+
),
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
def audit_run_in_flight_detail_for_lane(
|
|
506
673
|
entry: Mapping[str, Any],
|
|
507
674
|
lane: Mapping[str, Any],
|
|
508
675
|
*,
|
|
509
676
|
head_sha: str,
|
|
510
677
|
pr_number: int | str,
|
|
511
|
-
) ->
|
|
678
|
+
) -> AuditRunInFlight | None:
|
|
512
679
|
run = entry.get("run") if isinstance(entry.get("run"), Mapping) else entry
|
|
513
680
|
if not isinstance(run, Mapping):
|
|
514
|
-
return
|
|
515
|
-
|
|
516
|
-
|
|
681
|
+
return None
|
|
682
|
+
run_status = str(run.get("status") or "")
|
|
683
|
+
if run_status not in AUDIT_RUN_NON_TERMINAL_STATUSES:
|
|
684
|
+
return None
|
|
517
685
|
workflows = parse_csv_set(str(lane.get("github_actions_workflows") or ""))
|
|
518
686
|
if not workflow_path_matches(audit_run_workflow_path(run), workflows):
|
|
519
|
-
return
|
|
687
|
+
return None
|
|
520
688
|
if not audit_run_matches_pr_head(run, head_sha=head_sha, pr_number=pr_number):
|
|
521
|
-
return
|
|
689
|
+
return None
|
|
522
690
|
jobs = entry.get("jobs") if isinstance(entry.get("jobs"), list) else []
|
|
523
691
|
non_terminal_jobs = [
|
|
524
692
|
job
|
|
@@ -530,8 +698,45 @@ def audit_run_in_flight_for_lane(
|
|
|
530
698
|
)
|
|
531
699
|
]
|
|
532
700
|
if non_terminal_jobs:
|
|
533
|
-
|
|
534
|
-
|
|
701
|
+
for job in non_terminal_jobs:
|
|
702
|
+
if audit_job_matches_lane(job, lane):
|
|
703
|
+
return AuditRunInFlight(
|
|
704
|
+
run_id=str(run.get("id") or ""),
|
|
705
|
+
job_name=str(job.get("name") or ""),
|
|
706
|
+
queued_since=audit_run_queued_since(run, job),
|
|
707
|
+
run_status=run_status,
|
|
708
|
+
job_status=str(job.get("status") or ""),
|
|
709
|
+
job_conclusion=str(job.get("conclusion") or ""),
|
|
710
|
+
)
|
|
711
|
+
return None
|
|
712
|
+
if entry.get("jobs_fetch_failed") or not jobs:
|
|
713
|
+
return AuditRunInFlight(
|
|
714
|
+
run_id=str(run.get("id") or ""),
|
|
715
|
+
job_name="jobs unavailable",
|
|
716
|
+
queued_since=audit_run_queued_since(run),
|
|
717
|
+
run_status=run_status,
|
|
718
|
+
job_status="unknown",
|
|
719
|
+
job_conclusion="",
|
|
720
|
+
)
|
|
721
|
+
return None
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
def audit_run_in_flight_for_lane(
|
|
725
|
+
entry: Mapping[str, Any],
|
|
726
|
+
lane: Mapping[str, Any],
|
|
727
|
+
*,
|
|
728
|
+
head_sha: str,
|
|
729
|
+
pr_number: int | str,
|
|
730
|
+
) -> bool:
|
|
731
|
+
return (
|
|
732
|
+
audit_run_in_flight_detail_for_lane(
|
|
733
|
+
entry,
|
|
734
|
+
lane,
|
|
735
|
+
head_sha=head_sha,
|
|
736
|
+
pr_number=pr_number,
|
|
737
|
+
)
|
|
738
|
+
is not None
|
|
739
|
+
)
|
|
535
740
|
|
|
536
741
|
|
|
537
742
|
def _pr_item_matches_head(
|