maintainability-agent 3.6.2__tar.gz → 3.7.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.6.2/src/maintainability_agent.egg-info → maintainability_agent-3.7.0}/PKG-INFO +3 -2
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/README.md +1 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/pyproject.toml +9 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0/src/maintainability_agent.egg-info}/PKG-INFO +3 -2
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_agent.egg-info/SOURCES.txt +3 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_agent.egg-info/requires.txt +1 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_delegated_pillar.py +19 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_discovery.py +37 -2
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_pillars.py +9 -3
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_prompt_sections.py +24 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_scan_view.py +7 -0
- maintainability_agent-3.7.0/src/maintainability_audit/_security_delegate.py +121 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/config.py +1 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/git_tools.py +30 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/mcp_server.py +15 -9
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/prompts.py +2 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/renderers.py +6 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/report.py +29 -13
- maintainability_agent-3.7.0/tests/test_build_output_is_not_the_repositorys_code.py +165 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_consent_and_grant.py +8 -3
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_first_run_elicitation.py +1 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_mcp_baseline_payload.py +1 -1
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_mcp_history.py +7 -3
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_mcp_server.py +1 -1
- maintainability_agent-3.7.0/tests/test_security_pillar_runs_and_shows.py +207 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/LICENSE +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/setup.cfg +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_analyzer_sections.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_anchor.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_arguments.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_banner.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_criteria_scope.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_evidence_reader.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_grammar.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_in_loop.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_in_loop_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_operator_reads.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_precommit.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_precommit_install.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_precommit_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_go.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_php.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_ruby.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_rust.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_ratio_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_run_comparison.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_test_execution.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_work_order.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/cli.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_added_lines.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_anchor_and_mode.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_anchor_disclosure.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_architecture.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_attestation.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_audit_components.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_backfill.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_bands.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_chat_leads_with_the_work_order.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_check_refuses_plus_only_fragments.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_child_sandbox.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_cli.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_config_shape.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_corroborate.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_criteria_completion.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_dead_code.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declaration_criteria_scope.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declarative_parsers.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declared_authorship.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_delegated_security_pillar.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_demo_tree.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_determinism.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_discovery.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_docs_links.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_economic_context.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_every_surface_says_what_the_run_found.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_evidence_properties.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_example_config_opens_claimed_languages.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_exposure_never_outranks_band.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_format_ask.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_git_argv.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_go_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_grammar_constructs.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_grammar_token_coverage.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_history.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_history_window.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_html_executive.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_in_loop_budgets.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_in_loop_check.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_java_scored.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_language_support_honesty.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_mcp_format_contract.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_operator_named_paths.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_operator_named_reads.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pairing_reads_imports.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_php_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_platform_claim.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_policy_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_population_floors.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_precommit_staged.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_promises.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_python_complexity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_recurrence.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_release_needs_an_empty_ledger.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_release_plan.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_roles_recorded.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_root_grants.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_ruby_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_runner.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_rust_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_sarif.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scan_history.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scanning.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_skill_install.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_sonar_resolve.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_source_index.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_stdout_outputs.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_suite_isolation.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_terminal_asks_the_same_questions.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_test_commands.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_tool_resolution.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_tree_chosen_spawn.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_tree_reads_use_the_primitive.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_trends.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_unanchored_set_matches_corpus.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_unread_code.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_version_claim.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_work_items_state_their_own_finding.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_work_order.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-3.6.2 → maintainability_agent-3.7.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.7.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -19,6 +19,7 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
+
Requires-Dist: secure-code-agent<0.11,>=0.10
|
|
22
23
|
Provides-Extra: test
|
|
23
24
|
Requires-Dist: pytest>=8; extra == "test"
|
|
24
25
|
Requires-Dist: pytest-cov>=5; extra == "test"
|
|
@@ -46,7 +47,7 @@ Dynamic: license-file
|
|
|
46
47
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
47
48
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
48
49
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
49
|
-
Version **3.
|
|
50
|
+
Version **3.7.0**.
|
|
50
51
|
|
|
51
52
|
**Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
|
|
52
53
|
COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
|
|
@@ -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.7.0**.
|
|
9
9
|
|
|
10
10
|
**Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
|
|
11
11
|
COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
|
|
@@ -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.7.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
|
|
@@ -13,6 +13,14 @@ readme = "README.md"
|
|
|
13
13
|
# metadata said a user could stand: the suite runs 3.12 and the
|
|
14
14
|
# composite action pins 3.11 (D42).
|
|
15
15
|
requires-python = ">=3.11"
|
|
16
|
+
# The security pillar is complete (D177): every audit runs secure-code-agent,
|
|
17
|
+
# so it installs with this package rather than being left to the operator.
|
|
18
|
+
# Its own dependency is PyYAML; this package still imports no YAML
|
|
19
|
+
# (`test_the_shipped_package_does_not_import_yaml`) — it runs the tool as a
|
|
20
|
+
# child and reads the JSON document it writes.
|
|
21
|
+
dependencies = [
|
|
22
|
+
"secure-code-agent>=0.10,<0.11",
|
|
23
|
+
]
|
|
16
24
|
license = { text = "MIT" }
|
|
17
25
|
authors = [
|
|
18
26
|
{ name = "Marshall Guillory" }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maintainability-agent
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.0
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -19,6 +19,7 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
+
Requires-Dist: secure-code-agent<0.11,>=0.10
|
|
22
23
|
Provides-Extra: test
|
|
23
24
|
Requires-Dist: pytest>=8; extra == "test"
|
|
24
25
|
Requires-Dist: pytest-cov>=5; extra == "test"
|
|
@@ -46,7 +47,7 @@ Dynamic: license-file
|
|
|
46
47
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
47
48
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
48
49
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
49
|
-
Version **3.
|
|
50
|
+
Version **3.7.0**.
|
|
50
51
|
|
|
51
52
|
**Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
|
|
52
53
|
COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
|
|
@@ -94,6 +94,7 @@ src/maintainability_audit/_safe_write.py
|
|
|
94
94
|
src/maintainability_audit/_scan_history.py
|
|
95
95
|
src/maintainability_audit/_scan_view.py
|
|
96
96
|
src/maintainability_audit/_second_source.py
|
|
97
|
+
src/maintainability_audit/_security_delegate.py
|
|
97
98
|
src/maintainability_audit/_selection.py
|
|
98
99
|
src/maintainability_audit/_semantic.py
|
|
99
100
|
src/maintainability_audit/_semantic_policy.py
|
|
@@ -182,6 +183,7 @@ tests/test_band_concealment_p3.py
|
|
|
182
183
|
tests/test_band_pressures.py
|
|
183
184
|
tests/test_bands.py
|
|
184
185
|
tests/test_body_or_signature_class.py
|
|
186
|
+
tests/test_build_output_is_not_the_repositorys_code.py
|
|
185
187
|
tests/test_c_declarations.py
|
|
186
188
|
tests/test_calibration_corpus.py
|
|
187
189
|
tests/test_calibration_drift.py
|
|
@@ -339,6 +341,7 @@ tests/test_scanning.py
|
|
|
339
341
|
tests/test_schema_fidelity.py
|
|
340
342
|
tests/test_scope_conformance.py
|
|
341
343
|
tests/test_scoring_calibration.py
|
|
344
|
+
tests/test_security_pillar_runs_and_shows.py
|
|
342
345
|
tests/test_semantic_policy.py
|
|
343
346
|
tests/test_setup_gate_completeness.py
|
|
344
347
|
tests/test_setup_gate_independent_contract.py
|
|
@@ -123,6 +123,25 @@ def read_delegated(root: Path, relative: str = DEFAULT_PILLAR_PATH) -> dict[str,
|
|
|
123
123
|
if isinstance(error, PathNotAllowed):
|
|
124
124
|
raise
|
|
125
125
|
return None
|
|
126
|
+
return trusted(payload)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def read_produced(path: Path) -> dict[str, Any] | None:
|
|
130
|
+
"""The document this tool's own run of secure-code-agent just wrote (D177).
|
|
131
|
+
|
|
132
|
+
The file sits in a temporary directory this process created, not in the
|
|
133
|
+
audited tree, so it is read directly; every check a handed-over document
|
|
134
|
+
passes still applies, because the producer is the same tool either way.
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
payload = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
138
|
+
except (OSError, ValueError):
|
|
139
|
+
return None
|
|
140
|
+
return trusted(payload)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def trusted(payload: Any) -> dict[str, Any] | None:
|
|
144
|
+
"""The payload when it is a document this module understands, else `None`."""
|
|
126
145
|
if not isinstance(payload, dict):
|
|
127
146
|
return None
|
|
128
147
|
if payload.get("schema") != SCHEMA:
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_discovery.py
RENAMED
|
@@ -222,8 +222,31 @@ def _text_of(path: Path) -> str:
|
|
|
222
222
|
return "\n".join(read_source_file(path))
|
|
223
223
|
|
|
224
224
|
|
|
225
|
+
#: The evidence recorded for a path the repository ignores and git does not
|
|
226
|
+
#: track (D175), so a reader can see why it left the scored population.
|
|
227
|
+
IGNORED_BUILD_OUTPUT_EVIDENCE = (
|
|
228
|
+
"untracked, and excluded by this repository's .gitignore "
|
|
229
|
+
"(git ls-files --others --ignored)"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _ignored_build_output(root: Path) -> dict[str, str]:
|
|
234
|
+
"""Untracked paths the repository's `.gitignore` excludes (D175).
|
|
235
|
+
|
|
236
|
+
A Maven build copied jsoup's test resources into `target/test-classes`,
|
|
237
|
+
and the next audit scored 29 more files — one a failing file — as the
|
|
238
|
+
team's own. The same commit scored one way before a build and another
|
|
239
|
+
after it. `target/` is not added to a list of names: ADR 010 §1 forbids
|
|
240
|
+
that, and the next build tool will choose another word. The repository
|
|
241
|
+
already says which paths are not its source.
|
|
242
|
+
"""
|
|
243
|
+
from .git_tools import ignored_untracked_paths
|
|
244
|
+
|
|
245
|
+
return dict.fromkeys(ignored_untracked_paths(root), IGNORED_BUILD_OUTPUT_EVIDENCE)
|
|
246
|
+
|
|
247
|
+
|
|
225
248
|
def _generated_directories(root: Path, excludes: tuple[str, ...]) -> dict[str, str]:
|
|
226
|
-
"""Directories a `package.json` script deletes and rebuilds."""
|
|
249
|
+
"""Directories a `package.json` script deletes and rebuilds, then ignored build output."""
|
|
227
250
|
found: dict[str, str] = {}
|
|
228
251
|
for manifest in root.rglob("package.json"):
|
|
229
252
|
relative = manifest.relative_to(root).as_posix()
|
|
@@ -237,6 +260,10 @@ def _generated_directories(root: Path, excludes: tuple[str, ...]) -> dict[str, s
|
|
|
237
260
|
f"deleted and rebuilt by `{name}` in {relative}: "
|
|
238
261
|
f"`{str(command)[:60]}`",
|
|
239
262
|
)
|
|
263
|
+
# A manifest's own statement about a directory is the more specific
|
|
264
|
+
# evidence, so it wins where both apply.
|
|
265
|
+
for path, evidence in _ignored_build_output(root).items():
|
|
266
|
+
found.setdefault(path, evidence)
|
|
240
267
|
return found
|
|
241
268
|
|
|
242
269
|
|
|
@@ -458,10 +485,18 @@ def discover(root: Path, config: dict[str, Any]) -> Inventory:
|
|
|
458
485
|
inventory.directories = _directory_provenance(
|
|
459
486
|
vendored_dirs, generated_dirs, asset_dirs)
|
|
460
487
|
seen_directories: set[tuple[str, str]] = set()
|
|
488
|
+
# What the scanner reads, beyond source code: a generated or vendored
|
|
489
|
+
# tree's HTML, XML and JSON are scored too unless classified here (D175).
|
|
490
|
+
read = set((config.get("paths") or {}).get("include_extensions", ()))
|
|
491
|
+
not_ours_dirs = (*generated_dirs, *vendored_dirs)
|
|
461
492
|
for path in sorted(root.rglob("*")):
|
|
462
|
-
if not path.is_file()
|
|
493
|
+
if not path.is_file():
|
|
463
494
|
continue
|
|
464
495
|
relative = path.relative_to(root).as_posix()
|
|
496
|
+
if path.suffix not in KNOWN_SOURCE_SUFFIXES and not (
|
|
497
|
+
path.suffix in read and any(_under(relative, owner) for owner in not_ours_dirs)
|
|
498
|
+
):
|
|
499
|
+
continue
|
|
465
500
|
if is_excluded(relative, list(excludes)):
|
|
466
501
|
continue
|
|
467
502
|
verdict, evidence, owner = _classify(
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_pillars.py
RENAMED
|
@@ -87,8 +87,9 @@ PILLARS: tuple[Pillar, ...] = (
|
|
|
87
87
|
name="security",
|
|
88
88
|
scope=Scope.DELEGATED,
|
|
89
89
|
reason=(
|
|
90
|
-
"delegated to secure-code-agent
|
|
91
|
-
"
|
|
90
|
+
"delegated to secure-code-agent, which this audit runs for the pillar; "
|
|
91
|
+
"when no measurement comes back the reason is given here, because "
|
|
92
|
+
"silence is not safety"
|
|
92
93
|
),
|
|
93
94
|
),
|
|
94
95
|
Pillar(
|
|
@@ -213,9 +214,14 @@ def pillar_report(
|
|
|
213
214
|
score: dict[str, Any],
|
|
214
215
|
practice: dict[str, Any],
|
|
215
216
|
delegated: dict[str, dict[str, Any]] | None = None,
|
|
217
|
+
unmeasured: dict[str, str] | None = None,
|
|
216
218
|
) -> list[dict[str, Any]]:
|
|
217
219
|
"""The pillar block exactly as it ships.
|
|
218
220
|
|
|
221
|
+
`unmeasured` names, per delegated pillar, why no measurement came back
|
|
222
|
+
from a run of the tool that owns it (D177), and replaces the generic
|
|
223
|
+
reason so the reader learns what actually happened.
|
|
224
|
+
|
|
219
225
|
Practice arrives as an argument rather than being computed here.
|
|
220
226
|
`_practice` reads the repository's configuration off disk, which
|
|
221
227
|
makes it a scanner, and the scoring layer may not reach upward into
|
|
@@ -251,7 +257,7 @@ def pillar_report(
|
|
|
251
257
|
report.append({
|
|
252
258
|
"pillar": pillar.name,
|
|
253
259
|
"scope": pillar.scope.value,
|
|
254
|
-
"reason": pillar.reason,
|
|
260
|
+
"reason": (unmeasured or {}).get(pillar.name) or pillar.reason,
|
|
255
261
|
# Both axes, side by side, never merged. A consumer reads
|
|
256
262
|
# either one; nothing in the document offers their mean.
|
|
257
263
|
"practice": resolved["level"],
|
|
@@ -118,6 +118,30 @@ def prompt_analyzer_caveat(report: dict[str, Any]) -> list[str]:
|
|
|
118
118
|
]
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
def prompt_security_pillar(report: dict[str, Any]) -> list[str]:
|
|
122
|
+
"""What the security pillar reported, stated where an agent reads the run (D176).
|
|
123
|
+
|
|
124
|
+
Evidence, never a task: security remediation is secure-code-agent's own
|
|
125
|
+
work order, not this prompt's. But a prompt that says nothing about
|
|
126
|
+
security lets an agent read silence as a clean bill, which is the one
|
|
127
|
+
reading ADR 007 exists to prevent.
|
|
128
|
+
"""
|
|
129
|
+
entry = next((p for p in report.get("pillars") or [] if p.get("pillar") == "security"), None)
|
|
130
|
+
if entry is None:
|
|
131
|
+
return []
|
|
132
|
+
if not entry.get("delegated_to"):
|
|
133
|
+
return [f"**Security pillar: not measured.** {entry.get('reason')}.", ""]
|
|
134
|
+
producer = entry.get("delegated_to") or "the delegated tool"
|
|
135
|
+
version = f" {entry['producer_version']}" if entry.get("producer_version") else ""
|
|
136
|
+
condition = "not graded" if entry.get("condition") is None else f"{entry['condition']:.1f}"
|
|
137
|
+
return [
|
|
138
|
+
f"**Security pillar (measured by {producer}{version}):** posture "
|
|
139
|
+
f"{entry.get('posture')}, practice level {entry.get('practice')}, condition "
|
|
140
|
+
f"{condition}. Its findings are that tool's work order, not this one.",
|
|
141
|
+
"",
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
|
|
121
145
|
def prompt_escalation_note(report: dict[str, Any]) -> list[str]:
|
|
122
146
|
"""Tell the agent what is deliberately absent, and why.
|
|
123
147
|
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/_scan_view.py
RENAMED
|
@@ -364,6 +364,13 @@ def pillar_cells(entry: dict[str, Any]) -> tuple[str, str]:
|
|
|
364
364
|
condition = "—" if entry["condition"] is None else f"{entry['condition']:.1f}"
|
|
365
365
|
if entry["posture"] is None:
|
|
366
366
|
return condition, "not measured — see below"
|
|
367
|
+
if entry["condition"] is None:
|
|
368
|
+
# An ungraded pillar is `unverified` because nothing could be graded,
|
|
369
|
+
# not because a clean scan lacks enforcement — the note for that cell
|
|
370
|
+
# told a reader of secure-code-agent's partial-coverage pillar that
|
|
371
|
+
# its scan was clean (D176). Say why no grade was issued instead.
|
|
372
|
+
why = (entry.get("evidence_reasons") or [None])[0] or "the evidence could not support a grade"
|
|
373
|
+
return condition, f"{entry['posture']}: not graded — {why}"
|
|
367
374
|
note = POSTURE_NOTE.get(entry["posture"], entry["posture"])
|
|
368
375
|
return condition, f"{entry['posture']}: {note}"
|
|
369
376
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""This tool runs secure-code-agent for the security pillar (D177).
|
|
2
|
+
|
|
3
|
+
[ADR 007](adr-007-pillars-and-practice.md) delegates the security pillar to
|
|
4
|
+
`secure-code-agent`. Until 3.7.0 the delegation was a handoff: the other
|
|
5
|
+
tool wrote `security-pillar.json` and this one read it if it happened to be
|
|
6
|
+
there. Nothing ran it, so every audit that did not follow a manual or CI run
|
|
7
|
+
of the other tool reported the pillar as unmeasured — including every audit
|
|
8
|
+
through the chat door, which cannot run it at all. Decided 2026-09-13 with
|
|
9
|
+
Marshall: the pillar is complete, so the audit runs it.
|
|
10
|
+
|
|
11
|
+
**What the child writes.** Every report `secure-code-agent` can produce is
|
|
12
|
+
redirected into a temporary directory this process owns: the Markdown and
|
|
13
|
+
JSON reports, SARIF, the PR comment, the remediation prompt and the pillar
|
|
14
|
+
document itself. The one write that cannot be redirected is its append-only
|
|
15
|
+
trend, `.secure-code/history.jsonl` in the audited tree, which it writes on
|
|
16
|
+
every run from its own configuration. Turning that off would mean handing
|
|
17
|
+
it a configuration from outside the tree, and `secure-code-agent` trusts an
|
|
18
|
+
outside configuration to name executables in the tree — so the override
|
|
19
|
+
would launder repository content past the other tool's own boundary. The
|
|
20
|
+
history is therefore declared, not suppressed.
|
|
21
|
+
|
|
22
|
+
**How the child is started.** Through `_runner.run`, like every analyzer and
|
|
23
|
+
the opted-in test command, so architecture rule 7 still holds: the tree can
|
|
24
|
+
reach one execution path, not a new one per feature. The command is the
|
|
25
|
+
interpreter doing the auditing, the way D144 and D166 bound theirs, so the
|
|
26
|
+
pillar is measured by the `secure-code-agent` installed beside this package
|
|
27
|
+
rather than whichever one `PATH` finds. It gets the runner's stripped
|
|
28
|
+
environment and a neutral working directory: not a sandbox, and not claimed
|
|
29
|
+
as one.
|
|
30
|
+
|
|
31
|
+
A run that produces no trustworthy document says why. Absence is never
|
|
32
|
+
silent, because silence is exactly what ADR 007 says must not read as safety.
|
|
33
|
+
"""
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import importlib.util
|
|
37
|
+
import shlex
|
|
38
|
+
import sys
|
|
39
|
+
import tempfile
|
|
40
|
+
from dataclasses import dataclass, field
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
from typing import Any
|
|
43
|
+
|
|
44
|
+
from ._delegated_pillar import read_produced
|
|
45
|
+
from ._runner import Invocation, Outcome, run
|
|
46
|
+
|
|
47
|
+
#: The distribution the pillar requires, and the range this tool reads.
|
|
48
|
+
REQUIREMENT = "secure-code-agent>=0.10,<0.11"
|
|
49
|
+
|
|
50
|
+
#: How long the child may run before the pillar is reported as unmeasured.
|
|
51
|
+
DEFAULT_TIMEOUT_SECONDS = 300
|
|
52
|
+
|
|
53
|
+
_ENTRY = "import sys; from secure_code_audit.cli import main; sys.exit(main())"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class DelegateRun:
|
|
58
|
+
"""What one run of the delegate produced, and why when it produced nothing."""
|
|
59
|
+
|
|
60
|
+
document: dict[str, Any] | None
|
|
61
|
+
reason: str | None = None
|
|
62
|
+
environment: list[dict[str, str]] = field(default_factory=list)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _install_remedy(reason: str) -> dict[str, str]:
|
|
66
|
+
"""An environment work-order entry, bound to the auditing interpreter (D144)."""
|
|
67
|
+
python = shlex.quote(sys.executable)
|
|
68
|
+
return {
|
|
69
|
+
"tool": "secure-code-agent",
|
|
70
|
+
"reason": reason,
|
|
71
|
+
"install": f"{python} -m pip install '{REQUIREMENT}'",
|
|
72
|
+
"verify": f"{python} -m pip show secure-code-agent",
|
|
73
|
+
"concepts": "security",
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def run_security_delegate(
|
|
78
|
+
root: Path, *, changed_revspec: str | None = None,
|
|
79
|
+
timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS,
|
|
80
|
+
) -> DelegateRun:
|
|
81
|
+
"""Run `secure-code-agent` over `root` and return its pillar document."""
|
|
82
|
+
if importlib.util.find_spec("secure_code_audit") is None:
|
|
83
|
+
reason = "secure-code-agent is not installed for the interpreter running this audit"
|
|
84
|
+
return DelegateRun(None, reason, [_install_remedy(reason)])
|
|
85
|
+
with tempfile.TemporaryDirectory(prefix="ma-security-") as scratch:
|
|
86
|
+
out = Path(scratch)
|
|
87
|
+
pillar = out / "security-pillar.json"
|
|
88
|
+
argv = [
|
|
89
|
+
sys.executable, "-c", _ENTRY, str(root),
|
|
90
|
+
"--security-pillar", str(pillar),
|
|
91
|
+
"--output", str(out / "report.md"),
|
|
92
|
+
"--json-output", str(out / "report.json"),
|
|
93
|
+
"--sarif-output", str(out / "report.sarif"),
|
|
94
|
+
"--comment-output", str(out / "comment.md"),
|
|
95
|
+
"--prompt-output", str(out / "prompt.md"),
|
|
96
|
+
]
|
|
97
|
+
if changed_revspec:
|
|
98
|
+
argv += ["--changed-only", changed_revspec]
|
|
99
|
+
# Exit 1 is the tool's gate verdict, not a failure to measure: the
|
|
100
|
+
# pillar document is still written, and the pillar reports the gate.
|
|
101
|
+
result = run("secure-code-agent", Invocation(
|
|
102
|
+
argv=tuple(argv), findings_exit_codes=(0, 1), cwd=out,
|
|
103
|
+
), timeout_seconds=timeout_seconds)
|
|
104
|
+
document = read_produced(pillar)
|
|
105
|
+
if document is not None:
|
|
106
|
+
return DelegateRun(document)
|
|
107
|
+
if result.outcome is Outcome.TIMED_OUT:
|
|
108
|
+
return DelegateRun(None, f"secure-code-agent did not finish within {timeout_seconds}s")
|
|
109
|
+
detail = _last_line(result.stderr) or _last_line(result.stdout) or result.detail
|
|
110
|
+
# No install remedy here: the tool is installed and ran. A rejected
|
|
111
|
+
# configuration or a crash is fixed in the repository or reported
|
|
112
|
+
# upstream, and an install command would send the reader to the
|
|
113
|
+
# wrong place.
|
|
114
|
+
reason = (f"secure-code-agent exited {result.exit_code} without a pillar document"
|
|
115
|
+
+ (f": {detail}" if detail else ""))
|
|
116
|
+
return DelegateRun(None, reason)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _last_line(text: str | None) -> str:
|
|
120
|
+
lines = [line.strip() for line in (text or "").splitlines() if line.strip()]
|
|
121
|
+
return lines[-1][:200] if lines else ""
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/config.py
RENAMED
|
@@ -20,7 +20,7 @@ from ._operator_reads import (
|
|
|
20
20
|
# still the door every caller comes through.
|
|
21
21
|
__all__ = ["DEFAULT_CONFIG", "DEFAULT_IDIOM_GROUPS", "PROJECT_URL", "VERSION"]
|
|
22
22
|
|
|
23
|
-
VERSION = "3.
|
|
23
|
+
VERSION = "3.7.0"
|
|
24
24
|
|
|
25
25
|
PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
|
|
26
26
|
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/git_tools.py
RENAMED
|
@@ -231,6 +231,36 @@ def probe_git(args: list[str], cwd: Path) -> str:
|
|
|
231
231
|
return ""
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
def ignored_untracked_paths(root: Path) -> set[str]:
|
|
235
|
+
"""Paths the repository's own `.gitignore` files exclude and git does not track (D175).
|
|
236
|
+
|
|
237
|
+
A build writes `target/`, `out/` or `bin/` into the working tree, and the
|
|
238
|
+
repository's `.gitignore` is where it says those are not its source.
|
|
239
|
+
That is evidence the repository provides, so ADR 010 can act on it where
|
|
240
|
+
a list of directory names cannot.
|
|
241
|
+
|
|
242
|
+
Only the per-directory `.gitignore` files are read. `--exclude-standard`
|
|
243
|
+
would also honour `.git/info/exclude` and the user's `core.excludesFile`,
|
|
244
|
+
which differ by machine — the same commit would then score differently
|
|
245
|
+
on two laptops (P1). A tracked file matched by an ignore rule is not
|
|
246
|
+
listed, because git tracks it, and an untracked file that is *not*
|
|
247
|
+
ignored stays in: that is uncommitted work, which D56 keeps visible.
|
|
248
|
+
|
|
249
|
+
Directories come back with a trailing slash, which is stripped. A tree
|
|
250
|
+
git cannot read — not a repository, git absent — yields nothing, which
|
|
251
|
+
is the absence of evidence rather than a verdict.
|
|
252
|
+
"""
|
|
253
|
+
try:
|
|
254
|
+
output = run_git(
|
|
255
|
+
["ls-files", "--others", "--ignored",
|
|
256
|
+
"--exclude-per-directory=.gitignore", "--directory", "-z"],
|
|
257
|
+
root, strip=False,
|
|
258
|
+
)
|
|
259
|
+
except GitCommandFailed:
|
|
260
|
+
return set()
|
|
261
|
+
return {entry.rstrip("/") for entry in output.split("\0") if entry.strip("/")}
|
|
262
|
+
|
|
263
|
+
|
|
234
264
|
def changed_paths(root: Path, revspec: str) -> set[str]:
|
|
235
265
|
"""Paths touched by `revspec`, as forward-slash relative strings.
|
|
236
266
|
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/mcp_server.py
RENAMED
|
@@ -4,10 +4,12 @@ This module is transport assembly: tool bindings, resources, prompts and
|
|
|
4
4
|
the stdio entry point. The audit tool's own logic — authorization,
|
|
5
5
|
tri-state resolution, history recording — lives in ``_mcp_audit`` and is
|
|
6
6
|
re-exported here so every consumer keeps one import path. Setup, the
|
|
7
|
-
loop record and baseline adoption may write only
|
|
7
|
+
loop record and baseline adoption may write only six local artifacts:
|
|
8
8
|
repository and user configuration, user state, the repository's scan
|
|
9
|
-
history,
|
|
10
|
-
|
|
9
|
+
history, the repository's baseline, and — because an audit runs
|
|
10
|
+
secure-code-agent for the security pillar (D177) — that tool's own
|
|
11
|
+
append-only trend. It never writes source or a report, accepts a command
|
|
12
|
+
string, or invokes a shell.
|
|
11
13
|
"""
|
|
12
14
|
|
|
13
15
|
from __future__ import annotations
|
|
@@ -66,11 +68,13 @@ SERVER_INSTRUCTIONS = (
|
|
|
66
68
|
"step: do not inspect configuration first and do not ask the user "
|
|
67
69
|
"which config to use — the tool resolves that itself. First contact with an "
|
|
68
70
|
"unconfigured repository elicits setup, and the audit records its scan "
|
|
69
|
-
"history and can adopt a baseline, so it may write exactly
|
|
71
|
+
"history and can adopt a baseline, so it may write exactly six local "
|
|
70
72
|
"artifacts: the repository's maintainability-agent.json, the user-level "
|
|
71
73
|
"config, the user state file, the repository's scan history "
|
|
72
|
-
"(.maintainability/history.jsonl by default),
|
|
73
|
-
"(.maintainability/baseline.json by default)
|
|
74
|
+
"(.maintainability/history.jsonl by default), a requested baseline "
|
|
75
|
+
"(.maintainability/baseline.json by default), and secure-code-agent's own "
|
|
76
|
+
"trend (.secure-code/history.jsonl), which that tool appends when the audit "
|
|
77
|
+
"runs it for the security pillar. Scan history rides the "
|
|
74
78
|
"record_history tri-state, where unset means an existing history file "
|
|
75
79
|
"appends and otherwise the persisted first-run consent decides, "
|
|
76
80
|
"true forces the write, and false suppresses it. Nothing is audited "
|
|
@@ -109,12 +113,14 @@ def server_info(roots: tuple[Path, ...] | None = None) -> dict[str, Any]:
|
|
|
109
113
|
"transport": "stdio",
|
|
110
114
|
"local": True,
|
|
111
115
|
# Not blanket read-only since D2/D5: setup, the loop record and
|
|
112
|
-
# baseline adoption write
|
|
113
|
-
#
|
|
116
|
+
# baseline adoption write the local artifacts listed below, and the
|
|
117
|
+
# security pillar's run of secure-code-agent appends that tool's own
|
|
118
|
+
# trend (D177). Never source and never a report.
|
|
114
119
|
"read_only": False,
|
|
115
120
|
"writes": [CONFIG_FILENAME, "user config", "user state",
|
|
116
121
|
f"scan history ({DEFAULT_HISTORY_PATH})",
|
|
117
|
-
"baseline (.maintainability/baseline.json)"
|
|
122
|
+
"baseline (.maintainability/baseline.json)",
|
|
123
|
+
"secure-code-agent history (.secure-code/history.jsonl)"],
|
|
118
124
|
"never_writes": ["source", "reports"],
|
|
119
125
|
"allowed_roots": [str(root) for root in authorized_roots],
|
|
120
126
|
# Stored grants this process will not honour. A hand-written
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/prompts.py
RENAMED
|
@@ -69,6 +69,7 @@ def render_ai_prompt(report: dict[str, Any]) -> str:
|
|
|
69
69
|
"",
|
|
70
70
|
])
|
|
71
71
|
lines.extend(prompt_analyzer_caveat(report))
|
|
72
|
+
lines.extend(prompt_security_pillar(report))
|
|
72
73
|
# The prompt is the product artifact (H1): its remedy follows the
|
|
73
74
|
# same report fact as every other skin, never a stale default.
|
|
74
75
|
lines.extend(view.remediation_note(
|
|
@@ -155,6 +156,7 @@ from ._prompt_sections import ( # noqa: E402,F401 - re-export after the split
|
|
|
155
156
|
prompt_focus_sections,
|
|
156
157
|
prompt_has_work,
|
|
157
158
|
prompt_pressure_section,
|
|
159
|
+
prompt_security_pillar,
|
|
158
160
|
prompt_semantic_section,
|
|
159
161
|
prompt_tdd_section,
|
|
160
162
|
prompt_work_order,
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/renderers.py
RENAMED
|
@@ -214,6 +214,12 @@ def _bounded_markdown(report: dict[str, Any], score: dict[str, Any],
|
|
|
214
214
|
lines.extend(summary)
|
|
215
215
|
lines.extend(render_grade_blockers(report))
|
|
216
216
|
lines.extend(score_table(score))
|
|
217
|
+
# The pillars, security among them, in the view most people read (D176).
|
|
218
|
+
# Rendered by the same function the complete report uses, so the two
|
|
219
|
+
# skins cannot disagree about a pillar (ADR 011); before this the chat
|
|
220
|
+
# view printed nothing about security at all, measured or not, and a
|
|
221
|
+
# missing pillar read exactly like a clean one (ADR 007).
|
|
222
|
+
lines.extend(pillars_markdown(report.get("pillars"), report.get("practice")))
|
|
217
223
|
lines.extend([
|
|
218
224
|
"---", "",
|
|
219
225
|
"This is the bounded UI view. The complete report — every finding, "
|
{maintainability_agent-3.6.2 → maintainability_agent-3.7.0}/src/maintainability_audit/report.py
RENAMED
|
@@ -22,6 +22,7 @@ from ._economics import economic_context_from, economic_impact, reorder_by_expos
|
|
|
22
22
|
from ._metrics_types import FileMetric, FunctionMetric
|
|
23
23
|
from ._pillars import pillar_report
|
|
24
24
|
from ._practice import practice_level
|
|
25
|
+
from ._security_delegate import run_security_delegate
|
|
25
26
|
from ._semantic import semantic_findings
|
|
26
27
|
from ._semantic_policy import load_semantic_policy
|
|
27
28
|
from ._semantic_ts import discover_type_analysis
|
|
@@ -399,27 +400,42 @@ def _attach_semantics(
|
|
|
399
400
|
|
|
400
401
|
def _pillars_with_delegation(
|
|
401
402
|
report: dict[str, Any], root: Path, pillar_path: str | None = None,
|
|
403
|
+
changed_revspec: str | None = None,
|
|
402
404
|
) -> list[dict[str, Any]]:
|
|
403
|
-
"""The pillar block, with
|
|
404
|
-
|
|
405
|
-
ADR 007 §1 makes Security a delegated pillar naming
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
405
|
+
"""The pillar block, with the delegated security pillar measured.
|
|
406
|
+
|
|
407
|
+
ADR 007 §1 makes Security a delegated pillar naming `secure-code-agent`.
|
|
408
|
+
Until D177 that was a handoff: the entry carried the other tool's
|
|
409
|
+
measurement only when a `security-pillar.json` had been left in the tree,
|
|
410
|
+
so every audit nobody had prepared — and every audit through the chat
|
|
411
|
+
door — reported the pillar unmeasured.
|
|
412
|
+
|
|
413
|
+
**The audit runs the delegate (D177).** An operator who names a document
|
|
414
|
+
with `--security-pillar` — CI, which runs secure-code-agent as its own
|
|
415
|
+
gated step — has that document used as given. Otherwise this audit runs
|
|
416
|
+
secure-code-agent itself. A `security-pillar.json` sitting in the tree is
|
|
417
|
+
no longer read on its own authority: it is repository content, and a
|
|
418
|
+
repository may not report its own security posture in place of a
|
|
419
|
+
measurement. When nothing trustworthy comes back, the entry says why.
|
|
413
420
|
|
|
414
421
|
Its own function because `build_report` was at eighty lines against a
|
|
415
422
|
limit of eighty, and adding this inline took it to eighty-eight —
|
|
416
423
|
caught by this tool's gate on the commit that added it.
|
|
417
424
|
"""
|
|
418
|
-
|
|
419
|
-
|
|
425
|
+
if pillar_path:
|
|
426
|
+
handed_over = read_delegated(root, pillar_path)
|
|
427
|
+
reason = None if handed_over else (
|
|
428
|
+
f"the --security-pillar document {pillar_path} was absent or could not be trusted")
|
|
429
|
+
else:
|
|
430
|
+
run = run_security_delegate(root, changed_revspec=changed_revspec)
|
|
431
|
+
handed_over, reason = run.document, run.reason
|
|
432
|
+
if run.environment:
|
|
433
|
+
report["environment_work_order"] = [
|
|
434
|
+
*(report.get("environment_work_order") or []), *run.environment]
|
|
420
435
|
return pillar_report(
|
|
421
436
|
report["score"], report["practice"],
|
|
422
437
|
{"security": handed_over} if handed_over else None,
|
|
438
|
+
{"security": reason} if reason else None,
|
|
423
439
|
)
|
|
424
440
|
|
|
425
441
|
|
|
@@ -490,7 +506,7 @@ def build_report(
|
|
|
490
506
|
report["score"] = score_report(report, analyzer["pressures"])
|
|
491
507
|
# Condition rolls up aspects; practice stays a separate axis (ADR 007).
|
|
492
508
|
report["practice"] = practice_level(root, config).as_dict()
|
|
493
|
-
report["pillars"] = _pillars_with_delegation(report, root, security_pillar)
|
|
509
|
+
report["pillars"] = _pillars_with_delegation(report, root, security_pillar, changed_revspec)
|
|
494
510
|
_attach_semantics(report, root, config, only_paths)
|
|
495
511
|
# Last, because every item's delta is a rubric recomputation and the
|
|
496
512
|
# rubric needs the scored report to recompute against.
|