maintainability-agent 2.8.0__tar.gz → 2.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {maintainability_agent-2.8.0/src/maintainability_agent.egg-info → maintainability_agent-2.9.0}/PKG-INFO +50 -56
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/README.md +49 -55
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/pyproject.toml +1 -1
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0/src/maintainability_agent.egg-info}/PKG-INFO +50 -56
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_agent.egg-info/SOURCES.txt +6 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_arguments.py +23 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_conformance.py +51 -9
- maintainability_agent-2.9.0/src/maintainability_audit/_precommit.py +259 -0
- maintainability_agent-2.9.0/src/maintainability_audit/_precommit_install.py +229 -0
- maintainability_agent-2.9.0/src/maintainability_audit/_precommit_view.py +80 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_run_comparison.py +9 -3
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_safe_write.py +46 -1
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/baseline.py +5 -1
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/cli.py +70 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/config.py +67 -2
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/git_tools.py +88 -2
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_estimate_claims.py +5 -0
- maintainability_agent-2.9.0/tests/test_anchor_and_mode.py +139 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_authorship_gates.py +36 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_evidence_properties.py +3 -1
- maintainability_agent-2.9.0/tests/test_operator_named_paths.py +113 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_platform_claim.py +25 -15
- maintainability_agent-2.9.0/tests/test_precommit_staged.py +372 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_prove_falsifiers.py +61 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_readme_claims.py +134 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scope_conformance.py +52 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_three_presentations.py +3 -1
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_tree_chosen_spawn.py +76 -27
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_write_route_class.py +15 -2
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/LICENSE +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/setup.cfg +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_anchor.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_discovery.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_pillars.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_scan_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_test_execution.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_work_order.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/mcp_server.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/prompts.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/renderers.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/report.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_added_lines.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_anchor_disclosure.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_architecture.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_attestation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_audit_components.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_backfill.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_bands.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_cli.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_config_shape.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_corroborate.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_dead_code.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declared_authorship.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_determinism.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_discovery.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_docs_links.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_economic_context.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_format_ask.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_git_argv.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_history.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_history_window.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_html_executive.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_java_scored.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_mcp_server.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_population_floors.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_promises.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_recurrence.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_release_plan.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_roles_recorded.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_root_grants.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_runner.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_sarif.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scan_history.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scanning.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_skill_install.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_source_index.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_suite_isolation.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_test_commands.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_trends.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_unread_code.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_version_claim.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_work_order.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/tests/test_written_record.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maintainability-agent
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -39,12 +39,12 @@ Dynamic: license-file
|
|
|
39
39
|
|
|
40
40
|
# Maintainability Agent
|
|
41
41
|
|
|
42
|
-

|
|
42
|
+

|
|
43
43
|
|
|
44
44
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
45
45
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
46
46
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
47
|
-
Version **2.
|
|
47
|
+
Version **2.9.0**.
|
|
48
48
|
|
|
49
49
|
**Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
|
|
50
50
|
*and* fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -201,6 +201,8 @@ integration](docs/ide-agent-integration.md).
|
|
|
201
201
|
|
|
202
202
|
## Automation / CI: CLI
|
|
203
203
|
|
|
204
|
+

