code-mower 0.9.1b1__tar.gz → 0.9.3b1__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.9.1b1 → code_mower-0.9.3b1}/PKG-INFO +13 -11
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/README.md +12 -10
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/pyproject.toml +1 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/__init__.py +1 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/board.py +29 -2
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/board_store.py +4 -2
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cli.py +0 -3
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/__init__.py +5 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/adoption.py +36 -5
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_human_token.py +4 -6
- code_mower-0.9.3b1/src/code_mower/doctor_checks/github_trusted_authors.py +72 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_review_hygiene.py +22 -10
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/providers.py +2 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/runner.py +19 -6
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_status.py +72 -20
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/migration.py +139 -6
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package_manifest.py +0 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/PKG-INFO +13 -11
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/SOURCES.txt +0 -2
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/builder-provenance.yml.j2 +1 -1
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_board.py +15 -2
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_github_checks.py +42 -5
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_provider_review_hygiene.py +22 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_registry.py +84 -9
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_lane_status.py +105 -13
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_release_hygiene.py +212 -38
- code_mower-0.9.1b1/src/code_mower/doctor_checks/github_trusted_authors.py +0 -38
- code_mower-0.9.1b1/src/code_mower/observe.py +0 -324
- code_mower-0.9.1b1/tests/test_observe.py +0 -111
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/CODE_OF_CONDUCT.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/LICENSE +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/MANIFEST.in +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/NOTICE +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/SUPPORT.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/requirements/requirements.txt +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/setup.cfg +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/_base.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/cursor_bugbot.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/gitar.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/greptile.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/adapters/qodo.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/antigravity_sdk_probe.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/audit_handoff_log.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/audit_labeler_lib.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/audit_limits.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/audit_progress.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/blind_review_artifacts.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/blind_review_coordinator.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/bootstrap.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/builder_experiment.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/builder_runs.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/arms.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/auto_discovery.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/commands.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/context_inputs.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/corpus.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/effect_report.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/evidence.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/evidence_report.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/identity.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/metrics.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/overlap.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/planning.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/policy.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/results.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/run_results.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/run_status.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/runner.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/truth.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/calibration/value_report.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/checks.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/claude_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/claude_cli_bounce.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/claude_cli_environment.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/clear_stale.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/bundle.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/doctor.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/dogfood.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/endpoints.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/errors.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/events.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/export.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/git_metadata.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/manifest.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/operations.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/reports.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/setup.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/tokens.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/cloud_client/upload.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/code_mower_calibration.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/code_mower_context_packs.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/code_mower_merge.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/code_mower_telemetry.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/codex_audit_env_preflight.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/codex_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/codex_audit_schema_smoke.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/codex_audit_verdict.schema.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/config.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/decisions.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/audit_limits.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/cloud.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/common.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_api.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_branch.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_config.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_provider.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_repo.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/groups.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/models.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/output.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/presets.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/privacy.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_env.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_local_audit_setup.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_probe.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/registry.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/runtime.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/self_hosted_runner.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/gate_health.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/gemini_cli_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/git_identity.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/grok_build_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/hermes_cli_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/init.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/aider.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/claude.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/codex.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/devin.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/gemini_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/grok_build.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/hermes_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/lane_configs/local_llm.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/local_llm_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/local_llm_bakeoff.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/local_llm_calibration.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/local_llm_profiles.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/migration_install.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/migration_mirror.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/migration_readiness.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/migration_rehearsal.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/next_steps.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package_content.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package_paths.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package_rendering.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/package_static.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/plan_context.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/prompts.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_registry.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/comments.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/exit_codes.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/git.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/github_auth.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/github_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/pr_worktree.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/process.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/repo_paths.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/text_schema.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/provider_runners/workspace.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/providers/__init__.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/providers/local_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/providers/provenance.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/release_readiness.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/reviewer_metrics.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/reviewer_spend.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/saas_reviewer_labeler.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/secrets.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/builder-experiment.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/calibration-corpus.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/code-mower.example.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/context-packs.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/operability.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/plan-conformance.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/README.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/claude.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/codex.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/cursor.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/generic.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/lanes/run_mac_lane.sh +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/code_mower +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/product-support/status_report.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/providers.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/code-mower-gate.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/dispatch-lanes.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/lane-mac-runner.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/needs-owner-notify.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/templates/workflows/weekly-status.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/trailer_comment_labeler.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/versioning.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/work_orders.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/workflow_actionlint.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/dependency_links.txt +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/entry_points.txt +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/requires.txt +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower.egg-info/top_level.txt +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/builder-experiment.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/calibration-corpus.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/code-mower.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/context-packs.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/cursor/BUGBOT.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/README.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/claude.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/codex.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/cursor.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/generic.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/lanes/run_mac_lane.sh +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/acp_bridge.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/aider.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/antigravity_cli.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/claude_audit.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/claude_review.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/coderabbit_cli.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/codex.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/cursor_bugbot.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/devin.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/gemini_cli.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/gitar.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/greptile.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/hermes_cli.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/local_llm.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers/qodo.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/providers.yml +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/code-mower-agent-pr-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/code-mower-fix-round-dispatch.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/code-mower-gate-health.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/code-mower-gate.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/dispatch-lanes.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/lane-mac-runner.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/self-hosted-local-audit.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_antigravity_sdk_probe.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_audit_comment_posture.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_audit_limits.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_builder_experiment.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_builder_identity.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_builder_runs.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_calibration_effect_report.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_calibration_truth.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_checks.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_claude_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_claude_cli_bounce.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_clear_stale.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_cloud_client.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_cloud_git_metadata.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_cloud_manifest.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_cloud_reports.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_codex_audit_env_preflight.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_codex_audit_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_decision_audit_integration.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_decisions.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_actions_cost_summary.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_actions_failure_selection.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_boundaries.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_output.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_privacy.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_provider_env_required.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_provider_env_tokens.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_provider_local_audit_setup.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_provider_probe.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_runtime.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_doctor_self_hosted_runner.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_gate_health.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_init_actionlint.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_init_build_loop.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_local_llm_github_helpers.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_migration_setup_drift.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_plan_context.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_prompts.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_fixture_contracts.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_local_cli.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_comments.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_git.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_github_pr.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_pr_worktree.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_process.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_repo_paths.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_text_schema.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_provider_runners_workspace.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_reviewer_metrics_core.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_reviewer_spend.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/tests/test_trailer_comment_labeler.py +0 -0
- {code_mower-0.9.1b1 → code_mower-0.9.3b1}/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.9.
|
|
3
|
+
Version: 0.9.3b1
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -113,8 +113,9 @@ Plain `board serve` is read-only. If the default Board port is busy, the CLI
|
|
|
113
113
|
uses a nearby free loopback port and prints the URL; an explicit `--port` stays
|
|
114
114
|
strict and reports a friendly conflict. To build local history while the browser
|
|
115
115
|
view is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
|
|
116
|
-
records at most one snapshot every 60 seconds by default.
|
|
117
|
-
|
|
116
|
+
records at most one snapshot every 60 seconds by default. The Board header shows
|
|
117
|
+
the Code Mower version serving the page and flags when a restart is needed after
|
|
118
|
+
an upgrade. To append one snapshot without serving the browser view, run
|
|
118
119
|
`code-mower board record --repo OWNER/REPO` from the repository checkout; it
|
|
119
120
|
writes metadata-only snapshots to `.code-mower/board/events.jsonl` with default
|
|
120
121
|
14-day and 500-event retention. `code-mower board events` prints recent stored
|
|
@@ -169,12 +170,13 @@ after reinstalling, especially when switching between pipx and uv.
|
|
|
169
170
|
| C. Builder experiment | You want to compare authoring loops before trusting them broadly. | Use a work order or experiment spec, run `code-mower builder-experiment run` around an explicit command, then review the source-free `authoringRun` artifact and normal audit evidence. | [Builder Experiments](docs/builder-experiments.md) |
|
|
170
171
|
|
|
171
172
|
The current package-index announcement entry point is the tagged
|
|
172
|
-
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.
|
|
173
|
+
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.3-beta.1/docs/try-in-10-minutes.md)
|
|
173
174
|
guide. The v0.9 beta includes the completed native Board work plus the adoption
|
|
174
|
-
and upgrade hardening from recent install rehearsals; v0.9.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
and upgrade hardening from recent install rehearsals; v0.9.3 keeps the path
|
|
176
|
+
smooth by clarifying starter-package diagnostics, surfacing richer top-level
|
|
177
|
+
lane status detail, showing Board version drift, and reporting standalone pin
|
|
178
|
+
drift during existing-repo upgrades. Package-only users can start from the
|
|
179
|
+
public package rather than a source checkout.
|
|
178
180
|
|
|
179
181
|
## What Calibration Does And Does Not Prove
|
|
180
182
|
|
|
@@ -205,7 +207,7 @@ Provider-contract baseline for the next release train:
|
|
|
205
207
|
|
|
206
208
|
For release verification,
|
|
207
209
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
208
|
-
the package-index procedure for `v0.9.
|
|
210
|
+
the package-index procedure for `v0.9.3-beta.1` / `code-mower==0.9.3b1`. The
|
|
209
211
|
GitHub release records the workflow and rehearsal evidence for the exact tag.
|
|
210
212
|
|
|
211
213
|
## Optional: Plan Before Coding
|
|
@@ -391,8 +393,8 @@ measurement work.
|
|
|
391
393
|
|
|
392
394
|
## Installation Status
|
|
393
395
|
|
|
394
|
-
The current package-index beta baseline is `v0.9.
|
|
395
|
-
install spec `code-mower==0.9.
|
|
396
|
+
The current package-index beta baseline is `v0.9.3-beta.1`, with pinned package
|
|
397
|
+
install spec `code-mower==0.9.3b1`. Release evidence is recorded on the GitHub
|
|
396
398
|
release and in the first-user install rehearsal. The public repository is
|
|
397
399
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
|
|
398
400
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
@@ -96,8 +96,9 @@ Plain `board serve` is read-only. If the default Board port is busy, the CLI
|
|
|
96
96
|
uses a nearby free loopback port and prints the URL; an explicit `--port` stays
|
|
97
97
|
strict and reports a friendly conflict. To build local history while the browser
|
|
98
98
|
view is open, run `code-mower board serve --repo OWNER/REPO --record-events`; it
|
|
99
|
-
records at most one snapshot every 60 seconds by default.
|
|
100
|
-
|
|
99
|
+
records at most one snapshot every 60 seconds by default. The Board header shows
|
|
100
|
+
the Code Mower version serving the page and flags when a restart is needed after
|
|
101
|
+
an upgrade. To append one snapshot without serving the browser view, run
|
|
101
102
|
`code-mower board record --repo OWNER/REPO` from the repository checkout; it
|
|
102
103
|
writes metadata-only snapshots to `.code-mower/board/events.jsonl` with default
|
|
103
104
|
14-day and 500-event retention. `code-mower board events` prints recent stored
|
|
@@ -152,12 +153,13 @@ after reinstalling, especially when switching between pipx and uv.
|
|
|
152
153
|
| C. Builder experiment | You want to compare authoring loops before trusting them broadly. | Use a work order or experiment spec, run `code-mower builder-experiment run` around an explicit command, then review the source-free `authoringRun` artifact and normal audit evidence. | [Builder Experiments](docs/builder-experiments.md) |
|
|
153
154
|
|
|
154
155
|
The current package-index announcement entry point is the tagged
|
|
155
|
-
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.
|
|
156
|
+
[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v0.9.3-beta.1/docs/try-in-10-minutes.md)
|
|
156
157
|
guide. The v0.9 beta includes the completed native Board work plus the adoption
|
|
157
|
-
and upgrade hardening from recent install rehearsals; v0.9.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
and upgrade hardening from recent install rehearsals; v0.9.3 keeps the path
|
|
159
|
+
smooth by clarifying starter-package diagnostics, surfacing richer top-level
|
|
160
|
+
lane status detail, showing Board version drift, and reporting standalone pin
|
|
161
|
+
drift during existing-repo upgrades. Package-only users can start from the
|
|
162
|
+
public package rather than a source checkout.
|
|
161
163
|
|
|
162
164
|
## What Calibration Does And Does Not Prove
|
|
163
165
|
|
|
@@ -188,7 +190,7 @@ Provider-contract baseline for the next release train:
|
|
|
188
190
|
|
|
189
191
|
For release verification,
|
|
190
192
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
191
|
-
the package-index procedure for `v0.9.
|
|
193
|
+
the package-index procedure for `v0.9.3-beta.1` / `code-mower==0.9.3b1`. The
|
|
192
194
|
GitHub release records the workflow and rehearsal evidence for the exact tag.
|
|
193
195
|
|
|
194
196
|
## Optional: Plan Before Coding
|
|
@@ -374,8 +376,8 @@ measurement work.
|
|
|
374
376
|
|
|
375
377
|
## Installation Status
|
|
376
378
|
|
|
377
|
-
The current package-index beta baseline is `v0.9.
|
|
378
|
-
install spec `code-mower==0.9.
|
|
379
|
+
The current package-index beta baseline is `v0.9.3-beta.1`, with pinned package
|
|
380
|
+
install spec `code-mower==0.9.3b1`. Release evidence is recorded on the GitHub
|
|
379
381
|
release and in the first-user install rehearsal. The public repository is
|
|
380
382
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and
|
|
381
383
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
@@ -15,11 +15,13 @@ from dataclasses import dataclass
|
|
|
15
15
|
from datetime import UTC, datetime
|
|
16
16
|
from http import HTTPStatus
|
|
17
17
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
18
|
+
from importlib import metadata
|
|
18
19
|
from pathlib import Path
|
|
19
20
|
from threading import Lock
|
|
20
21
|
from typing import Any
|
|
21
22
|
from urllib.parse import urlparse
|
|
22
23
|
|
|
24
|
+
from . import __version__ as CODE_MOWER_VERSION
|
|
23
25
|
from . import board_store
|
|
24
26
|
from . import lane_status
|
|
25
27
|
from . import reviewer_spend
|
|
@@ -120,6 +122,22 @@ def _candidate_ports(config: BoardConfig) -> list[int]:
|
|
|
120
122
|
return list(range(config.port, last_port + 1))
|
|
121
123
|
|
|
122
124
|
|
|
125
|
+
def _installed_package_version() -> str:
|
|
126
|
+
try:
|
|
127
|
+
return metadata.version("code-mower")
|
|
128
|
+
except metadata.PackageNotFoundError:
|
|
129
|
+
return ""
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def board_version_payload() -> dict[str, Any]:
|
|
133
|
+
installed_version = _installed_package_version()
|
|
134
|
+
return {
|
|
135
|
+
"serving_version": CODE_MOWER_VERSION,
|
|
136
|
+
"installed_version": installed_version,
|
|
137
|
+
"restart_recommended": bool(installed_version and installed_version != CODE_MOWER_VERSION),
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
123
141
|
def _explicit_port_conflict_message(host: str, port: int) -> str:
|
|
124
142
|
suggestions = list(range(port + 1, min(65535, port + 3) + 1))
|
|
125
143
|
suggestion_text = f" such as {', '.join(str(candidate) for candidate in suggestions)}" if suggestions else ""
|
|
@@ -171,6 +189,7 @@ def status_payload(
|
|
|
171
189
|
payload["board"] = {
|
|
172
190
|
"schema": "code_mower.board.v1",
|
|
173
191
|
"mode": "local_recording" if config.record_events else "local_read_only",
|
|
192
|
+
"version": board_version_payload(),
|
|
174
193
|
"refresh_seconds": config.refresh_seconds,
|
|
175
194
|
"local_paths": "shown" if config.show_local_paths else "redacted",
|
|
176
195
|
"recording": {
|
|
@@ -628,7 +647,7 @@ def render_board_html(config: BoardConfig) -> str:
|
|
|
628
647
|
</head>
|
|
629
648
|
<body>
|
|
630
649
|
<header>
|
|
631
|
-
<div><h1>Code Mower Board</h1><div class="muted" id="repo"></div></div>
|
|
650
|
+
<div><h1>Code Mower Board</h1><div class="muted" id="repo"></div><div class="muted" id="version"></div></div>
|
|
632
651
|
<div class="muted" id="generated">Loading...</div>
|
|
633
652
|
</header>
|
|
634
653
|
<main>
|
|
@@ -671,6 +690,12 @@ def render_board_html(config: BoardConfig) -> str:
|
|
|
671
690
|
}}
|
|
672
691
|
function render(data) {{
|
|
673
692
|
document.getElementById("repo").textContent = REPO;
|
|
693
|
+
const version = data.board?.version || {{}};
|
|
694
|
+
const servingVersion = version.serving_version || "unknown";
|
|
695
|
+
const installedVersion = version.installed_version || servingVersion;
|
|
696
|
+
document.getElementById("version").textContent = version.restart_recommended
|
|
697
|
+
? `serving ${{servingVersion}}; installed ${{installedVersion}} available after restart`
|
|
698
|
+
: `serving ${{servingVersion}}`;
|
|
674
699
|
document.getElementById("generated").innerHTML = data.generated_at ? `Generated ${{localTime(data.generated_at)}}` : "Loading...";
|
|
675
700
|
const prs = data.remote?.pull_requests || [];
|
|
676
701
|
const runs = data.remote?.workflow_runs || [];
|
|
@@ -683,6 +708,7 @@ def render_board_html(config: BoardConfig) -> str:
|
|
|
683
708
|
const spendGroups = spend.groups || [];
|
|
684
709
|
put("summary", [
|
|
685
710
|
`<div class="metric"><span class="muted">Next action</span><b>${{esc(data.next_action || "inspect")}}</b></div>`,
|
|
711
|
+
data.next_detail ? `<div class="metric"><span class="muted">Detail</span><b>${{esc(data.next_detail)}}</b></div>` : "",
|
|
686
712
|
`<div class="metric"><span class="muted">GitHub</span><b class="${{data.remote?.available ? "ok" : "warn"}}">${{data.remote?.available ? "available" : "unavailable"}}</b></div>`,
|
|
687
713
|
`<div class="metric"><span class="muted">Open PRs</span><b>${{prs.length}}</b></div>`,
|
|
688
714
|
`<div class="metric"><span class="muted">Owner queue</span><b class="${{ownerQueue.length ? "warn" : "ok"}}">${{ownerQueue.length}}</b></div>`,
|
|
@@ -697,6 +723,7 @@ def render_board_html(config: BoardConfig) -> str:
|
|
|
697
723
|
<div>labels: ${{labels(pr.labels)}}</div>
|
|
698
724
|
<div>checks: ${{checks(pr.checks)}}</div>
|
|
699
725
|
<div>next: <b>${{esc(pr.next_action)}}</b></div>
|
|
726
|
+
${{pr.next_detail ? `<div class="muted">${{esc(pr.next_detail)}}</div>` : ""}}
|
|
700
727
|
</div>`).join("") : empty("No open pull requests."));
|
|
701
728
|
put("alerts", alerts.length ? alerts.map(a => `<div class="row"><b class="warn">${{esc(a.kind)}}</b> ${{esc(a.message)}}</div>`).join("") : empty("No gate alerts."));
|
|
702
729
|
put("runs", runs.length ? runs.slice(0, 8).map(run => `<div class="row"><div class="line"><a href="${{esc(href(run.url))}}">${{esc(run.workflow || "workflow")}}</a>${{pill(run.conclusion || run.status || "unknown")}}</div><div class="muted">${{esc(run.branch)}}${{run.updated_at ? ` updated ${{localTime(run.updated_at)}}` : ""}}</div></div>`).join("") : empty("No recent Code Mower workflow runs."));
|
|
@@ -707,7 +734,7 @@ def render_board_html(config: BoardConfig) -> str:
|
|
|
707
734
|
spend.filtered_rows ? `<div class="row muted">Filtered ${{esc(spend.filtered_rows)}} spend row(s) from other repos.</div>` : ""
|
|
708
735
|
].filter(Boolean);
|
|
709
736
|
put("spend", spendRows.length ? spendRows.join("") : empty(spend.message || "No reviewer spend rows for this repo yet."));
|
|
710
|
-
const boards = data.
|
|
737
|
+
const boards = data.local_boards?.boards || [];
|
|
711
738
|
const procs = data.local_processes?.processes || [];
|
|
712
739
|
put("local", [...boards.map(b => `<div class="row">board localhost:${{esc(b.port)}} pid=${{esc(b.pid)}} cwd=<code>${{esc(b.cwd || "")}}</code></div>`), ...procs.slice(0, 8).map(p => `<div class="row">${{esc(p.provider)}} pid=${{esc(p.pid)}} cwd=<code>${{esc(p.cwd || "")}}</code></div>`)].join("") || empty("No local boards or lane processes visible."));
|
|
713
740
|
}}
|
|
@@ -83,14 +83,16 @@ def _redact_local_paths(value: Any) -> Any:
|
|
|
83
83
|
|
|
84
84
|
def _snapshot_summary(snapshot: Mapping[str, Any]) -> dict[str, Any]:
|
|
85
85
|
remote = snapshot.get("remote") if isinstance(snapshot.get("remote"), dict) else {}
|
|
86
|
-
|
|
86
|
+
local_boards = (
|
|
87
|
+
snapshot.get("local_boards") if isinstance(snapshot.get("local_boards"), dict) else {}
|
|
88
|
+
)
|
|
87
89
|
local_processes = (
|
|
88
90
|
snapshot.get("local_processes") if isinstance(snapshot.get("local_processes"), dict) else {}
|
|
89
91
|
)
|
|
90
92
|
pull_requests = remote.get("pull_requests") if isinstance(remote.get("pull_requests"), list) else []
|
|
91
93
|
gate_health = remote.get("gate_health") if isinstance(remote.get("gate_health"), dict) else {}
|
|
92
94
|
gate_alerts = gate_health.get("alerts") if isinstance(gate_health.get("alerts"), list) else []
|
|
93
|
-
boards =
|
|
95
|
+
boards = local_boards.get("boards") if isinstance(local_boards.get("boards"), list) else []
|
|
94
96
|
processes = (
|
|
95
97
|
local_processes.get("processes")
|
|
96
98
|
if isinstance(local_processes.get("processes"), list)
|
|
@@ -71,7 +71,6 @@ from . import local_llm_calibration
|
|
|
71
71
|
from . import local_llm_profiles
|
|
72
72
|
from . import migration as code_mower_migration
|
|
73
73
|
from . import next_steps as code_mower_next_steps
|
|
74
|
-
from . import observe as code_mower_observe
|
|
75
74
|
from . import package as code_mower_package
|
|
76
75
|
from . import prompts as code_mower_prompts
|
|
77
76
|
from . import reviewer_metrics
|
|
@@ -456,7 +455,6 @@ COMMAND_DESCRIPTIONS: dict[str, str] = {
|
|
|
456
455
|
"migration": "Rehearse standalone package and wrapper migration paths.",
|
|
457
456
|
"merge-plan": "Inspect merge-readiness signals and lane labels.",
|
|
458
457
|
"next-steps": "Print the recommended next actions after setup.",
|
|
459
|
-
"observe": "Run legacy optional local observability companions.",
|
|
460
458
|
"package": "Build or inspect package extraction artifacts.",
|
|
461
459
|
"plan": "Create local issue-derived planning artifacts.",
|
|
462
460
|
"project-context": "Create editable local project-context doctrine docs.",
|
|
@@ -596,7 +594,6 @@ COMMAND_HANDLERS: dict[str, CommandHandler] = {
|
|
|
596
594
|
"migration": code_mower_migration.main,
|
|
597
595
|
"merge-plan": code_mower_merge.main,
|
|
598
596
|
"next-steps": code_mower_next_steps.main,
|
|
599
|
-
"observe": code_mower_observe.main,
|
|
600
597
|
"package": _package_main,
|
|
601
598
|
"plan": code_mower_work_orders.plan_main,
|
|
602
599
|
"project-context": code_mower_work_orders.project_context_main,
|
|
@@ -32,7 +32,10 @@ from .github_human_token import (
|
|
|
32
32
|
human_automation_token_config,
|
|
33
33
|
human_automation_token_required,
|
|
34
34
|
)
|
|
35
|
-
from .github_trusted_authors import
|
|
35
|
+
from .github_trusted_authors import (
|
|
36
|
+
trusted_author_variable_probe,
|
|
37
|
+
trusted_author_variable_statuses,
|
|
38
|
+
)
|
|
36
39
|
from .groups import GROUP_LABELS, doctor_check_group_id
|
|
37
40
|
from .models import (
|
|
38
41
|
STATUS_FAIL,
|
|
@@ -113,6 +116,7 @@ __all__ = [
|
|
|
113
116
|
"check_macos_runner_launchagent",
|
|
114
117
|
"check_github_setup",
|
|
115
118
|
"check_human_automation_token",
|
|
119
|
+
"trusted_author_variable_probe",
|
|
116
120
|
"trusted_author_variable_statuses",
|
|
117
121
|
"check_repository_posture",
|
|
118
122
|
"check_lane_runtime",
|
|
@@ -170,7 +170,7 @@ def check_adoption_posture_guidance(
|
|
|
170
170
|
name="doctor.adoption.posture_hint",
|
|
171
171
|
status=STATUS_WARN,
|
|
172
172
|
message=(
|
|
173
|
-
"default reviewer-gate posture
|
|
173
|
+
"default reviewer-gate posture checks local reviewer CLIs on this host"
|
|
174
174
|
),
|
|
175
175
|
detail={
|
|
176
176
|
"adoption_posture": adoption_posture,
|
|
@@ -186,9 +186,12 @@ def check_adoption_posture_guidance(
|
|
|
186
186
|
],
|
|
187
187
|
},
|
|
188
188
|
remediation=(
|
|
189
|
-
"If this host only coordinates
|
|
190
|
-
"
|
|
191
|
-
"
|
|
189
|
+
"If this host only coordinates work, rerun "
|
|
190
|
+
"`code-mower doctor --adoption --orchestrator-only --repo OWNER/REPO`. "
|
|
191
|
+
"If it observes hosted builder lanes, rerun "
|
|
192
|
+
"`code-mower doctor --adoption --hosted-builders --repo OWNER/REPO`. "
|
|
193
|
+
"Only keep the default reviewer-gate posture on machines that "
|
|
194
|
+
"run local reviewer CLIs."
|
|
192
195
|
),
|
|
193
196
|
),
|
|
194
197
|
)
|
|
@@ -205,6 +208,7 @@ def check_adoption_setup(
|
|
|
205
208
|
config_source: str = "",
|
|
206
209
|
repo_root: Path | None = None,
|
|
207
210
|
trusted_author_variables: Mapping[str, str] | None = None,
|
|
211
|
+
trusted_author_variable_errors: Mapping[str, Any] | None = None,
|
|
208
212
|
) -> tuple[DoctorCheck, ...]:
|
|
209
213
|
"""Return first-run adoption posture checks."""
|
|
210
214
|
|
|
@@ -371,10 +375,16 @@ def check_adoption_setup(
|
|
|
371
375
|
}
|
|
372
376
|
if trusted_author_variables is not None:
|
|
373
377
|
variable_status = {
|
|
374
|
-
name: str(trusted_author_variables.get(name) or "
|
|
378
|
+
name: str(trusted_author_variables.get(name) or "not_confirmed")
|
|
375
379
|
for name in TRUSTED_AUDIT_AUTHOR_VARIABLES
|
|
376
380
|
}
|
|
377
381
|
trusted_detail["variable_status"] = variable_status
|
|
382
|
+
if trusted_author_variable_errors:
|
|
383
|
+
trusted_detail["variable_read_errors"] = {
|
|
384
|
+
name: trusted_author_variable_errors[name]
|
|
385
|
+
for name in sorted(trusted_author_variable_errors)
|
|
386
|
+
if name in TRUSTED_AUDIT_AUTHOR_VARIABLES
|
|
387
|
+
}
|
|
378
388
|
all_present = all(
|
|
379
389
|
variable_status[name] == "present" for name in TRUSTED_AUDIT_AUTHOR_VARIABLES
|
|
380
390
|
)
|
|
@@ -388,6 +398,27 @@ def check_adoption_setup(
|
|
|
388
398
|
)
|
|
389
399
|
)
|
|
390
400
|
return tuple(checks)
|
|
401
|
+
if any(
|
|
402
|
+
variable_status[name] == "not_confirmed"
|
|
403
|
+
for name in TRUSTED_AUDIT_AUTHOR_VARIABLES
|
|
404
|
+
):
|
|
405
|
+
checks.append(
|
|
406
|
+
DoctorCheck(
|
|
407
|
+
name="doctor.adoption.trusted_authors",
|
|
408
|
+
status=STATUS_WARN,
|
|
409
|
+
message=(
|
|
410
|
+
"trusted audit-comment author variables were not fully confirmed"
|
|
411
|
+
),
|
|
412
|
+
detail=trusted_detail,
|
|
413
|
+
remediation=(
|
|
414
|
+
"Ensure `gh auth status` can read repository Actions "
|
|
415
|
+
"variables for this repo, then set CLAUDE_AUDIT_BOT_AUTHORS "
|
|
416
|
+
"and CODEX_BOT_AUTHORS to the GitHub logins that may post "
|
|
417
|
+
"trusted audit verdicts."
|
|
418
|
+
),
|
|
419
|
+
)
|
|
420
|
+
)
|
|
421
|
+
return tuple(checks)
|
|
391
422
|
|
|
392
423
|
checks.append(
|
|
393
424
|
DoctorCheck(
|
{code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/github_human_token.py
RENAMED
|
@@ -173,11 +173,10 @@ def check_human_automation_token(
|
|
|
173
173
|
http_timeout=http_timeout,
|
|
174
174
|
)
|
|
175
175
|
if variable_payload is None:
|
|
176
|
-
status = _blocking_status_for_posture(adoption_posture)
|
|
177
176
|
return DoctorCheck(
|
|
178
177
|
name="github.human_automation_token",
|
|
179
|
-
status=
|
|
180
|
-
message=f"{slug} is missing the {expires_var} human token expiry
|
|
178
|
+
status=STATUS_WARN,
|
|
179
|
+
message=f"{slug} is missing the {expires_var} human token expiry metadata",
|
|
181
180
|
detail={
|
|
182
181
|
**detail,
|
|
183
182
|
"created_at": str(secret_payload.get("created_at") or ""),
|
|
@@ -219,10 +218,9 @@ def check_human_automation_token(
|
|
|
219
218
|
)
|
|
220
219
|
expiry = _parse_expiry(expiry_text)
|
|
221
220
|
if expiry is None:
|
|
222
|
-
status = _blocking_status_for_posture(adoption_posture)
|
|
223
221
|
return DoctorCheck(
|
|
224
222
|
name="github.human_automation_token",
|
|
225
|
-
status=
|
|
223
|
+
status=STATUS_WARN,
|
|
226
224
|
message=f"{slug} has an invalid {expires_var} value",
|
|
227
225
|
detail={**detail, "expires_at": expiry_text},
|
|
228
226
|
remediation=(
|
|
@@ -235,7 +233,7 @@ def check_human_automation_token(
|
|
|
235
233
|
days_remaining = (expiry - today).days
|
|
236
234
|
status = STATUS_PASS
|
|
237
235
|
if days_remaining < 0:
|
|
238
|
-
status =
|
|
236
|
+
status = STATUS_WARN
|
|
239
237
|
elif days_remaining <= EXPIRY_WARNING_DAYS:
|
|
240
238
|
status = STATUS_WARN
|
|
241
239
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""GitHub repository variable checks for trusted audit-comment authors."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .github_api import _github_api_json
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def trusted_author_variable_probe(
|
|
12
|
+
*,
|
|
13
|
+
gh_path: str,
|
|
14
|
+
slug: str,
|
|
15
|
+
variables: Iterable[str],
|
|
16
|
+
http_timeout: int,
|
|
17
|
+
) -> dict[str, Any]:
|
|
18
|
+
"""Return safe probe results for trusted-author repository variables."""
|
|
19
|
+
|
|
20
|
+
statuses: dict[str, str] = {}
|
|
21
|
+
read_errors: dict[str, dict[str, Any]] = {}
|
|
22
|
+
for variable in variables:
|
|
23
|
+
name = str(variable).strip()
|
|
24
|
+
if not name:
|
|
25
|
+
continue
|
|
26
|
+
payload, _detail = _github_api_json(
|
|
27
|
+
gh_path,
|
|
28
|
+
f"repos/{slug}/actions/variables/{name}",
|
|
29
|
+
http_timeout=http_timeout,
|
|
30
|
+
)
|
|
31
|
+
if payload is None:
|
|
32
|
+
statuses[name] = "not_confirmed"
|
|
33
|
+
read_errors[name] = {
|
|
34
|
+
key: value
|
|
35
|
+
for key, value in _detail.items()
|
|
36
|
+
if key
|
|
37
|
+
in {
|
|
38
|
+
"endpoint",
|
|
39
|
+
"returncode",
|
|
40
|
+
"error_type",
|
|
41
|
+
"parse_error",
|
|
42
|
+
"output_redacted",
|
|
43
|
+
"output_line_count",
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
elif str(payload.get("value") or "").strip():
|
|
47
|
+
statuses[name] = "present"
|
|
48
|
+
else:
|
|
49
|
+
statuses[name] = "empty"
|
|
50
|
+
return {"statuses": statuses, "read_errors": read_errors}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def trusted_author_variable_statuses(
|
|
54
|
+
*,
|
|
55
|
+
gh_path: str,
|
|
56
|
+
slug: str,
|
|
57
|
+
variables: Iterable[str],
|
|
58
|
+
http_timeout: int,
|
|
59
|
+
) -> dict[str, str]:
|
|
60
|
+
"""Return safe presence statuses for trusted-author repository variables."""
|
|
61
|
+
|
|
62
|
+
probe = trusted_author_variable_probe(
|
|
63
|
+
gh_path=gh_path,
|
|
64
|
+
slug=slug,
|
|
65
|
+
variables=variables,
|
|
66
|
+
http_timeout=http_timeout,
|
|
67
|
+
)
|
|
68
|
+
statuses = probe.get("statuses")
|
|
69
|
+
return dict(statuses) if isinstance(statuses, dict) else {}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ("trusted_author_variable_probe", "trusted_author_variable_statuses")
|
{code_mower-0.9.1b1 → code_mower-0.9.3b1}/src/code_mower/doctor_checks/provider_review_hygiene.py
RENAMED
|
@@ -21,6 +21,7 @@ def check_review_hygiene(
|
|
|
21
21
|
*,
|
|
22
22
|
effective_lane: Mapping[str, Any] | None = None,
|
|
23
23
|
repo_root: Path | None = None,
|
|
24
|
+
missing_workflow_is_warning: bool = False,
|
|
24
25
|
) -> DoctorCheck:
|
|
25
26
|
"""Verify that merge-authority lanes have stale terminal-label protection."""
|
|
26
27
|
|
|
@@ -108,24 +109,35 @@ def check_review_hygiene(
|
|
|
108
109
|
if not workflow_path.is_absolute():
|
|
109
110
|
workflow_path = repo_root / workflow_path
|
|
110
111
|
if not workflow_path.is_file():
|
|
112
|
+
status = STATUS_WARN if missing_workflow_is_warning else STATUS_FAIL
|
|
113
|
+
message = (
|
|
114
|
+
"starter config names stale terminal-label workflow, but it is not "
|
|
115
|
+
f"present in this checkout yet: {workflow}"
|
|
116
|
+
if missing_workflow_is_warning
|
|
117
|
+
else "merge-authority lane stale terminal-label workflow is "
|
|
118
|
+
f"configured but missing from the repo: {workflow}"
|
|
119
|
+
)
|
|
120
|
+
remediation = (
|
|
121
|
+
"This is expected before generated workflows are applied. Run "
|
|
122
|
+
"`code-mower init --easy --apply` from the repository root, review "
|
|
123
|
+
"and commit the generated clear-stale workflow, then rerun doctor."
|
|
124
|
+
if missing_workflow_is_warning
|
|
125
|
+
else "Run `code-mower init --easy --apply` from the repository "
|
|
126
|
+
"root, commit the generated clear-stale workflow, then rerun "
|
|
127
|
+
"doctor before relying on this lane as merge authority."
|
|
128
|
+
)
|
|
111
129
|
return DoctorCheck(
|
|
112
130
|
name="provider.review_hygiene",
|
|
113
|
-
status=
|
|
131
|
+
status=status,
|
|
114
132
|
lane=lane_id,
|
|
115
|
-
message=
|
|
116
|
-
"merge-authority lane stale terminal-label workflow is "
|
|
117
|
-
f"configured but missing from the repo: {workflow}"
|
|
118
|
-
),
|
|
133
|
+
message=message,
|
|
119
134
|
detail={
|
|
120
135
|
**detail,
|
|
121
136
|
"workflow_exists": False,
|
|
122
137
|
"workflow_path": str(workflow_path),
|
|
138
|
+
"missing_workflow_is_warning": missing_workflow_is_warning,
|
|
123
139
|
},
|
|
124
|
-
remediation=
|
|
125
|
-
"Run `code-mower init --easy --apply` from the repository "
|
|
126
|
-
"root, commit the generated clear-stale workflow, then rerun "
|
|
127
|
-
"doctor before relying on this lane as merge authority."
|
|
128
|
-
),
|
|
140
|
+
remediation=remediation,
|
|
129
141
|
)
|
|
130
142
|
detail = {
|
|
131
143
|
**detail,
|
|
@@ -176,6 +176,7 @@ def check_lane_runtime(
|
|
|
176
176
|
probe_runtime: bool,
|
|
177
177
|
http_timeout: int,
|
|
178
178
|
adoption_posture: str = "reviewer-gate",
|
|
179
|
+
missing_workflow_is_warning: bool = False,
|
|
179
180
|
) -> list[DoctorCheck]:
|
|
180
181
|
hygiene_source = source_lane if source_lane is not None else lane
|
|
181
182
|
checks = [
|
|
@@ -184,6 +185,7 @@ def check_lane_runtime(
|
|
|
184
185
|
hygiene_source,
|
|
185
186
|
effective_lane=lane,
|
|
186
187
|
repo_root=repo_root,
|
|
188
|
+
missing_workflow_is_warning=missing_workflow_is_warning,
|
|
187
189
|
)
|
|
188
190
|
]
|
|
189
191
|
driver = str(lane.get("driver", ""))
|
|
@@ -19,7 +19,7 @@ from .cloud import check_cloud_token_surface
|
|
|
19
19
|
from .common import ACTIONS_COST_SAMPLE_DEFAULT, load_inputs
|
|
20
20
|
from .github import check_github_setup
|
|
21
21
|
from .github_config import check_repository_posture
|
|
22
|
-
from .github_trusted_authors import
|
|
22
|
+
from .github_trusted_authors import trusted_author_variable_probe
|
|
23
23
|
from .models import STATUS_FAIL, STATUS_PASS, DoctorCheck, DoctorReport
|
|
24
24
|
from .providers import check_lane_runtime, effective_lane, provider_template_coverage, selected_lanes
|
|
25
25
|
from .registry import DoctorCheckStage, build_doctor_run_plan
|
|
@@ -109,13 +109,15 @@ def run_doctor(
|
|
|
109
109
|
adoption=adoption or bool(repo_slug),
|
|
110
110
|
)
|
|
111
111
|
enabled_stages = {stage.id for stage in plan}
|
|
112
|
-
# `doctor --easy` can inspect the packaged example before a repo has written
|
|
113
|
-
# code-mower.yml. In that mode the example should teach the user about stale
|
|
114
|
-
# guards without failing because product workflow files are not installed yet.
|
|
115
|
-
repo_root = None if config_path.name == "code-mower.example.yml" else config_path.parent
|
|
116
112
|
config, templates, checks = load_inputs(config_path, provider_templates_path)
|
|
117
113
|
using_packaged_example = config_path.name == "code-mower.example.yml"
|
|
114
|
+
# `doctor --easy` can inspect the packaged example before a repo has written
|
|
115
|
+
# code-mower.yml. In that mode the example should teach the user about stale
|
|
116
|
+
# guards without failing because product workflow files are not installed
|
|
117
|
+
# yet, but it may still verify workflows already present in the checkout.
|
|
118
|
+
repo_root = Path.cwd() if using_packaged_example else config_path.parent
|
|
118
119
|
trusted_author_variables = None
|
|
120
|
+
trusted_author_variable_errors = None
|
|
119
121
|
trusted_author_repo_slug = repo_slug
|
|
120
122
|
if not trusted_author_repo_slug and isinstance(config, Mapping):
|
|
121
123
|
for repository in config.get("repositories") or []:
|
|
@@ -125,12 +127,21 @@ def run_doctor(
|
|
|
125
127
|
if github and trusted_author_repo_slug:
|
|
126
128
|
gh_path = shutil.which("gh")
|
|
127
129
|
if gh_path:
|
|
128
|
-
|
|
130
|
+
trusted_author_probe = trusted_author_variable_probe(
|
|
129
131
|
gh_path=gh_path,
|
|
130
132
|
slug=trusted_author_repo_slug,
|
|
131
133
|
variables=TRUSTED_AUDIT_AUTHOR_VARIABLES,
|
|
132
134
|
http_timeout=http_timeout,
|
|
133
135
|
)
|
|
136
|
+
statuses = trusted_author_probe.get("statuses")
|
|
137
|
+
if isinstance(statuses, Mapping):
|
|
138
|
+
trusted_author_variables = {
|
|
139
|
+
str(name): str(status)
|
|
140
|
+
for name, status in statuses.items()
|
|
141
|
+
}
|
|
142
|
+
errors = trusted_author_probe.get("read_errors")
|
|
143
|
+
if isinstance(errors, Mapping):
|
|
144
|
+
trusted_author_variable_errors = dict(errors)
|
|
134
145
|
checks.extend(
|
|
135
146
|
check_adoption_setup(
|
|
136
147
|
config=config,
|
|
@@ -142,6 +153,7 @@ def run_doctor(
|
|
|
142
153
|
using_packaged_example=using_packaged_example,
|
|
143
154
|
repo_root=Path.cwd() if using_packaged_example else config_path.parent,
|
|
144
155
|
trusted_author_variables=trusted_author_variables,
|
|
156
|
+
trusted_author_variable_errors=trusted_author_variable_errors,
|
|
145
157
|
)
|
|
146
158
|
)
|
|
147
159
|
if config is not None and repo_slug:
|
|
@@ -237,6 +249,7 @@ def run_doctor(
|
|
|
237
249
|
effective,
|
|
238
250
|
source_lane=lane,
|
|
239
251
|
repo_root=repo_root,
|
|
252
|
+
missing_workflow_is_warning=using_packaged_example,
|
|
240
253
|
adoption_posture=adoption_posture,
|
|
241
254
|
probe_runtime=probe_runtime,
|
|
242
255
|
http_timeout=http_timeout,
|