maintainability-agent 3.6.1__tar.gz → 3.6.2__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.1/src/maintainability_agent.egg-info → maintainability_agent-3.6.2}/PKG-INFO +2 -2
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/README.md +1 -1
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/pyproject.toml +1 -1
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2/src/maintainability_agent.egg-info}/PKG-INFO +2 -2
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_agent.egg-info/SOURCES.txt +1 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/__init__.py +1 -1
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_precommit.py +6 -1
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_prompt_sections.py +57 -9
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_work_order.py +3 -2
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_work_order_view.py +13 -4
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/config.py +1 -1
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/prompts.py +30 -14
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/renderers.py +2 -8
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/report.py +19 -3
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_grading.py +11 -2
- maintainability_agent-3.6.2/tests/test_every_surface_says_what_the_run_found.py +239 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/LICENSE +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/setup.cfg +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_agent.egg-info/requires.txt +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_agent.egg-info/top_level.txt +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/__main__.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_analysis.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_analyzer_sections.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_anchor.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_arguments.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_aspects.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_assets/standard.md +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_attestation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_backfill.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_bands.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_banner.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_built_ins.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_calibration.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_catalog.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_charts.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_cognitive.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_config_defaults.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_conformance.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_corroborate.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_coverage_notes.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_criteria_scope.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_delegated_pillar.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_derive.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_discovery.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_documents.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_economics.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_economics_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_environment.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_evidence_reader.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_evidence_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_finding_match.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_first_run.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_formula.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_gates.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_generic.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_grammar.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_grant_ledger.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_history_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_hostile_prompt.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_hotspots.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_html_report_sections.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_html_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_identity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_in_loop.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_in_loop_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_jvm_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_markdown_sections.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_masking.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_audit.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_gate.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_grants.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_refusals.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_resources.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_mcp_setup.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_metric_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_metrics_types.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_operator_reads.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_pillars.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_practice.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_precommit_install.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_precommit_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_pressures.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_c.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_cobol.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_core.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_cpp.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_csharp.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_fortran.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_go.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_java.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_js.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_php.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_ruby.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_rust.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ranges_swift.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ratchet.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_ratio_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_recurrence.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_run_comparison.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_runner.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_safe_write.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_scan_history.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_scan_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_second_source.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_selection.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_semantic.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_semantic_policy.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_semantic_ts.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_semantic_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_setup_errors.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_setup_persist.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_skill_install.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_stored_grants.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_tdd_view.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_test_commands.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_test_execution.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_test_pairing.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_tokens.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_tool_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_trends.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_user_config.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_verdict_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_verification.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_work_order_weights.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_xml.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/baseline.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/cli.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/deadcode.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/duplication.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/evidence.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/git_tools.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/history.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/idioms.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/instructions.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/mcp_server.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/metrics.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/sarif.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/scoring.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/similarity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/source.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_acquisition_trust.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_adapter_docs.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_adapter_recordings.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_added_lines.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analysis_coverage.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analysis_execution.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_bridge.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_config_isolation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_estimate_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_pinning.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_primary_estimate.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_provenance.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_provenance_exclusions.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_scoring_path.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_spread_range.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_analyzer_xml_bounds.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_anchor_and_mode.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_anchor_disclosure.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_annotations_match_behaviour.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_anticipated_refusals.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_architecture.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_artifact_write_route_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_aspect_coverage.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_asset_snapshot_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_ast_reading_resolves_spellings.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_attestation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_audit_components.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_authorization_freshness.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_authorship_gates.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_backfill.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_band_concealment_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_band_concealment_p3.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_band_pressures.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_bands.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_body_or_signature_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_c_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_calibration_corpus.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_calibration_drift.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_calibration_tooling.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_catalog_selection.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_catalog_tier_promise.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_chat_leads_with_the_work_order.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_chat_primary_docs.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_check_refuses_plus_only_fragments.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_checkstyle_adapter.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_checkstyle_catalog.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_child_sandbox.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_ci_history_recipe.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_claimed_languages.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_cli.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_clone_group_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_cobol_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_cognitive_complexity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_cohort_statistics.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_concealment_properties.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_config_shape.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_consent_and_grant.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_consumer_migration.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_contract_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_corroborate.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_coverage_by_language.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_cpp_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_criteria_completion.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_csharp_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_d15_composition.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_d15_goal_directed.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_dead_code.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_criteria_scope.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_edge_cases.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_ranges.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_source.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declarative_parsers.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declared_authorship.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declared_imports.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_delegated_security_pillar.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_demo_tree.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_derivation_mix.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_determinism.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_dimension_ratchet.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_direct_runner_availability_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_discovery.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_doc_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_docs_links.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_economic_context.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_empty_output_not_clean.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_empty_output_not_clean_adapters.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_environment_work_order.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_evidence_invariants.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_evidence_normalization.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_evidence_properties.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_example_config_opens_claimed_languages.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_exclusion_dialects.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_exposure_never_outranks_band.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_falsifier_standard.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_file_list_cap_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_finding_identity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_first_run_elicitation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_first_run_prompt.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_first_run_reelicitation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_fix_breadth_window.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_fixed_form_fortran.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_format_ask.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_fortran_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_fortran_metrics.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_fortran_practice.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_git_argv.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_git_read_only.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_git_readonly_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_go_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_grammar_constructs.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_grammar_token_coverage.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_grant_only_user_tier.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_history.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_history_boundary.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_history_manifest.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_history_schema2.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_history_window.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_hostile_prompt.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_html_executive.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_html_section_parity_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_identity_docs.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_identity_resolution.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_idiom_divergence.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_in_loop_budgets.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_in_loop_check.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_installed_wheel_runtime.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_instruction_targets.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_java_range_guard.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_java_ranges.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_java_scored.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_java_wiring.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_js_complexity_operators.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_js_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_language_coverage.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_language_support_honesty.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_mcp_baseline_payload.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_mcp_format_contract.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_mcp_history.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_mcp_server.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_migration_1_0.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_near_duplicates.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_network_disclosure.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_one_setup_across_surfaces_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_operator_named_paths.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_operator_named_reads.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pairing_reads_imports.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pattern_budget.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_phase6_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_php_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pillars_and_practice.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_platform_claim.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pmd_adapter.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pmd_audit_closures.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_policy_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_pool_runs_by_config.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_population_floors.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_practice_nested_gates_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_precommit_staged.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_presentation_refusals.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_promises.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_prompt_escalation_once.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_prompt_honesty.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_prompt_location_escalation_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_prove_falsifiers.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_python_complexity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_python_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_read_boundary.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_readme_claims.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_recurrence.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_release_needs_an_empty_ledger.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_release_plan.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_release_plan_status.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_report_remedy_copy.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_roles_recorded.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_root_grants.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_rubric_ignores_project_lint_config.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_ruby_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_run_comparison.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_runner.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_rust_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_sarif.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scan_history.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scan_scope.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scanner_unsafe_direction.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scanning.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_schema_fidelity.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scope_conformance.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_scoring_calibration.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_semantic_policy.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_setup_gate_completeness.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_setup_gate_independent_contract.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_setup_precondition.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_skill_install.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_sonar_resolve.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_source_index.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_spotbugs_adapter.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_spotbugs_catalog.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_stage8_contract.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_stdout_outputs.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_suite_isolation.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_swift_declarations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_tdd_structure.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_terminal_asks_the_same_questions.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_test_commands.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_test_execution_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_three_presentations.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_tool_resolution.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_tree_chosen_spawn.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_tree_reads_use_the_primitive.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_trends.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_type_fields_not_functions_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_uat_falsifiers.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_unanchored_set_matches_corpus.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_unread_code.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_user_config_tier.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_verification_audit_closures.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_verified_grade.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_version_claim.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_wheel_contents.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_work_items_state_their_own_finding.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_work_order.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_work_order_items.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_work_order_selection.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_workflow_supply_chain.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_write_boundary.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_write_route_class.py +0 -0
- {maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/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.6.
|
|
3
|
+
Version: 3.6.2
|
|
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.6.
|
|
49
|
+
Version **3.6.2**.
|
|
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
|
|
@@ -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.6.
|
|
8
|
+
Version **3.6.2**.
|
|
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.6.
|
|
7
|
+
version = "3.6.2"
|
|
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.6.
|
|
3
|
+
Version: 3.6.2
|
|
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.6.
|
|
49
|
+
Version **3.6.2**.
|
|
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
|
|
@@ -236,6 +236,7 @@ tests/test_economic_context.py
|
|
|
236
236
|
tests/test_empty_output_not_clean.py
|
|
237
237
|
tests/test_empty_output_not_clean_adapters.py
|
|
238
238
|
tests/test_environment_work_order.py
|
|
239
|
+
tests/test_every_surface_says_what_the_run_found.py
|
|
239
240
|
tests/test_evidence_invariants.py
|
|
240
241
|
tests/test_evidence_normalization.py
|
|
241
242
|
tests/test_evidence_properties.py
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_precommit.py
RENAMED
|
@@ -171,6 +171,11 @@ def staged_report(root: Path, config: dict[str, Any]) -> dict[str, Any]:
|
|
|
171
171
|
return {
|
|
172
172
|
"root": str(root),
|
|
173
173
|
"scanned": scannable,
|
|
174
|
+
# The limits these hotspots were graded against, so the work-order
|
|
175
|
+
# builder can name them. Without this the hook worded a class
|
|
176
|
+
# "graded on length alone" while the audit said "against the
|
|
177
|
+
# 300-line class limit" (D171).
|
|
178
|
+
"thresholds": thresholds,
|
|
174
179
|
"largest_files": largest,
|
|
175
180
|
"function_hotspots": hotspots,
|
|
176
181
|
"risk_findings": risk,
|
|
@@ -288,7 +293,7 @@ def staged_findings(report: dict[str, Any]) -> list[dict[str, Any]]:
|
|
|
288
293
|
from ._work_order import _items_from_files, _items_from_hotspots, band_of
|
|
289
294
|
|
|
290
295
|
items: list[dict[str, Any]] = []
|
|
291
|
-
for entry in _items_from_hotspots(report) + _items_from_files(report):
|
|
296
|
+
for entry in _items_from_hotspots(report, report.get("thresholds")) + _items_from_files(report):
|
|
292
297
|
weight = entry.pop("weight")
|
|
293
298
|
rationale = entry.pop("rationale", None) or weight.rationale
|
|
294
299
|
items.append({**entry, "rationale": rationale,
|
|
@@ -89,7 +89,17 @@ def prompt_analyzer_caveat(report: dict[str, Any]) -> list[str]:
|
|
|
89
89
|
"""
|
|
90
90
|
if not (report.get("analyzer_measurements") or report.get("analyzer_findings")):
|
|
91
91
|
return []
|
|
92
|
-
|
|
92
|
+
score = report.get("score") or {}
|
|
93
|
+
if not view.is_scored(score):
|
|
94
|
+
# No estimate was issued, so none can have a source (D172). The
|
|
95
|
+
# analyzer output is still evidence about the code, and says so.
|
|
96
|
+
return [
|
|
97
|
+
"**No maintainability estimate was issued for this run**, so none is "
|
|
98
|
+
"attributed to the analyzers. Their output is reported here as "
|
|
99
|
+
"evidence about the code, never as a change to a score.",
|
|
100
|
+
"",
|
|
101
|
+
]
|
|
102
|
+
scored = score.get("analyzer_scored_dimensions") or []
|
|
93
103
|
if scored:
|
|
94
104
|
return [
|
|
95
105
|
"**The maintainability estimate above uses the analyzer readings** for "
|
|
@@ -149,6 +159,50 @@ def _withheld_paragraph(report: dict[str, Any]) -> list[str]:
|
|
|
149
159
|
]
|
|
150
160
|
|
|
151
161
|
|
|
162
|
+
def _prompt_work_items(report: dict[str, Any]) -> list[dict[str, Any]]:
|
|
163
|
+
"""The items this prompt hands to an agent, after withholding."""
|
|
164
|
+
# Withhold anything the history shows was fixed and came back
|
|
165
|
+
# twice. Naming it as a design candidate while asking an agent to
|
|
166
|
+
# patch it a third time would change nothing.
|
|
167
|
+
escalated = {
|
|
168
|
+
item["fingerprint"] for item in report.get("design_review_candidates") or []
|
|
169
|
+
}
|
|
170
|
+
return prompt_items(report.get("work_order") or [], escalated=escalated)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def prompt_has_work(report: dict[str, Any]) -> bool:
|
|
174
|
+
"""Whether this prompt hands an agent anything to change (D173).
|
|
175
|
+
|
|
176
|
+
A report with no `work_order` key at all — stored before the field
|
|
177
|
+
existed, or assembled by hand — cannot say there is nothing to do, so
|
|
178
|
+
it keeps the prompt it always had rather than reading as "Nothing to
|
|
179
|
+
do" over findings it does carry.
|
|
180
|
+
"""
|
|
181
|
+
return "work_order" not in report or bool(_prompt_work_items(report))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _no_prompt_work(report: dict[str, Any]) -> list[str]:
|
|
185
|
+
"""What the prompt says in place of a task when there is none (D173).
|
|
186
|
+
|
|
187
|
+
Two cases, because they are different facts. An empty work order is the
|
|
188
|
+
chat report's "Nothing to do", in the same words. A work order whose
|
|
189
|
+
every item was withheld — a Major Project, or a finding escalated for
|
|
190
|
+
design review — has work in it, none of it an agent's to patch.
|
|
191
|
+
"""
|
|
192
|
+
if not report.get("work_order"):
|
|
193
|
+
from ._work_order_view import NOTHING_TO_DO
|
|
194
|
+
|
|
195
|
+
return [NOTHING_TO_DO, "", "Do not change code on the strength of this audit.", ""]
|
|
196
|
+
return [
|
|
197
|
+
"**Nothing in scope for this prompt.** Every work-order item needs a "
|
|
198
|
+
"design decision or keeps coming back, so none is handed to an agent. "
|
|
199
|
+
"They are in the report. Do not change code on the strength of this "
|
|
200
|
+
"prompt.",
|
|
201
|
+
"",
|
|
202
|
+
*_withheld_paragraph(report),
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
|
|
152
206
|
def prompt_work_order(report: dict[str, Any]) -> list[str]:
|
|
153
207
|
"""The ordered work, leading the prompt, Major Projects withheld.
|
|
154
208
|
|
|
@@ -161,15 +215,9 @@ def prompt_work_order(report: dict[str, Any]) -> list[str]:
|
|
|
161
215
|
told to deduplicate a pattern across forty files produces exactly the
|
|
162
216
|
sprawling, unreviewable diff a bounded prompt exists to prevent.
|
|
163
217
|
"""
|
|
164
|
-
|
|
165
|
-
# twice. Naming it as a design candidate while asking an agent to
|
|
166
|
-
# patch it a third time would change nothing.
|
|
167
|
-
escalated = {
|
|
168
|
-
item["fingerprint"] for item in report.get("design_review_candidates") or []
|
|
169
|
-
}
|
|
170
|
-
items = prompt_items(report.get("work_order") or [], escalated=escalated)
|
|
218
|
+
items = _prompt_work_items(report)
|
|
171
219
|
if not items:
|
|
172
|
-
return []
|
|
220
|
+
return _no_prompt_work(report) if "work_order" in report else []
|
|
173
221
|
lines = [
|
|
174
222
|
# What the order is, not what it is worth (D169): `prompt_items`
|
|
175
223
|
# promotes risk-5 classes and keeps one item per class, so this
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/_work_order.py
RENAMED
|
@@ -483,8 +483,9 @@ def prompt_items(items: list[dict[str, Any]], limit: int = 12,
|
|
|
483
483
|
escalated: set[str] | None = None) -> list[dict[str, Any]]:
|
|
484
484
|
"""Agent subset: no major projects, no escalated returns; Severe leads.
|
|
485
485
|
|
|
486
|
-
|
|
487
|
-
|
|
486
|
+
The economic reorder orders items by exposure within each band (D170),
|
|
487
|
+
so a risk-5 item can still sit below hotter Quick Wins of other classes.
|
|
488
|
+
The table can stay exposure-ordered; the paste of 12 cannot drop Severe.
|
|
488
489
|
"""
|
|
489
490
|
blocked = escalated or set()
|
|
490
491
|
eligible = [
|
|
@@ -85,10 +85,11 @@ def item_prompt_block(item: dict[str, Any], root_label: str = ".") -> list[str]:
|
|
|
85
85
|
#: The order sentence, by which sort actually produced the list (D169).
|
|
86
86
|
#:
|
|
87
87
|
#: `reorder_by_exposure` re-sorts the stored work order by recurrence and
|
|
88
|
-
#: churn whenever an economic context is configured
|
|
89
|
-
#:
|
|
90
|
-
#: it costs to fix" over a list that
|
|
91
|
-
#:
|
|
88
|
+
#: churn whenever an economic context is configured — within each band
|
|
89
|
+
#: since D170, across bands before it. The heading went on saying "ordered
|
|
90
|
+
#: by what it costs to leave against what it costs to fix" over a list that
|
|
91
|
+
#: sort had reordered, so the table and the prompt named different first
|
|
92
|
+
#: items and neither said why.
|
|
92
93
|
_ORDER_BY_BAND = (
|
|
93
94
|
"Ordered by what it costs to leave against what it costs to fix "
|
|
94
95
|
"(see the standard)."
|
|
@@ -97,6 +98,14 @@ _ORDER_BY_EXPOSURE = (
|
|
|
97
98
|
"Ordered by band, then by exposure within each band — how often a "
|
|
98
99
|
"finding came back and how much its file changes (ADR 004)."
|
|
99
100
|
)
|
|
101
|
+
#: What a run with no work order says, on every skin that would otherwise
|
|
102
|
+
#: hand over a task (D173). The chat report said this while the prompt from
|
|
103
|
+
#: the same run asked for "the smallest coherent patch".
|
|
104
|
+
NOTHING_TO_DO = (
|
|
105
|
+
"**Nothing to do.** No finding reached a band worth a work-order "
|
|
106
|
+
"item, so there is no prompt to paste. The evidence behind that is "
|
|
107
|
+
"below."
|
|
108
|
+
)
|
|
100
109
|
_BAND_IS_PER_CLASS = (
|
|
101
110
|
"A band is declared per kind of finding in the standard, not sized per "
|
|
102
111
|
"item: each target states that item's own reading."
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/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.6.
|
|
23
|
+
VERSION = "3.6.2"
|
|
24
24
|
|
|
25
25
|
PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
|
|
26
26
|
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/prompts.py
RENAMED
|
@@ -32,23 +32,17 @@ def render_ai_prompt(report: dict[str, Any]) -> str:
|
|
|
32
32
|
"""
|
|
33
33
|
summary = report["summary"]
|
|
34
34
|
score = report["score"]
|
|
35
|
+
# A run with nothing in scope hands over no task (D173): the chat report
|
|
36
|
+
# from the same run said "Nothing to do" while this file asked for a
|
|
37
|
+
# patch and listed warn-band hotspots the work order had refused.
|
|
38
|
+
has_work = prompt_has_work(report)
|
|
35
39
|
lines = [
|
|
36
40
|
"# AI Remediation Prompt",
|
|
37
41
|
"",
|
|
38
42
|
"You are working in a git repository that has just produced a maintainability audit.",
|
|
39
43
|
"",
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"Rules:",
|
|
43
|
-
"",
|
|
44
|
-
"- Do not rewrite the whole codebase.",
|
|
45
|
-
"- Do not change public behavior unless a finding explicitly requires it.",
|
|
46
|
-
"- Prefer existing architecture, naming, and local patterns.",
|
|
47
|
-
"- Add or update tests for meaningful behavior before changing production code where practical.",
|
|
48
|
-
"- Keep unrelated refactors out of scope.",
|
|
49
|
-
"- If a finding is a false positive, explain why and leave the code unchanged.",
|
|
50
|
-
"- After changes, run the repo's native tests/lints and this maintainability audit again.",
|
|
51
|
-
"",
|
|
44
|
+
*(_TASK if has_work else ()),
|
|
45
|
+
*_RULES,
|
|
52
46
|
]
|
|
53
47
|
# The product, before anything describing the run that produced it.
|
|
54
48
|
lines.extend(prompt_escalation_note(report))
|
|
@@ -82,11 +76,32 @@ def render_ai_prompt(report: dict[str, Any]) -> str:
|
|
|
82
76
|
lines.extend(prompt_tdd_section(report))
|
|
83
77
|
lines.extend(prompt_semantic_section(report))
|
|
84
78
|
lines.extend(prompt_pressure_section(score, (report.get("summary") or {}).get("languages")))
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
if has_work:
|
|
80
|
+
lines.extend(prompt_focus_sections(report))
|
|
81
|
+
lines.extend(prompt_deliverable())
|
|
87
82
|
return "\n".join(lines)
|
|
88
83
|
|
|
89
84
|
|
|
85
|
+
_TASK = (
|
|
86
|
+
"Your task is to fix the highest-value maintainability issues in a small, reviewable change.",
|
|
87
|
+
"",
|
|
88
|
+
)
|
|
89
|
+
# Kept on every prompt: they bound what an agent may do, and a run with
|
|
90
|
+
# nothing in scope is still bounded by them.
|
|
91
|
+
_RULES = (
|
|
92
|
+
"Rules:",
|
|
93
|
+
"",
|
|
94
|
+
"- Do not rewrite the whole codebase.",
|
|
95
|
+
"- Do not change public behavior unless a finding explicitly requires it.",
|
|
96
|
+
"- Prefer existing architecture, naming, and local patterns.",
|
|
97
|
+
"- Add or update tests for meaningful behavior before changing production code where practical.",
|
|
98
|
+
"- Keep unrelated refactors out of scope.",
|
|
99
|
+
"- If a finding is a false positive, explain why and leave the code unchanged.",
|
|
100
|
+
"- After changes, run the repo's native tests/lints and this maintainability audit again.",
|
|
101
|
+
"",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
90
105
|
def render_agent_instructions(report: dict[str, Any]) -> str:
|
|
91
106
|
return "\n".join(
|
|
92
107
|
[
|
|
@@ -138,6 +153,7 @@ from ._prompt_sections import ( # noqa: E402,F401 - re-export after the split
|
|
|
138
153
|
prompt_deliverable,
|
|
139
154
|
prompt_escalation_note,
|
|
140
155
|
prompt_focus_sections,
|
|
156
|
+
prompt_has_work,
|
|
141
157
|
prompt_pressure_section,
|
|
142
158
|
prompt_semantic_section,
|
|
143
159
|
prompt_tdd_section,
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/renderers.py
RENAMED
|
@@ -32,7 +32,7 @@ from ._scan_view import (
|
|
|
32
32
|
)
|
|
33
33
|
from ._semantic_view import semantic_markdown, without_semantic_suffixes
|
|
34
34
|
from ._tdd_view import tdd_structure_markdown
|
|
35
|
-
from ._work_order_view import work_order_markdown, work_order_selection_markdown
|
|
35
|
+
from ._work_order_view import NOTHING_TO_DO, work_order_markdown, work_order_selection_markdown
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def _pool_ran(report: dict[str, Any]) -> bool:
|
|
@@ -188,13 +188,7 @@ def _no_work_order_lines() -> list[str]:
|
|
|
188
188
|
"nothing met the bands" from "this tool does not do that" — and the
|
|
189
189
|
second reading is the one a stranger takes on a first run.
|
|
190
190
|
"""
|
|
191
|
-
return [
|
|
192
|
-
"## Work Order", "",
|
|
193
|
-
"**Nothing to do.** No finding reached a band worth a work-order "
|
|
194
|
-
"item, so there is no prompt to paste. The evidence behind that is "
|
|
195
|
-
"below.",
|
|
196
|
-
"",
|
|
197
|
-
]
|
|
191
|
+
return ["## Work Order", "", NOTHING_TO_DO, ""]
|
|
198
192
|
|
|
199
193
|
|
|
200
194
|
def _bounded_markdown(report: dict[str, Any], score: dict[str, Any],
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/src/maintainability_audit/report.py
RENAMED
|
@@ -367,17 +367,33 @@ def _assemble(
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
|
|
370
|
-
def _attach_semantics(
|
|
370
|
+
def _attach_semantics(
|
|
371
|
+
report: dict[str, Any], root: Path, config: dict[str, Any],
|
|
372
|
+
only_paths: set[str] | None = None,
|
|
373
|
+
) -> None:
|
|
371
374
|
"""ADR 003 option C, after the score is sealed and before the work
|
|
372
375
|
order reads it: semantic results are findings and prompt material,
|
|
373
376
|
never rubric input — nothing from here reaches `score_report`.
|
|
377
|
+
|
|
378
|
+
**A changed-only run keeps the findings its paths hold (D174).** The
|
|
379
|
+
semantic walk reads the whole tree, so a changed-only audit of two
|
|
380
|
+
commits nominated a TypeScript fixture neither commit touched and
|
|
381
|
+
handed it to the prompt. A finding with no located source path cannot
|
|
382
|
+
be placed in or out of the change, and is not work anyone can act on
|
|
383
|
+
either (`_items_from_semantic` drops it), so it is left out here too.
|
|
374
384
|
"""
|
|
375
385
|
semantic = semantic_findings(
|
|
376
386
|
root,
|
|
377
387
|
policy=load_semantic_policy(config),
|
|
378
388
|
type_analysis=discover_type_analysis(root),
|
|
379
389
|
)
|
|
380
|
-
|
|
390
|
+
findings = semantic["findings"]
|
|
391
|
+
if only_paths is not None:
|
|
392
|
+
findings = [
|
|
393
|
+
finding for finding in findings
|
|
394
|
+
if ((finding.get("source_evidence") or {}).get("path")) in only_paths
|
|
395
|
+
]
|
|
396
|
+
report["semantic_findings"] = findings
|
|
381
397
|
report["semantic_coverage"] = semantic["coverage"]
|
|
382
398
|
|
|
383
399
|
|
|
@@ -475,7 +491,7 @@ def build_report(
|
|
|
475
491
|
# Condition rolls up aspects; practice stays a separate axis (ADR 007).
|
|
476
492
|
report["practice"] = practice_level(root, config).as_dict()
|
|
477
493
|
report["pillars"] = _pillars_with_delegation(report, root, security_pillar)
|
|
478
|
-
_attach_semantics(report, root, config)
|
|
494
|
+
_attach_semantics(report, root, config, only_paths)
|
|
479
495
|
# Last, because every item's delta is a rubric recomputation and the
|
|
480
496
|
# rubric needs the scored report to recompute against.
|
|
481
497
|
report["work_order"] = work_order(report, thresholds=config["thresholds"])
|
{maintainability_agent-3.6.1 → maintainability_agent-3.6.2}/tests/test_declaration_grading.py
RENAMED
|
@@ -174,8 +174,17 @@ def test_function_hotspot_still_reports_its_complexity() -> None:
|
|
|
174
174
|
|
|
175
175
|
def test_class_label_reaches_the_prompt_the_pr_comment_and_sarif() -> None:
|
|
176
176
|
report = flagged_class_report()
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
# The prompt lists hotspots only when it hands over work (D173); a
|
|
178
|
+
# warn-only run is "Nothing to do" there. Give the prompt one item so
|
|
179
|
+
# its hotspot section — where the label is checked — renders.
|
|
180
|
+
prompted = {**report, "work_order": [{
|
|
181
|
+
"finding_class": "oversized-declaration", "title": "ScanWorker in scanner.py",
|
|
182
|
+
"path": "scanner.py", "line": 1, "band": "quick-win", "risk": 4, "effort": 2,
|
|
183
|
+
"target": "t", "rationale": "r", "verification": "v", "class_delta": 0.0,
|
|
184
|
+
"class_count": 1, "fingerprint": "fp", "severity": 1.0,
|
|
185
|
+
}]}
|
|
186
|
+
|
|
187
|
+
assert "`ScanWorker` (class) (260 lines, warn)" in render_ai_prompt(prompted)
|
|
179
188
|
assert "`ScanWorker` (class) (260 lines, warn)" in render_pr_comment(report)
|
|
180
189
|
message = report_to_sarif(report)["runs"][0]["results"][0]["message"]["text"]
|
|
181
190
|
assert message == "ScanWorker (class) (260 lines, warn)."
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""Every surface of one run says what that run found, and nothing else.
|
|
2
|
+
|
|
3
|
+
D171–D174, from Grok's hostile audit of `77de21c` (3.6.0 + 3.6.1). Each is
|
|
4
|
+
one surface telling a different story from the report it belongs to:
|
|
5
|
+
|
|
6
|
+
* D171 — the pre-commit hook worded a declaration unlike the audit.
|
|
7
|
+
* D172 — the prompt named a source for an estimate that was not issued.
|
|
8
|
+
* D173 — the prompt asked for a patch on a run whose report said
|
|
9
|
+
"Nothing to do".
|
|
10
|
+
* D174 — a changed-only run handed the prompt a finding from a file the
|
|
11
|
+
change never touched.
|
|
12
|
+
|
|
13
|
+
Populations are derived: declarations from every grammar fixture on disk,
|
|
14
|
+
dimensions from the score document, the "patch" instructions from
|
|
15
|
+
`prompt_deliverable` itself, and semantic findings from a tree carrying the
|
|
16
|
+
semantic fixture at several locations. Each sweep asserts it is not empty.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import copy
|
|
21
|
+
import shutil
|
|
22
|
+
import subprocess
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
27
|
+
|
|
28
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
29
|
+
GRAMMAR = ROOT / "tests" / "fixtures" / "grammar"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _failing_everything() -> dict[str, Any]:
|
|
33
|
+
"""Every declaration breaches; class and function budgets differ, so a
|
|
34
|
+
target naming the wrong one is visible."""
|
|
35
|
+
from maintainability_audit.config import load_config
|
|
36
|
+
|
|
37
|
+
config = copy.deepcopy(load_config(None))
|
|
38
|
+
config["thresholds"].update({
|
|
39
|
+
"max_function_lines": 3, "warn_function_lines": 2,
|
|
40
|
+
"max_class_lines": 1, "warn_class_lines": 1,
|
|
41
|
+
"max_complexity": 0, "warn_complexity": 0,
|
|
42
|
+
})
|
|
43
|
+
return config
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _git(repo: Path, *args: str) -> None:
|
|
47
|
+
subprocess.run(["git", "-C", str(repo), *args], check=True, capture_output=True)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_the_hook_words_every_declaration_as_the_audit_does(tmp_path) -> None:
|
|
51
|
+
"""D171: `staged_findings` and the audit give one target per declaration.
|
|
52
|
+
|
|
53
|
+
D164 passed thresholds to `_items_from_hotspots` from `build_report` and
|
|
54
|
+
`check_content` but not from the hook, so a staged 2876-line class read
|
|
55
|
+
"a class is graded on length alone" where the audit read "against the
|
|
56
|
+
300-line class limit".
|
|
57
|
+
"""
|
|
58
|
+
from maintainability_audit._precommit import staged_findings, staged_report
|
|
59
|
+
from maintainability_audit.report import build_report
|
|
60
|
+
|
|
61
|
+
fixtures = sorted(GRAMMAR.rglob("constructs.*"))
|
|
62
|
+
assert fixtures, f"no grammar fixtures under {GRAMMAR}; this sweep would pass vacuously"
|
|
63
|
+
repo = tmp_path / "repo"
|
|
64
|
+
repo.mkdir()
|
|
65
|
+
_git(repo, "init", "-q")
|
|
66
|
+
for fixture in fixtures:
|
|
67
|
+
shutil.copy(fixture, repo / fixture.name)
|
|
68
|
+
_git(repo, "add", ".")
|
|
69
|
+
config = _failing_everything()
|
|
70
|
+
|
|
71
|
+
def targets(items: list[dict[str, Any]]) -> dict[tuple[str, int], str]:
|
|
72
|
+
return {(item["path"], item["line"]): item["target"] for item in items
|
|
73
|
+
if item["finding_class"] == "oversized-declaration"}
|
|
74
|
+
|
|
75
|
+
hook = targets(staged_findings(staged_report(repo, config)))
|
|
76
|
+
audit = targets(build_report(repo, config, run_analyzers=False)["work_order"])
|
|
77
|
+
assert any("-line class limit" in target for target in audit.values()), (
|
|
78
|
+
"the audit produced no class targets, so the class half was never compared"
|
|
79
|
+
)
|
|
80
|
+
shared = hook.keys() & audit.keys()
|
|
81
|
+
assert shared, "the hook and the audit located no declaration in common"
|
|
82
|
+
differing = {key: (hook[key], audit[key]) for key in shared if hook[key] != audit[key]}
|
|
83
|
+
assert not differing, f"hook and audit word these declarations differently: {list(differing.items())[:3]}"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _unscored_report(root: Path) -> dict[str, Any]:
|
|
87
|
+
from maintainability_audit.config import load_config
|
|
88
|
+
from maintainability_audit.report import build_report
|
|
89
|
+
|
|
90
|
+
root.mkdir()
|
|
91
|
+
body = "".join(f" value = {line}\n" for line in range(900))
|
|
92
|
+
(root / "module.py").write_text(f"def value():\n{body} return value\n", encoding="utf-8")
|
|
93
|
+
report = build_report(root, load_config(None), run_analyzers=False)
|
|
94
|
+
assert report["score"]["maintainability_estimate"] is None, "the tree was scored; the floors did not hold"
|
|
95
|
+
return report
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.mark.usefixtures("real_population_floors")
|
|
99
|
+
def test_no_prompt_names_a_source_for_an_estimate_that_was_not_issued(tmp_path) -> None:
|
|
100
|
+
"""D172: with no estimate, neither caveat branch attributes one.
|
|
101
|
+
|
|
102
|
+
`prompt_analyzer_caveat` said "the maintainability estimate above uses the
|
|
103
|
+
analyzer readings" beside "Maintainability estimate: Not scored". The
|
|
104
|
+
other branch — "comes from the built-in detectors" — made the same claim
|
|
105
|
+
about the same absent number.
|
|
106
|
+
"""
|
|
107
|
+
from maintainability_audit.prompts import render_ai_prompt
|
|
108
|
+
|
|
109
|
+
base = _unscored_report(tmp_path / "tree")
|
|
110
|
+
dimensions = sorted(base["score"]["dimensions"])
|
|
111
|
+
assert dimensions, "the score document names no dimensions"
|
|
112
|
+
states = [[], *([name] for name in dimensions)]
|
|
113
|
+
wrong = []
|
|
114
|
+
for scored in states:
|
|
115
|
+
report = copy.deepcopy(base)
|
|
116
|
+
report["analyzer_measurements"] = [{"tool": "lizard"}]
|
|
117
|
+
report["score"]["analyzer_scored_dimensions"] = scored
|
|
118
|
+
prompt = render_ai_prompt(report)
|
|
119
|
+
if "maintainability estimate above" in prompt.lower():
|
|
120
|
+
wrong.append(scored)
|
|
121
|
+
assert not wrong, f"unscored prompts attributing an estimate, by scored dimensions: {wrong}"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _deliverable_lines() -> list[str]:
|
|
125
|
+
from maintainability_audit._prompt_sections import prompt_deliverable
|
|
126
|
+
|
|
127
|
+
lines = [line for line in prompt_deliverable() if len(line.strip()) > 12]
|
|
128
|
+
assert lines, "prompt_deliverable produced no instruction lines"
|
|
129
|
+
return lines
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _task_lines(prompt: str) -> list[str]:
|
|
133
|
+
handed = [line for line in _deliverable_lines() if line in prompt]
|
|
134
|
+
if "Your task is to fix" in prompt:
|
|
135
|
+
handed.append("Your task is to fix")
|
|
136
|
+
if "Function hotspots to inspect first" in prompt:
|
|
137
|
+
handed.append("Function hotspots to inspect first")
|
|
138
|
+
return handed
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_a_run_with_no_work_order_hands_the_prompt_no_task(tmp_path) -> None:
|
|
142
|
+
"""D173: a warn-only run is "Nothing to do" in the chat report and the prompt alike."""
|
|
143
|
+
from maintainability_audit._work_order_view import NOTHING_TO_DO
|
|
144
|
+
from maintainability_audit.config import load_config
|
|
145
|
+
from maintainability_audit.prompts import render_ai_prompt
|
|
146
|
+
from maintainability_audit.renderers import render_markdown
|
|
147
|
+
from maintainability_audit.report import build_report
|
|
148
|
+
|
|
149
|
+
config = load_config(None)
|
|
150
|
+
thresholds = config["thresholds"]
|
|
151
|
+
between = (thresholds["warn_function_lines"] + thresholds["max_function_lines"]) // 2
|
|
152
|
+
tree = tmp_path / "warn"
|
|
153
|
+
tree.mkdir()
|
|
154
|
+
body = "".join(f" v = {line}\n" for line in range(between - 2))
|
|
155
|
+
(tree / "module.py").write_text(f"def warned():\n{body} return v\n", encoding="utf-8")
|
|
156
|
+
report = build_report(tree, config, run_analyzers=False)
|
|
157
|
+
assert report["function_hotspots"], "no hotspot at all; the warn band was never reached"
|
|
158
|
+
assert report["work_order"] == [], f"the tree produced work: {report['work_order']}"
|
|
159
|
+
assert NOTHING_TO_DO in render_markdown(report, complete=False)
|
|
160
|
+
|
|
161
|
+
prompt = render_ai_prompt(report)
|
|
162
|
+
assert NOTHING_TO_DO in prompt, "the prompt does not say what the chat report says"
|
|
163
|
+
assert not _task_lines(prompt), f"a 'Nothing to do' run's prompt still hands over: {_task_lines(prompt)}"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_a_work_order_withheld_whole_hands_the_prompt_no_task(tmp_path) -> None:
|
|
167
|
+
"""D173's second case: every item withheld from the prompt is not a job either."""
|
|
168
|
+
from maintainability_audit.config import load_config
|
|
169
|
+
from maintainability_audit.prompts import render_ai_prompt
|
|
170
|
+
from maintainability_audit.report import build_report
|
|
171
|
+
|
|
172
|
+
tree = tmp_path / "tree"
|
|
173
|
+
tree.mkdir()
|
|
174
|
+
(tree / "a.py").write_text("def a():\n return 1\n", encoding="utf-8")
|
|
175
|
+
report = build_report(tree, load_config(None), run_analyzers=False)
|
|
176
|
+
report["work_order"] = [{
|
|
177
|
+
"finding_class": "duplicate-block", "title": "duplicated block in a.py", "path": "a.py",
|
|
178
|
+
"line": 1, "band": "major-project", "risk": 4, "effort": 4, "target": "t",
|
|
179
|
+
"rationale": "r", "verification": "v", "class_delta": 0.0, "class_count": 1,
|
|
180
|
+
"fingerprint": "fp", "severity": 1.0,
|
|
181
|
+
}]
|
|
182
|
+
prompt = render_ai_prompt(report)
|
|
183
|
+
assert "Nothing in scope for this prompt" in prompt
|
|
184
|
+
assert not _task_lines(prompt), f"a fully withheld work order still hands over: {_task_lines(prompt)}"
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def test_a_prompt_with_work_still_hands_over_its_task(tmp_path) -> None:
|
|
188
|
+
"""D173 must not strip the task where there is one.
|
|
189
|
+
|
|
190
|
+
Covers existing behaviour: a run with work already carried its task and
|
|
191
|
+
deliverable; this guards the D173 narrowing against removing them.
|
|
192
|
+
"""
|
|
193
|
+
from maintainability_audit.config import load_config
|
|
194
|
+
from maintainability_audit.prompts import render_ai_prompt
|
|
195
|
+
from maintainability_audit.report import build_report
|
|
196
|
+
|
|
197
|
+
tree = tmp_path / "tree"
|
|
198
|
+
tree.mkdir()
|
|
199
|
+
body = "".join(f" v = {line}\n" for line in range(120))
|
|
200
|
+
(tree / "module.py").write_text(f"def huge():\n{body} return v\n", encoding="utf-8")
|
|
201
|
+
report = build_report(tree, load_config(None), run_analyzers=False)
|
|
202
|
+
assert report["work_order"], "the fixture produced no work"
|
|
203
|
+
prompt = render_ai_prompt(report)
|
|
204
|
+
assert all(line in prompt for line in _deliverable_lines())
|
|
205
|
+
assert "Your task is to fix" in prompt
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_a_changed_only_run_hands_over_no_semantic_finding_outside_its_paths(tmp_path) -> None:
|
|
209
|
+
"""D174: a semantic finding is kept exactly where its source path is in the change.
|
|
210
|
+
|
|
211
|
+
The semantic walk reads the whole tree; changed-only over two commits
|
|
212
|
+
handed the prompt `tests/fixtures/semantic_ts/src/operations.ts`, which
|
|
213
|
+
neither touched. This repository holds that one located finding, so a
|
|
214
|
+
population drawn from it would be the sample itself: the tree here
|
|
215
|
+
carries every copy of the semantic fixture at more than one location,
|
|
216
|
+
and a change that touches one of them.
|
|
217
|
+
"""
|
|
218
|
+
from maintainability_audit._semantic import semantic_findings
|
|
219
|
+
from maintainability_audit._semantic_ts import discover_type_analysis
|
|
220
|
+
from maintainability_audit.config import load_config
|
|
221
|
+
from maintainability_audit.prompts import render_ai_prompt
|
|
222
|
+
from maintainability_audit.report import build_report
|
|
223
|
+
|
|
224
|
+
fixture = ROOT / "tests" / "fixtures" / "semantic_ts"
|
|
225
|
+
tree = tmp_path / "tree"
|
|
226
|
+
for place in ("lib/alpha", "services/beta", "tools/gamma"):
|
|
227
|
+
shutil.copytree(fixture, tree / place)
|
|
228
|
+
full = semantic_findings(tree, type_analysis=discover_type_analysis(tree))["findings"]
|
|
229
|
+
located = sorted({(finding.get("source_evidence") or {}).get("path") for finding in full} - {None})
|
|
230
|
+
assert len(located) >= 2, f"the tree located {located}; nothing to keep one of and drop the rest"
|
|
231
|
+
changed = located[0]
|
|
232
|
+
report = build_report(tree, load_config(None), only_paths={changed},
|
|
233
|
+
changed_revspec="HEAD~1...HEAD", run_analyzers=False)
|
|
234
|
+
kept = sorted({(finding.get("source_evidence") or {}).get("path")
|
|
235
|
+
for finding in report["semantic_findings"]})
|
|
236
|
+
assert kept == [changed], f"changed-only over {changed} kept semantic findings at {kept}"
|
|
237
|
+
prompt = render_ai_prompt(report)
|
|
238
|
+
named = [path for path in located[1:] if path in prompt]
|
|
239
|
+
assert not named, f"the changed-only prompt names files outside the change: {named}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|