|
|
205
|
+
|
|
204
206
|
Use the CLI for scripts, repeatable automation, and CI gates. Copy the example
|
|
205
207
|
config to your repo root as `maintainability-agent.json`, then:
|
|
206
208
|
|
|
@@ -260,6 +262,30 @@ maintainability-agent \
|
|
|
260
262
|
The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
|
|
261
263
|
has the history of why this was the hole under the product's central claim.
|
|
262
264
|
|
|
265
|
+
### Before the commit
|
|
266
|
+
|
|
267
|
+
The gate above runs after the work is done. `--staged` runs while it is still in
|
|
268
|
+
the author's hands:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
maintainability-agent --install-precommit-hook # writes .git/hooks/pre-commit
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
It scans **the index, not the working tree** — stage half a file with `git add
|
|
275
|
+
-p` and keep typing, and what gets measured is what the commit will actually
|
|
276
|
+
contain. Clean, it prints nothing and exits 0. Breaching, it names each path,
|
|
277
|
+
line and remedy and exits 1; `--format json` gives an agent the same findings.
|
|
278
|
+
|
|
279
|
+
It is not a small audit. It produces **no score**, because a diff has no
|
|
280
|
+
population to draw a rate from — only threshold breaches, including a `# noqa`
|
|
281
|
+
this change added. It applies no repository gates: a missing README is a
|
|
282
|
+
property of the repository, not of your diff. And it runs nothing and writes
|
|
283
|
+
nothing, so it costs 0.17s here against the full audit's 266 — a hook slower
|
|
284
|
+
than the author's patience is one they uninstall.
|
|
285
|
+
|
|
286
|
+
`--install-precommit-hook` refuses to replace a hook it did not write, printing
|
|
287
|
+
the line to add to yours instead, and honours `core.hooksPath`.
|
|
288
|
+
|
|
263
289
|
## What it analyzes
|
|
264
290
|
|
|
265
291
|
The deterministic scanner reads code from your repo (no LLM calls) and produces
|
|
@@ -322,42 +348,16 @@ Any language **not** in that table — Go, Rust, Ruby, PHP, Kotlin, and the rest
|
|
|
322
348
|
is **not parsed for declarations by the built-in scanner.** Its files still count
|
|
323
349
|
toward repo size, but the built-ins produce no function-size, complexity,
|
|
324
350
|
duplication or dead-code findings for them, and the estimate leans on whatever
|
|
325
|
-
evidence *is* available
|
|
326
|
-
can withhold the grade
|
|
327
|
-
|
|
328
|
-
**Which analyzer covers which language** (the opt-in pool, when installed):
|
|
329
|
-
|
|
330
|
-
| Language | Built-in scanner | External analyzer |
|
|
331
|
-
|---|---|---|
|
|
332
|
-
| Python | `ast`, exact | ruff, radon, mypy, vulture, complexipy, interrogate, pydocstyle, pylint, cohesion |
|
|
333
|
-
| Java | dedicated scanner | lizard, PMD, Checkstyle, SpotBugs |
|
|
334
|
-
| C / C++ / C# | dedicated scanners | lizard, multimetric |
|
|
335
|
-
| **Fortran** (free- and fixed-form) | dedicated scanner | **fortitude** — 100+ rules; **lizard** — complexity, NLOC, params |
|
|
336
|
-
| **COBOL** | dedicated scanner | **none** — no offline analyzer in the catalog reads it |
|
|
337
|
-
| JS / TS / JSX / TSX | brace scanner | ESLint, lizard, jscpd |
|
|
338
|
-
|
|
339
|
-
Fortran reached parity in 1.6.0: lizard had read it for years behind a
|
|
340
|
-
stale catalog row, so it came out `not-applicable` and never ran. A lint fails
|
|
341
|
-
the build if a parsed language has no analyzer measuring complexity — **COBOL is
|
|
342
|
-
the one disclosed exemption**, because the tooling that reads it is licensed and
|
|
343
|
-
host-resident, so its external tier is empty and the report says so.
|
|
344
|
-
|
|
345
|
-
**External analyzer adapters (opt-in pool)** — this is how coverage extends
|
|
346
|
-
beyond the built-in set. When you enable the analyzer pool, the tool shells out
|
|
347
|
-
to mature analyzers and folds their output in through per-tool
|
|
348
|
-
[adapters](docs/adapters.md): **lizard** (cyclomatic complexity across ~a dozen
|
|
349
|
-
languages), **jscpd** (cross-language duplication), **ESLint** (JS/TS),
|
|
350
|
-
**PMD** / **SpotBugs** (JVM), and others in the catalog. These run only when
|
|
351
|
-
selected *and* installed (acquisition is opt-in and off by default), and where
|
|
352
|
-
they measured a full concept set they become the *primary* evidence, with the
|
|
353
|
-
built-ins as the fallback.
|
|
351
|
+
evidence *is* available — which is why the report discloses its evidence tier
|
|
352
|
+
and can withhold the grade.
|
|
354
353
|
|
|
355
354
|
So: **first-class today is Python** (and TypeScript for semantics); every other
|
|
356
355
|
parsed language is bounded-but-real; anything outside the table is only as
|
|
357
|
-
covered as the analyzer you point at it
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
356
|
+
covered as the analyzer you point at it. Per-language accuracy and limits:
|
|
357
|
+
[docs/language-support.md](docs/language-support.md). Which analyzer covers
|
|
358
|
+
which language, how the opt-in pool extends coverage past the built-in set, and
|
|
359
|
+
why COBOL's external tier is empty:
|
|
360
|
+
[docs/adapters.md](docs/adapters.md#which-analyzer-covers-which-language).
|
|
361
361
|
|
|
362
362
|
## What it produces
|
|
363
363
|
|
|
@@ -430,35 +430,29 @@ and costs roughly a grade — use `fetch-depth: 0`.)
|
|
|
430
430
|
|
|
431
431
|
## Platform support
|
|
432
432
|
|
|
433
|
-
**POSIX.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
433
|
+
**POSIX. Windows is not claimed, for a measured reason.** A `windows-latest` probe
|
|
434
|
+
found most failures in two POSIX-only calls, `os.fchmod` and `os.O_DIRECTORY`. The
|
|
435
|
+
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
436
|
+
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
437
|
+
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
438
|
+
buys green by weakening the supported ones.**
|
|
439
439
|
|
|
440
440
|
## Invokable skill / slash command
|
|
441
441
|
|
|
442
442
|
This repo ships a portable skill under
|
|
443
|
-
[`skills/maintainability-agent/`](skills/maintainability-agent/) so
|
|
444
|
-
`/maintainability-agent` is one keystroke away
|
|
445
|
-
|
|
443
|
+
[`skills/maintainability-agent/`](skills/maintainability-agent/), so
|
|
444
|
+
`/maintainability-agent` is one keystroke away in Claude Code, Codex and
|
|
445
|
+
Copilot Chat:
|
|
446
446
|
|
|
447
447
|
```bash
|
|
448
448
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
-
Re-run after every upgrade
|
|
452
|
-
list of differences
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
| Codex / OpenAI | via `skills/maintainability-agent/agents/openai.yaml` | per Codex's skills convention |
|
|
457
|
-
| Claude Code | `skills/maintainability-agent/` → `~/.claude/skills/maintainability-agent/` (or repo `.claude/skills/`) | `/maintainability-agent` |
|
|
458
|
-
| GitHub Copilot (VS Code) | `skills/maintainability-agent/copilot/maintainability-agent.prompt.md` → `<repo>/.github/prompts/` | `/maintainability-agent` in Copilot Chat |
|
|
459
|
-
|
|
460
|
-
For always-on guidance instead of an invokable skill, use
|
|
461
|
-
`--init-agent-standards` (see [docs/ide-agent-integration.md](docs/ide-agent-integration.md)).
|
|
451
|
+
Re-run it after every upgrade — a drifted skill teaches agents a dead workflow,
|
|
452
|
+
so a differing installed copy is refused with the list of differences. Per-host
|
|
453
|
+
install destinations, and `--init-agent-standards` for always-on guidance
|
|
454
|
+
instead of an invokable skill:
|
|
455
|
+
[docs/ide-agent-integration.md](docs/ide-agent-integration.md#invokable-skill--slash-command).
|
|
462
456
|
|
|
463
457
|
## GitHub Action
|
|
464
458
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Maintainability Agent
|
|
2
2
|
|
|
3
|
-

|
|
3
|
+

|
|
4
4
|
|
|
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 **2.
|
|
8
|
+
Version **2.9.0**.
|
|
9
9
|
|
|
10
10
|
**Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
|
|
11
11
|
*and* fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -162,6 +162,8 @@ integration](docs/ide-agent-integration.md).
|
|
|
162
162
|
|
|
163
163
|
## Automation / CI: CLI
|
|
164
164
|
|
|
165
|
+

|
|
166
|
+
|
|
165
167
|
Use the CLI for scripts, repeatable automation, and CI gates. Copy the example
|
|
166
168
|
config to your repo root as `maintainability-agent.json`, then:
|
|
167
169
|
|
|
@@ -221,6 +223,30 @@ maintainability-agent \
|
|
|
221
223
|
The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
|
|
222
224
|
has the history of why this was the hole under the product's central claim.
|
|
223
225
|
|
|
226
|
+
### Before the commit
|
|
227
|
+
|
|
228
|
+
The gate above runs after the work is done. `--staged` runs while it is still in
|
|
229
|
+
the author's hands:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
maintainability-agent --install-precommit-hook # writes .git/hooks/pre-commit
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
It scans **the index, not the working tree** — stage half a file with `git add
|
|
236
|
+
-p` and keep typing, and what gets measured is what the commit will actually
|
|
237
|
+
contain. Clean, it prints nothing and exits 0. Breaching, it names each path,
|
|
238
|
+
line and remedy and exits 1; `--format json` gives an agent the same findings.
|
|
239
|
+
|
|
240
|
+
It is not a small audit. It produces **no score**, because a diff has no
|
|
241
|
+
population to draw a rate from — only threshold breaches, including a `# noqa`
|
|
242
|
+
this change added. It applies no repository gates: a missing README is a
|
|
243
|
+
property of the repository, not of your diff. And it runs nothing and writes
|
|
244
|
+
nothing, so it costs 0.17s here against the full audit's 266 — a hook slower
|
|
245
|
+
than the author's patience is one they uninstall.
|
|
246
|
+
|
|
247
|
+
`--install-precommit-hook` refuses to replace a hook it did not write, printing
|
|
248
|
+
the line to add to yours instead, and honours `core.hooksPath`.
|
|
249
|
+
|
|
224
250
|
## What it analyzes
|
|
225
251
|
|
|
226
252
|
The deterministic scanner reads code from your repo (no LLM calls) and produces
|
|
@@ -283,42 +309,16 @@ Any language **not** in that table — Go, Rust, Ruby, PHP, Kotlin, and the rest
|
|
|
283
309
|
is **not parsed for declarations by the built-in scanner.** Its files still count
|
|
284
310
|
toward repo size, but the built-ins produce no function-size, complexity,
|
|
285
311
|
duplication or dead-code findings for them, and the estimate leans on whatever
|
|
286
|
-
evidence *is* available
|
|
287
|
-
can withhold the grade
|
|
288
|
-
|
|
289
|
-
**Which analyzer covers which language** (the opt-in pool, when installed):
|
|
290
|
-
|
|
291
|
-
| Language | Built-in scanner | External analyzer |
|
|
292
|
-
|---|---|---|
|
|
293
|
-
| Python | `ast`, exact | ruff, radon, mypy, vulture, complexipy, interrogate, pydocstyle, pylint, cohesion |
|
|
294
|
-
| Java | dedicated scanner | lizard, PMD, Checkstyle, SpotBugs |
|
|
295
|
-
| C / C++ / C# | dedicated scanners | lizard, multimetric |
|
|
296
|
-
| **Fortran** (free- and fixed-form) | dedicated scanner | **fortitude** — 100+ rules; **lizard** — complexity, NLOC, params |
|
|
297
|
-
| **COBOL** | dedicated scanner | **none** — no offline analyzer in the catalog reads it |
|
|
298
|
-
| JS / TS / JSX / TSX | brace scanner | ESLint, lizard, jscpd |
|
|
299
|
-
|
|
300
|
-
Fortran reached parity in 1.6.0: lizard had read it for years behind a
|
|
301
|
-
stale catalog row, so it came out `not-applicable` and never ran. A lint fails
|
|
302
|
-
the build if a parsed language has no analyzer measuring complexity — **COBOL is
|
|
303
|
-
the one disclosed exemption**, because the tooling that reads it is licensed and
|
|
304
|
-
host-resident, so its external tier is empty and the report says so.
|
|
305
|
-
|
|
306
|
-
**External analyzer adapters (opt-in pool)** — this is how coverage extends
|
|
307
|
-
beyond the built-in set. When you enable the analyzer pool, the tool shells out
|
|
308
|
-
to mature analyzers and folds their output in through per-tool
|
|
309
|
-
[adapters](docs/adapters.md): **lizard** (cyclomatic complexity across ~a dozen
|
|
310
|
-
languages), **jscpd** (cross-language duplication), **ESLint** (JS/TS),
|
|
311
|
-
**PMD** / **SpotBugs** (JVM), and others in the catalog. These run only when
|
|
312
|
-
selected *and* installed (acquisition is opt-in and off by default), and where
|
|
313
|
-
they measured a full concept set they become the *primary* evidence, with the
|
|
314
|
-
built-ins as the fallback.
|
|
312
|
+
evidence *is* available — which is why the report discloses its evidence tier
|
|
313
|
+
and can withhold the grade.
|
|
315
314
|
|
|
316
315
|
So: **first-class today is Python** (and TypeScript for semantics); every other
|
|
317
316
|
parsed language is bounded-but-real; anything outside the table is only as
|
|
318
|
-
covered as the analyzer you point at it
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
317
|
+
covered as the analyzer you point at it. Per-language accuracy and limits:
|
|
318
|
+
[docs/language-support.md](docs/language-support.md). Which analyzer covers
|
|
319
|
+
which language, how the opt-in pool extends coverage past the built-in set, and
|
|
320
|
+
why COBOL's external tier is empty:
|
|
321
|
+
[docs/adapters.md](docs/adapters.md#which-analyzer-covers-which-language).
|
|
322
322
|
|
|
323
323
|
## What it produces
|
|
324
324
|
|
|
@@ -391,35 +391,29 @@ and costs roughly a grade — use `fetch-depth: 0`.)
|
|
|
391
391
|
|
|
392
392
|
## Platform support
|
|
393
393
|
|
|
394
|
-
**POSIX.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
394
|
+
**POSIX. Windows is not claimed, for a measured reason.** A `windows-latest` probe
|
|
395
|
+
found most failures in two POSIX-only calls, `os.fchmod` and `os.O_DIRECTORY`. The
|
|
396
|
+
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
397
|
+
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
398
|
+
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
399
|
+
buys green by weakening the supported ones.**
|
|
400
400
|
|
|
401
401
|
## Invokable skill / slash command
|
|
402
402
|
|
|
403
403
|
This repo ships a portable skill under
|
|
404
|
-
[`skills/maintainability-agent/`](skills/maintainability-agent/) so
|
|
405
|
-
`/maintainability-agent` is one keystroke away
|
|
406
|
-
|
|
404
|
+
[`skills/maintainability-agent/`](skills/maintainability-agent/), so
|
|
405
|
+
`/maintainability-agent` is one keystroke away in Claude Code, Codex and
|
|
406
|
+
Copilot Chat:
|
|
407
407
|
|
|
408
408
|
```bash
|
|
409
409
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
410
410
|
```
|
|
411
411
|
|
|
412
|
-
Re-run after every upgrade
|
|
413
|
-
list of differences
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
| Codex / OpenAI | via `skills/maintainability-agent/agents/openai.yaml` | per Codex's skills convention |
|
|
418
|
-
| Claude Code | `skills/maintainability-agent/` → `~/.claude/skills/maintainability-agent/` (or repo `.claude/skills/`) | `/maintainability-agent` |
|
|
419
|
-
| GitHub Copilot (VS Code) | `skills/maintainability-agent/copilot/maintainability-agent.prompt.md` → `<repo>/.github/prompts/` | `/maintainability-agent` in Copilot Chat |
|
|
420
|
-
|
|
421
|
-
For always-on guidance instead of an invokable skill, use
|
|
422
|
-
`--init-agent-standards` (see [docs/ide-agent-integration.md](docs/ide-agent-integration.md)).
|
|
412
|
+
Re-run it after every upgrade — a drifted skill teaches agents a dead workflow,
|
|
413
|
+
so a differing installed copy is refused with the list of differences. Per-host
|
|
414
|
+
install destinations, and `--init-agent-standards` for always-on guidance
|
|
415
|
+
instead of an invokable skill:
|
|
416
|
+
[docs/ide-agent-integration.md](docs/ide-agent-integration.md#invokable-skill--slash-command).
|
|
423
417
|
|
|
424
418
|
## GitHub Action
|
|
425
419
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "maintainability-agent"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.9.0"
|
|
8
8
|
description = "Maintainability gate and AI remediation prompt generator for CI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# 3.11, not 3.10. `_discovery`, `_pillars` and `_runner` all import
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maintainability-agent
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -39,12 +39,12 @@ Dynamic: license-file
|
|
|
39
39
|
|
|
40
40
|
# Maintainability Agent
|
|
41
41
|
|
|
42
|
-

|
|
42
|
+

|
|
43
43
|
|
|
44
44
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
45
45
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
46
46
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
47
|
-
Version **2.
|
|
47
|
+
Version **2.9.0**.
|
|
48
48
|
|
|
49
49
|
**Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
|
|
50
50
|
*and* fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -201,6 +201,8 @@ integration](docs/ide-agent-integration.md).
|
|
|
201
201
|
|
|
202
202
|
## Automation / CI: CLI
|
|
203
203
|
|
|
204
|
+

