maintainability-agent 3.1.0__tar.gz → 3.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-3.1.0/src/maintainability_agent.egg-info → maintainability_agent-3.3.0}/PKG-INFO +2 -2
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/README.md +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/pyproject.toml +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0/src/maintainability_agent.egg-info}/PKG-INFO +2 -2
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_agent.egg-info/SOURCES.txt +12 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_anchor.py +6 -3
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_arguments.py +9 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_catalog.py +22 -2
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_coverage_notes.py +36 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_criteria_scope.py +37 -31
- maintainability_agent-3.3.0/src/maintainability_audit/_delegated_pillar.py +204 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_derive.py +2 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_discovery.py +70 -26
- maintainability_agent-3.3.0/src/maintainability_audit/_evidence_reader.py +305 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_evidence_view.py +11 -4
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_first_run.py +57 -16
- maintainability_agent-3.3.0/src/maintainability_audit/_grammar.py +93 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_grant_ledger.py +0 -8
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_history_view.py +85 -24
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_html_report_sections.py +101 -31
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_html_view.py +5 -3
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_in_loop_view.py +32 -15
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_audit.py +36 -4
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_metric_adapters.py +14 -127
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_pillars.py +84 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_practice.py +46 -24
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_pressures.py +61 -70
- maintainability_agent-3.1.0/src/maintainability_audit/prompts.py → maintainability_agent-3.3.0/src/maintainability_audit/_prompt_sections.py +40 -114
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_core.py +44 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_fortran.py +29 -11
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_php.py +2 -28
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_rust.py +2 -31
- maintainability_agent-3.3.0/src/maintainability_audit/_ratio_adapters.py +153 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_scan_history.py +130 -9
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_scan_view.py +46 -18
- maintainability_agent-3.3.0/src/maintainability_audit/_selection.py +177 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_semantic_policy.py +18 -8
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_test_execution.py +81 -15
- maintainability_agent-3.3.0/src/maintainability_audit/_test_pairing.py +291 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_trends.py +1 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_verdict_adapters.py +50 -36
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_work_order.py +39 -27
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/cli.py +2 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/config.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/duplication.py +21 -10
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/evidence.py +1 -227
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/history.py +58 -28
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/idioms.py +22 -6
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/metrics.py +17 -9
- maintainability_agent-3.3.0/src/maintainability_audit/prompts.py +128 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/report.py +30 -3
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/scoring.py +2 -5
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_primary_estimate.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_scoring_path.py +3 -3
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_spread_range.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_anchor_disclosure.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_band_concealment_p3.py +2 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_bands.py +80 -0
- maintainability_agent-3.3.0/tests/test_child_sandbox.py +203 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_consumer_migration.py +2 -1
- maintainability_agent-3.3.0/tests/test_declarative_parsers.py +220 -0
- maintainability_agent-3.3.0/tests/test_delegated_security_pillar.py +312 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_docs_links.py +30 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_evidence_invariants.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_evidence_normalization.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_evidence_properties.py +1 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_history_window.py +10 -25
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_html_section_parity_class.py +21 -1
- maintainability_agent-3.3.0/tests/test_mcp_format_contract.py +22 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_mcp_server.py +33 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_operator_named_reads.py +5 -1
- maintainability_agent-3.3.0/tests/test_pairing_reads_imports.py +213 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_population_floors.py +1 -1
- maintainability_agent-3.3.0/tests/test_release_needs_an_empty_ledger.py +150 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_release_plan_status.py +8 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scan_scope.py +2 -6
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scoring_calibration.py +2 -5
- maintainability_agent-3.3.0/tests/test_terminal_asks_the_same_questions.py +98 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_test_execution_class.py +28 -8
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_tree_cannot_opt_the_host_in.py +61 -3
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_trends.py +14 -1
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_unanchored_set_matches_corpus.py +7 -2
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_verified_grade.py +1 -1
- maintainability_agent-3.1.0/src/maintainability_audit/_selection.py +0 -136
- maintainability_agent-3.1.0/src/maintainability_audit/_test_pairing.py +0 -149
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/LICENSE +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/setup.cfg +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_analyzer_sections.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_banner.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_in_loop.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_operator_reads.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_precommit.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_precommit_install.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_precommit_view.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_go.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_ruby.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_run_comparison.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/git_tools.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/mcp_server.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/renderers.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_adapters.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_added_lines.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_anchor_and_mode.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_architecture.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_attestation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_audit_components.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_backfill.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_check_refuses_plus_only_fragments.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_cli.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_config_shape.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_corroborate.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_criteria_completion.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_dead_code.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declaration_criteria_scope.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declared_authorship.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_determinism.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_discovery.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_economic_context.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_format_ask.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_git_argv.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_go_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_grammar_constructs.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_grammar_token_coverage.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_history.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_html_executive.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_in_loop_budgets.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_in_loop_check.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_java_scored.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_language_support_honesty.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_operator_named_paths.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_php_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_platform_claim.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_policy_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_precommit_staged.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_promises.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_python_complexity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_recurrence.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_release_plan.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_roles_recorded.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_root_grants.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_ruby_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_runner.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_rust_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_sarif.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scan_history.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scanning.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_skill_install.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_sonar_resolve.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_source_index.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_suite_isolation.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_test_commands.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_tool_resolution.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_tree_chosen_spawn.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_tree_reads_use_the_primitive.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_unread_code.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_version_claim.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_work_order.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-3.1.0 → maintainability_agent-3.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: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -45,7 +45,7 @@ Dynamic: license-file
|
|
|
45
45
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
46
46
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
47
47
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
48
|
-
Version **3.
|
|
48
|
+
Version **3.3.0**.
|
|
49
49
|
|
|
50
50
|
**Planned, not shipped:** the audit tool will become `maintainability-audit`;
|
|
51
51
|
a new `maintainability-agent` companion will run it and automate human-selected
|
|
@@ -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 **3.
|
|
8
|
+
Version **3.3.0**.
|
|
9
9
|
|
|
10
10
|
**Planned, not shipped:** the audit tool will become `maintainability-audit`;
|
|
11
11
|
a new `maintainability-agent` companion will run it and automate human-selected
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "maintainability-agent"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.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: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -45,7 +45,7 @@ Dynamic: license-file
|
|
|
45
45
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
46
46
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
47
47
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
48
|
-
Version **3.
|
|
48
|
+
Version **3.3.0**.
|
|
49
49
|
|
|
50
50
|
**Planned, not shipped:** the audit tool will become `maintainability-audit`;
|
|
51
51
|
a new `maintainability-agent` companion will run it and automate human-selected
|
|
@@ -29,18 +29,21 @@ src/maintainability_audit/_conformance.py
|
|
|
29
29
|
src/maintainability_audit/_corroborate.py
|
|
30
30
|
src/maintainability_audit/_coverage_notes.py
|
|
31
31
|
src/maintainability_audit/_criteria_scope.py
|
|
32
|
+
src/maintainability_audit/_delegated_pillar.py
|
|
32
33
|
src/maintainability_audit/_derive.py
|
|
33
34
|
src/maintainability_audit/_discovery.py
|
|
34
35
|
src/maintainability_audit/_documents.py
|
|
35
36
|
src/maintainability_audit/_economics.py
|
|
36
37
|
src/maintainability_audit/_economics_view.py
|
|
37
38
|
src/maintainability_audit/_environment.py
|
|
39
|
+
src/maintainability_audit/_evidence_reader.py
|
|
38
40
|
src/maintainability_audit/_evidence_view.py
|
|
39
41
|
src/maintainability_audit/_finding_match.py
|
|
40
42
|
src/maintainability_audit/_first_run.py
|
|
41
43
|
src/maintainability_audit/_formula.py
|
|
42
44
|
src/maintainability_audit/_gates.py
|
|
43
45
|
src/maintainability_audit/_generic.py
|
|
46
|
+
src/maintainability_audit/_grammar.py
|
|
44
47
|
src/maintainability_audit/_grant_ledger.py
|
|
45
48
|
src/maintainability_audit/_history_view.py
|
|
46
49
|
src/maintainability_audit/_hostile_prompt.py
|
|
@@ -68,6 +71,7 @@ src/maintainability_audit/_precommit.py
|
|
|
68
71
|
src/maintainability_audit/_precommit_install.py
|
|
69
72
|
src/maintainability_audit/_precommit_view.py
|
|
70
73
|
src/maintainability_audit/_pressures.py
|
|
74
|
+
src/maintainability_audit/_prompt_sections.py
|
|
71
75
|
src/maintainability_audit/_ranges_c.py
|
|
72
76
|
src/maintainability_audit/_ranges_cobol.py
|
|
73
77
|
src/maintainability_audit/_ranges_core.py
|
|
@@ -82,6 +86,7 @@ src/maintainability_audit/_ranges_ruby.py
|
|
|
82
86
|
src/maintainability_audit/_ranges_rust.py
|
|
83
87
|
src/maintainability_audit/_ranges_swift.py
|
|
84
88
|
src/maintainability_audit/_ratchet.py
|
|
89
|
+
src/maintainability_audit/_ratio_adapters.py
|
|
85
90
|
src/maintainability_audit/_recurrence.py
|
|
86
91
|
src/maintainability_audit/_run_comparison.py
|
|
87
92
|
src/maintainability_audit/_runner.py
|
|
@@ -186,6 +191,7 @@ tests/test_chat_primary_docs.py
|
|
|
186
191
|
tests/test_check_refuses_plus_only_fragments.py
|
|
187
192
|
tests/test_checkstyle_adapter.py
|
|
188
193
|
tests/test_checkstyle_catalog.py
|
|
194
|
+
tests/test_child_sandbox.py
|
|
189
195
|
tests/test_ci_history_recipe.py
|
|
190
196
|
tests/test_ci_installs_the_analyzer_pool.py
|
|
191
197
|
tests/test_claimed_languages.py
|
|
@@ -212,8 +218,10 @@ tests/test_declaration_edge_cases.py
|
|
|
212
218
|
tests/test_declaration_grading.py
|
|
213
219
|
tests/test_declaration_ranges.py
|
|
214
220
|
tests/test_declaration_source.py
|
|
221
|
+
tests/test_declarative_parsers.py
|
|
215
222
|
tests/test_declared_authorship.py
|
|
216
223
|
tests/test_declared_imports.py
|
|
224
|
+
tests/test_delegated_security_pillar.py
|
|
217
225
|
tests/test_derivation_mix.py
|
|
218
226
|
tests/test_determinism.py
|
|
219
227
|
tests/test_dimension_ratchet.py
|
|
@@ -272,6 +280,7 @@ tests/test_js_declarations.py
|
|
|
272
280
|
tests/test_language_coverage.py
|
|
273
281
|
tests/test_language_support_honesty.py
|
|
274
282
|
tests/test_mcp_baseline_payload.py
|
|
283
|
+
tests/test_mcp_format_contract.py
|
|
275
284
|
tests/test_mcp_history.py
|
|
276
285
|
tests/test_mcp_server.py
|
|
277
286
|
tests/test_migration_1_0.py
|
|
@@ -280,6 +289,7 @@ tests/test_network_disclosure.py
|
|
|
280
289
|
tests/test_one_setup_across_surfaces_class.py
|
|
281
290
|
tests/test_operator_named_paths.py
|
|
282
291
|
tests/test_operator_named_reads.py
|
|
292
|
+
tests/test_pairing_reads_imports.py
|
|
283
293
|
tests/test_pattern_budget.py
|
|
284
294
|
tests/test_phase6_claims.py
|
|
285
295
|
tests/test_php_declarations.py
|
|
@@ -303,6 +313,7 @@ tests/test_python_declarations.py
|
|
|
303
313
|
tests/test_read_boundary.py
|
|
304
314
|
tests/test_readme_claims.py
|
|
305
315
|
tests/test_recurrence.py
|
|
316
|
+
tests/test_release_needs_an_empty_ledger.py
|
|
306
317
|
tests/test_release_plan.py
|
|
307
318
|
tests/test_release_plan_status.py
|
|
308
319
|
tests/test_report_remedy_copy.py
|
|
@@ -334,6 +345,7 @@ tests/test_stage8_contract.py
|
|
|
334
345
|
tests/test_suite_isolation.py
|
|
335
346
|
tests/test_swift_declarations.py
|
|
336
347
|
tests/test_tdd_structure.py
|
|
348
|
+
tests/test_terminal_asks_the_same_questions.py
|
|
337
349
|
tests/test_test_commands.py
|
|
338
350
|
tests/test_test_execution_class.py
|
|
339
351
|
tests/test_three_presentations.py
|
{maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_anchor.py
RENAMED
|
@@ -63,8 +63,11 @@ def unanchored_sentence() -> str:
|
|
|
63
63
|
"""One sentence naming what the anchor omits, for the corpus note."""
|
|
64
64
|
if not UNANCHORED_LANGUAGES:
|
|
65
65
|
return ""
|
|
66
|
+
from ._grammar import agreement
|
|
67
|
+
|
|
68
|
+
say = agreement(len(UNANCHORED_LANGUAGES))
|
|
66
69
|
return (
|
|
67
|
-
f"{unanchored_names()}
|
|
68
|
-
"findings are as good as
|
|
69
|
-
"provisional."
|
|
70
|
+
f"{unanchored_names()} {say.verb} parsed but absent from it, so "
|
|
71
|
+
f"{say.possessive} findings are as good as {say.possessive} "
|
|
72
|
+
f"parser while {say.possessive} grade is provisional."
|
|
70
73
|
)
|
{maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_arguments.py
RENAMED
|
@@ -120,6 +120,15 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
120
120
|
parser.add_argument("--output", help="Output file. Defaults to stdout.")
|
|
121
121
|
_add_artifact_arguments(parser)
|
|
122
122
|
parser.add_argument("--sarif-output", help="Optional SARIF output path for GitHub code scanning.")
|
|
123
|
+
parser.add_argument(
|
|
124
|
+
"--security-pillar",
|
|
125
|
+
help=(
|
|
126
|
+
"Path to the security-pillar.json secure-code-agent writes with its "
|
|
127
|
+
"own --security-pillar. ADR 007 delegates the security pillar, and "
|
|
128
|
+
"this is the document it is read from; defaults to "
|
|
129
|
+
".maintainability/security-pillar.json."
|
|
130
|
+
),
|
|
131
|
+
)
|
|
123
132
|
parser.add_argument("--sarif-input", action="append", help="Optional external SARIF file to summarize in reports. Repeatable.")
|
|
124
133
|
parser.add_argument("--changed-only", help="Audit only files changed in a git revspec, for example main...HEAD.")
|
|
125
134
|
parser.add_argument("--baseline", help="Existing baseline JSON. With --fail-on-new, only new findings fail.")
|
{maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_catalog.py
RENAMED
|
@@ -190,7 +190,23 @@ def decide(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
|
|
|
190
190
|
3. the depth, licence and concern tiers.
|
|
191
191
|
"""
|
|
192
192
|
slug = tool["slug"]
|
|
193
|
+
return (
|
|
194
|
+
_denial(tool, settings)
|
|
195
|
+
or (Selection(slug, True, "explicitly allowed by name")
|
|
196
|
+
if slug in settings["allow_tools"] else None)
|
|
197
|
+
or _tier_decision(tool, settings)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _denial(tool: dict[str, Any], settings: dict[str, Any]) -> Selection | None:
|
|
202
|
+
"""Step 1: every deny, which beats even an explicit allow.
|
|
193
203
|
|
|
204
|
+
`None` means nothing here refused the tool, not that it was admitted —
|
|
205
|
+
the caller has two more steps. Separate from the tiers because these
|
|
206
|
+
are the operator's own prohibitions and the tiers are policy: a deny
|
|
207
|
+
that could be overridden by an allow would not be a deny.
|
|
208
|
+
"""
|
|
209
|
+
slug = tool["slug"]
|
|
194
210
|
if slug in settings["deny_tools"]:
|
|
195
211
|
return Selection(slug, False, "denied by name")
|
|
196
212
|
if tool["license_class"] in settings["deny_license_classes"]:
|
|
@@ -198,10 +214,14 @@ def decide(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
|
|
|
198
214
|
denied_concerns = set(tool["upstream_tags"]) & set(settings["deny_concerns"])
|
|
199
215
|
if denied_concerns:
|
|
200
216
|
return Selection(slug, False, f"concern {','.join(sorted(denied_concerns))} denied")
|
|
217
|
+
return None
|
|
201
218
|
|
|
202
|
-
if slug in settings["allow_tools"]:
|
|
203
|
-
return Selection(slug, True, "explicitly allowed by name")
|
|
204
219
|
|
|
220
|
+
def _tier_decision(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
|
|
221
|
+
"""Step 3: the depth, licence and concern tiers, for a tool no deny
|
|
222
|
+
caught and no allow admitted. The only step that can end in `True`
|
|
223
|
+
on the tool's own merits."""
|
|
224
|
+
slug = tool["slug"]
|
|
205
225
|
if tool["deprecated"]:
|
|
206
226
|
return Selection(slug, False, "deprecated upstream")
|
|
207
227
|
if not tool["languages"]:
|
|
@@ -59,4 +59,40 @@ def coverage_notes(coverage: dict[str, Any]) -> list[str]:
|
|
|
59
59
|
"or widen `analyzers.depth`, to have them reported.",
|
|
60
60
|
"",
|
|
61
61
|
])
|
|
62
|
+
|
|
63
|
+
lines.extend(_child_boundary_note(coverage))
|
|
62
64
|
return lines
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _child_boundary_note(coverage: dict[str, Any]) -> list[str]:
|
|
68
|
+
"""What this run does not control about the tools it spawned.
|
|
69
|
+
|
|
70
|
+
`docs/product-intent.md` has said since P1 was amended that this
|
|
71
|
+
package "does not sandbox children", and lists *"that third-party
|
|
72
|
+
tools cannot use the network"* among the things it does not promise.
|
|
73
|
+
The **report** did not say it. A reader holding a page headed "the
|
|
74
|
+
analysis itself performs no network access" and a table naming the
|
|
75
|
+
external tools that ran had no way to learn the second sentence does
|
|
76
|
+
not cover the first.
|
|
77
|
+
|
|
78
|
+
That makes it P8's gap rather than P1's: the promise was correctly
|
|
79
|
+
scoped all along, and the run relying on that scoping never disclosed
|
|
80
|
+
it to the person reading the output.
|
|
81
|
+
|
|
82
|
+
Only when an external tool actually ran. With no children spawned
|
|
83
|
+
there is nothing to disclose, and saying it anyway would be the noise
|
|
84
|
+
this section is careful to avoid.
|
|
85
|
+
"""
|
|
86
|
+
spawned = coverage.get("tools_contributed") or 0
|
|
87
|
+
if not spawned:
|
|
88
|
+
return []
|
|
89
|
+
return [
|
|
90
|
+
"**Analyzer children are not network-isolated.** "
|
|
91
|
+
f"{spawned} external {'tool' if spawned == 1 else 'tools'} ran as local "
|
|
92
|
+
"child processes. This agent does not transmit the audited source and "
|
|
93
|
+
"opens no socket of its own, but it does not sandbox what it spawns: a "
|
|
94
|
+
"third-party analyzer that reaches the network is outside what this run "
|
|
95
|
+
"controls or observes. Determinism and no upload are the promise; a "
|
|
96
|
+
"kernel air-gap is not.",
|
|
97
|
+
"",
|
|
98
|
+
]
|
|
@@ -154,40 +154,46 @@ def complete_from_built_ins(
|
|
|
154
154
|
"""
|
|
155
155
|
completed: dict[str, dict[str, float]] = {}
|
|
156
156
|
for unit, values in per_unit.items():
|
|
157
|
-
|
|
158
|
-
if not
|
|
159
|
-
completed[unit] =
|
|
160
|
-
continue
|
|
161
|
-
location = unit_locations.get(unit)
|
|
162
|
-
fallback = built_in.get(location) if location else None
|
|
163
|
-
filled = dict(values)
|
|
164
|
-
for concept in missing:
|
|
165
|
-
if fallback and concept in fallback:
|
|
166
|
-
filled[concept] = fallback[concept]
|
|
167
|
-
if declaration_concepts_missing(set(filled)):
|
|
168
|
-
# No counterpart in the scanner's reading, so this
|
|
169
|
-
# declaration is not scoreable on the full criterion set by
|
|
170
|
-
# either tier — and it is dropped rather than left to
|
|
171
|
-
# disqualify its language.
|
|
172
|
-
#
|
|
173
|
-
# Measured, because the alternative looked reasonable and was
|
|
174
|
-
# not: `lizard` reads files the built-in scanner produces no
|
|
175
|
-
# declarations for — Alamofire's `docs/js/jquery.min.js` and
|
|
176
|
-
# `jazzy.js`, five generated documentation assets. Keeping
|
|
177
|
-
# them gave JavaScript a bucket that could never be completed
|
|
178
|
-
# and took the whole repository to the built-in tier, Swift
|
|
179
|
-
# and all. The same shape hid Java behind a repository's
|
|
180
|
-
# bundled `.js`.
|
|
181
|
-
#
|
|
182
|
-
# Dropping them also aligns the two populations: a unit the
|
|
183
|
-
# scanner never read is not in the built-in rate either, so
|
|
184
|
-
# including it in the analyzer rate compares a wider
|
|
185
|
-
# population against a narrower one.
|
|
186
|
-
continue
|
|
187
|
-
completed[unit] = filled
|
|
157
|
+
filled = _completed_unit(values, unit_locations.get(unit), built_in)
|
|
158
|
+
if filled is not None:
|
|
159
|
+
completed[unit] = filled
|
|
188
160
|
return completed
|
|
189
161
|
|
|
190
162
|
|
|
163
|
+
def _completed_unit(
|
|
164
|
+
values: dict[str, float],
|
|
165
|
+
location: tuple[str, int] | None,
|
|
166
|
+
built_in: dict[tuple[str, int], dict[str, float]],
|
|
167
|
+
) -> dict[str, float] | None:
|
|
168
|
+
"""One declaration's readings, completed from the built-in tier.
|
|
169
|
+
|
|
170
|
+
`None` means the union of both tiers still does not cover the
|
|
171
|
+
criterion set, so this declaration is **dropped** rather than left to
|
|
172
|
+
disqualify its language.
|
|
173
|
+
|
|
174
|
+
Measured, because the alternative looked reasonable and was not:
|
|
175
|
+
`lizard` reads files the built-in scanner produces no declarations
|
|
176
|
+
for — Alamofire's `docs/js/jquery.min.js` and `jazzy.js`, five
|
|
177
|
+
generated documentation assets. Keeping them gave JavaScript a bucket
|
|
178
|
+
that could never be completed and took the whole repository to the
|
|
179
|
+
built-in tier, Swift and all. The same shape hid Java behind a
|
|
180
|
+
repository's bundled `.js`.
|
|
181
|
+
|
|
182
|
+
Dropping them also aligns the two populations: a unit the scanner
|
|
183
|
+
never read is not in the built-in rate either, so including it in the
|
|
184
|
+
analyzer rate compares a wider population against a narrower one.
|
|
185
|
+
"""
|
|
186
|
+
missing = declaration_concepts_missing(set(values))
|
|
187
|
+
if not missing:
|
|
188
|
+
return values
|
|
189
|
+
fallback = (built_in.get(location) if location else None) or {}
|
|
190
|
+
filled = dict(values)
|
|
191
|
+
for concept in missing:
|
|
192
|
+
if concept in fallback:
|
|
193
|
+
filled[concept] = fallback[concept]
|
|
194
|
+
return None if declaration_concepts_missing(set(filled)) else filled
|
|
195
|
+
|
|
196
|
+
|
|
191
197
|
def built_in_readings(
|
|
192
198
|
metrics: object, root: str = ""
|
|
193
199
|
) -> dict[tuple[str, int], dict[str, float]]:
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Reading a delegated pillar's own report of itself.
|
|
2
|
+
|
|
3
|
+
[ADR 007](adr-007-pillars-and-practice.md) makes the five pillars of the
|
|
4
|
+
source framework the top-level taxonomy and declares **Security
|
|
5
|
+
delegated to `secure-code-agent`**, reported as `NotApplicable` so that
|
|
6
|
+
silence is never read as safety. That entry was always a placeholder for
|
|
7
|
+
an artifact that did not exist yet: the other tool measures the pillar,
|
|
8
|
+
so the other tool has to be the one that reports it.
|
|
9
|
+
|
|
10
|
+
`secure-code-agent` 0.5.0 ships the emitter — `--security-pillar <path>`
|
|
11
|
+
writes `security-pillar.json`, schema `secure-code-agent/security-pillar`
|
|
12
|
+
— and it was built against *this* vocabulary rather than its own. The
|
|
13
|
+
scope words, the two-axis split and the posture matrix with its
|
|
14
|
+
thresholds all come from `_pillars.py`, because two tools saying "level
|
|
15
|
+
3" or "healthy" about one repository have to mean the same thing by it
|
|
16
|
+
or the joined view is worse than either alone.
|
|
17
|
+
|
|
18
|
+
This module reads the document and checks it is the one expected. The
|
|
19
|
+
*shaping* of the pillar entry lives in `_pillars` beside the entries it
|
|
20
|
+
sits among — scoring may not import a scanner, and reading a path the
|
|
21
|
+
audited tree chooses is what makes this one. Neither half computes a
|
|
22
|
+
number: a delegated pillar's numbers belong to the tool that measured
|
|
23
|
+
them, and a consumer that recomputed anything would be a second opinion
|
|
24
|
+
nobody asked for.
|
|
25
|
+
|
|
26
|
+
**Absence is the normal case and stays the documented one.** No file
|
|
27
|
+
means the pillar reports exactly what it reported before — delegated,
|
|
28
|
+
`NotApplicable`, naming the other tool. That path is not a failure and
|
|
29
|
+
does not warn: most repositories run one tool.
|
|
30
|
+
|
|
31
|
+
**A file that cannot be trusted is refused rather than partly believed.**
|
|
32
|
+
Wrong schema, unreadable JSON, a shape that is not an object — each
|
|
33
|
+
returns `None`, and the pillar falls back to the honest placeholder. The
|
|
34
|
+
alternative is a security posture assembled from a document this tool
|
|
35
|
+
does not actually understand, which is worse than no posture at all.
|
|
36
|
+
|
|
37
|
+
A trailing note on where this sits: it reads a path from the audited
|
|
38
|
+
tree, so it is a scanner rather than part of the rubric.
|
|
39
|
+
`test_scoring_never_imports_scanners_or_assembly` holds that boundary,
|
|
40
|
+
and `report` is what joins the two.
|
|
41
|
+
"""
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import json
|
|
45
|
+
from pathlib import Path
|
|
46
|
+
from typing import Any
|
|
47
|
+
|
|
48
|
+
from ._operator_reads import PathNotAllowed, read_source_file
|
|
49
|
+
|
|
50
|
+
#: Written beside the other artifacts a repository keeps about itself.
|
|
51
|
+
#: The path is a convention rather than a search: a document this tool
|
|
52
|
+
#: trusts for a whole pillar should be somewhere a reader can find, not
|
|
53
|
+
#: wherever a glob happened to match.
|
|
54
|
+
DEFAULT_PILLAR_PATH = ".maintainability/security-pillar.json"
|
|
55
|
+
|
|
56
|
+
#: The contract this module understands. A document announcing anything
|
|
57
|
+
#: else is refused rather than read hopefully — the schema string is the
|
|
58
|
+
#: producer's promise about the shape, and guessing past it is how a
|
|
59
|
+
#: consumer starts reporting fields that mean something different.
|
|
60
|
+
SCHEMA = "secure-code-agent/security-pillar"
|
|
61
|
+
#: Versions of that contract this tool can read. **Two, deliberately.**
|
|
62
|
+
#: v2 is v1 plus `scoring_model` and nothing else, so a reader that
|
|
63
|
+
#: handles both is not guessing: the producer asserts the key-set
|
|
64
|
+
#: difference is exactly that one field.
|
|
65
|
+
#:
|
|
66
|
+
#: Accepting v2 before the producer emits it is what removes the
|
|
67
|
+
#: deadlock. If MA required v1 while `secure-code-agent` shipped v2,
|
|
68
|
+
#: every document would be refused for the window between the two
|
|
69
|
+
#: releases -- silently, since a refused document reads as no delegated
|
|
70
|
+
#: pillar. Either side can now release first.
|
|
71
|
+
SCHEMA_VERSIONS = frozenset({1, 2})
|
|
72
|
+
|
|
73
|
+
#: Kept for callers that imported the old name. The gate reads the set.
|
|
74
|
+
SCHEMA_VERSION = 1
|
|
75
|
+
|
|
76
|
+
#: What the pillar block takes from the document. Named rather than
|
|
77
|
+
#: copied wholesale so a field added upstream cannot silently appear in
|
|
78
|
+
#: this tool's report carrying meaning nobody here has checked.
|
|
79
|
+
CARRIED = (
|
|
80
|
+
"practice",
|
|
81
|
+
"condition",
|
|
82
|
+
"condition_letter",
|
|
83
|
+
"posture",
|
|
84
|
+
"verified_grade",
|
|
85
|
+
"evidence_status",
|
|
86
|
+
"evidence_reasons",
|
|
87
|
+
"coverage",
|
|
88
|
+
"findings_by_severity",
|
|
89
|
+
"reported_not_scored",
|
|
90
|
+
"loc_scanned",
|
|
91
|
+
#: v2. The producer's own identifier for its scoring model, bumped
|
|
92
|
+
#: when a repository's condition could differ for reasons that are
|
|
93
|
+
#: not the repository -- normalizer, slope, weights, letter bands,
|
|
94
|
+
#: the scanner floor, or the built-in rule profile. Absent on v1.
|
|
95
|
+
#:
|
|
96
|
+
#: This is what MA keys a delegated trend on, in preference to the
|
|
97
|
+
#: producer's version, because the version moves on docs releases
|
|
98
|
+
#: that change no score and fragmenting a trend for those teaches a
|
|
99
|
+
#: reader to ignore the breaks (D155).
|
|
100
|
+
"scoring_model",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def read_delegated(root: Path, relative: str = DEFAULT_PILLAR_PATH) -> dict[str, Any] | None:
|
|
105
|
+
"""The delegated pillar's own report, or `None` when there is none.
|
|
106
|
+
|
|
107
|
+
`None` for every reason a reader might not get a usable document:
|
|
108
|
+
the file is absent, it is not a regular file, it does not parse, it
|
|
109
|
+
is not an object, or it announces a schema this tool does not know.
|
|
110
|
+
All five collapse to one answer because the caller does the same
|
|
111
|
+
thing with each — keep the placeholder that names the other tool.
|
|
112
|
+
|
|
113
|
+
Read through the regular-file primitive like every other path the
|
|
114
|
+
audited tree chooses (D145): a FIFO here would hang the audit rather
|
|
115
|
+
than fail it.
|
|
116
|
+
"""
|
|
117
|
+
path = Path(root) / relative
|
|
118
|
+
if not path.exists():
|
|
119
|
+
return None
|
|
120
|
+
try:
|
|
121
|
+
payload = json.loads("\n".join(read_source_file(path)))
|
|
122
|
+
except (OSError, ValueError) as error:
|
|
123
|
+
if isinstance(error, PathNotAllowed):
|
|
124
|
+
raise
|
|
125
|
+
return None
|
|
126
|
+
if not isinstance(payload, dict):
|
|
127
|
+
return None
|
|
128
|
+
if payload.get("schema") != SCHEMA:
|
|
129
|
+
return None
|
|
130
|
+
if payload.get("schema_version") not in SCHEMA_VERSIONS:
|
|
131
|
+
return None
|
|
132
|
+
return payload if _is_well_formed(payload) else None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
#: Fields whose *shape* the consumer depends on. A header check alone
|
|
136
|
+
#: accepts any object announcing the right schema, and the pillar then
|
|
137
|
+
#: reads these as if the producer had promised them.
|
|
138
|
+
_SHAPES: tuple[tuple[str, type | tuple[type, ...]], ...] = (
|
|
139
|
+
("producer", dict),
|
|
140
|
+
("practice", dict),
|
|
141
|
+
("condition", (int, float, type(None))),
|
|
142
|
+
("posture", (str, type(None))),
|
|
143
|
+
("evidence_status", (str, type(None))),
|
|
144
|
+
("coverage", (dict, type(None))),
|
|
145
|
+
("findings_by_severity", (dict, type(None))),
|
|
146
|
+
("reported_not_scored", (dict, type(None))),
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
#: The postures this tool knows how to render. A document naming one it
|
|
150
|
+
#: does not is refused rather than printed through: the word is the
|
|
151
|
+
#: reader's whole summary of the pillar.
|
|
152
|
+
_POSTURES = frozenset({"healthy", "managed debt", "unmanaged debt", "unverified"})
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _is_well_formed(payload: dict[str, Any]) -> bool:
|
|
156
|
+
"""Whether the document's fields are the shapes the pillar reads.
|
|
157
|
+
|
|
158
|
+
The header said what the document *claims to be*; this asks whether
|
|
159
|
+
it is. Checking only `schema` accepted
|
|
160
|
+
`{"producer": "not-an-object", ...}`, which the pillar then indexed
|
|
161
|
+
as a mapping and crashed on — a well-formed announcement with a
|
|
162
|
+
malformed body, which is the shape a header check cannot see.
|
|
163
|
+
|
|
164
|
+
Also refused: a `posture` this tool cannot render, and a `posture`
|
|
165
|
+
the document's own two axes do not support. The second is the one
|
|
166
|
+
worth stating. `healthy` requires practice at or above
|
|
167
|
+
`HIGH_PRACTICE` and a condition at or above `GOOD_CONDITION`; a
|
|
168
|
+
document claiming `healthy` at practice 1 is either a different
|
|
169
|
+
matrix or a mistake, and either way this tool must not print it.
|
|
170
|
+
Both tools are supposed to mean the same thing by the word — the
|
|
171
|
+
consumer is where that is checkable.
|
|
172
|
+
"""
|
|
173
|
+
for name, kinds in _SHAPES:
|
|
174
|
+
if name in payload and not isinstance(payload[name], kinds):
|
|
175
|
+
return False
|
|
176
|
+
practice = payload.get("practice")
|
|
177
|
+
if isinstance(practice, dict) and not isinstance(practice.get("level"), int):
|
|
178
|
+
return False
|
|
179
|
+
posture = payload.get("posture")
|
|
180
|
+
if posture is not None and posture not in _POSTURES:
|
|
181
|
+
return False
|
|
182
|
+
return _posture_agrees(payload)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _posture_agrees(payload: dict[str, Any]) -> bool:
|
|
186
|
+
"""Whether the stated posture follows from the two axes given.
|
|
187
|
+
|
|
188
|
+
Recomputed rather than trusted. The matrix and its thresholds are
|
|
189
|
+
`_pillars.py`'s, copied into the producer by value, and a copied
|
|
190
|
+
constant is a constant that can drift — so the one place the two
|
|
191
|
+
can be compared is here, against a document carrying both inputs
|
|
192
|
+
and the answer.
|
|
193
|
+
"""
|
|
194
|
+
from ._pillars import posture as compute
|
|
195
|
+
|
|
196
|
+
stated = payload.get("posture")
|
|
197
|
+
practice = payload.get("practice")
|
|
198
|
+
if stated is None or not isinstance(practice, dict):
|
|
199
|
+
return True
|
|
200
|
+
level = practice.get("level")
|
|
201
|
+
condition = payload.get("condition")
|
|
202
|
+
if not isinstance(level, int):
|
|
203
|
+
return False
|
|
204
|
+
return compute(level, condition) == stated
|
{maintainability_agent-3.1.0 → maintainability_agent-3.3.0}/src/maintainability_audit/_derive.py
RENAMED
|
@@ -17,9 +17,10 @@ from statistics import median
|
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
19
|
from ._aspects import evidence_aspect_scores, is_untested
|
|
20
|
+
from ._evidence_reader import normalize_report_evidence
|
|
20
21
|
from ._formula import CALIBRATED_ASPECTS, curve, overall_from_aspects
|
|
21
22
|
from ._pressures import production_pressures
|
|
22
|
-
from .evidence import REPORT_SCHEMA_VERSION, SCHEMA_VERSION_KEY
|
|
23
|
+
from .evidence import REPORT_SCHEMA_VERSION, SCHEMA_VERSION_KEY
|
|
23
24
|
|
|
24
25
|
# The stored column holding the analyzers' production reading. Named
|
|
25
26
|
# once because both the refusal and the mix key on it.
|