maintainability-agent 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {maintainability_agent-2.2.0/src/maintainability_agent.egg-info → maintainability_agent-2.3.0}/PKG-INFO +2 -2
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/README.md +1 -1
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/pyproject.toml +1 -1
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0/src/maintainability_agent.egg-info}/PKG-INFO +2 -2
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_agent.egg-info/SOURCES.txt +2 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/__init__.py +1 -1
- maintainability_agent-2.3.0/src/maintainability_audit/_attestation.py +166 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/cli.py +12 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/config.py +1 -1
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/prompts.py +1 -0
- maintainability_agent-2.3.0/tests/test_attestation.py +151 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/LICENSE +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/setup.cfg +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_discovery.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_pillars.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_scan_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_test_execution.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_work_order.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/git_tools.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/mcp_server.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/renderers.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/report.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_added_lines.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_architecture.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_audit_components.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_backfill.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_bands.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_cli.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_config_shape.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_corroborate.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_dead_code.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declared_authorship.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_determinism.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_discovery.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_docs_links.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_economic_context.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_evidence_properties.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_format_ask.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_git_argv.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_history.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_history_window.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_html_executive.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_java_scored.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_mcp_server.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_platform_claim.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_population_floors.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_promises.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_recurrence.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_release_plan.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_roles_recorded.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_root_grants.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_runner.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_sarif.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_scan_history.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_scanning.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_skill_install.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_source_index.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_trends.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_unread_code.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_version_claim.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_work_order.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-2.2.0 → maintainability_agent-2.3.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.3.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -44,7 +44,7 @@ Dynamic: license-file
|
|
|
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.3.0**.
|
|
48
48
|
|
|
49
49
|
**Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
|
|
50
50
|
fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -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 **2.
|
|
8
|
+
Version **2.3.0**.
|
|
9
9
|
|
|
10
10
|
**Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
|
|
11
11
|
fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -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.3.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.3.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -44,7 +44,7 @@ Dynamic: license-file
|
|
|
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.3.0**.
|
|
48
48
|
|
|
49
49
|
**Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
|
|
50
50
|
fixed-form), and the JS/TS family — each by a scanner written for it, and
|
|
@@ -12,6 +12,7 @@ src/maintainability_audit/__main__.py
|
|
|
12
12
|
src/maintainability_audit/_adapters.py
|
|
13
13
|
src/maintainability_audit/_analysis.py
|
|
14
14
|
src/maintainability_audit/_aspects.py
|
|
15
|
+
src/maintainability_audit/_attestation.py
|
|
15
16
|
src/maintainability_audit/_backfill.py
|
|
16
17
|
src/maintainability_audit/_bands.py
|
|
17
18
|
src/maintainability_audit/_built_ins.py
|
|
@@ -144,6 +145,7 @@ tests/test_artifact_write_route_class.py
|
|
|
144
145
|
tests/test_aspect_coverage.py
|
|
145
146
|
tests/test_asset_snapshot_class.py
|
|
146
147
|
tests/test_ast_reading_resolves_spellings.py
|
|
148
|
+
tests/test_attestation.py
|
|
147
149
|
tests/test_audit_components.py
|
|
148
150
|
tests/test_authorization_freshness.py
|
|
149
151
|
tests/test_authorship_gates.py
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""The record a generator cannot produce about its own output.
|
|
2
|
+
|
|
3
|
+
The three mechanisms — scope conformance, suppression detection, the
|
|
4
|
+
dimension ratchet — each answer one question about a change. This composes
|
|
5
|
+
them into the artifact they were built for: a per-change record of what was
|
|
6
|
+
measured, what the agent was told to change, what it actually changed, and
|
|
7
|
+
what moved.
|
|
8
|
+
|
|
9
|
+
**Why an independent process has to emit it.** A platform that generates
|
|
10
|
+
code and then reports on its quality is producing a self-assessment. That
|
|
11
|
+
is a property of the arrangement, not a criticism of any particular one,
|
|
12
|
+
and no amount of engineering removes it. The question a reviewer asks is
|
|
13
|
+
*who checked this, and can they re-derive the check months from now* — and
|
|
14
|
+
an author cannot be the answer. This tool writes nothing, runs no model,
|
|
15
|
+
and returns the same verdict from the same inputs, which is the only reason
|
|
16
|
+
its answer can be evidence rather than an opinion.
|
|
17
|
+
|
|
18
|
+
**It is reproducible, not signed.** Every field is derived from the report
|
|
19
|
+
and the pinned inputs, and the digest at the end is over the record's own
|
|
20
|
+
content, so two runs on the same commit with the same analyzer versions
|
|
21
|
+
produce the same digest. That makes it *verifiable* — anyone can re-run and
|
|
22
|
+
compare. It is deliberately not called a signature: nothing here holds a
|
|
23
|
+
key, and claiming a cryptographic guarantee this does not provide would be
|
|
24
|
+
exactly the kind of overclaim the rest of the project spends its time
|
|
25
|
+
removing. Signing the artifact, if a caller wants that, is a step they take
|
|
26
|
+
with their own key on a file whose bytes are stable.
|
|
27
|
+
|
|
28
|
+
**What it does not establish.** The record says which files the work order
|
|
29
|
+
named and whether a checker was switched off — not whether the edits were
|
|
30
|
+
correct. It never opens the diff to judge it, and it never touches a score.
|
|
31
|
+
Review is still review.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import hashlib
|
|
37
|
+
import json
|
|
38
|
+
from typing import Any
|
|
39
|
+
|
|
40
|
+
ARTIFACT_VERSION = 1
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _verdicts(report: dict[str, Any]) -> list[str]:
|
|
44
|
+
"""One line per question that was actually asked."""
|
|
45
|
+
lines: list[str] = []
|
|
46
|
+
conformance = report.get("scope_conformance")
|
|
47
|
+
if conformance:
|
|
48
|
+
out = len(conformance["out_of_scope"])
|
|
49
|
+
silenced = conformance["suppressions_on_named_paths"]
|
|
50
|
+
lines.append(
|
|
51
|
+
f"- **Stayed inside the work order:** "
|
|
52
|
+
f"{'yes' if conformance['conformant'] else f'no — {out} file(s) outside it'}"
|
|
53
|
+
)
|
|
54
|
+
lines.append(
|
|
55
|
+
f"- **Without silencing a finding:** "
|
|
56
|
+
f"{'yes' if not silenced else f'no — {silenced} suppression(s) on flagged files'}"
|
|
57
|
+
)
|
|
58
|
+
ratchet = report.get("dimension_ratchet")
|
|
59
|
+
if ratchet:
|
|
60
|
+
if not ratchet["comparable"]:
|
|
61
|
+
lines.append(
|
|
62
|
+
f"- **No dimension regressed:** not established — {ratchet['reason']}"
|
|
63
|
+
)
|
|
64
|
+
elif ratchet["regressed"]:
|
|
65
|
+
names = ", ".join(item["name"] for item in ratchet["regressed"])
|
|
66
|
+
lines.append(f"- **No dimension regressed:** no — {names}")
|
|
67
|
+
else:
|
|
68
|
+
lines.append("- **No dimension regressed:** yes")
|
|
69
|
+
return lines
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _measured(report: dict[str, Any]) -> list[str]:
|
|
73
|
+
score = report.get("score") or {}
|
|
74
|
+
coverage = report.get("analyzer_coverage") or {}
|
|
75
|
+
status = score.get("evidence_status")
|
|
76
|
+
if isinstance(status, dict):
|
|
77
|
+
status = status.get("status")
|
|
78
|
+
ran = (coverage.get("by_outcome") or {}).get("ran") or []
|
|
79
|
+
return [
|
|
80
|
+
f"- Estimate: {score.get('maintainability_estimate', 'withheld')}",
|
|
81
|
+
f"- Verified grade: {score.get('verified_grade') or 'withheld'}",
|
|
82
|
+
f"- Evidence: {status or 'unstated'}",
|
|
83
|
+
f"- Analyzers that ran: {len(ran)}",
|
|
84
|
+
f"- Hard gate failures: {len(report.get('hard_gate_failures') or [])}",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def attestation_record(report: dict[str, Any]) -> dict[str, Any]:
|
|
89
|
+
"""The structured record, before rendering."""
|
|
90
|
+
conformance = report.get("scope_conformance") or {}
|
|
91
|
+
ratchet = report.get("dimension_ratchet") or {}
|
|
92
|
+
score = report.get("score") or {}
|
|
93
|
+
record = {
|
|
94
|
+
"artifact_version": ARTIFACT_VERSION,
|
|
95
|
+
"tool_version": report.get("tool_version"),
|
|
96
|
+
"commit": report.get("git_commit"),
|
|
97
|
+
"branch": report.get("git_branch"),
|
|
98
|
+
# A finding reported against "the commit" that actually depends on
|
|
99
|
+
# uncommitted work is unreproducible, so the state of the tree is
|
|
100
|
+
# part of what is attested rather than a footnote.
|
|
101
|
+
"tree_dirty": bool(report.get("git_status_short")),
|
|
102
|
+
"revspec": conformance.get("revspec"),
|
|
103
|
+
"estimate": score.get("maintainability_estimate"),
|
|
104
|
+
"verified_grade": score.get("verified_grade"),
|
|
105
|
+
"stayed_in_scope": conformance.get("conformant"),
|
|
106
|
+
"no_finding_silenced": (
|
|
107
|
+
None if not conformance else conformance["suppressions_on_named_paths"] == 0
|
|
108
|
+
),
|
|
109
|
+
"no_dimension_regressed": (
|
|
110
|
+
None if not ratchet or not ratchet.get("comparable")
|
|
111
|
+
else not ratchet["regressed"]
|
|
112
|
+
),
|
|
113
|
+
"scope_conformance": conformance or None,
|
|
114
|
+
"dimension_ratchet": ratchet or None,
|
|
115
|
+
}
|
|
116
|
+
# The digest is over the record without it, so it is reproducible: the
|
|
117
|
+
# same commit measured with the same analyzer versions yields the same
|
|
118
|
+
# value, and anyone can recompute it rather than trust it.
|
|
119
|
+
record["digest"] = hashlib.sha256(
|
|
120
|
+
json.dumps(record, sort_keys=True, default=str).encode("utf-8")
|
|
121
|
+
).hexdigest()[:16]
|
|
122
|
+
return record
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def render_attestation(report: dict[str, Any]) -> str:
|
|
126
|
+
"""The record as text, for a reviewer or an audit trail."""
|
|
127
|
+
record = attestation_record(report)
|
|
128
|
+
dirty = " (uncommitted changes present)" if record["tree_dirty"] else ""
|
|
129
|
+
lines = [
|
|
130
|
+
"# Maintainability attestation",
|
|
131
|
+
"",
|
|
132
|
+
"An independent, deterministic check on a change. Produced by a "
|
|
133
|
+
"process that generated none of the code it examined.",
|
|
134
|
+
"",
|
|
135
|
+
f"- Commit: `{record['commit'] or 'unknown'}`{dirty}",
|
|
136
|
+
f"- Branch: `{record['branch'] or 'unknown'}`",
|
|
137
|
+
f"- Tool version: {record['tool_version'] or 'unknown'}",
|
|
138
|
+
f"- Compared: `{record['revspec'] or 'not asked'}`",
|
|
139
|
+
"",
|
|
140
|
+
"## What was measured",
|
|
141
|
+
"",
|
|
142
|
+
*_measured(report),
|
|
143
|
+
"",
|
|
144
|
+
"## What the change did",
|
|
145
|
+
"",
|
|
146
|
+
]
|
|
147
|
+
verdicts = _verdicts(report)
|
|
148
|
+
lines += verdicts or ["- Nothing was asked: run with `--conformance` and "
|
|
149
|
+
"`--fail-on-regression` to populate this section."]
|
|
150
|
+
lines += [
|
|
151
|
+
"",
|
|
152
|
+
"## What this does not establish",
|
|
153
|
+
"",
|
|
154
|
+
"- It compares paths and reads added lines. A file in scope means the "
|
|
155
|
+
"work order named it, **not** that the change to it was correct — this "
|
|
156
|
+
"never opens the diff to judge it.",
|
|
157
|
+
"- It touches no score. Whether a change obeyed its instructions is a "
|
|
158
|
+
"fact about behaviour, not evidence about the code's condition.",
|
|
159
|
+
"- It is reproducible, **not signed**. The digest is over this "
|
|
160
|
+
"record's own content, so the same inputs reproduce it and anyone can "
|
|
161
|
+
"recompute it. Nothing here holds a key.",
|
|
162
|
+
"",
|
|
163
|
+
f"Digest: `{record['digest']}`",
|
|
164
|
+
"",
|
|
165
|
+
]
|
|
166
|
+
return "\n".join(lines)
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/cli.py
RENAMED
|
@@ -97,6 +97,14 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
97
97
|
parser.add_argument("--prompt-output", help="Optional Markdown prompt for AI-assisted remediation.")
|
|
98
98
|
parser.add_argument("--comment-output", help="Optional Markdown body suitable for a PR comment.")
|
|
99
99
|
parser.add_argument("--agent-instructions-output", help="Optional reusable instructions for AI coding agents.")
|
|
100
|
+
parser.add_argument(
|
|
101
|
+
"--attestation-output",
|
|
102
|
+
help="Write the attestation: an independent, reproducible record of "
|
|
103
|
+
"what was measured, what the change was told to do, what it did, "
|
|
104
|
+
"and what moved. Populated by --conformance and "
|
|
105
|
+
"--fail-on-regression; a generator cannot produce this about its "
|
|
106
|
+
"own output.",
|
|
107
|
+
)
|
|
100
108
|
parser.add_argument("--hostile-prompt-output",
|
|
101
109
|
help="Optional adversarial audit brief seeded from this run (ADR 013). "
|
|
102
110
|
"Text only: it does not gate, score, or send anything.")
|
|
@@ -227,6 +235,10 @@ def write_outputs(args: argparse.Namespace, report: dict, rendered: str) -> None
|
|
|
227
235
|
write_artifact(root, Path(args.comment_output), render_pr_comment(report) + "\n")
|
|
228
236
|
if args.agent_instructions_output:
|
|
229
237
|
write_artifact(root, Path(args.agent_instructions_output), render_agent_instructions(report) + "\n")
|
|
238
|
+
if args.attestation_output:
|
|
239
|
+
from ._attestation import render_attestation
|
|
240
|
+
|
|
241
|
+
write_artifact(root, Path(args.attestation_output), render_attestation(report))
|
|
230
242
|
if args.hostile_prompt_output:
|
|
231
243
|
write_artifact(root, Path(args.hostile_prompt_output),
|
|
232
244
|
render_hostile_audit_prompt(report) + "\n")
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/config.py
RENAMED
|
@@ -11,7 +11,7 @@ from ._config_defaults import DEFAULT_CONFIG, DEFAULT_IDIOM_GROUPS
|
|
|
11
11
|
# still the door every caller comes through.
|
|
12
12
|
__all__ = ["DEFAULT_CONFIG", "DEFAULT_IDIOM_GROUPS", "PROJECT_URL", "VERSION"]
|
|
13
13
|
|
|
14
|
-
VERSION = "2.
|
|
14
|
+
VERSION = "2.3.0"
|
|
15
15
|
|
|
16
16
|
PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
|
|
17
17
|
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/prompts.py
RENAMED
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
from typing import Any
|
|
12
12
|
|
|
13
13
|
from . import _evidence_view as view
|
|
14
|
+
from ._attestation import render_attestation # noqa: F401
|
|
14
15
|
from ._hostile_prompt import render_hostile_audit_prompt # noqa: F401
|
|
15
16
|
from ._hotspots import hotspot_measure, hotspot_name
|
|
16
17
|
from ._tdd_view import tdd_sentences
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""The record an author cannot produce about their own work.
|
|
2
|
+
|
|
3
|
+
The three mechanisms each answer one question about a change. This composes
|
|
4
|
+
them into the artifact they were built for — and the value of that artifact
|
|
5
|
+
is entirely in what it refuses to overstate, so that is what is tested here.
|
|
6
|
+
|
|
7
|
+
Three properties, and all three are about honesty rather than plumbing:
|
|
8
|
+
|
|
9
|
+
- **A mixed result reads as mixed.** A change that stayed in scope while
|
|
10
|
+
silencing a finding must not produce a document anyone could wave as a
|
|
11
|
+
pass.
|
|
12
|
+
- **Not asked is not the same as passed.** A question nobody ran must not
|
|
13
|
+
render as a verdict.
|
|
14
|
+
- **It claims reproducible, never signed.** Nothing here holds a key, and a
|
|
15
|
+
document that implied otherwise would be the exact overclaim the rest of
|
|
16
|
+
this project spends its time removing.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from maintainability_audit._attestation import attestation_record, render_attestation
|
|
22
|
+
|
|
23
|
+
CLEAN = {
|
|
24
|
+
"tool_version": "2.3.0",
|
|
25
|
+
"git_commit": "a" * 40,
|
|
26
|
+
"git_branch": "main",
|
|
27
|
+
"git_status_short": "",
|
|
28
|
+
"score": {
|
|
29
|
+
"maintainability_estimate": 4.2,
|
|
30
|
+
"verified_grade": "B",
|
|
31
|
+
"evidence_status": {"status": "complete"},
|
|
32
|
+
},
|
|
33
|
+
"analyzer_coverage": {"by_outcome": {"ran": [{"tool": "lizard"}]}},
|
|
34
|
+
"hard_gate_failures": [],
|
|
35
|
+
"scope_conformance": {
|
|
36
|
+
"revspec": "main...HEAD", "conformant": True, "out_of_scope": [],
|
|
37
|
+
"suppressions_on_named_paths": 0, "clean": True,
|
|
38
|
+
},
|
|
39
|
+
"dimension_ratchet": {"comparable": True, "regressed": []},
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _with(**changes: object) -> dict:
|
|
44
|
+
report = {key: dict(value) if isinstance(value, dict) else value
|
|
45
|
+
for key, value in CLEAN.items()}
|
|
46
|
+
report.update(changes)
|
|
47
|
+
return report
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_a_clean_change_says_so_on_every_question() -> None:
|
|
51
|
+
text = render_attestation(CLEAN)
|
|
52
|
+
|
|
53
|
+
assert "**Stayed inside the work order:** yes" in text
|
|
54
|
+
assert "**Without silencing a finding:** yes" in text
|
|
55
|
+
assert "**No dimension regressed:** yes" in text
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_a_silenced_finding_is_not_hidden_by_staying_in_scope() -> None:
|
|
59
|
+
"""The mixed verdict the artifact exists to make unmissable.
|
|
60
|
+
|
|
61
|
+
Scope and silence are separate questions, so a change that obeyed the
|
|
62
|
+
first and failed the second must not produce a document that reads as a
|
|
63
|
+
pass on either.
|
|
64
|
+
"""
|
|
65
|
+
report = _with(scope_conformance={
|
|
66
|
+
"revspec": "main...HEAD", "conformant": True, "out_of_scope": [],
|
|
67
|
+
"suppressions_on_named_paths": 2, "clean": False,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
text = render_attestation(report)
|
|
71
|
+
|
|
72
|
+
assert "**Stayed inside the work order:** yes" in text
|
|
73
|
+
assert "**Without silencing a finding:** no" in text
|
|
74
|
+
assert attestation_record(report)["no_finding_silenced"] is False
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_a_question_nobody_asked_is_not_reported_as_passed() -> None:
|
|
78
|
+
"""`None`, not `True`. An unrun check is not a clean result."""
|
|
79
|
+
report = _with(scope_conformance=None, dimension_ratchet=None)
|
|
80
|
+
|
|
81
|
+
record = attestation_record(report)
|
|
82
|
+
|
|
83
|
+
assert record["stayed_in_scope"] is None
|
|
84
|
+
assert record["no_finding_silenced"] is None
|
|
85
|
+
assert record["no_dimension_regressed"] is None
|
|
86
|
+
assert "Nothing was asked" in render_attestation(report)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_an_incomparable_ratchet_is_not_reported_as_no_regression() -> None:
|
|
90
|
+
"""Two scans under different calibration cannot be differenced.
|
|
91
|
+
|
|
92
|
+
"Not established" is the honest rendering; "yes" would be a claim the
|
|
93
|
+
evidence cannot support.
|
|
94
|
+
"""
|
|
95
|
+
report = _with(dimension_ratchet={
|
|
96
|
+
"comparable": False, "regressed": [],
|
|
97
|
+
"reason": "calibration changed, so scans cannot be joined",
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
text = render_attestation(report)
|
|
101
|
+
|
|
102
|
+
assert "not established" in text
|
|
103
|
+
assert attestation_record(report)["no_dimension_regressed"] is None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_an_uncommitted_tree_is_disclosed() -> None:
|
|
107
|
+
"""A verdict about "the commit" that depends on unstaged work is a lie."""
|
|
108
|
+
report = _with(git_status_short=" M src/thing.py")
|
|
109
|
+
|
|
110
|
+
assert attestation_record(report)["tree_dirty"] is True
|
|
111
|
+
assert "uncommitted changes present" in render_attestation(report)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_the_document_claims_reproducible_and_refuses_to_claim_signed() -> None:
|
|
115
|
+
"""Nothing here holds a key, and the artifact must not imply one.
|
|
116
|
+
|
|
117
|
+
"Signed" is the word a reader reaches for with an attestation, which is
|
|
118
|
+
exactly why the document has to say the opposite in its own text.
|
|
119
|
+
"""
|
|
120
|
+
text = render_attestation(CLEAN)
|
|
121
|
+
|
|
122
|
+
assert "not signed" in text.lower()
|
|
123
|
+
assert "Digest:" in text
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_the_digest_is_reproducible_and_content_bound() -> None:
|
|
127
|
+
first = attestation_record(CLEAN)["digest"]
|
|
128
|
+
second = attestation_record(CLEAN)["digest"]
|
|
129
|
+
moved = attestation_record(_with(score={
|
|
130
|
+
"maintainability_estimate": 3.1, "verified_grade": "C",
|
|
131
|
+
"evidence_status": {"status": "complete"},
|
|
132
|
+
}))["digest"]
|
|
133
|
+
|
|
134
|
+
assert first == second, "the same inputs produced two different digests"
|
|
135
|
+
assert first != moved, "the digest did not follow the record's content"
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def test_the_record_carries_no_score_verdict_of_its_own() -> None:
|
|
139
|
+
"""It reports the estimate the audit produced; it never computes one."""
|
|
140
|
+
record = attestation_record(CLEAN)
|
|
141
|
+
|
|
142
|
+
assert record["estimate"] == 4.2
|
|
143
|
+
assert "categories" not in record
|
|
144
|
+
assert "dimensions" not in record
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_the_document_states_that_it_never_opened_the_diff() -> None:
|
|
148
|
+
text = render_attestation(CLEAN)
|
|
149
|
+
|
|
150
|
+
assert "not** that the change to it was correct" in text
|
|
151
|
+
assert "touches no score" in text
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/__main__.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_adapters.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_analysis.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_aspects.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_backfill.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_bands.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_built_ins.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_catalog.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_charts.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_cognitive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_derive.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_discovery.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_documents.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_economics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_first_run.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_formula.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_gates.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_generic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_hotspots.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_html_view.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_identity.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_masking.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_audit.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_gate.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_grants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_mcp_setup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_pillars.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_practice.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_pressures.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_c.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_cpp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ranges_js.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_ratchet.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_recurrence.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_runner.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_safe_write.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_scan_view.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_selection.py
RENAMED
|
File without changes
|
{maintainability_agent-2.2.0 → maintainability_agent-2.3.0}/src/maintainability_audit/_semantic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|