|
|
205
|
+
|
|
204
206
|
Use the CLI for scripts, repeatable automation, and CI gates. Copy the example
|
|
205
207
|
config to your repo root as `maintainability-agent.json`, then:
|
|
206
208
|
|
|
@@ -260,6 +262,30 @@ maintainability-agent \
|
|
|
260
262
|
The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
|
|
261
263
|
has the history of why this was the hole under the product's central claim.
|
|
262
264
|
|
|
265
|
+
### Before the commit
|
|
266
|
+
|
|
267
|
+
The gate above runs after the work is done. `--staged` runs while it is still in
|
|
268
|
+
the author's hands:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
maintainability-agent --install-precommit-hook # writes .git/hooks/pre-commit
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
It scans **the index, not the working tree** — stage half a file with `git add
|
|
275
|
+
-p` and keep typing, and what gets measured is what the commit will actually
|
|
276
|
+
contain. Clean, it prints nothing and exits 0. Breaching, it names each path,
|
|
277
|
+
line and remedy and exits 1; `--format json` gives an agent the same findings.
|
|
278
|
+
|
|
279
|
+
It is not a small audit. It produces **no score**, because a diff has no
|
|
280
|
+
population to draw a rate from — only threshold breaches, including a `# noqa`
|
|
281
|
+
this change added. It applies no repository gates: a missing README is a
|
|
282
|
+
property of the repository, not of your diff. And it runs nothing and writes
|
|
283
|
+
nothing, so it costs 0.17s here against the full audit's 266 — a hook slower
|
|
284
|
+
than the author's patience is one they uninstall.
|
|
285
|
+
|
|
286
|
+
`--install-precommit-hook` refuses to replace a hook it did not write, printing
|
|
287
|
+
the line to add to yours instead, and honours `core.hooksPath`.
|
|
288
|
+
|
|
263
289
|
## What it analyzes
|
|
264
290
|
|
|
265
291
|
The deterministic scanner reads code from your repo (no LLM calls) and produces
|
|
@@ -322,42 +348,16 @@ Any language **not** in that table — Go, Rust, Ruby, PHP, Kotlin, and the rest
|
|
|
322
348
|
is **not parsed for declarations by the built-in scanner.** Its files still count
|
|
323
349
|
toward repo size, but the built-ins produce no function-size, complexity,
|
|
324
350
|
duplication or dead-code findings for them, and the estimate leans on whatever
|
|
325
|
-
evidence *is* available
|
|
326
|
-
can withhold the grade
|
|
327
|
-
|
|
328
|
-
**Which analyzer covers which language** (the opt-in pool, when installed):
|
|
329
|
-
|
|
330
|
-
| Language | Built-in scanner | External analyzer |
|
|
331
|
-
|---|---|---|
|
|
332
|
-
| Python | `ast`, exact | ruff, radon, mypy, vulture, complexipy, interrogate, pydocstyle, pylint, cohesion |
|
|
333
|
-
| Java | dedicated scanner | lizard, PMD, Checkstyle, SpotBugs |
|
|
334
|
-
| C / C++ / C# | dedicated scanners | lizard, multimetric |
|
|
335
|
-
| **Fortran** (free- and fixed-form) | dedicated scanner | **fortitude** — 100+ rules; **lizard** — complexity, NLOC, params |
|
|
336
|
-
| **COBOL** | dedicated scanner | **none** — no offline analyzer in the catalog reads it |
|
|
337
|
-
| JS / TS / JSX / TSX | brace scanner | ESLint, lizard, jscpd |
|
|
338
|
-
|
|
339
|
-
Fortran reached parity in 1.6.0: lizard had read it for years behind a
|
|
340
|
-
stale catalog row, so it came out `not-applicable` and never ran. A lint fails
|
|
341
|
-
the build if a parsed language has no analyzer measuring complexity — **COBOL is
|
|
342
|
-
the one disclosed exemption**, because the tooling that reads it is licensed and
|
|
343
|
-
host-resident, so its external tier is empty and the report says so.
|
|
344
|
-
|
|
345
|
-
**External analyzer adapters (opt-in pool)** — this is how coverage extends
|
|
346
|
-
beyond the built-in set. When you enable the analyzer pool, the tool shells out
|
|
347
|
-
to mature analyzers and folds their output in through per-tool
|
|
348
|
-
[adapters](docs/adapters.md): **lizard** (cyclomatic complexity across ~a dozen
|
|
349
|
-
languages), **jscpd** (cross-language duplication), **ESLint** (JS/TS),
|
|
350
|
-
**PMD** / **SpotBugs** (JVM), and others in the catalog. These run only when
|
|
351
|
-
selected *and* installed (acquisition is opt-in and off by default), and where
|
|
352
|
-
they measured a full concept set they become the *primary* evidence, with the
|
|
353
|
-
built-ins as the fallback.
|
|
351
|
+
evidence *is* available — which is why the report discloses its evidence tier
|
|
352
|
+
and can withhold the grade.
|
|
354
353
|
|
|
355
354
|
So: **first-class today is Python** (and TypeScript for semantics); every other
|
|
356
355
|
parsed language is bounded-but-real; anything outside the table is only as
|
|
357
|
-
covered as the analyzer you point at it
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
356
|
+
covered as the analyzer you point at it. Per-language accuracy and limits:
|
|
357
|
+
[docs/language-support.md](docs/language-support.md). Which analyzer covers
|
|
358
|
+
which language, how the opt-in pool extends coverage past the built-in set, and
|
|
359
|
+
why COBOL's external tier is empty:
|
|
360
|
+
[docs/adapters.md](docs/adapters.md#which-analyzer-covers-which-language).
|
|
361
361
|
|
|
362
362
|
## What it produces
|
|
363
363
|
|
|
@@ -430,35 +430,29 @@ and costs roughly a grade — use `fetch-depth: 0`.)
|
|
|
430
430
|
|
|
431
431
|
## Platform support
|
|
432
432
|
|
|
433
|
-
**POSIX.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
433
|
+
**POSIX. Windows is not claimed, for a measured reason.** A `windows-latest` probe
|
|
434
|
+
found most failures in two POSIX-only calls, `os.fchmod` and `os.O_DIRECTORY`. The
|
|
435
|
+
bounded, symlink-refusing write works through a *file descriptor*, so a validated
|
|
436
|
+
path cannot be swapped for a symlink before the write lands — Windows has no
|
|
437
|
+
equivalent and the portable rewrite is the hole. **An unsupported platform never
|
|
438
|
+
buys green by weakening the supported ones.**
|
|
439
439
|
|
|
440
440
|
## Invokable skill / slash command
|
|
441
441
|
|
|
442
442
|
This repo ships a portable skill under
|
|
443
|
-
[`skills/maintainability-agent/`](skills/maintainability-agent/) so
|
|
444
|
-
`/maintainability-agent` is one keystroke away
|
|
445
|
-
|
|
443
|
+
[`skills/maintainability-agent/`](skills/maintainability-agent/), so
|
|
444
|
+
`/maintainability-agent` is one keystroke away in Claude Code, Codex and
|
|
445
|
+
Copilot Chat:
|
|
446
446
|
|
|
447
447
|
```bash
|
|
448
448
|
maintainability-agent --install-skill # writes ~/.claude/skills
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
-
Re-run after every upgrade
|
|
452
|
-
list of differences
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
| Codex / OpenAI | via `skills/maintainability-agent/agents/openai.yaml` | per Codex's skills convention |
|
|
457
|
-
| Claude Code | `skills/maintainability-agent/` → `~/.claude/skills/maintainability-agent/` (or repo `.claude/skills/`) | `/maintainability-agent` |
|
|
458
|
-
| GitHub Copilot (VS Code) | `skills/maintainability-agent/copilot/maintainability-agent.prompt.md` → `<repo>/.github/prompts/` | `/maintainability-agent` in Copilot Chat |
|
|
459
|
-
|
|
460
|
-
For always-on guidance instead of an invokable skill, use
|
|
461
|
-
`--init-agent-standards` (see [docs/ide-agent-integration.md](docs/ide-agent-integration.md)).
|
|
451
|
+
Re-run it after every upgrade — a drifted skill teaches agents a dead workflow,
|
|
452
|
+
so a differing installed copy is refused with the list of differences. Per-host
|
|
453
|
+
install destinations, and `--init-agent-standards` for always-on guidance
|
|
454
|
+
instead of an invokable skill:
|
|
455
|
+
[docs/ide-agent-integration.md](docs/ide-agent-integration.md#invokable-skill--slash-command).
|
|
462
456
|
|
|
463
457
|
## GitHub Action
|
|
464
458
|
|
|
@@ -58,6 +58,9 @@ src/maintainability_audit/_metric_adapters.py
|
|
|
58
58
|
src/maintainability_audit/_metrics_types.py
|
|
59
59
|
src/maintainability_audit/_pillars.py
|
|
60
60
|
src/maintainability_audit/_practice.py
|
|
61
|
+
src/maintainability_audit/_precommit.py
|
|
62
|
+
src/maintainability_audit/_precommit_install.py
|
|
63
|
+
src/maintainability_audit/_precommit_view.py
|
|
61
64
|
src/maintainability_audit/_pressures.py
|
|
62
65
|
src/maintainability_audit/_ranges_c.py
|
|
63
66
|
src/maintainability_audit/_ranges_cobol.py
|
|
@@ -144,6 +147,7 @@ tests/test_analyzer_provenance_exclusions.py
|
|
|
144
147
|
tests/test_analyzer_scoring_path.py
|
|
145
148
|
tests/test_analyzer_spread_range.py
|
|
146
149
|
tests/test_analyzer_xml_bounds.py
|
|
150
|
+
tests/test_anchor_and_mode.py
|
|
147
151
|
tests/test_anchor_disclosure.py
|
|
148
152
|
tests/test_annotations_match_behaviour.py
|
|
149
153
|
tests/test_anticipated_refusals.py
|
|
@@ -255,6 +259,7 @@ tests/test_migration_1_0.py
|
|
|
255
259
|
tests/test_near_duplicates.py
|
|
256
260
|
tests/test_network_disclosure.py
|
|
257
261
|
tests/test_one_setup_across_surfaces_class.py
|
|
262
|
+
tests/test_operator_named_paths.py
|
|
258
263
|
tests/test_pattern_budget.py
|
|
259
264
|
tests/test_phase6_claims.py
|
|
260
265
|
tests/test_pillars_and_practice.py
|
|
@@ -264,6 +269,7 @@ tests/test_pmd_audit_closures.py
|
|
|
264
269
|
tests/test_pool_runs_by_config.py
|
|
265
270
|
tests/test_population_floors.py
|
|
266
271
|
tests/test_practice_nested_gates_class.py
|
|
272
|
+
tests/test_precommit_staged.py
|
|
267
273
|
tests/test_presentation_refusals.py
|
|
268
274
|
tests/test_promises.py
|
|
269
275
|
tests/test_prompt_escalation_once.py
|
{maintainability_agent-2.8.0 → maintainability_agent-2.9.0}/src/maintainability_audit/_arguments.py
RENAMED
|
@@ -23,8 +23,23 @@ def _add_gate_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
23
23
|
Split from `add_arguments` when the conformance flags took it past this
|
|
24
24
|
project's own function-length gate — which is the gate doing its job on
|
|
25
25
|
the change that added a gate.
|
|
26
|
+
|
|
27
|
+
`--staged` belongs here rather than with the artifact flags: it
|
|
28
|
+
produces no artifact and decides whether work proceeds, which is what
|
|
29
|
+
every other flag in this group does. It differs only in *when* — a
|
|
30
|
+
commit rather than a build — and that is the point of it.
|
|
26
31
|
"""
|
|
27
32
|
parser.add_argument("--fail-on-gate", action="store_true", help="Exit 1 when hard gates fail.")
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--staged", action="store_true",
|
|
35
|
+
help="Scan what the git index will commit, for a pre-commit hook. "
|
|
36
|
+
"Reads the index rather than the working tree, so half-staged "
|
|
37
|
+
"edits are measured as they will land. Reports threshold "
|
|
38
|
+
"breaches only and never a score — a diff has no population to "
|
|
39
|
+
"draw a rate from. Applies no repository gates, writes nothing, "
|
|
40
|
+
"and never runs the opt-in test suite. Exits 1 when something "
|
|
41
|
+
"blocks, silently 0 when nothing does.",
|
|
42
|
+
)
|
|
28
43
|
parser.add_argument(
|
|
29
44
|
"--conformance",
|
|
30
45
|
metavar="REVSPEC",
|
|
@@ -158,6 +173,14 @@ def _add_setup_actions(parser: argparse.ArgumentParser) -> None:
|
|
|
158
173
|
"exit. Re-run after every upgrade: an installed skill that "
|
|
159
174
|
"drifts from the shipped one teaches agents a dead workflow.",
|
|
160
175
|
)
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"--install-precommit-hook", action="store_true",
|
|
178
|
+
help="Write a git pre-commit hook that runs --staged, and exit. "
|
|
179
|
+
"Refuses to replace a hook this tool did not write, and "
|
|
180
|
+
"prints the line to add to that hook instead; replaces its "
|
|
181
|
+
"own without asking, because that is an upgrade. Honours "
|
|
182
|
+
"core.hooksPath.",
|
|
183
|
+
)
|
|
161
184
|
parser.add_argument(
|
|
162
185
|
"--skills-dir", default=None, metavar="DIR",
|
|
163
186
|
help="Where --install-skill writes (default: ~/.claude/skills).",
|
|
@@ -98,6 +98,49 @@ _SUPPRESSION = tuple(
|
|
|
98
98
|
)
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
def _is_quoted(text: str, start: int) -> bool:
|
|
102
|
+
"""Whether the marker at `start` is being *mentioned* rather than used.
|
|
103
|
+
|
|
104
|
+
A directive is never immediately preceded by a quote or a backtick,
|
|
105
|
+
and never sits inside an open backtick span. Prose about directives
|
|
106
|
+
does both constantly — this file's own comments do it, and so does
|
|
107
|
+
the docstring that says a marker in a docstring is not a suppression.
|
|
108
|
+
"""
|
|
109
|
+
prefix = text[:start]
|
|
110
|
+
if prefix[-1:] in {"`", "'", '"'}:
|
|
111
|
+
return True
|
|
112
|
+
return prefix.count("`") % 2 == 1
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def markers_in(text: str) -> str | None:
|
|
116
|
+
"""The suppression this line declares, or None if it only mentions one.
|
|
117
|
+
|
|
118
|
+
The one place that question is answered, because it is asked twice —
|
|
119
|
+
by the conformance record after a change, and by the pre-commit scan
|
|
120
|
+
before one — and a rule that disagrees with itself between the hook
|
|
121
|
+
and the gate blocks commits CI would pass.
|
|
122
|
+
|
|
123
|
+
D108: the marker set's own comment promised that "`# type: ignore` in
|
|
124
|
+
a docstring explaining the convention is not a suppression", and for
|
|
125
|
+
four versions nothing enforced it. The `--staged` scan found it
|
|
126
|
+
immediately, by blocking the commit of a docstring containing the
|
|
127
|
+
words `# noqa` — the first time the rule ran somewhere a false
|
|
128
|
+
positive cost something.
|
|
129
|
+
|
|
130
|
+
Still narrow, and deliberately: a marker written into ordinary prose
|
|
131
|
+
with no quoting around it is still reported. Quoting is the signal
|
|
132
|
+
that is actually reliable, and widening past it starts guessing at
|
|
133
|
+
English. This paragraph cannot give the example it would like to,
|
|
134
|
+
because writing one unquoted would report this line — which is the
|
|
135
|
+
rule demonstrating itself, and the reason the sentence stays abstract.
|
|
136
|
+
"""
|
|
137
|
+
for pattern, label in _SUPPRESSION:
|
|
138
|
+
match = pattern.search(text)
|
|
139
|
+
if match and not _is_quoted(text, match.start()):
|
|
140
|
+
return label
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
|
|
101
144
|
def suppressions_added(
|
|
102
145
|
added: dict[str, list[tuple[int, str]]], named: set[str]
|
|
103
146
|
) -> list[dict[str, Any]]:
|
|
@@ -120,15 +163,14 @@ def suppressions_added(
|
|
|
120
163
|
found: list[dict[str, Any]] = []
|
|
121
164
|
for path in sorted(added):
|
|
122
165
|
for line_number, text in added[path]:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
break
|
|
166
|
+
label = markers_in(text)
|
|
167
|
+
if label:
|
|
168
|
+
found.append({
|
|
169
|
+
"path": path,
|
|
170
|
+
"line": line_number,
|
|
171
|
+
"marker": label,
|
|
172
|
+
"on_named_path": path in named,
|
|
173
|
+
})
|
|
132
174
|
return found
|
|
133
175
|
|
|
134
176
|
|