maintainability-agent 3.7.7__tar.gz → 3.7.8__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.7.7/src/maintainability_agent.egg-info → maintainability_agent-3.7.8}/PKG-INFO +3 -3
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/README.md +2 -2
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/pyproject.toml +1 -1
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8/src/maintainability_agent.egg-info}/PKG-INFO +3 -3
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_agent.egg-info/SOURCES.txt +4 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_gate.py +11 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_security_delegate.py +10 -2
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_test_execution.py +22 -1
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/config.py +1 -1
- maintainability_agent-3.7.8/tests/test_code_scanning_gets_alerts_not_the_record.py +83 -0
- maintainability_agent-3.7.8/tests/test_consent_without_command_has_a_remedy.py +66 -0
- maintainability_agent-3.7.8/tests/test_declared_capabilities_match_the_delegate.py +118 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_security_delegate_versions_agree.py +9 -2
- maintainability_agent-3.7.8/tests/test_security_pillar_asserts_a_scanner_set.py +58 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/LICENSE +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/setup.cfg +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_analyzer_sections.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_anchor.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_arguments.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_banner.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_criteria_scope.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_delegated_pillar.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_discovery.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_evidence_reader.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_grammar.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_in_loop.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_in_loop_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_operator_reads.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_pillars.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_precommit.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_precommit_install.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_precommit_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_prompt_sections.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_go.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_php.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_ruby.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_rust.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_ratio_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_run_comparison.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_scan_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_security_work_order.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_work_order.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_work_order_view.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/cli.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/git_tools.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/mcp_server.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/prompts.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/renderers.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/report.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_added_lines.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_anchor_and_mode.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_anchor_disclosure.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_architecture.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_attestation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_audit_components.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_backfill.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_bands.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_build_output_is_not_the_repositorys_code.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_chat_leads_with_the_work_order.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_check_refuses_plus_only_fragments.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_child_sandbox.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_cli.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_config_shape.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_corroborate.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_criteria_completion.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_dead_code.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declaration_criteria_scope.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declaration_grading.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declarative_parsers.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_delegated_security_pillar.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_demo_tree.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_determinism.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_discovery.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_docs_links.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_economic_context.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_every_surface_says_what_the_run_found.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_evidence_properties.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_example_config_opens_claimed_languages.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_exposure_never_outranks_band.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_format_ask.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_git_argv.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_go_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_grammar_constructs.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_grammar_token_coverage.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_history.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_history_window.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_html_executive.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_in_loop_budgets.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_in_loop_check.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_java_scored.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_language_support_honesty.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mcp_format_contract.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mcp_server.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mcp_start_failure_names_what_is_installed.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_mutation_recorded.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_operator_named_paths.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_operator_named_reads.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pairing_reads_imports.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_php_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_platform_claim.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_policy_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_population_floors.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_precommit_staged.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_promises.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_python_complexity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_recurrence.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_release_needs_an_empty_ledger.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_release_plan.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_root_grants.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_ruby_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_runner.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_rust_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_sarif.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scan_history.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scanning.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_security_findings_keep_their_handoff.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_security_pillar_runs_and_shows.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_semantic_findings_stay_inside_the_audited_files.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_skill_install.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_sonar_resolve.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_source_index.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_stdout_outputs.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_suite_isolation.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_terminal_asks_the_same_questions.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_test_commands.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_tool_resolution.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_tree_chosen_spawn.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_tree_reads_use_the_primitive.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_trends.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_unanchored_set_matches_corpus.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_unread_code.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_version_claim.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_withheld_work_keeps_its_boundary.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_work_items_state_their_own_finding.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_work_order.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/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.7.
|
|
3
|
+
Version: 3.7.8
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -46,7 +46,7 @@ Dynamic: license-file
|
|
|
46
46
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
47
47
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
48
48
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
49
|
-
Version **3.7.
|
|
49
|
+
Version **3.7.8**.
|
|
50
50
|
|
|
51
51
|
**Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
|
|
52
52
|
COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
|
|
@@ -473,7 +473,7 @@ instead of an invokable skill:
|
|
|
473
473
|
This repo ships `action.yml`, usable as a composite action:
|
|
474
474
|
|
|
475
475
|
```yaml
|
|
476
|
-
- uses: marshallguillory86/maintainability-agent@v3.7.
|
|
476
|
+
- uses: marshallguillory86/maintainability-agent@v3.7.8
|
|
477
477
|
with:
|
|
478
478
|
config: maintainability-agent.json
|
|
479
479
|
changed-only: main...HEAD
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
6
6
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
7
7
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
8
|
-
Version **3.7.
|
|
8
|
+
Version **3.7.8**.
|
|
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
|
|
@@ -432,7 +432,7 @@ instead of an invokable skill:
|
|
|
432
432
|
This repo ships `action.yml`, usable as a composite action:
|
|
433
433
|
|
|
434
434
|
```yaml
|
|
435
|
-
- uses: marshallguillory86/maintainability-agent@v3.7.
|
|
435
|
+
- uses: marshallguillory86/maintainability-agent@v3.7.8
|
|
436
436
|
with:
|
|
437
437
|
config: maintainability-agent.json
|
|
438
438
|
changed-only: main...HEAD
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "maintainability-agent"
|
|
7
|
-
version = "3.7.
|
|
7
|
+
version = "3.7.8"
|
|
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.7.
|
|
3
|
+
Version: 3.7.8
|
|
4
4
|
Summary: Maintainability gate and AI remediation prompt generator for CI.
|
|
5
5
|
Author: Marshall Guillory
|
|
6
6
|
License: MIT
|
|
@@ -46,7 +46,7 @@ Dynamic: license-file
|
|
|
46
46
|
**A deterministic, offline maintainability audit whose output is a _bounded
|
|
47
47
|
work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
|
|
48
48
|
says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
|
|
49
|
-
Version **3.7.
|
|
49
|
+
Version **3.7.8**.
|
|
50
50
|
|
|
51
51
|
**Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
|
|
52
52
|
COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
|
|
@@ -473,7 +473,7 @@ instead of an invokable skill:
|
|
|
473
473
|
This repo ships `action.yml`, usable as a composite action:
|
|
474
474
|
|
|
475
475
|
```yaml
|
|
476
|
-
- uses: marshallguillory86/maintainability-agent@v3.7.
|
|
476
|
+
- uses: marshallguillory86/maintainability-agent@v3.7.8
|
|
477
477
|
with:
|
|
478
478
|
config: maintainability-agent.json
|
|
479
479
|
changed-only: main...HEAD
|
|
@@ -203,11 +203,13 @@ tests/test_claimed_languages.py
|
|
|
203
203
|
tests/test_cli.py
|
|
204
204
|
tests/test_clone_group_class.py
|
|
205
205
|
tests/test_cobol_declarations.py
|
|
206
|
+
tests/test_code_scanning_gets_alerts_not_the_record.py
|
|
206
207
|
tests/test_cognitive_complexity.py
|
|
207
208
|
tests/test_cohort_statistics.py
|
|
208
209
|
tests/test_concealment_properties.py
|
|
209
210
|
tests/test_config_shape.py
|
|
210
211
|
tests/test_consent_and_grant.py
|
|
212
|
+
tests/test_consent_without_command_has_a_remedy.py
|
|
211
213
|
tests/test_consumer_migration.py
|
|
212
214
|
tests/test_contract_claims.py
|
|
213
215
|
tests/test_corroborate.py
|
|
@@ -224,6 +226,7 @@ tests/test_declaration_grading.py
|
|
|
224
226
|
tests/test_declaration_ranges.py
|
|
225
227
|
tests/test_declaration_source.py
|
|
226
228
|
tests/test_declarative_parsers.py
|
|
229
|
+
tests/test_declared_capabilities_match_the_delegate.py
|
|
227
230
|
tests/test_declared_imports.py
|
|
228
231
|
tests/test_delegated_security_pillar.py
|
|
229
232
|
tests/test_demo_tree.py
|
|
@@ -344,6 +347,7 @@ tests/test_scope_conformance.py
|
|
|
344
347
|
tests/test_scoring_calibration.py
|
|
345
348
|
tests/test_security_delegate_versions_agree.py
|
|
346
349
|
tests/test_security_findings_keep_their_handoff.py
|
|
350
|
+
tests/test_security_pillar_asserts_a_scanner_set.py
|
|
347
351
|
tests/test_security_pillar_runs_and_shows.py
|
|
348
352
|
tests/test_semantic_findings_stay_inside_the_audited_files.py
|
|
349
353
|
tests/test_semantic_policy.py
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_mcp_gate.py
RENAMED
|
@@ -18,6 +18,7 @@ from pathlib import Path
|
|
|
18
18
|
from typing import Any
|
|
19
19
|
|
|
20
20
|
from ._mcp_setup import run_tests_pending, setup_pending, setup_questions
|
|
21
|
+
from ._test_execution import consented_without_command
|
|
21
22
|
from ._user_config import mark_repo_seen
|
|
22
23
|
from .config import VERSION, load_config
|
|
23
24
|
|
|
@@ -100,6 +101,16 @@ def _choose_next(root: Path) -> dict[str, Any]:
|
|
|
100
101
|
"own test suite for a coverage reading (test effectiveness). "
|
|
101
102
|
"Choose reconfigure to set it up."
|
|
102
103
|
)
|
|
104
|
+
elif consented_without_command():
|
|
105
|
+
# The opt-in was answered yes and the command never reached the
|
|
106
|
+
# person's tier, so `run_tests_pending` reads it as asked-and-done
|
|
107
|
+
# and said nothing. The suite then does not run on any audit, and
|
|
108
|
+
# the report explained the refusal without naming a remedy.
|
|
109
|
+
prompt += (
|
|
110
|
+
" Note: this host is opted in to running the test suite, but no "
|
|
111
|
+
"test command is recorded for it, so no suite runs. Choose "
|
|
112
|
+
"reconfigure to record the command."
|
|
113
|
+
)
|
|
103
114
|
result["choice_needed"] = {
|
|
104
115
|
"name": "next_action",
|
|
105
116
|
"prompt": prompt,
|
|
@@ -61,9 +61,17 @@ from ._runner import Invocation, Outcome, run
|
|
|
61
61
|
#: `paths:` globs against absolute finding paths. This audit always hands it an
|
|
62
62
|
#: absolute root, so under 0.12.1 every reviewed `paths:` suppression is ignored
|
|
63
63
|
#: and its finding counts as live in the pillar every skin shows (D179).
|
|
64
|
-
|
|
64
|
+
#:
|
|
65
|
+
#: **Raised to 0.12.7 by D186.** The delegate config now declares what this
|
|
66
|
+
#: tool is — `capabilities` — and secure-code-agent sweeps unknown top-level
|
|
67
|
+
#: keys strictly, so anything below 0.12.6 refuses the configuration outright
|
|
68
|
+
#: rather than ignoring the key: the audit would not run at all. 0.12.6 runs
|
|
69
|
+
#: it and prints no reason under the declared axes (its D25), which is a grade
|
|
70
|
+
#: moved in silence. The floor is the first release where the declaration is
|
|
71
|
+
#: both accepted and disclosed.
|
|
72
|
+
SUPPORTED_FLOOR = (0, 12, 7)
|
|
65
73
|
SUPPORTED_CEILING = (1,)
|
|
66
|
-
REQUIREMENT = "secure-code-agent>=0.12.
|
|
74
|
+
REQUIREMENT = "secure-code-agent>=0.12.7,<1"
|
|
67
75
|
|
|
68
76
|
#: How long the child may run before the pillar is reported as unmeasured.
|
|
69
77
|
DEFAULT_TIMEOUT_SECONDS = 300
|
|
@@ -113,6 +113,25 @@ def opted_in_command() -> list[str]:
|
|
|
113
113
|
return list(command) if isinstance(command, list) else []
|
|
114
114
|
|
|
115
115
|
|
|
116
|
+
def consented_without_command() -> bool:
|
|
117
|
+
"""Opted in to running the suite, with no command in the person's tier.
|
|
118
|
+
|
|
119
|
+
`run_tests_pending` covers the config written before the opt-in existed:
|
|
120
|
+
no `test_execution` key at all, so the question was never asked. This
|
|
121
|
+
covers the state after it — the answer is recorded, `requested` is true,
|
|
122
|
+
and `expected_commands.test` never reached the user tier because setup
|
|
123
|
+
captured the consent without capturing the program.
|
|
124
|
+
|
|
125
|
+
Neither surface said anything about it. The report explained why nothing
|
|
126
|
+
ran and named no remedy, and the MCP gate treats a present `test_execution`
|
|
127
|
+
key as asked-and-answered, so it offered no discovery line either. A person
|
|
128
|
+
who said yes got silence on every door.
|
|
129
|
+
"""
|
|
130
|
+
answers = user_config_answers() or {}
|
|
131
|
+
requested = bool((answers.get("test_execution") or {}).get("requested"))
|
|
132
|
+
return requested and not opted_in_command()
|
|
133
|
+
|
|
134
|
+
|
|
116
135
|
def _bounded_suite_timeout(configured: Any) -> int:
|
|
117
136
|
"""A suite timeout the audited tree cannot weaponise.
|
|
118
137
|
|
|
@@ -153,7 +172,9 @@ def run_test_suite(root: Path, config: dict[str, Any]) -> dict[str, Any] | None:
|
|
|
153
172
|
"ran": False, "exit_code": None, "passed": False,
|
|
154
173
|
"detail": (
|
|
155
174
|
"opted in, but no test command is recorded in the user tier; "
|
|
156
|
-
"the repository's documented command is not run on its own say-so"
|
|
175
|
+
"the repository's documented command is not run on its own say-so. "
|
|
176
|
+
"Reconfigure to record the command you consent to, or add it to "
|
|
177
|
+
"expected_commands.test in the user configuration"
|
|
157
178
|
),
|
|
158
179
|
"coverage_percent": None,
|
|
159
180
|
}
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/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.7.
|
|
23
|
+
VERSION = "3.7.8"
|
|
24
24
|
|
|
25
25
|
PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
|
|
26
26
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""What this repository uploads to code scanning is what should become an alert (D187).
|
|
2
|
+
|
|
3
|
+
secure-code-agent writes two SARIF documents (its D22). `--sarif-output` is the
|
|
4
|
+
record: every result, a suppressed one carrying its `suppressions` entry and
|
|
5
|
+
reason. `--code-scanning-sarif-output` is the same document without the
|
|
6
|
+
suppressed results — the test tree, documentation, and every reviewed
|
|
7
|
+
`.scignore.yaml` entry.
|
|
8
|
+
|
|
9
|
+
The difference matters because code scanning opens an alert for every result it
|
|
10
|
+
is handed, `suppressions` array or not, and this repository's branch protection
|
|
11
|
+
requires every resulting review thread resolved before a merge. Uploading the
|
|
12
|
+
record put seventeen threads on one pull request, all of them `assert` in a
|
|
13
|
+
pytest file, and blocked it. That is not a one-off: it is the outcome for every
|
|
14
|
+
pull request that adds a test, forever, and the shape secure-code-agent already
|
|
15
|
+
fixed upstream and this repository had not adopted.
|
|
16
|
+
|
|
17
|
+
Nothing is hidden by the change. The record is still written, still kept as a
|
|
18
|
+
build artifact, and still carries every finding; so do the JSON report, the
|
|
19
|
+
Markdown report and the work order. What changes is which document becomes
|
|
20
|
+
somebody's blocking alert.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import re
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
29
|
+
WORKFLOWS = ROOT / ".github" / "workflows"
|
|
30
|
+
|
|
31
|
+
#: The record. Never the thing uploaded to code scanning.
|
|
32
|
+
_RECORD = "secure-code.sarif"
|
|
33
|
+
#: The filtered document, which is.
|
|
34
|
+
_FILTERED = "secure-code.code-scanning.sarif"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _uploads() -> list[tuple[str, str]]:
|
|
38
|
+
"""Every `sarif_file:` value handed to the code-scanning upload action."""
|
|
39
|
+
found = []
|
|
40
|
+
for path in sorted(WORKFLOWS.glob("*.yml")):
|
|
41
|
+
for match in re.finditer(r"^\s*sarif_file:\s*(\S+)\s*$", path.read_text(encoding="utf-8"), re.MULTILINE):
|
|
42
|
+
found.append((path.name, match.group(1)))
|
|
43
|
+
return found
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_the_security_record_is_never_uploaded_to_code_scanning() -> None:
|
|
47
|
+
"""The record carries the test tree; code scanning turns each one into a thread."""
|
|
48
|
+
uploads = _uploads()
|
|
49
|
+
assert uploads, "no workflow uploads SARIF; this sweep would pass vacuously"
|
|
50
|
+
record = [(name, value) for name, value in uploads if value == _RECORD]
|
|
51
|
+
assert not record, (
|
|
52
|
+
f"the full secure-code-agent record is uploaded to code scanning: {record}. "
|
|
53
|
+
"Every suppressed finding becomes an alert, and under this repository's "
|
|
54
|
+
"required-conversation-resolution policy, a blocking review thread."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_the_filtered_document_is_what_is_uploaded() -> None:
|
|
59
|
+
"""Proving the record is absent is not proving the right file is present."""
|
|
60
|
+
uploaded = {value for _, value in _uploads()}
|
|
61
|
+
assert _FILTERED in uploaded, (
|
|
62
|
+
f"no workflow uploads {_FILTERED}; the security findings that should "
|
|
63
|
+
"become alerts would reach code scanning from nowhere"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_the_audit_asks_the_delegate_to_write_the_filtered_document() -> None:
|
|
68
|
+
"""An upload step naming a file nothing writes fails the job, loudly but late."""
|
|
69
|
+
writing = [
|
|
70
|
+
path.name
|
|
71
|
+
for path in sorted(WORKFLOWS.glob("*.yml"))
|
|
72
|
+
if f"--code-scanning-sarif-output {_FILTERED}" in path.read_text(encoding="utf-8")
|
|
73
|
+
]
|
|
74
|
+
assert writing, (
|
|
75
|
+
f"no workflow passes --code-scanning-sarif-output {_FILTERED}; the upload "
|
|
76
|
+
"step would name a file the security audit never produced"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_the_filtered_document_is_not_committed() -> None:
|
|
81
|
+
"""Generated per run, like every other audit output this repository writes."""
|
|
82
|
+
ignored = (ROOT / ".gitignore").read_text(encoding="utf-8").splitlines()
|
|
83
|
+
assert _FILTERED in ignored, f"{_FILTERED} is not in .gitignore"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Consent to run the suite, with no command, must name a way out (D185).
|
|
2
|
+
|
|
3
|
+
`test_execution.requested` true with no `expected_commands.test` in the user
|
|
4
|
+
tier is a reachable state: setup recorded the answer without recording the
|
|
5
|
+
program. In that state no suite runs on any audit.
|
|
6
|
+
|
|
7
|
+
Neither surface said what to do about it. The report explained the refusal and
|
|
8
|
+
stopped there, and the MCP gate treats a present `test_execution` key as
|
|
9
|
+
asked-and-answered, so `run_tests_pending` is false and no discovery line is
|
|
10
|
+
offered. A person who opted in got silence on every door, which is how this
|
|
11
|
+
repository's own audit reported "it did not run" for weeks.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
|
|
19
|
+
from maintainability_audit import _mcp_gate, _test_execution
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def consented(monkeypatch):
|
|
24
|
+
"""User tier that opted in and carries no command."""
|
|
25
|
+
monkeypatch.setattr(
|
|
26
|
+
_test_execution, "user_config_answers",
|
|
27
|
+
lambda: {"test_execution": {"requested": True}})
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_the_report_detail_names_a_remedy(consented, tmp_path):
|
|
32
|
+
"""The operator is told how to fix it, not only why it happened."""
|
|
33
|
+
result = _test_execution.run_test_suite(
|
|
34
|
+
tmp_path,
|
|
35
|
+
{"test_execution": {"requested": True},
|
|
36
|
+
"expected_commands": {"test": ["pytest", "-q"]}})
|
|
37
|
+
|
|
38
|
+
assert result is not None and result["ran"] is False
|
|
39
|
+
detail = result["detail"].lower()
|
|
40
|
+
assert "reconfigure" in detail or "expected_commands" in detail, (
|
|
41
|
+
f"the refusal names no remedy: {result['detail']!r}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_the_predicate_sees_consent_without_a_command(consented):
|
|
45
|
+
"""`run_tests_pending` cannot see this state; this is what does."""
|
|
46
|
+
assert _test_execution.consented_without_command() is True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_a_recorded_command_is_not_reported_as_missing(monkeypatch):
|
|
50
|
+
"""The predicate is about the gap, not about opting in."""
|
|
51
|
+
monkeypatch.setattr(
|
|
52
|
+
_test_execution, "user_config_answers",
|
|
53
|
+
lambda: {"test_execution": {"requested": True},
|
|
54
|
+
"expected_commands": {"test": ["pytest", "-q"]}})
|
|
55
|
+
assert _test_execution.consented_without_command() is False
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_the_mcp_gate_offers_reconfigure_for_the_gap(consented, monkeypatch, tmp_path):
|
|
59
|
+
"""The chat door surfaces it too, where `run_tests_pending` is false."""
|
|
60
|
+
monkeypatch.setattr(_mcp_gate, "run_tests_pending", lambda root: False)
|
|
61
|
+
|
|
62
|
+
result = _mcp_gate._choose_next(Path(tmp_path))
|
|
63
|
+
|
|
64
|
+
prompt = (result.get("choice_needed") or {}).get("prompt", "").lower()
|
|
65
|
+
assert "no test command is recorded" in prompt, (
|
|
66
|
+
f"the gate says nothing about the gap: {prompt!r}")
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""The capabilities this repository declares are ones its delegate will honour (D186).
|
|
2
|
+
|
|
3
|
+
The security pillar graded 3.82 (B+) on 68 true, permanent reports about what
|
|
4
|
+
this tool is: it spawns analyzer subprocesses, reads analyzer XML it did not
|
|
5
|
+
write, calls the SonarCloud API, and seeds a calibration bootstrap. None is a
|
|
6
|
+
defect and none is going to change.
|
|
7
|
+
|
|
8
|
+
`secure-code-agent.json` now declares those four, so they are reported on their
|
|
9
|
+
own axes rather than scored. That declaration is only worth anything if the
|
|
10
|
+
delegate actually honours it, and two ways of getting it wrong are silent from
|
|
11
|
+
this side:
|
|
12
|
+
|
|
13
|
+
* A capability name the delegate does not know declares nothing. The delegate
|
|
14
|
+
refuses it at config load, so it fails the audit rather than passing
|
|
15
|
+
quietly — but it fails in CI, and catching it here is cheaper.
|
|
16
|
+
* A delegate below the floor **refuses the whole configuration** on the
|
|
17
|
+
unknown `capabilities` key, so the audit does not run — and one at 0.12.6
|
|
18
|
+
routes the findings while printing no reason, which is the grade moved in
|
|
19
|
+
silence that declaring was supposed to replace (secure-code-agent D25).
|
|
20
|
+
|
|
21
|
+
These read the checked-in config against the pinned range, so neither can
|
|
22
|
+
drift without the suite saying so.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import json
|
|
28
|
+
import re
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
32
|
+
|
|
33
|
+
#: The first release where a declaration is both *accepted* and *disclosed*.
|
|
34
|
+
#: 0.12.6 accepts it and prints no reason under the axis.
|
|
35
|
+
_DISCLOSING_FLOOR = (0, 12, 7)
|
|
36
|
+
|
|
37
|
+
#: Every capability name secure-code-agent 0.12.7 defines.
|
|
38
|
+
#:
|
|
39
|
+
#: Copied, not imported. The two tools are independently releasable (ADR 008)
|
|
40
|
+
#: and this suite does not import the delegate, which the declared-imports
|
|
41
|
+
#: sweep enforces, and is right to.
|
|
42
|
+
#:
|
|
43
|
+
#: So this is a second source of truth, and the honest thing is to say what
|
|
44
|
+
#: guards it rather than to pretend it is derived. The delegate itself refuses
|
|
45
|
+
#: a capability name it does not define, loudly, at config load: a name that
|
|
46
|
+
#: drifts out of this set fails the security audit rather than passing it
|
|
47
|
+
#: quietly. This set exists to catch the typo in the suite instead of in CI,
|
|
48
|
+
#: not to be the authority on what the delegate defines.
|
|
49
|
+
_KNOWN_CAPABILITIES = frozenset(
|
|
50
|
+
{
|
|
51
|
+
"spawns_processes",
|
|
52
|
+
"parses_untrusted_xml",
|
|
53
|
+
"fetches_remote_urls",
|
|
54
|
+
"uses_nondeterministic_randomness",
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _config() -> dict:
|
|
60
|
+
return json.loads((ROOT / "secure-code-agent.json").read_text(encoding="utf-8"))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_every_declared_capability_is_one_the_delegate_defines() -> None:
|
|
64
|
+
"""A name this repository invented routes nothing and reads as a decision."""
|
|
65
|
+
declared = set(_config().get("capabilities", {}))
|
|
66
|
+
assert declared, "nothing is declared; D186 records four and this would pass vacuously"
|
|
67
|
+
unknown = sorted(declared - _KNOWN_CAPABILITIES)
|
|
68
|
+
assert not unknown, (
|
|
69
|
+
f"declared capabilities the delegate does not define: {unknown}; "
|
|
70
|
+
"these route no finding and account for nothing"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_every_declaration_states_a_reason() -> None:
|
|
75
|
+
"""The reason is what a reviewer reads to decide the declaration is still true."""
|
|
76
|
+
declared = _config().get("capabilities", {})
|
|
77
|
+
assert declared, (
|
|
78
|
+
"nothing is declared, so this sweep would pass over an empty loop; "
|
|
79
|
+
"D186 records four declarations and this test exists to hold their reasons"
|
|
80
|
+
)
|
|
81
|
+
for name, reason in declared.items():
|
|
82
|
+
assert isinstance(reason, str) and reason.strip(), f"{name} declares no reason"
|
|
83
|
+
assert len(reason.strip()) >= 40, (
|
|
84
|
+
f"{name}'s reason is too short to be one: {reason!r}. "
|
|
85
|
+
"A declaration without a statement of why is a skip with extra steps."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_declaring_capabilities_raised_the_supported_floor() -> None:
|
|
90
|
+
"""Below 0.12.7 the declaration is refused outright, or accepted and unstated."""
|
|
91
|
+
from maintainability_audit._security_delegate import SUPPORTED_FLOOR
|
|
92
|
+
|
|
93
|
+
assert _config().get("capabilities"), "nothing declared; the coupling would not exist"
|
|
94
|
+
assert SUPPORTED_FLOOR >= _DISCLOSING_FLOOR, (
|
|
95
|
+
f"this repository declares capabilities but admits secure-code-agent "
|
|
96
|
+
f"{'.'.join(map(str, SUPPORTED_FLOOR))}, which either refuses the whole "
|
|
97
|
+
"configuration on the unknown key or routes the findings without printing "
|
|
98
|
+
"the reason"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_no_ci_pin_predates_the_disclosing_release() -> None:
|
|
103
|
+
"""The floor is a declaration; the pins are what actually runs."""
|
|
104
|
+
pin = re.compile(r"secure-code-agent(?:\[[^\]]+\])?==([0-9][0-9.]*)")
|
|
105
|
+
pins = [
|
|
106
|
+
(path.name, found)
|
|
107
|
+
for path in sorted((ROOT / ".github" / "workflows").glob("*.yml"))
|
|
108
|
+
for found in pin.findall(path.read_text(encoding="utf-8"))
|
|
109
|
+
]
|
|
110
|
+
assert pins, "no workflow pins the delegate; this sweep would pass vacuously"
|
|
111
|
+
stale = [
|
|
112
|
+
(name, found)
|
|
113
|
+
for name, found in pins
|
|
114
|
+
if tuple(int(part) for part in found.split(".")) < _DISCLOSING_FLOOR
|
|
115
|
+
]
|
|
116
|
+
assert not stale, (
|
|
117
|
+
f"CI pins a delegate that will not disclose this repository's declarations: {stale}"
|
|
118
|
+
)
|
|
@@ -18,6 +18,13 @@ from pathlib import Path
|
|
|
18
18
|
|
|
19
19
|
ROOT = Path(__file__).resolve().parents[1]
|
|
20
20
|
|
|
21
|
+
#: A pinned install of the delegate, with or without extras. The job that runs
|
|
22
|
+
#: the security gate installs `secure-code-agent[required-scanners]==X` so the
|
|
23
|
+
#: scanners named in `gates.require_scanners` exist on the runner; a pattern
|
|
24
|
+
#: anchored on a bare `secure-code-agent==` stopped seeing that job's pin
|
|
25
|
+
#: entirely, which would have let the gate job drift unwatched.
|
|
26
|
+
_PIN = r"secure-code-agent(?:\[[^\]]+\])?==([0-9][0-9.]*)"
|
|
27
|
+
|
|
21
28
|
|
|
22
29
|
def _version_tuple(text: str) -> tuple[int, ...]:
|
|
23
30
|
return tuple(int(part) for part in text.split("."))
|
|
@@ -50,7 +57,7 @@ def test_every_ci_pin_is_a_release_the_audit_runs() -> None:
|
|
|
50
57
|
workflows = sorted((ROOT / ".github" / "workflows").glob("*.yml"))
|
|
51
58
|
assert workflows, "no workflows found"
|
|
52
59
|
pins = [(path.name, pin) for path in workflows
|
|
53
|
-
for pin in re.findall(
|
|
60
|
+
for pin in re.findall(_PIN, path.read_text(encoding="utf-8"))]
|
|
54
61
|
assert pins, "no workflow pins secure-code-agent; the gate would run whatever pip picks"
|
|
55
62
|
outside = [(name, pin) for name, pin in pins
|
|
56
63
|
if not (SUPPORTED_FLOOR <= _version_tuple(pin) < SUPPORTED_CEILING)]
|
|
@@ -82,5 +89,5 @@ def test_every_job_that_runs_the_suite_installs_secure_code_agent() -> None:
|
|
|
82
89
|
if re.search(r"-m pytest\b", body)
|
|
83
90
|
]
|
|
84
91
|
assert running, "no workflow job runs pytest; the sweep would pass vacuously"
|
|
85
|
-
missing = [(name, job) for name, job, body in running if
|
|
92
|
+
missing = [(name, job) for name, job, body in running if not re.search(_PIN, body)]
|
|
86
93
|
assert not missing, f"jobs that run the suite without installing secure-code-agent: {missing}"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""The delegate config asserts which scanners must have run (D184).
|
|
2
|
+
|
|
3
|
+
secure-code-agent withholds the security grade when no scanner set was
|
|
4
|
+
asserted — "grade withheld: no gates.require_scanners is declared, so no
|
|
5
|
+
scanner set was asserted to have run". This repository's delegate config
|
|
6
|
+
declared `fail_on_severity`, `fail_on_category`, `fail_on_new` and
|
|
7
|
+
`max_unsuppressed` and never that, so the pillar could reach complete
|
|
8
|
+
coverage and still report a posture of `unverified` rather than a grade.
|
|
9
|
+
|
|
10
|
+
The two halves have to stay together: naming a scanner here that the gate job
|
|
11
|
+
does not install turns coverage from complete into a hard failure, which is
|
|
12
|
+
the loud version of the same mistake.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import re
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
21
|
+
CONFIG = ROOT / "secure-code-agent.json"
|
|
22
|
+
QUALITY_GATES = ROOT / ".github" / "workflows" / "quality-gates.yml"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _gates() -> dict:
|
|
26
|
+
return json.loads(CONFIG.read_text(encoding="utf-8"))["gates"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_the_delegate_config_asserts_a_scanner_set() -> None:
|
|
30
|
+
required = _gates().get("require_scanners")
|
|
31
|
+
assert required, (
|
|
32
|
+
"secure-code-agent.json declares no gates.require_scanners, so the delegate "
|
|
33
|
+
"asserts no scanner set and withholds the security grade however complete "
|
|
34
|
+
"its coverage is"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_the_job_that_runs_the_gate_installs_the_scanners_it_requires() -> None:
|
|
39
|
+
"""The asserted scanners must exist on the runner that asserts them.
|
|
40
|
+
|
|
41
|
+
The gate job installs the delegate with its `required-scanners` extra for
|
|
42
|
+
this reason. Without it the runner has none of them, every required
|
|
43
|
+
scanner reports `unavailable`, and coverage becomes FAILED — the gate
|
|
44
|
+
fails on the absence of a tool rather than on anything about the code.
|
|
45
|
+
"""
|
|
46
|
+
text = QUALITY_GATES.read_text(encoding="utf-8")
|
|
47
|
+
gate_jobs = [
|
|
48
|
+
body
|
|
49
|
+
for body in re.split(r"^ [A-Za-z0-9_-]+:\s*$", text, flags=re.MULTILINE)
|
|
50
|
+
if re.search(r"^\s+secure-code-agent \\\s*$", body, flags=re.MULTILINE)
|
|
51
|
+
]
|
|
52
|
+
assert gate_jobs, "no job runs secure-code-agent; the security pillar is never measured"
|
|
53
|
+
for body in gate_jobs:
|
|
54
|
+
assert "secure-code-agent[required-scanners]==" in body, (
|
|
55
|
+
"the job that runs the security gate installs secure-code-agent without its "
|
|
56
|
+
"required-scanners extra, so the scanners gates.require_scanners names are "
|
|
57
|
+
"absent and coverage fails on missing tools"
|
|
58
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/__main__.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_adapters.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_analysis.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_anchor.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_arguments.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_aspects.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_backfill.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_bands.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_banner.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_built_ins.py
RENAMED
|
File without changes
|
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_catalog.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_charts.py
RENAMED
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_cognitive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maintainability_agent-3.7.7 → maintainability_agent-3.7.8}/src/maintainability_audit/_derive.py
RENAMED
|
File without changes
|