code-mower 1.2.1__tar.gz → 1.3.0__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-1.2.1 → code_mower-1.3.0}/PKG-INFO +18 -7
- {code_mower-1.2.1 → code_mower-1.3.0}/README.md +12 -6
- {code_mower-1.2.1 → code_mower-1.3.0}/pyproject.toml +2 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/__init__.py +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/audit_labeler_lib.py +29 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/claude_audit_pr.py +44 -5
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/codex_audit_pr.py +70 -15
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/config.py +13 -211
- code_mower-1.3.0/src/code_mower/context_audit.py +117 -0
- code_mower-1.3.0/src/code_mower/context_command.py +135 -0
- code_mower-1.3.0/src/code_mower/context_connections.py +274 -0
- code_mower-1.3.0/src/code_mower/context_contract.py +452 -0
- code_mower-1.3.0/src/code_mower/context_delivery.py +184 -0
- code_mower-1.3.0/src/code_mower/context_packets.py +215 -0
- code_mower-1.3.0/src/code_mower/context_readiness.py +105 -0
- code_mower-1.3.0/src/code_mower/context_review.py +133 -0
- code_mower-1.3.0/src/code_mower/context_store.py +214 -0
- code_mower-1.3.0/src/code_mower/coworker_mcp.py +379 -0
- code_mower-1.3.0/src/code_mower/coworker_retrieval.py +103 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor.py +4 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/groups.py +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/runner.py +10 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/file_locks.py +27 -22
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/init.py +56 -2
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/jira_cloud.py +2 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/jira_mutations.py +9 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/jira_pr_sync.py +12 -3
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_status.py +35 -2
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/migration.py +2 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package_content.py +3 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package_manifest.py +19 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/verdict_artifacts.py +2 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/session.py +23 -4
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/code-mower.example.yml +3 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +15 -2
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/tracker_contract.py +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/tracker_queue.py +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/work_orders.py +44 -7
- code_mower-1.3.0/src/code_mower/yaml_subset.py +220 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower.egg-info/PKG-INFO +18 -7
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower.egg-info/SOURCES.txt +22 -0
- code_mower-1.3.0/src/code_mower.egg-info/requires.txt +13 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/code-mower-gate.yml.j2 +15 -2
- code_mower-1.3.0/tests/test_context_audit.py +192 -0
- code_mower-1.3.0/tests/test_context_command.py +185 -0
- code_mower-1.3.0/tests/test_context_connections.py +274 -0
- code_mower-1.3.0/tests/test_context_contract.py +415 -0
- code_mower-1.3.0/tests/test_context_delivery.py +125 -0
- code_mower-1.3.0/tests/test_context_packets.py +188 -0
- code_mower-1.3.0/tests/test_context_readiness.py +223 -0
- code_mower-1.3.0/tests/test_context_review.py +106 -0
- code_mower-1.3.0/tests/test_coworker_mcp.py +152 -0
- code_mower-1.3.0/tests/test_coworker_retrieval.py +157 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_fork_pr_guard.py +22 -4
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_jira_adoption.py +2 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_jira_cloud.py +7 -3
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_jira_pr_sync.py +49 -1
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_lane_status.py +89 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_participant_sessions.py +21 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_release_hygiene.py +73 -47
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_tracker_contract.py +6 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_tracker_queue.py +2 -2
- code_mower-1.2.1/src/code_mower.egg-info/requires.txt +0 -7
- {code_mower-1.2.1 → code_mower-1.3.0}/CODE_OF_CONDUCT.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/LICENSE +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/MANIFEST.in +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/NOTICE +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/SUPPORT.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/requirements/requirements.txt +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/setup.cfg +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/_base.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/cursor_bugbot.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/gitar.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/greptile.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/adapters/qodo.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/antigravity_sdk_probe.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/audit_handoff_log.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/audit_limits.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/audit_progress.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/blind_review_artifacts.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/blind_review_coordinator.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/board.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/board_store.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/bootstrap.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/builder_experiment.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/builder_runs.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/arms.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/auto_discovery.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/commands.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/context_inputs.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/corpus.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/effect_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/evidence.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/evidence_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/identity.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/metrics.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/overlap.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/planning.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/policy.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/results.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/run_results.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/run_status.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/runner.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/truth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/calibration/value_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/campaign_adapters.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/campaign_discovery.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/checks.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/claude_cli_bounce.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/claude_cli_environment.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/clear_stale.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/adoption_runs.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/bundle.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/doctor.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/dogfood.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/endpoints.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/errors.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/events.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/export.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/finding_outcomes.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/git_metadata.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/manifest.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/operations.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/pr_outcomes.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/productivity.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/productivity_windows.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/reports.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/setup.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/tokens.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/upload.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/cloud_client/work_types.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/code_mower_calibration.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/code_mower_context_packs.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/code_mower_merge.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/code_mower_telemetry.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/codex_audit_env_preflight.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/codex_audit_schema_smoke.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/codex_audit_verdict.schema.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/controller.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/decisions.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/devin_api.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/devin_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/adoption.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/audit_limits.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/campaign_auth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/cloud.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/common.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_api.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_branch.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_config.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_human_token.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_provider.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_repo.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/github_trusted_authors.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/jira.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/models.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/output.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/presets.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/privacy.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_env.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_probe.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/provider_review_hygiene.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/providers.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/registry.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/runtime.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/doctor_checks/supervised_pilot.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/gate_health.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/gemini_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/git_identity.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/grok_build_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/hermes_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/aider.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/claude.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/codex.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/devin.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/devin_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/gemini_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/grok_build.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/hermes_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/local_llm.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_configs/muse_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/lane_delivery.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/local_llm_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/local_llm_bakeoff.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/local_llm_calibration.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/local_llm_profiles.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/migration_install.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/migration_mirror.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/migration_readiness.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/migration_rehearsal.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/muse_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/next_steps.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package_paths.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package_rendering.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/package_static.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/participants.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/plan_context.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/productivity_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/prompts.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_credentials.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_registry.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/comments.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/exit_codes.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/git.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/github_auth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/github_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/pr_worktree.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/process.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/repo_paths.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/text_schema.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/provider_runners/workspace.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/providers/__init__.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/providers/local_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/providers/provenance.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/release_campaigns.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/release_qualify.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/release_readiness.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/reviewer_metrics.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/reviewer_spend.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/saas_reviewer_labeler.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/secrets.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/session_lease.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/builder-experiment.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/calibration-corpus.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/calibration-corpus.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/context-packs.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/operability.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/README.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/claude.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/codex.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/cursor.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/devin.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/generic.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/lanes/run_mac_lane.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/code_mower +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/run_devin_cli_audit_pr.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/product-support/status_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/providers.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/reviewer-spend.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/trailer_comment_labeler.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/versioning.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower/workflow_actionlint.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower.egg-info/dependency_links.txt +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower.egg-info/entry_points.txt +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/src/code_mower.egg-info/top_level.txt +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/builder-experiment.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/calibration-corpus.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/calibration-corpus.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/code-mower.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/context-packs.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/cursor/BUGBOT.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/README.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/claude.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/codex.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/cursor.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/devin.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/generic.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/lanes/run_mac_lane.sh +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/acp_bridge.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/aider.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/antigravity_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/claude_audit.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/claude_review.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/coderabbit_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/codex.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/cursor_bugbot.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/cursor_cloud_agent.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/devin.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/devin_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/gemini_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/gitar.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/greptile.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/hermes_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/local_llm.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/muse_cli.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers/qodo.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/providers.yml +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/reviewer-spend.example.json +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/reviewer-value-report.example.md +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/dispatch-lanes.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_adoption_diagnostics.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_adoption_result_semantics.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_adoption_run_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_antigravity_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_antigravity_sdk_probe.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_audit_comment_posture.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_audit_limits.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_board.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_board_lease.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_builder_experiment.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_builder_identity.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_builder_runs.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_calibration_effect_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_calibration_truth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_campaign_adapters.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_campaign_discovery.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_campaign_gh_auth_and_issue_binding_817.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_campaign_retry_evidence_711.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_checks.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_claude_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_claude_cli_bounce.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_clear_stale.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_cloud_client.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_cloud_git_metadata.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_cloud_manifest.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_cloud_reports.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_coderabbit_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_codex_audit_env_preflight.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_codex_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_controller.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_decision_audit_integration.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_decisions.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_devin_api.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_devin_builder_lane.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_devin_cli_audit_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_devin_provider_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_actions_cost_summary.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_actions_failure_selection.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_boundaries.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_campaign_auth.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_campaign_readiness.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_github_checks.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_output.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_privacy.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_provider_env_required.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_provider_env_tokens.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_provider_local_audit_setup.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_provider_probe.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_provider_review_hygiene.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_registry.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_runtime.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_self_hosted_runner.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_doctor_supervised_pilot.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_file_locks.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_gate_automerge.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_gate_health.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_hosted_dispatch_profile.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_init_actionlint.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_init_build_loop.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_jira_mutations.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_lane_delivery_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_local_llm_github_helpers.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_migration_rehearsal.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_migration_setup_drift.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_next_steps.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_package_install_failure_taxonomy.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_plan_context.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_pr_outcome_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_pr_outcome_coverage.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_productivity_metrics_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_productivity_report.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_productivity_windows.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_prompts.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_credentials.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_fixture_contracts.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_local_cli.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_comments.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_git.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_github_pr.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_pr_worktree.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_process.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_repo_paths.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_text_schema.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_provider_runners_workspace.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_release_campaigns.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_release_qualify.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_remote_qualification_failure_reason_819.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_reviewer_finding_outcome_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_reviewer_metrics_core.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_reviewer_spend.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_session_lease.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_supervised_pilot_contract.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_tracker_config.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_trailer_comment_labeler.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_work_orders.py +0 -0
- {code_mower-1.2.1 → code_mower-1.3.0}/tests/test_work_type_contract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-mower
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/codemower-ai/code-mower
|
|
@@ -21,6 +21,11 @@ Description-Content-Type: text/markdown
|
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
License-File: NOTICE
|
|
23
23
|
Requires-Dist: PyYAML>=6.0
|
|
24
|
+
Provides-Extra: coworker
|
|
25
|
+
Requires-Dist: mcp<2.3,>=2.2.0; extra == "coworker"
|
|
26
|
+
Requires-Dist: httpx2<3,>=2.12; extra == "coworker"
|
|
27
|
+
Requires-Dist: PyJWT[crypto]<3,>=2.10; extra == "coworker"
|
|
28
|
+
Requires-Dist: keyring<26,>=25; extra == "coworker"
|
|
24
29
|
Provides-Extra: test
|
|
25
30
|
Requires-Dist: build>=1.2; extra == "test"
|
|
26
31
|
Requires-Dist: pytest>=8.0; extra == "test"
|
|
@@ -45,6 +50,8 @@ The short version:
|
|
|
45
50
|
exposure, or GitHub Actions churn;
|
|
46
51
|
- turn issue text, external docs, and project doctrine into local work orders
|
|
47
52
|
before an agent starts coding;
|
|
53
|
+
- optionally give Claude and Codex the same authorized organizational evidence
|
|
54
|
+
through a private Coworker connection, with fresh review when context changes;
|
|
48
55
|
- generate local reviewer value reports from known-clean and known-blocked PRs;
|
|
49
56
|
and
|
|
50
57
|
- optionally share sanitized metadata with [CodeMower.com](https://codemower.com)
|
|
@@ -56,8 +63,8 @@ Default cloud bundles exclude source code, raw diffs, raw model transcripts,
|
|
|
56
63
|
raw stdout/stderr, auth output, and secrets.
|
|
57
64
|
|
|
58
65
|
Documentation on `main` follows the source on `main`. If you install the
|
|
59
|
-
published `code-mower==1.
|
|
60
|
-
[`v1.
|
|
66
|
+
published `code-mower==1.3.0` package, use the documentation from the matching
|
|
67
|
+
[`v1.3.0` tag](https://github.com/codemower-ai/code-mower/tree/v1.3.0) so the
|
|
61
68
|
commands and package stay aligned as development continues.
|
|
62
69
|
|
|
63
70
|
## Design Principles
|
|
@@ -252,7 +259,7 @@ agent report its actual host posture, exact installed version, doctor result,
|
|
|
252
259
|
Board URL, and any owner-only click-list before it mutates the repo.
|
|
253
260
|
|
|
254
261
|
The current package-index announcement entry point is the tagged
|
|
255
|
-
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.
|
|
262
|
+
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.3.0/docs/try-in-10-minutes.md)
|
|
256
263
|
guide. The v1.0 supervised-pilot release includes the native Board, the
|
|
257
264
|
controller dry-run and policy contract, adoption and upgrade hardening from
|
|
258
265
|
recent install rehearsals, package-index release checks, provider-diversity
|
|
@@ -367,7 +374,7 @@ Provider-contract baseline for the next release train:
|
|
|
367
374
|
|
|
368
375
|
For release verification,
|
|
369
376
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
370
|
-
the package-index procedure for `v1.
|
|
377
|
+
the package-index procedure for `v1.3.0` / `code-mower==1.3.0`. The
|
|
371
378
|
GitHub release records the workflow and rehearsal evidence for the exact tag.
|
|
372
379
|
After publication, [Release Qualification](docs/release-qualification.md)
|
|
373
380
|
coordinates provider-specific install and operational checks without treating
|
|
@@ -561,8 +568,8 @@ measurement work.
|
|
|
561
568
|
|
|
562
569
|
## Installation Status
|
|
563
570
|
|
|
564
|
-
The current package-index release baseline is `v1.
|
|
565
|
-
install spec `code-mower==1.
|
|
571
|
+
The current package-index release baseline is `v1.3.0`, with pinned package
|
|
572
|
+
install spec `code-mower==1.3.0`. Release evidence is recorded on the GitHub
|
|
566
573
|
release and in the first-user install rehearsal. The public repository is
|
|
567
574
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
|
|
568
575
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
@@ -676,6 +683,10 @@ first so local work exercises the same package entrypoint users install.
|
|
|
676
683
|
- [v1.1.2 Release Notes](docs/v112-release-notes.md)
|
|
677
684
|
- [v1.2 Release Notes](docs/v12-release-notes.md)
|
|
678
685
|
- [v1.2.1 Release Notes](docs/v121-release-notes.md)
|
|
686
|
+
- [v1.2.2 Release Notes](docs/v122-release-notes.md)
|
|
687
|
+
- [v1.3.0 Release Notes](docs/v130-release-notes.md)
|
|
688
|
+
- [Optional Coworker Setup](docs/context-setup.md)
|
|
689
|
+
- [Context Qualification and Limits](docs/v130-context-qualification.md)
|
|
679
690
|
- [Post-v0.8 Effectiveness Assessment](docs/post-v08-effectiveness-assessment.md)
|
|
680
691
|
- [v1.0.1 Effectiveness Assessment](docs/v101-effectiveness-assessment.md)
|
|
681
692
|
|
|
@@ -15,6 +15,8 @@ The short version:
|
|
|
15
15
|
exposure, or GitHub Actions churn;
|
|
16
16
|
- turn issue text, external docs, and project doctrine into local work orders
|
|
17
17
|
before an agent starts coding;
|
|
18
|
+
- optionally give Claude and Codex the same authorized organizational evidence
|
|
19
|
+
through a private Coworker connection, with fresh review when context changes;
|
|
18
20
|
- generate local reviewer value reports from known-clean and known-blocked PRs;
|
|
19
21
|
and
|
|
20
22
|
- optionally share sanitized metadata with [CodeMower.com](https://codemower.com)
|
|
@@ -26,8 +28,8 @@ Default cloud bundles exclude source code, raw diffs, raw model transcripts,
|
|
|
26
28
|
raw stdout/stderr, auth output, and secrets.
|
|
27
29
|
|
|
28
30
|
Documentation on `main` follows the source on `main`. If you install the
|
|
29
|
-
published `code-mower==1.
|
|
30
|
-
[`v1.
|
|
31
|
+
published `code-mower==1.3.0` package, use the documentation from the matching
|
|
32
|
+
[`v1.3.0` tag](https://github.com/codemower-ai/code-mower/tree/v1.3.0) so the
|
|
31
33
|
commands and package stay aligned as development continues.
|
|
32
34
|
|
|
33
35
|
## Design Principles
|
|
@@ -222,7 +224,7 @@ agent report its actual host posture, exact installed version, doctor result,
|
|
|
222
224
|
Board URL, and any owner-only click-list before it mutates the repo.
|
|
223
225
|
|
|
224
226
|
The current package-index announcement entry point is the tagged
|
|
225
|
-
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.
|
|
227
|
+
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.3.0/docs/try-in-10-minutes.md)
|
|
226
228
|
guide. The v1.0 supervised-pilot release includes the native Board, the
|
|
227
229
|
controller dry-run and policy contract, adoption and upgrade hardening from
|
|
228
230
|
recent install rehearsals, package-index release checks, provider-diversity
|
|
@@ -337,7 +339,7 @@ Provider-contract baseline for the next release train:
|
|
|
337
339
|
|
|
338
340
|
For release verification,
|
|
339
341
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
340
|
-
the package-index procedure for `v1.
|
|
342
|
+
the package-index procedure for `v1.3.0` / `code-mower==1.3.0`. The
|
|
341
343
|
GitHub release records the workflow and rehearsal evidence for the exact tag.
|
|
342
344
|
After publication, [Release Qualification](docs/release-qualification.md)
|
|
343
345
|
coordinates provider-specific install and operational checks without treating
|
|
@@ -531,8 +533,8 @@ measurement work.
|
|
|
531
533
|
|
|
532
534
|
## Installation Status
|
|
533
535
|
|
|
534
|
-
The current package-index release baseline is `v1.
|
|
535
|
-
install spec `code-mower==1.
|
|
536
|
+
The current package-index release baseline is `v1.3.0`, with pinned package
|
|
537
|
+
install spec `code-mower==1.3.0`. Release evidence is recorded on the GitHub
|
|
536
538
|
release and in the first-user install rehearsal. The public repository is
|
|
537
539
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
|
|
538
540
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
@@ -646,6 +648,10 @@ first so local work exercises the same package entrypoint users install.
|
|
|
646
648
|
- [v1.1.2 Release Notes](docs/v112-release-notes.md)
|
|
647
649
|
- [v1.2 Release Notes](docs/v12-release-notes.md)
|
|
648
650
|
- [v1.2.1 Release Notes](docs/v121-release-notes.md)
|
|
651
|
+
- [v1.2.2 Release Notes](docs/v122-release-notes.md)
|
|
652
|
+
- [v1.3.0 Release Notes](docs/v130-release-notes.md)
|
|
653
|
+
- [Optional Coworker Setup](docs/context-setup.md)
|
|
654
|
+
- [Context Qualification and Limits](docs/v130-context-qualification.md)
|
|
649
655
|
- [Post-v0.8 Effectiveness Assessment](docs/post-v08-effectiveness-assessment.md)
|
|
650
656
|
- [v1.0.1 Effectiveness Assessment](docs/v101-effectiveness-assessment.md)
|
|
651
657
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-mower"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Multi-reviewer AI code audit orchestration"
|
|
9
9
|
requires-python = ">=3.12"
|
|
10
10
|
readme = "README.md"
|
|
@@ -29,6 +29,7 @@ Issues = "https://github.com/codemower-ai/code-mower/issues"
|
|
|
29
29
|
Changelog = "https://github.com/codemower-ai/code-mower/blob/main/CHANGELOG.md"
|
|
30
30
|
|
|
31
31
|
[project.optional-dependencies]
|
|
32
|
+
coworker = ["mcp>=2.2.0,<2.3", "httpx2>=2.12,<3", "PyJWT[crypto]>=2.10,<3", "keyring>=25,<26"]
|
|
32
33
|
test = [
|
|
33
34
|
"build>=1.2",
|
|
34
35
|
"pytest>=8.0",
|
|
@@ -25,10 +25,13 @@ import re
|
|
|
25
25
|
if __package__:
|
|
26
26
|
try:
|
|
27
27
|
from . import decisions as code_mower_decisions
|
|
28
|
+
from . import context_review as code_mower_context_review
|
|
28
29
|
except ImportError: # pragma: no cover - copied tools fallback
|
|
29
30
|
import decisions as code_mower_decisions # type: ignore
|
|
31
|
+
import context_review as code_mower_context_review # type: ignore
|
|
30
32
|
else: # pragma: no cover - direct helper execution
|
|
31
33
|
import decisions as code_mower_decisions # type: ignore
|
|
34
|
+
import context_review as code_mower_context_review # type: ignore
|
|
32
35
|
|
|
33
36
|
MIN_ABBREVIATED_SHA_LENGTH = 7
|
|
34
37
|
AUTHOR_EXCLUSION_ENV = "CODE_MOWER_AUTHOR_EXCLUSION_JSON"
|
|
@@ -454,6 +457,7 @@ def latest_current_audit_verdict(
|
|
|
454
457
|
bool,
|
|
455
458
|
],
|
|
456
459
|
decision_authorities: Sequence[str] = (),
|
|
460
|
+
context_required: bool = False,
|
|
457
461
|
) -> str:
|
|
458
462
|
verdict = latest_current_audit_verdict_detail(
|
|
459
463
|
lane,
|
|
@@ -461,6 +465,7 @@ def latest_current_audit_verdict(
|
|
|
461
465
|
head_sha=head_sha,
|
|
462
466
|
trusted_comment_author=trusted_comment_author,
|
|
463
467
|
decision_authorities=decision_authorities,
|
|
468
|
+
context_required=context_required,
|
|
464
469
|
)
|
|
465
470
|
return verdict.verdict if verdict else ""
|
|
466
471
|
|
|
@@ -475,8 +480,16 @@ def latest_current_audit_verdict_detail(
|
|
|
475
480
|
bool,
|
|
476
481
|
],
|
|
477
482
|
decision_authorities: Sequence[str] = (),
|
|
483
|
+
context_required: bool = False,
|
|
478
484
|
) -> AuditVerdict | None:
|
|
479
485
|
verdicts: list[AuditVerdict] = []
|
|
486
|
+
try:
|
|
487
|
+
context_input = code_mower_context_review.latest_input(comments, authorities=decision_authorities)
|
|
488
|
+
except (ValueError, TypeError, RecursionError):
|
|
489
|
+
# A broken latest control declaration cannot expose an older PASS.
|
|
490
|
+
return None
|
|
491
|
+
if context_required and (context_input is None or not context_input['required']):
|
|
492
|
+
return None
|
|
480
493
|
decisions = code_mower_decisions.collect_decision_records_from_comments(
|
|
481
494
|
comments,
|
|
482
495
|
authorities=decision_authorities,
|
|
@@ -492,6 +505,22 @@ def latest_current_audit_verdict_detail(
|
|
|
492
505
|
head_sha=head_sha,
|
|
493
506
|
decisions=decisions,
|
|
494
507
|
)
|
|
508
|
+
failed_context_check = any(marker in body for marker in (
|
|
509
|
+
"<!-- CODE_MOWER_AUDIT_REQUEUE: kind=unknown -->",
|
|
510
|
+
"<!-- CODE_MOWER_AUDIT_REQUEUE: kind=stale -->",
|
|
511
|
+
)) and audit_comment_head_sha(body) == head_sha
|
|
512
|
+
if context_input is not None:
|
|
513
|
+
matches = code_mower_context_review.review_matches(body, context_input, head=head_sha)
|
|
514
|
+
# If the control-comment fetch itself failed, the wrapper cannot
|
|
515
|
+
# name a revision. Its current-head UNKNOWN still invalidates PASS.
|
|
516
|
+
# A verdict explicitly bound to a different revision never does.
|
|
517
|
+
unbound_failure = failed_context_check and code_mower_context_review.REVIEW_MARKER not in body
|
|
518
|
+
if not matches and not unbound_failure:
|
|
519
|
+
continue
|
|
520
|
+
if context_input is not None and failed_context_check:
|
|
521
|
+
# A later failed authorization/input check must supersede an older
|
|
522
|
+
# PASS even when both the code head and selected revision match.
|
|
523
|
+
verdict = "unknown"
|
|
495
524
|
if verdict:
|
|
496
525
|
try:
|
|
497
526
|
comment_id = int(comment.get("id") or 0)
|
|
@@ -25,6 +25,8 @@ from datetime import datetime, timezone
|
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
from typing import Any, Dict, List, Optional, Tuple
|
|
27
27
|
|
|
28
|
+
from code_mower import context_audit, context_delivery, context_review
|
|
29
|
+
|
|
28
30
|
if __package__ in {None, "", "tools"}:
|
|
29
31
|
try:
|
|
30
32
|
from tools import audit_limits as code_mower_audit_limits
|
|
@@ -247,6 +249,8 @@ class ClaudeAuditConfig:
|
|
|
247
249
|
decision_authorities: Tuple[str, ...] = ()
|
|
248
250
|
merge_authority: bool = True
|
|
249
251
|
calibration_badge: str = ""
|
|
252
|
+
context_revision: Optional[str] = None
|
|
253
|
+
context_state_dir: Optional[Path] = None
|
|
250
254
|
|
|
251
255
|
|
|
252
256
|
@dataclass
|
|
@@ -949,6 +953,7 @@ def _review_prompt(
|
|
|
949
953
|
review_doctrine: str = "",
|
|
950
954
|
plan_context_text: str = "",
|
|
951
955
|
decision_registry_text: str = "",
|
|
956
|
+
private_evidence_text: str = "",
|
|
952
957
|
) -> str:
|
|
953
958
|
safe_branch_name = _one_line(branch_name, 200)
|
|
954
959
|
safe_title = _one_line(title, 500)
|
|
@@ -1005,6 +1010,7 @@ Return only the structured JSON object required by the provided schema.
|
|
|
1005
1010
|
{doctrine_block}
|
|
1006
1011
|
{plan_context_block}
|
|
1007
1012
|
{decision_registry_block}
|
|
1013
|
+
{private_evidence_text}
|
|
1008
1014
|
|
|
1009
1015
|
Repository: {repo}
|
|
1010
1016
|
Pull request: #{pr_number}
|
|
@@ -1473,7 +1479,18 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1473
1479
|
final_fixture_reason: Optional[str] = None
|
|
1474
1480
|
unknown_reason = ""
|
|
1475
1481
|
|
|
1476
|
-
|
|
1482
|
+
private_context = context_audit.prepare(
|
|
1483
|
+
repository=repo, pr=pr_number, head=head_sha_start, host="claude",
|
|
1484
|
+
authorities=decision_authorities, revision=config.context_revision,
|
|
1485
|
+
state_dir=config.context_state_dir,
|
|
1486
|
+
repo_path=local_repo, base_ref=config.base_ref,
|
|
1487
|
+
fetch_comments=lambda: fetch_issue_comments(repo, pr_number, token=config.github_token),
|
|
1488
|
+
)
|
|
1489
|
+
|
|
1490
|
+
if private_context is not None and not private_context.ready:
|
|
1491
|
+
unknown_reason = "Selected context input is unavailable; authorize the selected connection and retry"
|
|
1492
|
+
parsed = _unknown_structured_verdict(unknown_reason)
|
|
1493
|
+
elif diff_context.was_truncated:
|
|
1477
1494
|
unknown_reason = _diff_truncation_unknown_reason(diff_context)
|
|
1478
1495
|
parsed = _unknown_structured_verdict(unknown_reason)
|
|
1479
1496
|
print(
|
|
@@ -1534,6 +1551,7 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1534
1551
|
rendered_plan_context.text if rendered_plan_context is not None else ""
|
|
1535
1552
|
),
|
|
1536
1553
|
decision_registry_text=decision_registry_context,
|
|
1554
|
+
private_evidence_text=private_context.text if private_context is not None else "",
|
|
1537
1555
|
)
|
|
1538
1556
|
|
|
1539
1557
|
attempt_prompt = prompt
|
|
@@ -1579,9 +1597,10 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1579
1597
|
config = replace(config, max_budget_usd=raised_budget)
|
|
1580
1598
|
continue
|
|
1581
1599
|
if guardrail_reason and attempt < MAX_CLAUDE_AUDIT_ATTEMPTS:
|
|
1600
|
+
visible_reason = "private context verdict needs validation" if private_context is not None and private_context.private else guardrail_reason
|
|
1582
1601
|
print(
|
|
1583
1602
|
" structured-verdict guardrail rejected Claude output: "
|
|
1584
|
-
f"{
|
|
1603
|
+
f"{visible_reason}; retrying once",
|
|
1585
1604
|
file=sys.stderr,
|
|
1586
1605
|
flush=True,
|
|
1587
1606
|
)
|
|
@@ -1595,10 +1614,14 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1595
1614
|
dt = time.time() - t0
|
|
1596
1615
|
print(f" claude audit completed in {dt:.0f}s", file=sys.stderr, flush=True)
|
|
1597
1616
|
if parsed.mismatch_note:
|
|
1598
|
-
|
|
1617
|
+
note = "private context verdict needs validation" if private_context is not None and private_context.private else parsed.mismatch_note
|
|
1618
|
+
print(f" structured-verdict mismatch: {note}", file=sys.stderr, flush=True)
|
|
1599
1619
|
|
|
1600
1620
|
pr_meta_after = fetch_pull_request(repo, pr_number, token=config.github_token)
|
|
1601
1621
|
head_sha_end = pr_meta_after["head"]["sha"]
|
|
1622
|
+
if private_context is not None and not private_context.finish(head=head_sha_end, prose=parsed.prose):
|
|
1623
|
+
unknown_reason = "Selected context authorization or review input changed; reattach and review again"
|
|
1624
|
+
parsed = _unknown_structured_verdict(unknown_reason)
|
|
1602
1625
|
is_stale = head_sha_start != head_sha_end
|
|
1603
1626
|
actions_run_id = os.environ.get("GITHUB_RUN_ID") or None
|
|
1604
1627
|
claude_cli_reason = unknown_reason or _claude_cli_failure_reason(
|
|
@@ -1642,6 +1665,17 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1642
1665
|
result_verdict = parsed.verdict
|
|
1643
1666
|
trailer = BLOCKED_TRAILER if parsed.verdict == "BLOCKED" else DONE_TRAILER
|
|
1644
1667
|
|
|
1668
|
+
if private_context is not None and private_context.metadata is not None:
|
|
1669
|
+
if private_context.private:
|
|
1670
|
+
comment_body = context_delivery.public_verdict(
|
|
1671
|
+
private_context.delivery, provider="Claude", head=head_sha_start,
|
|
1672
|
+
verdict=result_verdict, counts=[parsed.p0_count, parsed.p1_count, parsed.p2_count, parsed.p3_count],
|
|
1673
|
+
trailer=trailer, actions_run_id=actions_run_id, merge_authority=config.merge_authority,
|
|
1674
|
+
)
|
|
1675
|
+
else:
|
|
1676
|
+
footer = context_review.marker(private_context.metadata, review=True) + "\n" + trailer
|
|
1677
|
+
comment_body = limit_comment_body(comment_body.rsplit(trailer, 1)[0] + footer + "\n", footer, provider_name="Claude")
|
|
1678
|
+
|
|
1645
1679
|
result = ClaudeAuditResult(
|
|
1646
1680
|
repo=repo,
|
|
1647
1681
|
pr_number=pr_number,
|
|
@@ -1656,7 +1690,7 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1656
1690
|
)
|
|
1657
1691
|
|
|
1658
1692
|
if not config.dry_run:
|
|
1659
|
-
if result_verdict == "UNKNOWN":
|
|
1693
|
+
if result_verdict == "UNKNOWN" and not (private_context is not None and private_context.private):
|
|
1660
1694
|
dump_path = _dump_claude_cli_failure(
|
|
1661
1695
|
repo=repo,
|
|
1662
1696
|
pr_number=pr_number,
|
|
@@ -1694,7 +1728,8 @@ def audit_pr(config: ClaudeAuditConfig, repo: str, pr_number: int) -> ClaudeAudi
|
|
|
1694
1728
|
file=sys.stderr,
|
|
1695
1729
|
flush=True,
|
|
1696
1730
|
)
|
|
1697
|
-
|
|
1731
|
+
if not (private_context is not None and private_context.private):
|
|
1732
|
+
_write_claude_raw_output_sidecar(artifact_path, raw_output_attempts)
|
|
1698
1733
|
if quarantine_reason:
|
|
1699
1734
|
print(
|
|
1700
1735
|
" runtime guard quarantined verdict artifact: "
|
|
@@ -1785,6 +1820,8 @@ def _parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
1785
1820
|
),
|
|
1786
1821
|
)
|
|
1787
1822
|
ap.add_argument("--repo-paths", default=os.environ.get("CLAUDE_AUDIT_REPO_PATHS", ""))
|
|
1823
|
+
ap.add_argument("--context-revision", help="Require this explicitly attached private context input revision")
|
|
1824
|
+
ap.add_argument("--context-state-dir", type=Path, help="Private context store outside the repository")
|
|
1788
1825
|
ap.add_argument("--claude-cli-path", default=os.environ.get("CLAUDE_CLI_PATH", DEFAULT_CLAUDE_CLI_PATH))
|
|
1789
1826
|
ap.add_argument("--model", default=os.environ.get("CLAUDE_AUDIT_MODEL", DEFAULT_CLAUDE_MODEL))
|
|
1790
1827
|
ap.add_argument("--max-budget-usd", default=_env_text("CLAUDE_AUDIT_MAX_BUDGET_USD"))
|
|
@@ -1997,6 +2034,8 @@ def main(argv: Optional[List[str]] = None) -> int:
|
|
|
1997
2034
|
prompt_lenses=code_mower_prompts.split_lenses(args.prompt_lenses),
|
|
1998
2035
|
prompt_dir=args.prompt_dir,
|
|
1999
2036
|
include_plan_context=not args.no_plan_context,
|
|
2037
|
+
context_revision=args.context_revision,
|
|
2038
|
+
context_state_dir=args.context_state_dir,
|
|
2000
2039
|
project_context_manifest=args.project_context_manifest,
|
|
2001
2040
|
external_context_manifest=args.external_context_manifest,
|
|
2002
2041
|
max_plan_context_bytes=args.max_plan_context_bytes,
|
|
@@ -68,6 +68,9 @@ Trailer protocol (mirrors Devin/local LLM):
|
|
|
68
68
|
|
|
69
69
|
from __future__ import annotations
|
|
70
70
|
|
|
71
|
+
from code_mower import context_audit, context_delivery, context_review
|
|
72
|
+
from code_mower.context_contract import ContextError
|
|
73
|
+
|
|
71
74
|
import argparse
|
|
72
75
|
import json
|
|
73
76
|
import os
|
|
@@ -288,6 +291,9 @@ class AuditConfig:
|
|
|
288
291
|
# Optional human-facing calibration status. This must never decide merge
|
|
289
292
|
# authority; it only renders as a separate badge line in the comment.
|
|
290
293
|
calibration_badge: str = ""
|
|
294
|
+
context_revision: Optional[str] = None
|
|
295
|
+
context_state_dir: Optional[Path] = None
|
|
296
|
+
private_evidence: str = field(default="", repr=False)
|
|
291
297
|
|
|
292
298
|
|
|
293
299
|
@dataclass
|
|
@@ -1351,12 +1357,15 @@ def run_codex_review(
|
|
|
1351
1357
|
review_path = tmp_dir / "review.txt"
|
|
1352
1358
|
prompt = ""
|
|
1353
1359
|
context_omission_notice = ""
|
|
1354
|
-
if trusted_context.strip():
|
|
1360
|
+
if trusted_context.strip() or config.private_evidence:
|
|
1355
1361
|
wrapper_context = _build_codex_wrapper_review_context(
|
|
1356
1362
|
worktree_path,
|
|
1357
1363
|
config,
|
|
1358
1364
|
)
|
|
1359
1365
|
if wrapper_context.was_truncated:
|
|
1366
|
+
if config.private_evidence:
|
|
1367
|
+
shutil.rmtree(str(tmp_dir), ignore_errors=True)
|
|
1368
|
+
raise ContextError("private evidence cannot be omitted from the review")
|
|
1360
1369
|
context_omission_notice = _codex_context_omission_notice(
|
|
1361
1370
|
diff_bytes=wrapper_context.full_diff_bytes,
|
|
1362
1371
|
hard_limit_bytes=wrapper_context.hard_limit_bytes,
|
|
@@ -1376,6 +1385,7 @@ def run_codex_review(
|
|
|
1376
1385
|
base_ref=config.base_ref,
|
|
1377
1386
|
trusted_context=trusted_context,
|
|
1378
1387
|
review_context=wrapper_context,
|
|
1388
|
+
private_evidence_text=config.private_evidence,
|
|
1379
1389
|
)
|
|
1380
1390
|
env = _build_subprocess_env(None)
|
|
1381
1391
|
if not prompt:
|
|
@@ -1461,6 +1471,7 @@ def _codex_wrapper_review_prompt(
|
|
|
1461
1471
|
base_ref: str,
|
|
1462
1472
|
trusted_context: str,
|
|
1463
1473
|
review_context: _CodexWrapperReviewContext,
|
|
1474
|
+
private_evidence_text: str = "",
|
|
1464
1475
|
) -> str:
|
|
1465
1476
|
nonce = secrets.token_hex(8)
|
|
1466
1477
|
context_begin = f"----- BEGIN TRUSTED AUDIT CONTEXT [{nonce}] -----"
|
|
@@ -1497,6 +1508,8 @@ Trusted Code Mower audit context:
|
|
|
1497
1508
|
{trusted_context.rstrip()}
|
|
1498
1509
|
{context_end}
|
|
1499
1510
|
|
|
1511
|
+
{private_evidence_text}
|
|
1512
|
+
|
|
1500
1513
|
Base ref: {base_ref}
|
|
1501
1514
|
Diff truncation: {truncation_note}
|
|
1502
1515
|
Diff bytes: included {review_context.included_diff_bytes} of at least
|
|
@@ -1863,6 +1876,16 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
1863
1876
|
config.decision_authorities,
|
|
1864
1877
|
trusted_ref=config.base_ref,
|
|
1865
1878
|
)
|
|
1879
|
+
private_context = context_audit.prepare(
|
|
1880
|
+
repository=repo, pr=pr_number, head=head_sha_start, host="codex",
|
|
1881
|
+
authorities=decision_authorities, revision=config.context_revision,
|
|
1882
|
+
state_dir=config.context_state_dir,
|
|
1883
|
+
repo_path=local_repo, base_ref=config.base_ref,
|
|
1884
|
+
fetch_comments=lambda: fetch_issue_comments(repo, pr_number, token=config.github_token),
|
|
1885
|
+
)
|
|
1886
|
+
private_input_unavailable = private_context is not None and not private_context.ready
|
|
1887
|
+
if private_context is not None:
|
|
1888
|
+
config = replace(config, private_evidence=private_context.text)
|
|
1866
1889
|
review_context_summary = "review context diagnostics unavailable"
|
|
1867
1890
|
review_context: ReviewContextDiagnostics | None = None
|
|
1868
1891
|
context_notice = ""
|
|
@@ -2027,7 +2050,7 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2027
2050
|
)
|
|
2028
2051
|
effective_trusted_context = trusted_audit_context
|
|
2029
2052
|
if (
|
|
2030
|
-
trusted_audit_context.strip()
|
|
2053
|
+
(trusted_audit_context.strip() or config.private_evidence)
|
|
2031
2054
|
and review_context is not None
|
|
2032
2055
|
and review_context.was_truncated
|
|
2033
2056
|
):
|
|
@@ -2036,23 +2059,33 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2036
2059
|
hard_limit_bytes=review_context.hard_limit_bytes,
|
|
2037
2060
|
)
|
|
2038
2061
|
effective_trusted_context = ""
|
|
2062
|
+
if config.private_evidence:
|
|
2063
|
+
private_input_unavailable = True
|
|
2039
2064
|
print(
|
|
2040
|
-
f" {context_notice};
|
|
2065
|
+
f" {context_notice}; " + ("selected context cannot be omitted; emitting UNKNOWN"
|
|
2066
|
+
if config.private_evidence else "using context-free codex review --base"),
|
|
2041
2067
|
file=sys.stderr,
|
|
2042
2068
|
flush=True,
|
|
2043
2069
|
)
|
|
2044
2070
|
t0 = time.time()
|
|
2045
|
-
review_text, review_stderr =
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2071
|
+
review_text, review_stderr = "", ""
|
|
2072
|
+
if not private_input_unavailable:
|
|
2073
|
+
try:
|
|
2074
|
+
review_text, review_stderr = run_codex_review(
|
|
2075
|
+
config,
|
|
2076
|
+
worktree_path,
|
|
2077
|
+
effective_trusted_context,
|
|
2078
|
+
)
|
|
2079
|
+
except ContextError:
|
|
2080
|
+
private_input_unavailable = True
|
|
2050
2081
|
if not context_notice:
|
|
2051
2082
|
context_notice = _codex_context_omission_notice_from_diagnostics(
|
|
2052
2083
|
review_stderr
|
|
2053
2084
|
)
|
|
2054
2085
|
if context_notice:
|
|
2055
2086
|
effective_trusted_context = ""
|
|
2087
|
+
if config.private_evidence:
|
|
2088
|
+
private_input_unavailable = True
|
|
2056
2089
|
dt = time.time() - t0
|
|
2057
2090
|
print(f" codex review completed in {dt:.0f}s", file=sys.stderr, flush=True)
|
|
2058
2091
|
finally:
|
|
@@ -2063,11 +2096,15 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2063
2096
|
# may receive the same trusted context only to apply transport policy
|
|
2064
2097
|
# to findings already present in the review prose.
|
|
2065
2098
|
t0 = time.time()
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2099
|
+
if private_input_unavailable:
|
|
2100
|
+
parsed = _unknown_structured_verdict("Selected context input could not be delivered; reattach and review again")
|
|
2101
|
+
structure_stdout, structure_stderr = "", ""
|
|
2102
|
+
else:
|
|
2103
|
+
parsed, structure_stdout, structure_stderr = run_codex_verdict_structuring(
|
|
2104
|
+
config,
|
|
2105
|
+
review_text,
|
|
2106
|
+
effective_trusted_context,
|
|
2107
|
+
)
|
|
2071
2108
|
dt = time.time() - t0
|
|
2072
2109
|
print(
|
|
2073
2110
|
f" codex verdict structuring completed in {dt:.0f}s",
|
|
@@ -2075,8 +2112,9 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2075
2112
|
flush=True,
|
|
2076
2113
|
)
|
|
2077
2114
|
if parsed.mismatch_note:
|
|
2115
|
+
note = "private context verdict needs validation" if private_context is not None and private_context.private else parsed.mismatch_note
|
|
2078
2116
|
print(
|
|
2079
|
-
f" structured-verdict mismatch: {
|
|
2117
|
+
f" structured-verdict mismatch: {note}",
|
|
2080
2118
|
file=sys.stderr,
|
|
2081
2119
|
flush=True,
|
|
2082
2120
|
)
|
|
@@ -2097,6 +2135,8 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2097
2135
|
# the verdict applies to a no-longer-current SHA — requeue.
|
|
2098
2136
|
pr_meta_after = fetch_pull_request(repo, pr_number, token=config.github_token)
|
|
2099
2137
|
head_sha_end = pr_meta_after["head"]["sha"]
|
|
2138
|
+
if private_context is not None and not private_context.finish(head=head_sha_end, prose=parsed.prose):
|
|
2139
|
+
parsed = _unknown_structured_verdict("Selected context authorization or review input changed; reattach and review again")
|
|
2100
2140
|
is_stale = head_sha_start != head_sha_end
|
|
2101
2141
|
actions_run_id = os.environ.get("GITHUB_RUN_ID") or None
|
|
2102
2142
|
|
|
@@ -2125,7 +2165,7 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2125
2165
|
# without this dump there's no way to diagnose "real structured
|
|
2126
2166
|
# output drift or one-shot Codex CLI flake?" after the fact.
|
|
2127
2167
|
# Best-effort: a logging failure must not interrupt the audit.
|
|
2128
|
-
dump_path = dump_cli_failure(
|
|
2168
|
+
dump_path = None if private_context is not None and private_context.private else dump_cli_failure(
|
|
2129
2169
|
repo=repo,
|
|
2130
2170
|
pr_number=pr_number,
|
|
2131
2171
|
head_sha=head_sha_start,
|
|
@@ -2166,6 +2206,17 @@ def audit_pr(config: AuditConfig, repo: str, pr_number: int) -> AuditResult:
|
|
|
2166
2206
|
result_verdict = parsed.verdict
|
|
2167
2207
|
trailer = BLOCKED_TRAILER if parsed.verdict == "BLOCKED" else DONE_TRAILER
|
|
2168
2208
|
|
|
2209
|
+
if private_context is not None and private_context.metadata is not None:
|
|
2210
|
+
if private_context.private:
|
|
2211
|
+
comment_body = context_delivery.public_verdict(
|
|
2212
|
+
private_context.delivery, provider="Codex", head=head_sha_start,
|
|
2213
|
+
verdict=result_verdict, counts=[parsed.p0_count, parsed.p1_count, parsed.p2_count, parsed.p3_count],
|
|
2214
|
+
trailer=trailer, actions_run_id=actions_run_id, merge_authority=config.merge_authority,
|
|
2215
|
+
)
|
|
2216
|
+
else:
|
|
2217
|
+
footer = context_review.marker(private_context.metadata, review=True) + "\n" + trailer
|
|
2218
|
+
comment_body = limit_comment_body(comment_body.rsplit(trailer, 1)[0] + footer + "\n", footer, provider_name="Codex")
|
|
2219
|
+
|
|
2169
2220
|
result = AuditResult(
|
|
2170
2221
|
repo=repo,
|
|
2171
2222
|
pr_number=pr_number,
|
|
@@ -2256,6 +2307,8 @@ def _parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
2256
2307
|
)
|
|
2257
2308
|
ap.add_argument("--repo", help="owner/repo, e.g. owner/repo")
|
|
2258
2309
|
ap.add_argument("--pr", type=int, help="PR number")
|
|
2310
|
+
ap.add_argument("--context-revision", help="Require this explicitly attached private context input revision")
|
|
2311
|
+
ap.add_argument("--context-state-dir", type=Path, help="Private context store outside the repository")
|
|
2259
2312
|
ap.add_argument(
|
|
2260
2313
|
"--repost-verdict-artifact",
|
|
2261
2314
|
type=Path,
|
|
@@ -2602,6 +2655,8 @@ def main(argv: Optional[List[str]] = None) -> int:
|
|
|
2602
2655
|
venv_path=explicit_venv,
|
|
2603
2656
|
disable_venv=disable_venv,
|
|
2604
2657
|
include_plan_context=not args.no_plan_context,
|
|
2658
|
+
context_revision=args.context_revision,
|
|
2659
|
+
context_state_dir=args.context_state_dir,
|
|
2605
2660
|
project_context_manifest=args.project_context_manifest,
|
|
2606
2661
|
external_context_manifest=args.external_context_manifest,
|
|
2607
2662
|
max_plan_context_bytes=args.max_plan_context_bytes,
|