maintainability-agent 4.4.1__tar.gz → 4.4.3__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.
- {maintainability_agent-4.4.1/src/maintainability_agent.egg-info → maintainability_agent-4.4.3}/PKG-INFO +10 -5
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/README.md +9 -4
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3/src/maintainability_agent.egg-info}/PKG-INFO +10 -5
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_agent.egg-info/SOURCES.txt +6 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_arguments.py +18 -0
- maintainability_agent-4.4.3/src/maintainability_audit/_mcp_servers.py +107 -0
- maintainability_agent-4.4.3/src/maintainability_audit/_self_update.py +141 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/cli.py +9 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/mcp_server.py +25 -16
- maintainability_agent-4.4.3/tests/test_ci_runs_once.py +98 -0
- maintainability_agent-4.4.3/tests/test_local_gate.py +187 -0
- maintainability_agent-4.4.3/tests/test_mcp_servers.py +191 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_operator_named_reads.py +3 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_platform_claim.py +58 -50
- maintainability_agent-4.4.3/tests/test_self_update.py +298 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_suite_isolation.py +65 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_workflow_supply_chain.py +29 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/LICENSE +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/pyproject.toml +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/setup.cfg +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_analyzer_sections.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_anchor.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_banner.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_changed_code_policy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_criteria_scope.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_delegated_pillar.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_discovery.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_evidence_reader.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_grammar.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_handoff.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_in_loop.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_in_loop_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_operator_reads.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_oracle.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_pillars.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_pipeline_results.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_precommit.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_precommit_install.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_precommit_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_prompt_sections.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_go.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_kotlin.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_php.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_ruby.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_rust.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_shell.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_ratio_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_run_comparison.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_running_version.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_scan_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_security_delegate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_security_work_order.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_test_execution.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_work_order.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/config.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/git_tools.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/prompts.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/renderers.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/report.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_clone_names_every_copy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_dangling_source_link_is_named_not_fatal.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_format_override_is_disclosed.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_matching_format_stays_silent.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_published_question_offers_what_it_accepts.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_rendered_docs_site_is_not_scored_as_source.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_a_setup_question_keeps_its_contract.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_added_lines.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_an_absent_work_order_renders_nothing.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_an_unmeasured_pillar_reports_no_number.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_file_lists_are_batched.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzers_against_the_real_tools.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzers_never_write.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_analyzers_report_what_actually_failed.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_anchor_and_mode.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_anchor_disclosure.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_architecture.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_attestation.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_audit_components.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_backfill.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_bands.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_behaviour_suites_are_tests.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_both_setup_paths_ask_the_same_stage.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_build_output_is_not_the_repositorys_code.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_changed_code_policy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_chat_leads_with_the_work_order.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_check_refuses_plus_only_fragments.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_child_sandbox.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_clean_sees_the_weakened_oracle.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cli.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_code_scanning_gets_alerts_not_the_record.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cohesion_with_nothing_to_read_is_not_applicable.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_config_shape.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_conformance_reads_the_operators_ask.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_consent_is_per_repository.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_consent_survives_setup_and_is_asked.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_consent_without_command_has_a_remedy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_corpus_note_counts_come_from_the_corpus.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_corroborate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_coverage_config_reaches_children.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_coverage_formats.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_criteria_completion.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_current_state_docs_name_every_parsed_language.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_dead_code.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declaration_criteria_scope.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declarative_parsers.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declared_capabilities_match_the_delegate.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_delegated_security_pillar.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_demo_tree.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_determinism.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_discovery.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_docs_links.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_economic_context.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_built_presentation_is_offered.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_job_tests_the_pinned_oracle.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_language_counts_its_own_loop.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_language_has_a_loop_fixture.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_pool_install_is_the_same_pool.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_question_can_be_answered.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_every_surface_says_what_the_run_found.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_evidence_properties.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_example_config_opens_claimed_languages.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_exclude_additional_keeps_the_defaults.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_exposure_never_outranks_band.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_first_stage_setup_wording_holds.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_format_ask.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_git_argv.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_go_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_grammar_constructs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_grammar_token_coverage.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_grok_audit_of_3_11.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_history.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_history_window.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_html_executive.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_in_loop_budgets.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_in_loop_check.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_java_scored.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_kotlin_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_kotlin_metrics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_language_support_honesty.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_list_tools_publishes_the_answer_path.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_maintenance_signals.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mcp_format_contract.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mcp_server.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mcp_start_failure_names_what_is_installed.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_missing_security_scanners_are_named_before_the_run.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_mutation_recorded.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_no_private_names.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_operator_named_paths.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_oracle_weakening_precision_bar.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pairing_reads_imports.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_php_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pipeline_results.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_policy_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_population_floors.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_precommit_staged.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_preflight_before_consent_runs_nothing_from_the_tree.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_previous_release_reached_pypi.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_promises.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_python_complexity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_recurrence.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_regular_file_reads_work_without_o_nonblock.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_release_needs_an_empty_ledger.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_release_plan.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_rendered_docs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_reported_but_not_scored.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_root_grants.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_ruby_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_runner.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_rust_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_sarif.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scan_history.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scanner_fingerprint_covers_the_measurement_path.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scanning.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_security_delegate_versions_agree.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_security_findings_keep_their_handoff.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_security_pillar_asserts_a_scanner_set.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_security_pillar_runs_and_shows.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_selection_covers_every_parsed_language.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_semantic_findings_stay_inside_the_audited_files.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_answers_are_the_same_setup.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_instruction_describes_its_own_reply.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_setup_writes_a_valid_config.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_shell_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_shell_metrics.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_skill_install.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_sonar_resolve.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_source_index.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_stamped_documents_stay_honest.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_stdout_outputs.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_terminal_asks_the_same_questions.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_test_commands.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_agent_knows_when_it_is_stale.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_changelog_covers_the_shipping_version.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_chat_payload_has_a_budget.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_condition_says_what_it_measured.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_handoff_rules_are_their_own_module.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_pillar_row_reads_cleanly.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_presentation_question_stays_answerable.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_previous_release_was_tagged.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_prompt_does_not_take_back_what_it_withheld.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_prompt_keeps_listing_what_it_did_not_withhold.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_release_process_describes_itself.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_release_record_stays_well_formed.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_report_is_saved_not_sent.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_security_run_has_a_configurable_limit.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_security_work_order_is_drawn.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_suite_names_the_program_it_ran.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_tree_cannot_redirect_a_read.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_the_version_has_one_source.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_tool_resolution.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_tree_chosen_spawn.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_tree_reads_use_the_primitive.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_trends.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_unanchored_set_matches_corpus.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_unread_code.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_version_claim.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_version_stamping.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_withheld_work_keeps_its_boundary.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_work_items_state_their_own_finding.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_work_order.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/tests/test_written_record.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maintainability-agent
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.3
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -47,7 +47,7 @@ Dynamic: license-file
|
|
|
47
47
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
48
48
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
49
49
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
50
|
-
Version **4.4.
|
|
50
|
+
Version **4.4.3**.
|
|
51
51
|
|
|
52
52
|
> ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
|
|
53
53
|
>
|
|
@@ -488,7 +488,8 @@ and is now the dominant failure in the probe, which is why the count moved. The
|
|
|
488
488
|
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
489
489
|
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
490
490
|
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
491
|
-
buys green by weakening the supported ones.**
|
|
491
|
+
buys green by weakening the supported ones.** Windows is not run in CI at all
|
|
492
|
+
(Decision 18); a Windows user who hits a problem can open an issue or a pull request.
|
|
492
493
|
|
|
493
494
|
## Invokable skill / slash command
|
|
494
495
|
|
|
@@ -501,7 +502,11 @@ Copilot Chat:
|
|
|
501
502
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
502
503
|
```
|
|
503
504
|
|
|
504
|
-
|
|
505
|
+
`maintainability-agent --update` upgrades the install to the newest release —
|
|
506
|
+
never a downgrade — re-syncs the skill, and says when the MCP server needs a
|
|
507
|
+
restart; `maintainability-agent --install-updater` runs it hourly (macOS launch
|
|
508
|
+
agent). Run `--install-skill` by hand after any other upgrade — a drifted skill
|
|
509
|
+
teaches agents a dead workflow,
|
|
505
510
|
so a differing installed copy is refused with the list of differences. Per-host
|
|
506
511
|
install destinations, and `--init-agent-standards` for always-on guidance
|
|
507
512
|
instead of an invokable skill:
|
|
@@ -512,7 +517,7 @@ instead of an invokable skill:
|
|
|
512
517
|
This repo ships `action.yml`, usable as a composite action:
|
|
513
518
|
|
|
514
519
|
```yaml
|
|
515
|
-
- uses: marshallguillory86/maintainability-agent@v4.4.
|
|
520
|
+
- uses: marshallguillory86/maintainability-agent@v4.4.3
|
|
516
521
|
with:
|
|
517
522
|
config: maintainability-agent.json
|
|
518
523
|
changed-only: main...HEAD
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
6
6
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
7
7
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
8
|
-
Version **4.4.
|
|
8
|
+
Version **4.4.3**.
|
|
9
9
|
|
|
10
10
|
> ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
|
|
11
11
|
>
|
|
@@ -446,7 +446,8 @@ and is now the dominant failure in the probe, which is why the count moved. The
|
|
|
446
446
|
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
447
447
|
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
448
448
|
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
449
|
-
buys green by weakening the supported ones.**
|
|
449
|
+
buys green by weakening the supported ones.** Windows is not run in CI at all
|
|
450
|
+
(Decision 18); a Windows user who hits a problem can open an issue or a pull request.
|
|
450
451
|
|
|
451
452
|
## Invokable skill / slash command
|
|
452
453
|
|
|
@@ -459,7 +460,11 @@ Copilot Chat:
|
|
|
459
460
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
460
461
|
```
|
|
461
462
|
|
|
462
|
-
|
|
463
|
+
`maintainability-agent --update` upgrades the install to the newest release —
|
|
464
|
+
never a downgrade — re-syncs the skill, and says when the MCP server needs a
|
|
465
|
+
restart; `maintainability-agent --install-updater` runs it hourly (macOS launch
|
|
466
|
+
agent). Run `--install-skill` by hand after any other upgrade — a drifted skill
|
|
467
|
+
teaches agents a dead workflow,
|
|
463
468
|
so a differing installed copy is refused with the list of differences. Per-host
|
|
464
469
|
install destinations, and `--init-agent-standards` for always-on guidance
|
|
465
470
|
instead of an invokable skill:
|
|
@@ -470,7 +475,7 @@ instead of an invokable skill:
|
|
|
470
475
|
This repo ships `action.yml`, usable as a composite action:
|
|
471
476
|
|
|
472
477
|
```yaml
|
|
473
|
-
- uses: marshallguillory86/maintainability-agent@v4.4.
|
|
478
|
+
- uses: marshallguillory86/maintainability-agent@v4.4.3
|
|
474
479
|
with:
|
|
475
480
|
config: maintainability-agent.json
|
|
476
481
|
changed-only: main...HEAD
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maintainability-agent
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.3
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -47,7 +47,7 @@ Dynamic: license-file
|
|
|
47
47
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
48
48
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
49
49
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
50
|
-
Version **4.4.
|
|
50
|
+
Version **4.4.3**.
|
|
51
51
|
|
|
52
52
|
> ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
|
|
53
53
|
>
|
|
@@ -488,7 +488,8 @@ and is now the dominant failure in the probe, which is why the count moved. The
|
|
|
488
488
|
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
489
489
|
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
490
490
|
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
491
|
-
buys green by weakening the supported ones.**
|
|
491
|
+
buys green by weakening the supported ones.** Windows is not run in CI at all
|
|
492
|
+
(Decision 18); a Windows user who hits a problem can open an issue or a pull request.
|
|
492
493
|
|
|
493
494
|
## Invokable skill / slash command
|
|
494
495
|
|
|
@@ -501,7 +502,11 @@ Copilot Chat:
|
|
|
501
502
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
502
503
|
```
|
|
503
504
|
|
|
504
|
-
|
|
505
|
+
`maintainability-agent --update` upgrades the install to the newest release —
|
|
506
|
+
never a downgrade — re-syncs the skill, and says when the MCP server needs a
|
|
507
|
+
restart; `maintainability-agent --install-updater` runs it hourly (macOS launch
|
|
508
|
+
agent). Run `--install-skill` by hand after any other upgrade — a drifted skill
|
|
509
|
+
teaches agents a dead workflow,
|
|
505
510
|
so a differing installed copy is refused with the list of differences. Per-host
|
|
506
511
|
install destinations, and `--init-agent-standards` for always-on guidance
|
|
507
512
|
instead of an invokable skill:
|
|
@@ -512,7 +517,7 @@ instead of an invokable skill:
|
|
|
512
517
|
This repo ships `action.yml`, usable as a composite action:
|
|
513
518
|
|
|
514
519
|
```yaml
|
|
515
|
-
- uses: marshallguillory86/maintainability-agent@v4.4.
|
|
520
|
+
- uses: marshallguillory86/maintainability-agent@v4.4.3
|
|
516
521
|
with:
|
|
517
522
|
config: maintainability-agent.json
|
|
518
523
|
changed-only: main...HEAD
|
|
@@ -63,6 +63,7 @@ src/maintainability_audit/_mcp_gate.py
|
|
|
63
63
|
src/maintainability_audit/_mcp_grants.py
|
|
64
64
|
src/maintainability_audit/_mcp_refusals.py
|
|
65
65
|
src/maintainability_audit/_mcp_resources.py
|
|
66
|
+
src/maintainability_audit/_mcp_servers.py
|
|
66
67
|
src/maintainability_audit/_mcp_setup.py
|
|
67
68
|
src/maintainability_audit/_metric_adapters.py
|
|
68
69
|
src/maintainability_audit/_metrics_types.py
|
|
@@ -104,6 +105,7 @@ src/maintainability_audit/_second_source.py
|
|
|
104
105
|
src/maintainability_audit/_security_delegate.py
|
|
105
106
|
src/maintainability_audit/_security_work_order.py
|
|
106
107
|
src/maintainability_audit/_selection.py
|
|
108
|
+
src/maintainability_audit/_self_update.py
|
|
107
109
|
src/maintainability_audit/_semantic.py
|
|
108
110
|
src/maintainability_audit/_semantic_policy.py
|
|
109
111
|
src/maintainability_audit/_semantic_ts.py
|
|
@@ -222,6 +224,7 @@ tests/test_checkstyle_catalog.py
|
|
|
222
224
|
tests/test_child_sandbox.py
|
|
223
225
|
tests/test_ci_history_recipe.py
|
|
224
226
|
tests/test_ci_installs_the_analyzer_pool.py
|
|
227
|
+
tests/test_ci_runs_once.py
|
|
225
228
|
tests/test_claimed_languages.py
|
|
226
229
|
tests/test_clean_sees_the_weakened_oracle.py
|
|
227
230
|
tests/test_cli.py
|
|
@@ -334,11 +337,13 @@ tests/test_kotlin_metrics.py
|
|
|
334
337
|
tests/test_language_coverage.py
|
|
335
338
|
tests/test_language_support_honesty.py
|
|
336
339
|
tests/test_list_tools_publishes_the_answer_path.py
|
|
340
|
+
tests/test_local_gate.py
|
|
337
341
|
tests/test_maintenance_signals.py
|
|
338
342
|
tests/test_mcp_baseline_payload.py
|
|
339
343
|
tests/test_mcp_format_contract.py
|
|
340
344
|
tests/test_mcp_history.py
|
|
341
345
|
tests/test_mcp_server.py
|
|
346
|
+
tests/test_mcp_servers.py
|
|
342
347
|
tests/test_mcp_start_failure_names_what_is_installed.py
|
|
343
348
|
tests/test_migration_1_0.py
|
|
344
349
|
tests/test_missing_security_scanners_are_named_before_the_run.py
|
|
@@ -405,6 +410,7 @@ tests/test_security_findings_keep_their_handoff.py
|
|
|
405
410
|
tests/test_security_pillar_asserts_a_scanner_set.py
|
|
406
411
|
tests/test_security_pillar_runs_and_shows.py
|
|
407
412
|
tests/test_selection_covers_every_parsed_language.py
|
|
413
|
+
tests/test_self_update.py
|
|
408
414
|
tests/test_semantic_findings_stay_inside_the_audited_files.py
|
|
409
415
|
tests/test_semantic_policy.py
|
|
410
416
|
tests/test_setup_answers_are_the_same_setup.py
|
{maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/_arguments.py
RENAMED
|
@@ -212,6 +212,24 @@ def _add_setup_actions(parser: argparse.ArgumentParser) -> None:
|
|
|
212
212
|
"own without asking, because that is an upgrade. Honours "
|
|
213
213
|
"core.hooksPath.",
|
|
214
214
|
)
|
|
215
|
+
parser.add_argument(
|
|
216
|
+
"--update", action="store_true",
|
|
217
|
+
help="Upgrade this install to the newest release (never a downgrade), "
|
|
218
|
+
"re-sync the skill, and say when the MCP server needs a restart.",
|
|
219
|
+
)
|
|
220
|
+
parser.add_argument(
|
|
221
|
+
"--install-updater", action="store_true",
|
|
222
|
+
help="Write the hourly launch agent that runs --update (macOS), "
|
|
223
|
+
"replacing the legacy one.",
|
|
224
|
+
)
|
|
225
|
+
parser.add_argument(
|
|
226
|
+
"--home", default=None, metavar="DIR",
|
|
227
|
+
help="With --install-updater: the home directory to write into (default: ~).",
|
|
228
|
+
)
|
|
229
|
+
parser.add_argument(
|
|
230
|
+
"--no-launchctl", action="store_true",
|
|
231
|
+
help="With --install-updater: write the agent without loading it.",
|
|
232
|
+
)
|
|
215
233
|
parser.add_argument(
|
|
216
234
|
"--skills-dir", default=None, metavar="DIR",
|
|
217
235
|
help="Where --install-skill writes (default: ~/.claude/skills).",
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Which MCP servers are running which version, so ``--update`` can stop stale ones.
|
|
2
|
+
|
|
3
|
+
A stdio MCP server holds the code it loaded at spawn. After an upgrade it
|
|
4
|
+
keeps serving the old version until it stops, and its host starts the new
|
|
5
|
+
one on the next call. 4.4.2 told the operator to run ``/mcp``, which in the
|
|
6
|
+
VS Code panel only lists servers (D232). Now each server records its pid and
|
|
7
|
+
version here, marks itself busy while an audit runs, and ``--update`` stops
|
|
8
|
+
the stale ones that are idle. A busy server is left alone; the next hourly
|
|
9
|
+
update stops it.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import os
|
|
16
|
+
import signal
|
|
17
|
+
from collections.abc import Callable, Iterator
|
|
18
|
+
from contextlib import contextmanager
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from . import _runner
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class Stopped:
|
|
27
|
+
stopped: tuple[int, ...] = ()
|
|
28
|
+
busy: tuple[int, ...] = ()
|
|
29
|
+
gone: tuple[int, ...] = ()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _servers(home: Path) -> Path:
|
|
33
|
+
return home / ".local" / "share" / "maintainability-agent" / "servers"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def register(home: Path, pid: int, version: str) -> Path:
|
|
37
|
+
folder = _servers(home)
|
|
38
|
+
folder.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
record = folder / f"{pid}.json"
|
|
40
|
+
record.write_text(json.dumps({"pid": pid, "version": version}) + "\n", encoding="utf-8")
|
|
41
|
+
return record
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def unregister(home: Path, pid: int) -> None:
|
|
45
|
+
(_servers(home) / f"{pid}.json").unlink(missing_ok=True)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@contextmanager
|
|
49
|
+
def busy(home: Path, pid: int) -> Iterator[None]:
|
|
50
|
+
folder = _servers(home)
|
|
51
|
+
folder.mkdir(parents=True, exist_ok=True)
|
|
52
|
+
marker = folder / f"{pid}.busy"
|
|
53
|
+
marker.touch()
|
|
54
|
+
try:
|
|
55
|
+
yield
|
|
56
|
+
finally:
|
|
57
|
+
marker.unlink(missing_ok=True)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _alive(pid: int) -> bool:
|
|
61
|
+
try:
|
|
62
|
+
os.kill(pid, 0)
|
|
63
|
+
except ProcessLookupError:
|
|
64
|
+
return False
|
|
65
|
+
except PermissionError:
|
|
66
|
+
return True
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _is_server(pid: int) -> bool:
|
|
71
|
+
"""The pid is still an MA MCP server, not a reused pid of something else."""
|
|
72
|
+
result = _runner.run("mcp-servers", _runner.Invocation(argv=("ps", "-o", "command=", "-p", str(pid))),
|
|
73
|
+
timeout_seconds=10)
|
|
74
|
+
command = result.stdout or ""
|
|
75
|
+
return "maintainability" in command and "mcp" in command
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def stop_stale(home: Path, installed: str, *,
|
|
79
|
+
alive: Callable[[int], bool] = _alive,
|
|
80
|
+
is_server: Callable[[int], bool] = _is_server,
|
|
81
|
+
kill: Callable[[int, int], None] = os.kill) -> Stopped:
|
|
82
|
+
folder = _servers(home)
|
|
83
|
+
stopped: list[int] = []
|
|
84
|
+
held: list[int] = []
|
|
85
|
+
gone: list[int] = []
|
|
86
|
+
for record in sorted(folder.glob("*.json")) if folder.is_dir() else []:
|
|
87
|
+
try:
|
|
88
|
+
data = json.loads(record.read_text(encoding="utf-8"))
|
|
89
|
+
pid, version = int(data["pid"]), str(data["version"])
|
|
90
|
+
except (OSError, ValueError, KeyError, TypeError):
|
|
91
|
+
record.unlink(missing_ok=True)
|
|
92
|
+
continue
|
|
93
|
+
if version == installed:
|
|
94
|
+
continue
|
|
95
|
+
if not alive(pid):
|
|
96
|
+
record.unlink(missing_ok=True)
|
|
97
|
+
gone.append(pid)
|
|
98
|
+
elif (folder / f"{pid}.busy").exists():
|
|
99
|
+
held.append(pid)
|
|
100
|
+
elif not is_server(pid):
|
|
101
|
+
record.unlink(missing_ok=True)
|
|
102
|
+
gone.append(pid)
|
|
103
|
+
else:
|
|
104
|
+
kill(pid, signal.SIGTERM)
|
|
105
|
+
record.unlink(missing_ok=True)
|
|
106
|
+
stopped.append(pid)
|
|
107
|
+
return Stopped(tuple(stopped), tuple(held), tuple(gone))
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Keep the local install current: ``--update`` and ``--install-updater``.
|
|
2
|
+
|
|
3
|
+
The updater used to be an untracked script beside the venv, run by a launch
|
|
4
|
+
agent. It trusted PyPI's ``info.version``, which lags a release, and on
|
|
5
|
+
2026-09-22 it *downgraded* 3.7.29 to 3.7.19; it never re-synced the skill the
|
|
6
|
+
README says to sync after every upgrade; and nothing tested it (D230).
|
|
7
|
+
|
|
8
|
+
Now it is a product command. The installer resolves the version — ``pip
|
|
9
|
+
install --upgrade`` picks the highest release the index lists and never moves
|
|
10
|
+
backwards — so this module holds no HTTP client and reads no release feed
|
|
11
|
+
(P1: analysis touches no network; updating is an operator action, like tool
|
|
12
|
+
acquisition). Every child process goes through ``_runner.run`` (rule 7). A
|
|
13
|
+
version that comes back lower than before is reported, never accepted
|
|
14
|
+
silently; a higher one re-syncs the skill and records that the MCP server,
|
|
15
|
+
which holds the code it loaded at spawn, needs a restart; stale servers
|
|
16
|
+
that are not mid-audit are stopped so their host restarts them (D232).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import plistlib
|
|
22
|
+
import re
|
|
23
|
+
import sys
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
from . import _mcp_servers, _runner
|
|
28
|
+
|
|
29
|
+
PACKAGE = "maintainability-agent"
|
|
30
|
+
#: The launch agent, named for the product and the component (reverse DNS of
|
|
31
|
+
#: the project's home), replacing the personal-prefix label it had before.
|
|
32
|
+
LABEL = "io.github.marshallguillory86.maintainability-agent.update"
|
|
33
|
+
LEGACY_LABEL = "com.marshallguillory.maintainability-agent-update"
|
|
34
|
+
_VERSION_CODE = f"import importlib.metadata as m; print(m.version({PACKAGE!r}))"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class UpdateResult:
|
|
39
|
+
before: str
|
|
40
|
+
after: str
|
|
41
|
+
skill_synced: bool
|
|
42
|
+
restart_needed: bool
|
|
43
|
+
error: str | None
|
|
44
|
+
message: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _key(version: str) -> tuple:
|
|
48
|
+
"""Release ordering for plain ``N.N.N`` versions; a suffix sorts before
|
|
49
|
+
the release it precedes (``4.4.1rc1`` < ``4.4.1``)."""
|
|
50
|
+
parts = []
|
|
51
|
+
for piece in version.strip().split("."):
|
|
52
|
+
number = re.match(r"\d+", piece)
|
|
53
|
+
parts.append((int(number.group()) if number else 0, 1 if number and number.end() == len(piece) else 0))
|
|
54
|
+
return tuple(parts)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _state_dir(home: Path) -> Path:
|
|
58
|
+
return home / ".local" / "share" / "maintainability-agent"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _run(argv: list[str]) -> _runner.ToolResult:
|
|
62
|
+
return _runner.run("self-update", _runner.Invocation(argv=tuple(argv)), timeout_seconds=600)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _installed(python: str) -> str:
|
|
66
|
+
return (_run([python, "-c", _VERSION_CODE]).stdout or "").strip()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def update(python: str, uv: str | None, home: Path) -> UpdateResult:
|
|
70
|
+
before = _installed(python)
|
|
71
|
+
if uv:
|
|
72
|
+
argv = [uv, "pip", "install", "--python", python, "--upgrade", PACKAGE]
|
|
73
|
+
else:
|
|
74
|
+
argv = [python, "-m", "pip", "install", "--upgrade", PACKAGE]
|
|
75
|
+
installed = _run(argv)
|
|
76
|
+
after = _installed(python)
|
|
77
|
+
if not installed.usable:
|
|
78
|
+
return UpdateResult(before, after, False, False, f"install failed: {installed.detail}",
|
|
79
|
+
f"Update failed; still on {before}.")
|
|
80
|
+
if _key(after) < _key(before):
|
|
81
|
+
return UpdateResult(before, after, False, False,
|
|
82
|
+
f"version went down from {before} to {after}",
|
|
83
|
+
f"Refused: the install moved {before} to {after}, a downgrade.")
|
|
84
|
+
if _key(after) == _key(before):
|
|
85
|
+
return UpdateResult(before, after, False, False, None,
|
|
86
|
+
f"Already up to date ({after}).{_servers_note(home, after)}")
|
|
87
|
+
_run([python, "-m", "maintainability_audit", "--install-skill"])
|
|
88
|
+
state = _state_dir(home)
|
|
89
|
+
state.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
(state / ".pending-restart").write_text(after + "\n", encoding="utf-8")
|
|
91
|
+
return UpdateResult(before, after, True, True, None,
|
|
92
|
+
f"Updated {before} -> {after}; skill re-synced.{_servers_note(home, after)}")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _servers_note(home: Path, installed: str) -> str:
|
|
96
|
+
"""Stop the MCP servers still on an older version (D232) and say so.
|
|
97
|
+
A host starts a stopped stdio server again on its next call."""
|
|
98
|
+
result = _mcp_servers.stop_stale(home, installed)
|
|
99
|
+
note = ""
|
|
100
|
+
if result.stopped:
|
|
101
|
+
note += (f" Stopped {len(result.stopped)} MCP server(s) on an older version;"
|
|
102
|
+
f" the host starts {installed} on its next call.")
|
|
103
|
+
if result.busy:
|
|
104
|
+
note += (f" {len(result.busy)} busy with an audit kept running;"
|
|
105
|
+
" the next update stops it.")
|
|
106
|
+
return note
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def update_action() -> int:
|
|
110
|
+
result = update(sys.executable, _runner.locate("uv"), Path.home())
|
|
111
|
+
print(result.message, file=sys.stderr if result.error else sys.stdout)
|
|
112
|
+
return 1 if result.error else 0
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def install_updater(home: Path, *, launchctl: bool = True) -> int:
|
|
116
|
+
"""Write the hourly launch agent that runs ``--update``; remove the
|
|
117
|
+
legacy one so two updaters never run."""
|
|
118
|
+
agents = home / "Library" / "LaunchAgents"
|
|
119
|
+
agents.mkdir(parents=True, exist_ok=True)
|
|
120
|
+
legacy = agents / f"{LEGACY_LABEL}.plist"
|
|
121
|
+
if legacy.exists():
|
|
122
|
+
if launchctl:
|
|
123
|
+
_run(["launchctl", "unload", str(legacy)])
|
|
124
|
+
legacy.unlink()
|
|
125
|
+
state = _state_dir(home)
|
|
126
|
+
state.mkdir(parents=True, exist_ok=True)
|
|
127
|
+
plist = agents / f"{LABEL}.plist"
|
|
128
|
+
plist.write_bytes(plistlib.dumps({
|
|
129
|
+
"Label": LABEL,
|
|
130
|
+
"ProgramArguments": [sys.executable, "-m", "maintainability_audit", "--update"],
|
|
131
|
+
"StartInterval": 3600,
|
|
132
|
+
"RunAtLoad": True,
|
|
133
|
+
"ProcessType": "Background",
|
|
134
|
+
"LowPriorityIO": True,
|
|
135
|
+
"StandardOutPath": str(state / "update.out.log"),
|
|
136
|
+
"StandardErrorPath": str(state / "update.err.log"),
|
|
137
|
+
}))
|
|
138
|
+
if launchctl:
|
|
139
|
+
_run(["launchctl", "load", str(plist)])
|
|
140
|
+
print(f"installed {plist}")
|
|
141
|
+
return 0
|
{maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/cli.py
RENAMED
|
@@ -393,6 +393,15 @@ def _action_before_config(
|
|
|
393
393
|
"""
|
|
394
394
|
if args.install_skill:
|
|
395
395
|
return _install_skill_action(args)
|
|
396
|
+
if args.update:
|
|
397
|
+
from ._self_update import update_action
|
|
398
|
+
|
|
399
|
+
return update_action()
|
|
400
|
+
if args.install_updater:
|
|
401
|
+
from ._self_update import install_updater
|
|
402
|
+
|
|
403
|
+
home = Path(args.home).expanduser() if args.home else Path.home()
|
|
404
|
+
return install_updater(home, launchctl=not args.no_launchctl)
|
|
396
405
|
if args.install_precommit_hook:
|
|
397
406
|
from ._precommit_install import install_precommit_hook
|
|
398
407
|
|
{maintainability_agent-4.4.1 → maintainability_agent-4.4.3}/src/maintainability_audit/mcp_server.py
RENAMED
|
@@ -16,9 +16,11 @@ string, or invokes a shell.
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
|
+
import os
|
|
19
20
|
from pathlib import Path
|
|
20
21
|
from typing import Any
|
|
21
22
|
|
|
23
|
+
from . import _mcp_servers
|
|
22
24
|
from ._catalog import PolicyError as PolicyError
|
|
23
25
|
|
|
24
26
|
# Redundant aliases on purpose: every name the split moved to
|
|
@@ -263,21 +265,23 @@ def _run_audit_tool(ledger, tool_error, repository_root, config_path, changed_on
|
|
|
263
265
|
"""
|
|
264
266
|
try:
|
|
265
267
|
_apply_call_consents(ledger, repository_root, setup, grant, setup_answers)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
268
|
+
# Busy while auditing: `--update` never stops a server mid-audit (D232).
|
|
269
|
+
with _mcp_servers.busy(Path.home(), os.getpid()):
|
|
270
|
+
return audit_repository(
|
|
271
|
+
repository_root,
|
|
272
|
+
config_path,
|
|
273
|
+
changed_only,
|
|
274
|
+
run_analyzers,
|
|
275
|
+
format,
|
|
276
|
+
record_history,
|
|
277
|
+
baseline_path,
|
|
278
|
+
write_baseline,
|
|
279
|
+
include_prompt,
|
|
280
|
+
# Interactive door never assumes go (D27); CLI default is "run".
|
|
281
|
+
action=action,
|
|
282
|
+
roots=ledger.current(),
|
|
283
|
+
output_path=output_path,
|
|
284
|
+
)
|
|
281
285
|
except ANTICIPATED_REFUSALS as refusal:
|
|
282
286
|
raise tool_error(str(refusal)) from refusal
|
|
283
287
|
|
|
@@ -548,7 +552,12 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
548
552
|
|
|
549
553
|
def main(argv: list[str] | None = None) -> int:
|
|
550
554
|
args = _parser().parse_args(argv)
|
|
551
|
-
|
|
555
|
+
# Recorded so `--update` can stop this server once it is stale (D232).
|
|
556
|
+
_mcp_servers.register(Path.home(), os.getpid(), VERSION)
|
|
557
|
+
try:
|
|
558
|
+
create_server(roots=allowed_roots(tuple(args.allow_root))).run("stdio")
|
|
559
|
+
finally:
|
|
560
|
+
_mcp_servers.unregister(Path.home(), os.getpid())
|
|
552
561
|
return 0
|
|
553
562
|
|
|
554
563
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Written by the Claude Sonnet test seat (Codex at its usage limit); Codex reviews.
|
|
2
|
+
|
|
3
|
+
His words: 'The CI is ridiculously unacceptable'. The evidence: Quality Gates
|
|
4
|
+
ran twice per PR (push on every branch plus pull_request), MA audited itself
|
|
5
|
+
twice (maintainability.yml plus the Quality Gates audit job), a Windows probe
|
|
6
|
+
failed every run while blocking nothing, and Sonar ran on every PR.
|
|
7
|
+
|
|
8
|
+
The required checks must still run on every pull_request, or merges deadlock;
|
|
9
|
+
that guard lives in test_workflow_supply_chain.py.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from _workflow_text import jobs, triggers
|
|
18
|
+
|
|
19
|
+
WORKFLOWS = Path(__file__).resolve().parents[1] / ".github" / "workflows"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_quality_gates_push_is_limited_to_main_so_a_pr_runs_once() -> None:
|
|
23
|
+
"""No push trigger at all (his pipeline lint: a merge never re-runs
|
|
24
|
+
tests), or one limited to main."""
|
|
25
|
+
push = triggers("quality-gates.yml").get("push")
|
|
26
|
+
if push is None:
|
|
27
|
+
return
|
|
28
|
+
body = " ".join(s.strip() for s in push)
|
|
29
|
+
assert re.search(r"branches:\s*\[\s*main\s*\]", body) or (
|
|
30
|
+
"branches:" in body and re.search(r"-\s*main\b", body)
|
|
31
|
+
), f"push must be absent or restricted to branches: [main]; got {body!r}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_maintainability_workflow_does_not_audit_every_pull_request_again() -> None:
|
|
35
|
+
assert "pull_request" not in triggers("maintainability.yml")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_no_windows_job_runs_at_all() -> None:
|
|
39
|
+
"""Decision 18 (his words: "just turn this shit off"): Windows is not
|
|
40
|
+
tested in CI; Windows users report problems as issues or PRs."""
|
|
41
|
+
assert "probe-windows" not in jobs("quality-gates.yml")
|
|
42
|
+
for path in WORKFLOWS.glob("*.yml"):
|
|
43
|
+
assert "windows-" not in path.read_text(encoding="utf-8"), path.name
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_sonar_does_not_run_on_pull_requests() -> None:
|
|
47
|
+
condition = jobs("quality-gates.yml")["sonar"]["if"]
|
|
48
|
+
assert condition, "sonar needs an `if:`"
|
|
49
|
+
assert "pull_request" not in condition
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _runs_on_pull_request(condition: str) -> bool:
|
|
53
|
+
"""True when an `if:` leaves the job running on pull_request."""
|
|
54
|
+
if not condition:
|
|
55
|
+
return True
|
|
56
|
+
if "!= 'pull_request'" in condition:
|
|
57
|
+
return False
|
|
58
|
+
return "pull_request" in condition or "!= 'push'" in condition
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _job_bodies(workflow: str) -> dict[str, str]:
|
|
62
|
+
"""Job id -> the job's raw text, so a test can read `runs-on` and steps."""
|
|
63
|
+
from _workflow_text import _code_lines, _sub_blocks, _top_block
|
|
64
|
+
|
|
65
|
+
blocks = _sub_blocks(_top_block(_code_lines(workflow), "jobs"), 2)
|
|
66
|
+
return {job_id: "\n".join(body) for job_id, body in blocks.items()}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_no_macos_job_runs_in_ci() -> None:
|
|
70
|
+
"""His decision (2026-10-15, option 1): each test runs once, on Linux
|
|
71
|
+
`verify`. macOS is covered by the local gate on his Mac."""
|
|
72
|
+
assert "verify-macos" not in jobs("quality-gates.yml")
|
|
73
|
+
for path in WORKFLOWS.glob("*.yml"):
|
|
74
|
+
for job_id, job in jobs(path.name).items():
|
|
75
|
+
assert "macos" not in job["name"].lower(), f"{path.name}:{job_id} name"
|
|
76
|
+
for job_id, body in _job_bodies(path.name).items():
|
|
77
|
+
runs_on = re.findall(r"^\s*runs-on:\s*(.*)$", body, flags=re.M)
|
|
78
|
+
assert not any("macos" in value.lower() for value in runs_on), (
|
|
79
|
+
f"{path.name}:{job_id} runs on macOS"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_verify_does_not_run_on_a_merge_to_main() -> None:
|
|
84
|
+
"""Tests run once, on the pull request; a push to main does not rerun them."""
|
|
85
|
+
condition = jobs("quality-gates.yml")["verify"]["if"]
|
|
86
|
+
assert condition, "verify needs an `if:` that excludes push"
|
|
87
|
+
assert "github.event_name != 'push'" in condition, condition
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_exactly_one_job_runs_the_test_suite_on_pull_requests() -> None:
|
|
91
|
+
bodies = _job_bodies("quality-gates.yml")
|
|
92
|
+
conditions = jobs("quality-gates.yml")
|
|
93
|
+
runners = [
|
|
94
|
+
job_id
|
|
95
|
+
for job_id, body in bodies.items()
|
|
96
|
+
if "pytest" in body and _runs_on_pull_request(conditions[job_id]["if"])
|
|
97
|
+
]
|
|
98
|
+
assert runners == ["verify"], f"jobs running pytest on pull_request: {runners}"
|