code-mower 0.5.0b16__tar.gz → 0.5.0b18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/PKG-INFO +6 -6
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/README.md +5 -5
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/pyproject.toml +1 -1
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/__init__.py +1 -1
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cli.py +1 -1
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_review_hygiene.py +32 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/providers.py +10 -1
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/runner.py +5 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/providers/provenance.py +29 -1
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/PKG-INFO +6 -6
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_provider_review_hygiene.py +46 -0
- code_mower-0.5.0b18/tests/test_doctor_registry.py +140 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_local_cli.py +42 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_release_hygiene.py +34 -34
- code_mower-0.5.0b16/tests/test_doctor_registry.py +0 -68
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/CODE_OF_CONDUCT.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/LICENSE +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/MANIFEST.in +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/NOTICE +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/SUPPORT.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/requirements/requirements.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/setup.cfg +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/_base.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/cursor_bugbot.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/gitar.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/greptile.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/adapters/qodo.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/antigravity_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/audit_handoff_log.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/audit_labeler_lib.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/audit_progress.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/blind_review_artifacts.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/blind_review_coordinator.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/bootstrap.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/builder_experiment.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/arms.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/auto_discovery.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/commands.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/context_inputs.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/corpus.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/effect_report.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/evidence.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/evidence_report.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/identity.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/metrics.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/overlap.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/planning.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/policy.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/results.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/run_results.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/run_status.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/runner.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/truth.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/calibration/value_report.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/checks.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/claude_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/claude_cli_environment.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/clear_stale.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/bundle.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/doctor.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/dogfood.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/endpoints.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/errors.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/events.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/export.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/git_metadata.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/manifest.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/operations.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/reports.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/setup.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/cloud_client/upload.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/code_mower_calibration.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/code_mower_context_packs.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/code_mower_merge.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/code_mower_telemetry.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/codex_audit_env_preflight.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/codex_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/codex_audit_schema_smoke.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/codex_audit_verdict.schema.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/config.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/cloud.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/common.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_cost.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_failure_annotations.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_failure_models.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_failure_scan.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_failures.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_actions_permissions.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_api.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_branch.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_config.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_provider.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/github_repo.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/groups.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/models.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/output.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/presets.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/privacy.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_api_model.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_api_model_openai.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_api_model_profiles.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_env.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_env_required.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_env_tokens.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_local_cli.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_local_cli_commands.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_local_cli_probe_config.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_probe.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_probe_auth.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_probe_evaluation.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_probe_json.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_probe_remediation.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/registry.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/runtime.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/runtime_github_auth.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/gemini_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/hermes_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/init.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/aider.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/antigravity_cli.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/claude.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/codex.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/devin.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/gemini_cli.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/hermes_cli.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/lane_configs/local_llm.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/local_llm_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/local_llm_bakeoff.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/local_llm_calibration.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/local_llm_profiles.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/migration.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/migration_install.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/migration_mirror.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/migration_readiness.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/migration_rehearsal.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/next_steps.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package_content.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package_manifest.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package_paths.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package_rendering.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/package_static.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/prompts.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_registry.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/comments.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/git.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/github_auth.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/github_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/pr_worktree.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/process.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/repo_paths.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/text_schema.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/verdict_artifacts.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/provider_runners/workspace.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/providers/__init__.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/providers/local_cli.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/release_readiness.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/reviewer_metrics.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/saas_reviewer_labeler.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/secrets.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/code-mower.example.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/base-audit.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/calibration-policy.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/context-driven-quality.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/docs-design.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/generic-programming.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/operability.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/package-runtime.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/lane_prompts/security-threat-model.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/code_mower +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/code_mower_standalone_pin.env +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/code_mower_standalone_shadow.sh +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/run_claude_audit_pr.sh +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/run_codex_audit_pr.sh +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/product-support/safe_gh_comment.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/providers.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/trailer_comment_labeler.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/versioning.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/SOURCES.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/dependency_links.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/entry_points.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/requires.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower.egg-info/top_level.txt +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/builder-experiment.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/calibration-corpus.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/calibration-corpus.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/code-mower.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/context-packs.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/cursor/BUGBOT.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/acp_bridge.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/aider.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/antigravity_cli.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/claude_audit.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/claude_review.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/coderabbit_cli.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/codex.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/cursor_bugbot.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/devin.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/gemini_cli.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/gitar.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/greptile.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/hermes_cli.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/local_llm.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers/qodo.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/providers.yml +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/reviewer-spend.example.json +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/reviewer-value-report.example.md +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/audit-label-cleanup.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/blind-review-artifacts-dry-run.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/hosted-bridge.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/local-cli-audit.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/private-standalone-shadow.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/review-clear-stale.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/saas-reviewer-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/templates/workflows/trailer-comment-labeler.yml.j2 +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_calibration_effect_report.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_calibration_truth.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_checks.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_claude_cli_bounce.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_clear_stale.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_cloud_client.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_cloud_git_metadata.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_cloud_manifest.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_cloud_reports.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_coderabbit_cli_audit_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_actions_cost_summary.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_actions_failure_selection.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_boundaries.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_github_checks.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_output.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_privacy.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_provider_env_required.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_provider_env_tokens.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_doctor_provider_probe.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_local_llm_github_helpers.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_comments.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_git.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_github_pr.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_pr_worktree.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_process.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_repo_paths.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_text_schema.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_provider_runners_workspace.py +0 -0
- {code_mower-0.5.0b16 → code_mower-0.5.0b18}/tests/test_reviewer_metrics_core.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-mower
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0b18
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -101,11 +101,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
103
|
python3.12 --version
|
|
104
|
-
pipx install --python python3.12 code-mower==0.5.
|
|
104
|
+
pipx install --python python3.12 code-mower==0.5.0b18
|
|
105
105
|
code-mower --version
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
`0.5.
|
|
108
|
+
`0.5.0b18` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
109
109
|
line, use the explicit beta version above or allow prereleases with:
|
|
110
110
|
|
|
111
111
|
```bash
|
|
@@ -148,7 +148,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
148
148
|
|
|
149
149
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
150
150
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
151
|
-
the latest 10/10 public-package readiness proof for `code-mower==0.5.
|
|
151
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b18`.
|
|
152
152
|
|
|
153
153
|
## Why Not Just Run Codex Or Claude Yourself?
|
|
154
154
|
|
|
@@ -253,9 +253,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
|
|
|
253
253
|
|
|
254
254
|
## Installation Status
|
|
255
255
|
|
|
256
|
-
The current public beta is `v0.5.0-beta.
|
|
256
|
+
The current public beta is `v0.5.0-beta.18` from
|
|
257
257
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
258
|
-
as `code-mower==0.5.
|
|
258
|
+
as `code-mower==0.5.0b18` on [PyPI](https://pypi.org/project/code-mower/).
|
|
259
259
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
260
260
|
release notes.
|
|
261
261
|
|
|
@@ -86,11 +86,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
88
|
python3.12 --version
|
|
89
|
-
pipx install --python python3.12 code-mower==0.5.
|
|
89
|
+
pipx install --python python3.12 code-mower==0.5.0b18
|
|
90
90
|
code-mower --version
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
`0.5.
|
|
93
|
+
`0.5.0b18` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
94
94
|
line, use the explicit beta version above or allow prereleases with:
|
|
95
95
|
|
|
96
96
|
```bash
|
|
@@ -133,7 +133,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
133
133
|
|
|
134
134
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
135
135
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
136
|
-
the latest 10/10 public-package readiness proof for `code-mower==0.5.
|
|
136
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b18`.
|
|
137
137
|
|
|
138
138
|
## Why Not Just Run Codex Or Claude Yourself?
|
|
139
139
|
|
|
@@ -238,9 +238,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
|
|
|
238
238
|
|
|
239
239
|
## Installation Status
|
|
240
240
|
|
|
241
|
-
The current public beta is `v0.5.0-beta.
|
|
241
|
+
The current public beta is `v0.5.0-beta.18` from
|
|
242
242
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
243
|
-
as `code-mower==0.5.
|
|
243
|
+
as `code-mower==0.5.0b18` on [PyPI](https://pypi.org/project/code-mower/).
|
|
244
244
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
245
245
|
release notes.
|
|
246
246
|
|
|
@@ -14,7 +14,7 @@ from pathlib import Path
|
|
|
14
14
|
if __package__ in {None, ""}:
|
|
15
15
|
raise SystemExit(
|
|
16
16
|
"code_mower.cli is a packaged entrypoint. Install Code Mower with "
|
|
17
|
-
"`pipx install code-mower==0.5.
|
|
17
|
+
"`pipx install code-mower==0.5.0b18`, or run source checkouts with "
|
|
18
18
|
"`PYTHONPATH=src python -m code_mower.cli`."
|
|
19
19
|
)
|
|
20
20
|
|
{code_mower-0.5.0b16 → code_mower-0.5.0b18}/src/code_mower/doctor_checks/provider_review_hygiene.py
RENAMED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any, Mapping
|
|
6
7
|
|
|
7
8
|
from .common import DoctorCheck, STATUS_FAIL, STATUS_PASS, STATUS_SKIP, as_sequence
|
|
@@ -12,6 +13,7 @@ def check_review_hygiene(
|
|
|
12
13
|
lane: Mapping[str, Any],
|
|
13
14
|
*,
|
|
14
15
|
effective_lane: Mapping[str, Any] | None = None,
|
|
16
|
+
repo_root: Path | None = None,
|
|
15
17
|
) -> DoctorCheck:
|
|
16
18
|
"""Verify that merge-authority lanes have stale terminal-label protection."""
|
|
17
19
|
|
|
@@ -78,6 +80,36 @@ def check_review_hygiene(
|
|
|
78
80
|
),
|
|
79
81
|
)
|
|
80
82
|
|
|
83
|
+
if repo_root is not None:
|
|
84
|
+
workflow_path = Path(workflow)
|
|
85
|
+
if not workflow_path.is_absolute():
|
|
86
|
+
workflow_path = repo_root / workflow_path
|
|
87
|
+
if not workflow_path.is_file():
|
|
88
|
+
return DoctorCheck(
|
|
89
|
+
name="provider.review_hygiene",
|
|
90
|
+
status=STATUS_FAIL,
|
|
91
|
+
lane=lane_id,
|
|
92
|
+
message=(
|
|
93
|
+
"merge-authority lane stale terminal-label workflow is "
|
|
94
|
+
f"configured but missing from the repo: {workflow}"
|
|
95
|
+
),
|
|
96
|
+
detail={
|
|
97
|
+
**detail,
|
|
98
|
+
"workflow_exists": False,
|
|
99
|
+
"workflow_path": str(workflow_path),
|
|
100
|
+
},
|
|
101
|
+
remediation=(
|
|
102
|
+
"Run `code-mower init --easy --apply` from the repository "
|
|
103
|
+
"root, commit the generated clear-stale workflow, then rerun "
|
|
104
|
+
"doctor before relying on this lane as merge authority."
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
detail = {
|
|
108
|
+
**detail,
|
|
109
|
+
"workflow_exists": True,
|
|
110
|
+
"workflow_path": str(workflow_path),
|
|
111
|
+
}
|
|
112
|
+
|
|
81
113
|
return DoctorCheck(
|
|
82
114
|
name="provider.review_hygiene",
|
|
83
115
|
status=STATUS_PASS,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any, Mapping
|
|
6
7
|
|
|
7
8
|
from .common import (
|
|
@@ -112,11 +113,19 @@ def check_lane_runtime(
|
|
|
112
113
|
lane: Mapping[str, Any],
|
|
113
114
|
*,
|
|
114
115
|
source_lane: Mapping[str, Any] | None = None,
|
|
116
|
+
repo_root: Path | None = None,
|
|
115
117
|
probe_runtime: bool,
|
|
116
118
|
http_timeout: int,
|
|
117
119
|
) -> list[DoctorCheck]:
|
|
118
120
|
hygiene_source = source_lane if source_lane is not None else lane
|
|
119
|
-
checks = [
|
|
121
|
+
checks = [
|
|
122
|
+
check_review_hygiene(
|
|
123
|
+
lane_id,
|
|
124
|
+
hygiene_source,
|
|
125
|
+
effective_lane=lane,
|
|
126
|
+
repo_root=repo_root,
|
|
127
|
+
)
|
|
128
|
+
]
|
|
120
129
|
checks.extend(check_token_env(lane_id, lane))
|
|
121
130
|
checks.extend(check_required_env(lane_id, lane))
|
|
122
131
|
driver = str(lane.get("driver", ""))
|
|
@@ -75,6 +75,10 @@ def run_doctor(
|
|
|
75
75
|
) -> DoctorReport:
|
|
76
76
|
plan = build_doctor_run_plan(github=github, cloud=cloud)
|
|
77
77
|
enabled_stages = {stage.id for stage in plan}
|
|
78
|
+
# `doctor --easy` can inspect the packaged example before a repo has written
|
|
79
|
+
# code-mower.yml. In that mode the example should teach the user about stale
|
|
80
|
+
# guards without failing because product workflow files are not installed yet.
|
|
81
|
+
repo_root = None if config_path.name == "code-mower.example.yml" else config_path.parent
|
|
78
82
|
config, templates, checks = load_inputs(config_path, provider_templates_path)
|
|
79
83
|
checks.append(
|
|
80
84
|
_run_plan_check(
|
|
@@ -163,6 +167,7 @@ def run_doctor(
|
|
|
163
167
|
lane_id,
|
|
164
168
|
effective,
|
|
165
169
|
source_lane=lane,
|
|
170
|
+
repo_root=repo_root,
|
|
166
171
|
probe_runtime=probe_runtime,
|
|
167
172
|
http_timeout=http_timeout,
|
|
168
173
|
)
|
|
@@ -162,6 +162,31 @@ def _env_value(config: Mapping[str, Any], key: str) -> str:
|
|
|
162
162
|
return _safe_text(os.environ.get(env_name)) if env_name else ""
|
|
163
163
|
|
|
164
164
|
|
|
165
|
+
def _profile_model(config: Mapping[str, Any]) -> tuple[str, str]:
|
|
166
|
+
profile_env = _safe_text(config.get("profile_env"))
|
|
167
|
+
profile_id = _safe_text(os.environ.get(profile_env)) if profile_env else ""
|
|
168
|
+
profiles = config.get("profiles")
|
|
169
|
+
if not profile_id or not isinstance(profiles, Mapping):
|
|
170
|
+
return "", ""
|
|
171
|
+
profile = profiles.get(profile_id)
|
|
172
|
+
if not isinstance(profile, Mapping):
|
|
173
|
+
return "", profile_id
|
|
174
|
+
return _safe_text(profile.get("model")), profile_id
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _configured_model(config: Mapping[str, Any]) -> tuple[str, str]:
|
|
178
|
+
env_model = _env_value(config, "model_env")
|
|
179
|
+
if env_model:
|
|
180
|
+
return env_model, "env"
|
|
181
|
+
profile_model, profile_id = _profile_model(config)
|
|
182
|
+
if profile_model:
|
|
183
|
+
return profile_model, f"profile:{profile_id}"
|
|
184
|
+
default_model = _safe_text(config.get("default_model"))
|
|
185
|
+
if default_model:
|
|
186
|
+
return default_model, "default"
|
|
187
|
+
return "", "missing"
|
|
188
|
+
|
|
189
|
+
|
|
165
190
|
def _configured_command_candidates(
|
|
166
191
|
config: Mapping[str, Any],
|
|
167
192
|
provider: str,
|
|
@@ -208,7 +233,7 @@ def build_provider_lane_tool_provenance(
|
|
|
208
233
|
driver = _safe_text(_lane_value(lane, "driver")) or "unknown"
|
|
209
234
|
command_candidates = _configured_command_candidates(config, provider)
|
|
210
235
|
command, resolved_command = _select_available_command(command_candidates)
|
|
211
|
-
model
|
|
236
|
+
model, model_source = _configured_model(config)
|
|
212
237
|
provider_from_env = _env_value(config, "provider_env")
|
|
213
238
|
if provider_from_env:
|
|
214
239
|
provider = provider_from_env
|
|
@@ -228,7 +253,9 @@ def build_provider_lane_tool_provenance(
|
|
|
228
253
|
"command": command if driver == "local_cli" else "",
|
|
229
254
|
"command_candidates": list(command_candidates) if driver == "local_cli" else [],
|
|
230
255
|
"model_known": bool(model),
|
|
256
|
+
"model_source": model_source,
|
|
231
257
|
"version_known": False,
|
|
258
|
+
"version_source": "not_probed" if driver != "local_cli" else "missing",
|
|
232
259
|
}
|
|
233
260
|
tool_version = ""
|
|
234
261
|
if driver == "local_cli" and include_version_probe and command:
|
|
@@ -238,6 +265,7 @@ def build_provider_lane_tool_provenance(
|
|
|
238
265
|
version_detail = detect_local_cli_version(resolved_command)
|
|
239
266
|
tool_version = _safe_text(version_detail.get("tool_version"))
|
|
240
267
|
detail["version_known"] = bool(tool_version)
|
|
268
|
+
detail["version_source"] = "cli_version_probe" if tool_version else "missing"
|
|
241
269
|
detail["tool_version_available"] = bool(
|
|
242
270
|
version_detail.get("tool_version_available")
|
|
243
271
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-mower
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0b18
|
|
4
4
|
Summary: Multi-reviewer AI code audit orchestration
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -101,11 +101,11 @@ Code Mower currently targets Python 3.11+; Python 3.12 is recommended.
|
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
103
|
python3.12 --version
|
|
104
|
-
pipx install --python python3.12 code-mower==0.5.
|
|
104
|
+
pipx install --python python3.12 code-mower==0.5.0b18
|
|
105
105
|
code-mower --version
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
`0.5.
|
|
108
|
+
`0.5.0b18` is a beta release. Until Code Mower publishes a stable `1.0`
|
|
109
109
|
line, use the explicit beta version above or allow prereleases with:
|
|
110
110
|
|
|
111
111
|
```bash
|
|
@@ -148,7 +148,7 @@ First-time command map: [docs/launch-command-surface.md](docs/launch-command-sur
|
|
|
148
148
|
|
|
149
149
|
The current PyPI beta has been rehearsed end-to-end from a clean install:
|
|
150
150
|
[First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records
|
|
151
|
-
the latest 10/10 public-package readiness proof for `code-mower==0.5.
|
|
151
|
+
the latest 10/10 public-package readiness proof for `code-mower==0.5.0b18`.
|
|
152
152
|
|
|
153
153
|
## Why Not Just Run Codex Or Claude Yourself?
|
|
154
154
|
|
|
@@ -253,9 +253,9 @@ best?" to "which AI builder plus reviewer loop ships best on this product?" See
|
|
|
253
253
|
|
|
254
254
|
## Installation Status
|
|
255
255
|
|
|
256
|
-
The current public beta is `v0.5.0-beta.
|
|
256
|
+
The current public beta is `v0.5.0-beta.18` from
|
|
257
257
|
[codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), published
|
|
258
|
-
as `code-mower==0.5.
|
|
258
|
+
as `code-mower==0.5.0b18` on [PyPI](https://pypi.org/project/code-mower/).
|
|
259
259
|
GitHub releases remain the auditable source for tags, build artifacts, and
|
|
260
260
|
release notes.
|
|
261
261
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from tempfile import TemporaryDirectory
|
|
3
5
|
import unittest
|
|
4
6
|
|
|
5
7
|
from code_mower.doctor_checks.provider_review_hygiene import check_review_hygiene
|
|
@@ -63,6 +65,50 @@ class DoctorProviderReviewHygieneTests(unittest.TestCase):
|
|
|
63
65
|
self.assertEqual(check.detail["dispatch_workflow"], "codex-audit-labeler.yml")
|
|
64
66
|
self.assertEqual(check.detail["trusted_authors"], ["codex[bot]"])
|
|
65
67
|
|
|
68
|
+
def test_merge_authority_lane_fails_when_configured_workflow_is_missing(self) -> None:
|
|
69
|
+
with TemporaryDirectory() as tmp:
|
|
70
|
+
repo_root = Path(tmp)
|
|
71
|
+
check = check_review_hygiene(
|
|
72
|
+
"codex",
|
|
73
|
+
{
|
|
74
|
+
"merge_authority": True,
|
|
75
|
+
"review_hygiene": {
|
|
76
|
+
"workflow": ".github/workflows/codex-clear-stale.yml",
|
|
77
|
+
"token_env": "GITHUB_TOKEN",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
repo_root=repo_root,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
self.assertEqual(check.status, "fail")
|
|
84
|
+
self.assertIn("configured but missing", check.message)
|
|
85
|
+
self.assertEqual(check.detail["workflow_exists"], False)
|
|
86
|
+
self.assertIn(".github/workflows/codex-clear-stale.yml", check.detail["workflow_path"])
|
|
87
|
+
self.assertIn("code-mower init --easy --apply", check.remediation)
|
|
88
|
+
|
|
89
|
+
def test_merge_authority_lane_passes_when_configured_workflow_exists(self) -> None:
|
|
90
|
+
with TemporaryDirectory() as tmp:
|
|
91
|
+
repo_root = Path(tmp)
|
|
92
|
+
workflow = repo_root / ".github/workflows/codex-clear-stale.yml"
|
|
93
|
+
workflow.parent.mkdir(parents=True)
|
|
94
|
+
workflow.write_text("name: clear stale\n", encoding="utf-8")
|
|
95
|
+
|
|
96
|
+
check = check_review_hygiene(
|
|
97
|
+
"codex",
|
|
98
|
+
{
|
|
99
|
+
"merge_authority": True,
|
|
100
|
+
"review_hygiene": {
|
|
101
|
+
"workflow": ".github/workflows/codex-clear-stale.yml",
|
|
102
|
+
"token_env": "GITHUB_TOKEN",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
repo_root=repo_root,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
self.assertEqual(check.status, "pass")
|
|
109
|
+
self.assertEqual(check.detail["workflow_exists"], True)
|
|
110
|
+
self.assertEqual(check.detail["workflow_path"], str(workflow))
|
|
111
|
+
|
|
66
112
|
def test_merge_authority_lane_rejects_custom_hygiene_token_until_template_supports_it(self) -> None:
|
|
67
113
|
check = check_review_hygiene(
|
|
68
114
|
"devin",
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import tempfile
|
|
2
|
+
import unittest
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from code_mower.doctor_checks import (
|
|
6
|
+
build_doctor_run_plan,
|
|
7
|
+
default_check_group_ids,
|
|
8
|
+
run_doctor,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DoctorRegistryTests(unittest.TestCase):
|
|
15
|
+
def test_default_check_groups_stay_stable(self) -> None:
|
|
16
|
+
self.assertEqual(
|
|
17
|
+
default_check_group_ids(),
|
|
18
|
+
("runtime", "github", "providers", "cloud", "output"),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def test_run_plan_enables_optional_stages_explicitly(self) -> None:
|
|
22
|
+
base_plan = build_doctor_run_plan()
|
|
23
|
+
self.assertEqual(
|
|
24
|
+
tuple(stage.id for stage in base_plan),
|
|
25
|
+
("load-inputs", "select-profile", "runtime", "providers"),
|
|
26
|
+
)
|
|
27
|
+
self.assertTrue(all(not stage.optional for stage in base_plan))
|
|
28
|
+
|
|
29
|
+
full_plan = build_doctor_run_plan(github=True, cloud=True)
|
|
30
|
+
self.assertEqual(
|
|
31
|
+
tuple(stage.id for stage in full_plan),
|
|
32
|
+
("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
|
|
33
|
+
)
|
|
34
|
+
self.assertEqual(
|
|
35
|
+
{stage.id for stage in full_plan if stage.optional},
|
|
36
|
+
{"github", "cloud"},
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def test_runner_emits_sanitized_run_plan_check_even_when_inputs_fail(self) -> None:
|
|
40
|
+
with tempfile.TemporaryDirectory() as root:
|
|
41
|
+
root_path = Path(root)
|
|
42
|
+
report = run_doctor(
|
|
43
|
+
config_path=root_path / "missing-code-mower.yml",
|
|
44
|
+
provider_templates_path=root_path / "missing-providers.yml",
|
|
45
|
+
profile="recommended",
|
|
46
|
+
github=True,
|
|
47
|
+
cloud=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
plan_check = next(check for check in report.checks if check.name == "doctor.plan")
|
|
51
|
+
self.assertEqual(plan_check.status, "pass")
|
|
52
|
+
self.assertIn("github", plan_check.message)
|
|
53
|
+
self.assertIn("cloud", plan_check.message)
|
|
54
|
+
self.assertEqual(plan_check.detail["probe_runtime"], False)
|
|
55
|
+
self.assertEqual(
|
|
56
|
+
tuple(stage["id"] for stage in plan_check.detail["stages"]),
|
|
57
|
+
("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
|
|
58
|
+
)
|
|
59
|
+
self.assertEqual(
|
|
60
|
+
tuple(stage["id"] for stage in report.run_plan),
|
|
61
|
+
("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
|
|
62
|
+
)
|
|
63
|
+
self.assertEqual(
|
|
64
|
+
tuple(stage["id"] for stage in report.as_dict()["run_plan"]),
|
|
65
|
+
("load-inputs", "select-profile", "runtime", "providers", "github", "cloud"),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def test_packaged_example_config_does_not_require_installed_stale_workflow(self) -> None:
|
|
69
|
+
report = run_doctor(
|
|
70
|
+
config_path=ROOT / "src/code_mower/templates/code-mower.example.yml",
|
|
71
|
+
provider_templates_path=ROOT / "src/code_mower/templates/providers.yml",
|
|
72
|
+
profile="recommended",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
hygiene_checks = [
|
|
76
|
+
check for check in report.checks if check.name == "provider.review_hygiene"
|
|
77
|
+
]
|
|
78
|
+
self.assertTrue(hygiene_checks)
|
|
79
|
+
self.assertFalse(
|
|
80
|
+
any(
|
|
81
|
+
check.status == "fail"
|
|
82
|
+
and "workflow is configured but missing" in check.message
|
|
83
|
+
for check in hygiene_checks
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def test_real_config_requires_configured_stale_workflow_file(self) -> None:
|
|
88
|
+
with tempfile.TemporaryDirectory() as root:
|
|
89
|
+
root_path = Path(root)
|
|
90
|
+
config_path = root_path / "code-mower.yml"
|
|
91
|
+
config_path.write_text(
|
|
92
|
+
"\n".join(
|
|
93
|
+
[
|
|
94
|
+
"version: 1",
|
|
95
|
+
"project:",
|
|
96
|
+
" name: test",
|
|
97
|
+
" state_dir: .code-mower",
|
|
98
|
+
"repositories:",
|
|
99
|
+
" - slug: owner/repo",
|
|
100
|
+
" default_branch: main",
|
|
101
|
+
"lanes:",
|
|
102
|
+
" codex:",
|
|
103
|
+
" type: audit",
|
|
104
|
+
" provider: codex",
|
|
105
|
+
" merge_authority: true",
|
|
106
|
+
" driver: manual",
|
|
107
|
+
" labels:",
|
|
108
|
+
" needs: needs-codex-audit",
|
|
109
|
+
" done: codex-audit-done",
|
|
110
|
+
" blocked: codex-audit-blocked",
|
|
111
|
+
" review_hygiene:",
|
|
112
|
+
" workflow: .github/workflows/codex-clear-stale.yml",
|
|
113
|
+
" token_env: GITHUB_TOKEN",
|
|
114
|
+
"profiles:",
|
|
115
|
+
" recommended:",
|
|
116
|
+
" description: recommended lanes",
|
|
117
|
+
" lanes: [codex]",
|
|
118
|
+
]
|
|
119
|
+
),
|
|
120
|
+
encoding="utf-8",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
report = run_doctor(
|
|
124
|
+
config_path=config_path,
|
|
125
|
+
provider_templates_path=ROOT / "src/code_mower/templates/providers.yml",
|
|
126
|
+
profile="recommended",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
hygiene_check = next(
|
|
130
|
+
check
|
|
131
|
+
for check in report.checks
|
|
132
|
+
if check.name == "provider.review_hygiene" and check.lane == "codex"
|
|
133
|
+
)
|
|
134
|
+
self.assertEqual(hygiene_check.status, "fail")
|
|
135
|
+
self.assertEqual(hygiene_check.detail["workflow_exists"], False)
|
|
136
|
+
self.assertIn("configured but missing", hygiene_check.message)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
unittest.main()
|
|
@@ -86,7 +86,9 @@ def test_provider_lane_tool_provenance_reads_version_and_model_env(
|
|
|
86
86
|
assert detail["command_candidates"] == ["provider-cli"]
|
|
87
87
|
assert detail["command_found"] is True
|
|
88
88
|
assert detail["model_known"] is True
|
|
89
|
+
assert detail["model_source"] == "env"
|
|
89
90
|
assert detail["version_known"] is True
|
|
91
|
+
assert detail["version_source"] == "cli_version_probe"
|
|
90
92
|
|
|
91
93
|
|
|
92
94
|
def test_provider_lane_tool_provenance_uses_available_alternate_command(
|
|
@@ -121,3 +123,43 @@ def test_provider_lane_tool_provenance_uses_available_alternate_command(
|
|
|
121
123
|
assert detail["command_candidates"] == ["agy", "antigravity"]
|
|
122
124
|
assert detail["command_found"] is True
|
|
123
125
|
assert detail["version_known"] is True
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_provider_lane_tool_provenance_reads_model_from_selected_profile(
|
|
129
|
+
monkeypatch,
|
|
130
|
+
tmp_path: Path,
|
|
131
|
+
) -> None:
|
|
132
|
+
executable = _write_executable(
|
|
133
|
+
tmp_path / "local-model-cli",
|
|
134
|
+
"#!/bin/sh\nprintf 'local-model-cli 1.0.0\\n'\n",
|
|
135
|
+
)
|
|
136
|
+
monkeypatch.setenv("PATH", os.fspath(executable.parent))
|
|
137
|
+
monkeypatch.setenv("LOCAL_LLM_PROFILE", "qwen3-coder-next-lmstudio")
|
|
138
|
+
monkeypatch.delenv("LOCAL_LLM_MODEL", raising=False)
|
|
139
|
+
lane = {
|
|
140
|
+
"driver": "local_cli",
|
|
141
|
+
"provider": "openai_compatible",
|
|
142
|
+
"provider_config": {
|
|
143
|
+
"command": "local-model-cli",
|
|
144
|
+
"model_env": "LOCAL_LLM_MODEL",
|
|
145
|
+
"profile_env": "LOCAL_LLM_PROFILE",
|
|
146
|
+
"profiles": {
|
|
147
|
+
"qwen3-coder-next-lmstudio": {
|
|
148
|
+
"model": "qwen/qwen3-coder-next",
|
|
149
|
+
"endpoint": "lmstudio",
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
tool, detail = build_provider_lane_tool_provenance(
|
|
156
|
+
"local_llm",
|
|
157
|
+
lane,
|
|
158
|
+
source="unit-test",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
assert tool["model"] == "qwen/qwen3-coder-next"
|
|
162
|
+
assert detail["model_known"] is True
|
|
163
|
+
assert detail["model_source"] == "profile:qwen3-coder-next-lmstudio"
|
|
164
|
+
assert detail["version_known"] is True
|
|
165
|
+
assert detail["version_source"] == "cli_version_probe"
|