code-mower 0.5.0b43__tar.gz → 0.5.0b45__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.0b43 → code_mower-0.5.0b45}/PKG-INFO +6 -6
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/README.md +5 -5
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/pyproject.toml +1 -1
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/__init__.py +1 -1
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/auto_discovery.py +3 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/claude_audit_pr.py +102 -23
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cli.py +4 -1
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/code_mower_telemetry.py +36 -9
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/codex_audit_pr.py +98 -9
- code_mower-0.5.0b45/src/code_mower/gate_health.py +739 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/init.py +28 -6
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/migration_mirror.py +1 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package_manifest.py +1 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/__init__.py +10 -0
- code_mower-0.5.0b45/src/code_mower/provider_runners/verdict_artifacts.py +247 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/code-mower.example.yml +3 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/base-audit.md +3 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
- code_mower-0.5.0b45/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +55 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +24 -1
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/PKG-INFO +6 -6
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/SOURCES.txt +4 -0
- code_mower-0.5.0b45/templates/workflows/code-mower-gate-health.yml.j2 +55 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/self-hosted-local-audit.yml.j2 +24 -1
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_calibration_truth.py +48 -0
- code_mower-0.5.0b45/tests/test_claude_audit_pr.py +321 -0
- code_mower-0.5.0b45/tests/test_codex_audit_pr.py +168 -0
- code_mower-0.5.0b45/tests/test_gate_health.py +669 -0
- code_mower-0.5.0b45/tests/test_prompts.py +18 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_release_hygiene.py +120 -135
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_reviewer_metrics_core.py +112 -13
- code_mower-0.5.0b43/src/code_mower/provider_runners/verdict_artifacts.py +0 -103
- code_mower-0.5.0b43/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -321
- code_mower-0.5.0b43/templates/workflows/code-mower-gate-health.yml.j2 +0 -321
- code_mower-0.5.0b43/tests/test_claude_audit_pr.py +0 -175
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/CODE_OF_CONDUCT.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/LICENSE +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/MANIFEST.in +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/NOTICE +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/SUPPORT.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/requirements/requirements.txt +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/setup.cfg +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/_base.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/cursor_bugbot.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/gitar.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/greptile.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/adapters/qodo.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/audit_handoff_log.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/audit_labeler_lib.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/audit_progress.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/blind_review_artifacts.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/blind_review_coordinator.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/bootstrap.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/builder_experiment.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/builder_runs.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/arms.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/commands.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/context_inputs.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/corpus.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/effect_report.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/evidence.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/evidence_report.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/identity.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/metrics.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/overlap.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/planning.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/policy.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/results.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/run_results.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/run_status.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/runner.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/truth.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/calibration/value_report.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/checks.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/claude_cli_environment.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/clear_stale.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/bundle.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/doctor.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/dogfood.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/endpoints.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/errors.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/events.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/export.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/git_metadata.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/manifest.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/operations.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/reports.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/setup.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/cloud_client/upload.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/code_mower_calibration.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/code_mower_context_packs.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/code_mower_merge.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/codex_audit_env_preflight.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/codex_audit_schema_smoke.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/codex_audit_verdict.schema.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/config.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/cloud.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/common.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_api.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_branch.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_config.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_provider.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/github_repo.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/groups.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/models.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/output.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/presets.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/privacy.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_env.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_probe.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/providers.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/registry.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/runner.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/runtime.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/gemini_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/grok_build_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/hermes_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/aider.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/claude.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/codex.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/devin.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/gemini_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/grok_build.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/hermes_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/lane_configs/local_llm.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/local_llm_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/local_llm_bakeoff.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/local_llm_calibration.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/local_llm_profiles.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/migration.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/migration_install.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/migration_readiness.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/migration_rehearsal.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/next_steps.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package_content.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package_paths.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package_rendering.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/package_static.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/plan_context.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/prompts.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_registry.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/comments.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/git.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/github_auth.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/github_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/pr_worktree.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/process.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/repo_paths.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/text_schema.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/provider_runners/workspace.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/providers/__init__.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/providers/local_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/providers/provenance.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/release_readiness.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/reviewer_metrics.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/reviewer_spend.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/saas_reviewer_labeler.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/secrets.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/operability.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/code_mower +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/product-support/status_report.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/providers.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/trailer_comment_labeler.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/versioning.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower/work_orders.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/dependency_links.txt +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/entry_points.txt +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/requires.txt +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/src/code_mower.egg-info/top_level.txt +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/code-mower.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/cursor/BUGBOT.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/acp_bridge.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/aider.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/antigravity_cli.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/claude_audit.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/claude_review.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/coderabbit_cli.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/codex.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/cursor_bugbot.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/devin.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/gemini_cli.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/gitar.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/greptile.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/hermes_cli.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/local_llm.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers/qodo.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/providers.yml +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/builder-provenance.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/code-mower-gate.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_audit_comment_posture.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_builder_identity.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_builder_runs.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_calibration_effect_report.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_checks.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_clear_stale.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_cloud_client.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_cloud_git_metadata.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_cloud_manifest.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_cloud_reports.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_codex_audit_env_preflight.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_boundaries.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_github_checks.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_output.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_privacy.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_provider_env_required.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_provider_env_tokens.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_provider_probe.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_provider_review_hygiene.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_doctor_registry.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_local_llm_github_helpers.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_plan_context.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_local_cli.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_comments.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_git.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_github_pr.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_pr_worktree.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_process.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_repo_paths.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_text_schema.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_provider_runners_workspace.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_reviewer_spend.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/tests/test_trailer_comment_labeler.py +0 -0
- {code_mower-0.5.0b43 → code_mower-0.5.0b45}/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.
|
|
3
|
+
Version: 0.5.0b45
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -103,11 +103,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
105
|
python3.12 --version
|
|
106
|
-
pipx install --python python3.12 code-mower==0.5.
|
|
106
|
+
pipx install --python python3.12 code-mower==0.5.0b45
|
|
107
107
|
code-mower --version
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
`0.5.
|
|
110
|
+
`0.5.0b45` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
111
111
|
line, use the explicit beta version above or allow prereleases with:
|
|
112
112
|
|
|
113
113
|
```bash
|
|
@@ -155,7 +155,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
155
155
|
|
|
156
156
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
157
157
|
[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.
|
|
158
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b45`.
|
|
159
159
|
|
|
160
160
|
## Optional: Plan Before Coding
|
|
161
161
|
|
|
@@ -310,9 +310,9 @@ builder provenance, start with
|
|
|
310
310
|
|
|
311
311
|
## Installation Status
|
|
312
312
|
|
|
313
|
-
The current public beta is `v0.5.0-beta.
|
|
313
|
+
The current public beta is `v0.5.0-beta.45` from
|
|
314
314
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
315
|
-
as `code-mower==0.5.
|
|
315
|
+
as `code-mower==0.5.0b45` on [PyPI](https://pypi.org/project/code-mower/).
|
|
316
316
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
317
317
|
release notes.
|
|
318
318
|
|
|
@@ -88,11 +88,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
90
|
python3.12 --version
|
|
91
|
-
pipx install --python python3.12 code-mower==0.5.
|
|
91
|
+
pipx install --python python3.12 code-mower==0.5.0b45
|
|
92
92
|
code-mower --version
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
`0.5.
|
|
95
|
+
`0.5.0b45` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
96
96
|
line, use the explicit beta version above or allow prereleases with:
|
|
97
97
|
|
|
98
98
|
```bash
|
|
@@ -140,7 +140,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
140
140
|
|
|
141
141
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
142
142
|
[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.
|
|
143
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b45`.
|
|
144
144
|
|
|
145
145
|
## Optional: Plan Before Coding
|
|
146
146
|
|
|
@@ -295,9 +295,9 @@ builder provenance, start with
|
|
|
295
295
|
|
|
296
296
|
## Installation Status
|
|
297
297
|
|
|
298
|
-
The current public beta is `v0.5.0-beta.
|
|
298
|
+
The current public beta is `v0.5.0-beta.45` from
|
|
299
299
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
300
|
-
as `code-mower==0.5.
|
|
300
|
+
as `code-mower==0.5.0b45` on [PyPI](https://pypi.org/project/code-mower/).
|
|
301
301
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
302
302
|
release notes.
|
|
303
303
|
|
|
@@ -12,6 +12,7 @@ from typing import Any, Mapping, Sequence
|
|
|
12
12
|
from .corpus import parse_int
|
|
13
13
|
from .identity import safe_slug
|
|
14
14
|
from .run_status import RUN_STATUS_BLOCKED, RUN_STATUS_PASS, RUN_STATUS_UNKNOWN
|
|
15
|
+
from ..provider_runners import is_fixture_verdict_comment
|
|
15
16
|
|
|
16
17
|
AUTO_DISCOVERY_SCHEMA = "code_mower.calibrationAutoDiscover.v1"
|
|
17
18
|
TRUTH_EXPECTATION_UNKNOWN = "unknown"
|
|
@@ -147,6 +148,8 @@ def _audit_runs_from_comments(comments: Sequence[Any]) -> list[dict[str, Any]]:
|
|
|
147
148
|
body = str(comment.get("body") or "")
|
|
148
149
|
if not body:
|
|
149
150
|
continue
|
|
151
|
+
if is_fixture_verdict_comment(body):
|
|
152
|
+
continue
|
|
150
153
|
for match in AUDIT_STATE_RE.finditer(body):
|
|
151
154
|
state = match.group("state")
|
|
152
155
|
reviewer = _provider_from_audit_state(match.group("provider"), state)
|
|
@@ -32,11 +32,13 @@ if __package__ in {None, "", "tools"}:
|
|
|
32
32
|
from tools.audit_progress import AuditProgress, run_subprocess_with_progress
|
|
33
33
|
from tools.claude_cli_environment import clean_claude_cli_env, env_flag
|
|
34
34
|
from tools.provider_runners import (
|
|
35
|
+
audit_runtime_quarantine_reason as _audit_runtime_quarantine_reason,
|
|
35
36
|
clip_text as _clip_text,
|
|
36
37
|
fetch_pull_request,
|
|
37
38
|
fetch_base_ref_sha as _shared_fetch_base_ref_sha,
|
|
38
39
|
fetch_pr_head_sha as _shared_fetch_pr_head_sha,
|
|
39
40
|
fetch_pr_head_sha_unless_local_matches as _shared_fetch_pr_head_sha_unless_local_matches,
|
|
41
|
+
is_fixture_structured_verdict as _is_fixture_structured_verdict,
|
|
40
42
|
limit_comment_body,
|
|
41
43
|
one_line as _one_line,
|
|
42
44
|
parse_repo_paths as _parse_repo_paths,
|
|
@@ -58,11 +60,13 @@ if __package__ in {None, "", "tools"}:
|
|
|
58
60
|
from audit_progress import AuditProgress, run_subprocess_with_progress # type: ignore
|
|
59
61
|
from claude_cli_environment import clean_claude_cli_env, env_flag # type: ignore
|
|
60
62
|
from provider_runners import ( # type: ignore
|
|
63
|
+
audit_runtime_quarantine_reason as _audit_runtime_quarantine_reason,
|
|
61
64
|
clip_text as _clip_text,
|
|
62
65
|
fetch_pull_request,
|
|
63
66
|
fetch_base_ref_sha as _shared_fetch_base_ref_sha,
|
|
64
67
|
fetch_pr_head_sha as _shared_fetch_pr_head_sha,
|
|
65
68
|
fetch_pr_head_sha_unless_local_matches as _shared_fetch_pr_head_sha_unless_local_matches,
|
|
69
|
+
is_fixture_structured_verdict as _is_fixture_structured_verdict,
|
|
66
70
|
limit_comment_body,
|
|
67
71
|
one_line as _one_line,
|
|
68
72
|
parse_repo_paths as _parse_repo_paths,
|
|
@@ -82,11 +86,13 @@ else: # pragma: no cover - exercised after package extraction.
|
|
|
82
86
|
from .claude_cli_environment import clean_claude_cli_env, env_flag
|
|
83
87
|
from .provider_runners import (
|
|
84
88
|
FetchedHeadMismatch,
|
|
89
|
+
audit_runtime_quarantine_reason as _audit_runtime_quarantine_reason,
|
|
85
90
|
clip_text as _clip_text,
|
|
86
91
|
fetch_base_ref_sha as _shared_fetch_base_ref_sha,
|
|
87
92
|
fetch_pull_request,
|
|
88
93
|
fetch_pr_head_sha as _shared_fetch_pr_head_sha,
|
|
89
94
|
fetch_pr_head_sha_unless_local_matches as _shared_fetch_pr_head_sha_unless_local_matches,
|
|
95
|
+
is_fixture_structured_verdict as _is_fixture_structured_verdict,
|
|
90
96
|
limit_comment_body,
|
|
91
97
|
one_line as _one_line,
|
|
92
98
|
parse_repo_paths as _parse_repo_paths,
|
|
@@ -445,6 +451,29 @@ def _apply_claude_verdict_guardrails(
|
|
|
445
451
|
return _unknown_structured_verdict(reason), reason
|
|
446
452
|
|
|
447
453
|
|
|
454
|
+
def _fixture_structured_quarantine_reason(parsed: ClaudeVerdict) -> Optional[str]:
|
|
455
|
+
if _is_fixture_structured_verdict(parsed.summary, list(parsed.findings)):
|
|
456
|
+
return "fixture-shaped structured verdict rejected by guardrail"
|
|
457
|
+
return None
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _quarantine_is_test_only(reason: Optional[str]) -> bool:
|
|
461
|
+
return reason == "PYTEST_CURRENT_TEST is set"
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def _comment_with_runtime_quarantine_note(comment_body: str, reason: str) -> str:
|
|
465
|
+
note = (
|
|
466
|
+
"\nRuntime quarantine: local verdict artifact was quarantined because "
|
|
467
|
+
f"{reason}. Posting UNKNOWN so the lane requeues visibly.\n"
|
|
468
|
+
)
|
|
469
|
+
marker = f"\n\n{STALE_TRAILER}"
|
|
470
|
+
if marker in comment_body:
|
|
471
|
+
body = comment_body.replace(marker, note + "\n" + STALE_TRAILER, 1)
|
|
472
|
+
else:
|
|
473
|
+
body = comment_body.rstrip() + note + "\n" + STALE_TRAILER + "\n"
|
|
474
|
+
return limit_comment_body(body, STALE_TRAILER, provider_name="Claude")
|
|
475
|
+
|
|
476
|
+
|
|
448
477
|
def _write_claude_raw_output_sidecar(
|
|
449
478
|
artifact_path: Optional[Path],
|
|
450
479
|
attempts: List[Dict[str, Any]],
|
|
@@ -917,6 +946,7 @@ def format_comment(
|
|
|
917
946
|
|
|
918
947
|
|
|
919
948
|
def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAuditResult:
|
|
949
|
+
audit_started = time.monotonic()
|
|
920
950
|
local_repo = config.repo_paths.get(repo)
|
|
921
951
|
if local_repo is None:
|
|
922
952
|
raise ValueError(
|
|
@@ -996,6 +1026,9 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
996
1026
|
parsed=parsed,
|
|
997
1027
|
)
|
|
998
1028
|
if not config.dry_run:
|
|
1029
|
+
quarantine_reason = _audit_runtime_quarantine_reason(
|
|
1030
|
+
comment_body=comment_body,
|
|
1031
|
+
)
|
|
999
1032
|
artifact_path = write_audit_verdict_artifact(
|
|
1000
1033
|
lane_id="claude-audit",
|
|
1001
1034
|
repo=repo,
|
|
@@ -1005,6 +1038,8 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1005
1038
|
verdict=result.verdict,
|
|
1006
1039
|
trailer=result.trailer,
|
|
1007
1040
|
comment_body=comment_body,
|
|
1041
|
+
quarantine_reason=quarantine_reason,
|
|
1042
|
+
duration_seconds=time.monotonic() - audit_started,
|
|
1008
1043
|
)
|
|
1009
1044
|
result.verdict_artifact_path = artifact_path
|
|
1010
1045
|
if artifact_path is not None:
|
|
@@ -1013,17 +1048,35 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1013
1048
|
file=sys.stderr,
|
|
1014
1049
|
flush=True,
|
|
1015
1050
|
)
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1051
|
+
if quarantine_reason:
|
|
1052
|
+
print(
|
|
1053
|
+
" runtime guard quarantined verdict artifact: "
|
|
1054
|
+
f"{quarantine_reason}",
|
|
1055
|
+
file=sys.stderr,
|
|
1056
|
+
flush=True,
|
|
1057
|
+
)
|
|
1058
|
+
if quarantine_reason and _quarantine_is_test_only(quarantine_reason):
|
|
1059
|
+
print(" skipped GitHub post for pytest-only quarantine", file=sys.stderr, flush=True)
|
|
1060
|
+
else:
|
|
1061
|
+
if quarantine_reason:
|
|
1062
|
+
result.verdict = "UNKNOWN"
|
|
1063
|
+
result.trailer = STALE_TRAILER
|
|
1064
|
+
comment_body = _comment_with_runtime_quarantine_note(
|
|
1065
|
+
comment_body,
|
|
1066
|
+
quarantine_reason,
|
|
1067
|
+
)
|
|
1068
|
+
result.comment_body = comment_body
|
|
1069
|
+
posted = post_pr_comment(repo, pr_number, comment_body, token=config.github_token)
|
|
1070
|
+
result.posted_comment_url = posted.get("html_url")
|
|
1071
|
+
_record_posted_comment_url(
|
|
1072
|
+
result.verdict_artifact_path,
|
|
1073
|
+
result.posted_comment_url,
|
|
1074
|
+
)
|
|
1075
|
+
print(
|
|
1076
|
+
f"posted {repo}#{pr_number} verdict=STALE "
|
|
1077
|
+
f"url={result.posted_comment_url}",
|
|
1078
|
+
file=sys.stderr,
|
|
1079
|
+
)
|
|
1027
1080
|
config.progress.emit(
|
|
1028
1081
|
"audit",
|
|
1029
1082
|
status="finish",
|
|
@@ -1082,6 +1135,7 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1082
1135
|
claude_stdout = ""
|
|
1083
1136
|
claude_stderr = ""
|
|
1084
1137
|
attempt_prompt = prompt
|
|
1138
|
+
final_fixture_reason: Optional[str] = None
|
|
1085
1139
|
t0 = time.time()
|
|
1086
1140
|
for attempt in range(1, MAX_CLAUDE_AUDIT_ATTEMPTS + 1):
|
|
1087
1141
|
parsed_candidate, attempt_stdout, attempt_stderr = run_claude_audit(
|
|
@@ -1094,6 +1148,7 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1094
1148
|
parsed_candidate,
|
|
1095
1149
|
diff_context.changed_files,
|
|
1096
1150
|
)
|
|
1151
|
+
final_fixture_reason = _fixture_structured_quarantine_reason(parsed_candidate)
|
|
1097
1152
|
raw_output_attempts.append(
|
|
1098
1153
|
{
|
|
1099
1154
|
"attempt": attempt,
|
|
@@ -1172,6 +1227,10 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1172
1227
|
)
|
|
1173
1228
|
|
|
1174
1229
|
if not config.dry_run:
|
|
1230
|
+
quarantine_reason = _audit_runtime_quarantine_reason(
|
|
1231
|
+
comment_body=comment_body,
|
|
1232
|
+
fixture_reason=final_fixture_reason if parsed.verdict == "UNKNOWN" else None,
|
|
1233
|
+
)
|
|
1175
1234
|
artifact_path = write_audit_verdict_artifact(
|
|
1176
1235
|
lane_id="claude-audit",
|
|
1177
1236
|
repo=repo,
|
|
@@ -1181,6 +1240,8 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1181
1240
|
verdict=result_verdict,
|
|
1182
1241
|
trailer=trailer,
|
|
1183
1242
|
comment_body=comment_body,
|
|
1243
|
+
quarantine_reason=quarantine_reason,
|
|
1244
|
+
duration_seconds=time.monotonic() - audit_started,
|
|
1184
1245
|
)
|
|
1185
1246
|
result.verdict_artifact_path = artifact_path
|
|
1186
1247
|
if artifact_path is not None:
|
|
@@ -1190,21 +1251,39 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1190
1251
|
flush=True,
|
|
1191
1252
|
)
|
|
1192
1253
|
_write_claude_raw_output_sidecar(artifact_path, raw_output_attempts)
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1254
|
+
if quarantine_reason:
|
|
1255
|
+
print(
|
|
1256
|
+
" runtime guard quarantined verdict artifact: "
|
|
1257
|
+
f"{quarantine_reason}",
|
|
1258
|
+
file=sys.stderr,
|
|
1259
|
+
flush=True,
|
|
1260
|
+
)
|
|
1261
|
+
if quarantine_reason and _quarantine_is_test_only(quarantine_reason):
|
|
1262
|
+
print(" skipped GitHub post for pytest-only quarantine", file=sys.stderr, flush=True)
|
|
1263
|
+
else:
|
|
1264
|
+
if quarantine_reason:
|
|
1265
|
+
result.verdict = "UNKNOWN"
|
|
1266
|
+
result.trailer = STALE_TRAILER
|
|
1267
|
+
comment_body = _comment_with_runtime_quarantine_note(
|
|
1268
|
+
comment_body,
|
|
1269
|
+
quarantine_reason,
|
|
1270
|
+
)
|
|
1271
|
+
result.comment_body = comment_body
|
|
1272
|
+
posted = post_pr_comment(repo, pr_number, comment_body, token=config.github_token)
|
|
1273
|
+
result.posted_comment_url = posted.get("html_url")
|
|
1274
|
+
_record_posted_comment_url(
|
|
1275
|
+
result.verdict_artifact_path,
|
|
1276
|
+
result.posted_comment_url,
|
|
1277
|
+
)
|
|
1278
|
+
print(
|
|
1279
|
+
f"posted {repo}#{pr_number} verdict={result_verdict} "
|
|
1280
|
+
f"url={result.posted_comment_url}",
|
|
1281
|
+
file=sys.stderr,
|
|
1282
|
+
)
|
|
1204
1283
|
config.progress.emit(
|
|
1205
1284
|
"audit",
|
|
1206
1285
|
status="finish",
|
|
1207
|
-
detail=f"{repo}#{pr_number} verdict={
|
|
1286
|
+
detail=f"{repo}#{pr_number} verdict={result.verdict}",
|
|
1208
1287
|
)
|
|
1209
1288
|
return result
|
|
1210
1289
|
|
|
@@ -14,7 +14,7 @@ from pathlib import Path
|
|
|
14
14
|
if __package__ in {None, ""}:
|
|
15
15
|
raise SystemExit(
|
|
16
16
|
"code_mower.cli is a packaged entrypoint. Install Code Mower with "
|
|
17
|
-
"`pipx install code-mower==0.5.
|
|
17
|
+
"`pipx install code-mower==0.5.0b45`, or run source checkouts with "
|
|
18
18
|
"`PYTHONPATH=src python -m code_mower.cli`."
|
|
19
19
|
)
|
|
20
20
|
|
|
@@ -40,6 +40,7 @@ from . import code_mower_telemetry
|
|
|
40
40
|
from . import config as code_mower_config
|
|
41
41
|
from . import doctor as code_mower_doctor
|
|
42
42
|
from . import gemini_cli_audit_pr
|
|
43
|
+
from . import gate_health as code_mower_gate_health
|
|
43
44
|
from . import grok_build_audit_pr
|
|
44
45
|
from . import hermes_cli_audit_pr
|
|
45
46
|
from . import init as code_mower_init
|
|
@@ -398,6 +399,7 @@ COMMAND_DESCRIPTIONS: dict[str, str] = {
|
|
|
398
399
|
"codex-audit-schema-smoke": "Smoke-test Codex audit schema parsing.",
|
|
399
400
|
"doctor": "Check runtime, GitHub, providers, privacy, and cloud setup.",
|
|
400
401
|
"gemini-cli": "Run a Gemini CLI structured audit lane.",
|
|
402
|
+
"gate-health": "Alert when audit gate infrastructure stalls.",
|
|
401
403
|
"grok-build": "Run a Grok Build informational audit lane.",
|
|
402
404
|
"hermes-cli": "Run a Hermes CLI structured audit lane.",
|
|
403
405
|
"init": "Render safe easy-mode setup output.",
|
|
@@ -529,6 +531,7 @@ COMMAND_HANDLERS: dict[str, CommandHandler] = {
|
|
|
529
531
|
"codex-audit-schema-smoke": codex_audit_schema_smoke.main,
|
|
530
532
|
"doctor": code_mower_doctor.main,
|
|
531
533
|
"gemini-cli": gemini_cli_audit_pr.main,
|
|
534
|
+
"gate-health": code_mower_gate_health.main,
|
|
532
535
|
"grok-build": grok_build_audit_pr.main,
|
|
533
536
|
"hermes-cli": hermes_cli_audit_pr.main,
|
|
534
537
|
"init": _init_main,
|
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
import argparse
|
|
7
7
|
import hashlib
|
|
8
8
|
import json
|
|
9
|
+
import math
|
|
9
10
|
import os
|
|
10
11
|
import re
|
|
11
12
|
import sys
|
|
@@ -18,12 +19,16 @@ if __package__ in {None, ""}:
|
|
|
18
19
|
sys.path.insert(0, str(module_dir.parent))
|
|
19
20
|
if module_dir.name == "code_mower": # pragma: no cover - extracted direct CLI.
|
|
20
21
|
from code_mower import audit_handoff_log
|
|
22
|
+
from code_mower.provider_runners import is_fixture_verdict_artifact
|
|
21
23
|
else:
|
|
22
24
|
from tools import audit_handoff_log
|
|
25
|
+
from tools.provider_runners import is_fixture_verdict_artifact
|
|
23
26
|
elif __package__ == "tools":
|
|
24
27
|
from tools import audit_handoff_log
|
|
28
|
+
from tools.provider_runners import is_fixture_verdict_artifact
|
|
25
29
|
else: # pragma: no cover - exercised after package extraction.
|
|
26
30
|
from . import audit_handoff_log
|
|
31
|
+
from .provider_runners import is_fixture_verdict_artifact
|
|
27
32
|
|
|
28
33
|
|
|
29
34
|
PASS_VERDICTS = {"completed", "done", "pass", "passed", "success", "succeeded"}
|
|
@@ -31,7 +36,6 @@ BLOCKED_VERDICTS = {"block", "blocked", "fail", "failed", "failure"}
|
|
|
31
36
|
VERDICT_ARTIFACT_SCHEMA = "code_mower.auditVerdictArtifact.v1"
|
|
32
37
|
BENCHMARK_EVENT_SCHEMA = "code_mower.benchmarkEvent.v1"
|
|
33
38
|
VERDICT_ARTIFACT_DIR_ENV = "CODE_MOWER_VERDICT_ARTIFACT_DIR"
|
|
34
|
-
DEFAULT_VERDICT_ARTIFACT_DIR = Path.home() / ".cache" / "code-mower-audits" / "verdicts"
|
|
35
39
|
SEVERITY_RE = re.compile(r"\b(P[0-3])=(\d+)\b")
|
|
36
40
|
AUDIT_TRAILER_RE = re.compile(
|
|
37
41
|
r"<!--\s*(?P<prefix>[A-Z0-9_]+_AUDIT_STATE)\s*:\s*(?P<label>[a-z0-9_.-]+)\s*-->",
|
|
@@ -43,7 +47,10 @@ def default_verdict_artifact_dir() -> Path:
|
|
|
43
47
|
configured = os.environ.get(VERDICT_ARTIFACT_DIR_ENV, "").strip()
|
|
44
48
|
if configured:
|
|
45
49
|
return Path(configured).expanduser()
|
|
46
|
-
|
|
50
|
+
cache_home = os.environ.get("XDG_CACHE_HOME", "").strip()
|
|
51
|
+
if cache_home:
|
|
52
|
+
return Path(cache_home).expanduser() / "code-mower-audits" / "verdicts"
|
|
53
|
+
return Path.home() / ".cache" / "code-mower-audits" / "verdicts"
|
|
47
54
|
|
|
48
55
|
|
|
49
56
|
def _normalize_repo_slug(value: str) -> str:
|
|
@@ -115,6 +122,19 @@ def _artifact_severity_counts(payload: Mapping[str, Any]) -> tuple[dict[str, int
|
|
|
115
122
|
return comment_counts, "unavailable"
|
|
116
123
|
|
|
117
124
|
|
|
125
|
+
def _artifact_duration_seconds(payload: Mapping[str, Any]) -> float | None:
|
|
126
|
+
raw = payload.get("duration_seconds")
|
|
127
|
+
if raw is None:
|
|
128
|
+
return None
|
|
129
|
+
try:
|
|
130
|
+
value = float(raw)
|
|
131
|
+
except (TypeError, ValueError):
|
|
132
|
+
return None
|
|
133
|
+
if not math.isfinite(value) or value < 0:
|
|
134
|
+
return None
|
|
135
|
+
return round(value, 3)
|
|
136
|
+
|
|
137
|
+
|
|
118
138
|
def _normal_artifact_verdict(value: Any) -> str:
|
|
119
139
|
verdict = str(value or "").strip().lower()
|
|
120
140
|
if verdict in PASS_VERDICTS:
|
|
@@ -199,6 +219,17 @@ def reviewer_run_event_from_verdict_artifact(
|
|
|
199
219
|
head = str(payload.get("head_sha_end") or payload.get("head_sha_start") or "")
|
|
200
220
|
dimensions["head_sha"] = head
|
|
201
221
|
dimensions["head_sha_short"] = head[:12]
|
|
222
|
+
metrics: dict[str, Any] = {
|
|
223
|
+
"finding_count": finding_count,
|
|
224
|
+
"p0_count": severities["p0"],
|
|
225
|
+
"p1_count": severities["p1"],
|
|
226
|
+
"p2_count": severities["p2"],
|
|
227
|
+
"p3_count": severities["p3"],
|
|
228
|
+
}
|
|
229
|
+
duration_seconds = _artifact_duration_seconds(payload)
|
|
230
|
+
if duration_seconds is not None:
|
|
231
|
+
metrics["duration_seconds_total"] = duration_seconds
|
|
232
|
+
dimensions["duration_source"] = "verdict_artifact"
|
|
202
233
|
return {
|
|
203
234
|
"schema": BENCHMARK_EVENT_SCHEMA,
|
|
204
235
|
"event_type": "reviewer_run",
|
|
@@ -209,13 +240,7 @@ def reviewer_run_event_from_verdict_artifact(
|
|
|
209
240
|
"provider": _lane_provider(lane_id),
|
|
210
241
|
"lens": "base",
|
|
211
242
|
"status": status,
|
|
212
|
-
"metrics":
|
|
213
|
-
"finding_count": finding_count,
|
|
214
|
-
"p0_count": severities["p0"],
|
|
215
|
-
"p1_count": severities["p1"],
|
|
216
|
-
"p2_count": severities["p2"],
|
|
217
|
-
"p3_count": severities["p3"],
|
|
218
|
-
},
|
|
243
|
+
"metrics": metrics,
|
|
219
244
|
"dimensions": dimensions,
|
|
220
245
|
}
|
|
221
246
|
|
|
@@ -249,6 +274,8 @@ def export_reviewer_run_events_from_verdicts(
|
|
|
249
274
|
raise ValueError(f"{path}: verdict artifact must be a JSON object")
|
|
250
275
|
if payload.get("schema") != VERDICT_ARTIFACT_SCHEMA:
|
|
251
276
|
continue
|
|
277
|
+
if is_fixture_verdict_artifact(payload):
|
|
278
|
+
continue
|
|
252
279
|
artifact_repo = _normalize_repo_slug(
|
|
253
280
|
str(payload.get("repo") or _repo_slug_from_artifact_path(path))
|
|
254
281
|
)
|