maintainability-agent 3.7.0__tar.gz → 3.7.3__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.
Files changed (389) hide show
  1. {maintainability_agent-3.7.0/src/maintainability_agent.egg-info → maintainability_agent-3.7.3}/PKG-INFO +14 -3
  2. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/README.md +13 -1
  3. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/pyproject.toml +1 -9
  4. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3/src/maintainability_agent.egg-info}/PKG-INFO +14 -3
  5. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_agent.egg-info/SOURCES.txt +2 -0
  6. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_agent.egg-info/requires.txt +0 -1
  7. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/__init__.py +1 -1
  8. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_security_delegate.py +44 -2
  9. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/config.py +1 -1
  10. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/mcp_server.py +42 -4
  11. maintainability_agent-3.7.3/tests/test_mcp_start_failure_names_what_is_installed.py +94 -0
  12. maintainability_agent-3.7.3/tests/test_security_delegate_versions_agree.py +86 -0
  13. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_security_pillar_runs_and_shows.py +38 -0
  14. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/LICENSE +0 -0
  15. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/setup.cfg +0 -0
  16. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  17. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  18. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  19. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/__main__.py +0 -0
  20. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_adapters.py +0 -0
  21. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_analysis.py +0 -0
  22. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_analyzer_sections.py +0 -0
  23. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_anchor.py +0 -0
  24. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_arguments.py +0 -0
  25. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_aspects.py +0 -0
  26. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  27. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_assets/standard.md +0 -0
  28. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_attestation.py +0 -0
  29. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_backfill.py +0 -0
  30. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_bands.py +0 -0
  31. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_banner.py +0 -0
  32. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_built_ins.py +0 -0
  33. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_calibration.py +0 -0
  34. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_catalog.py +0 -0
  35. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_charts.py +0 -0
  36. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_cognitive.py +0 -0
  37. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_config_defaults.py +0 -0
  38. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_conformance.py +0 -0
  39. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_corroborate.py +0 -0
  40. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_coverage_notes.py +0 -0
  41. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_criteria_scope.py +0 -0
  42. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_delegated_pillar.py +0 -0
  43. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_derive.py +0 -0
  44. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_discovery.py +0 -0
  45. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_documents.py +0 -0
  46. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_economics.py +0 -0
  47. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_economics_view.py +0 -0
  48. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_environment.py +0 -0
  49. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_evidence_reader.py +0 -0
  50. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_evidence_view.py +0 -0
  51. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_finding_match.py +0 -0
  52. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_first_run.py +0 -0
  53. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_formula.py +0 -0
  54. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_gates.py +0 -0
  55. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_generic.py +0 -0
  56. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_grammar.py +0 -0
  57. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_grant_ledger.py +0 -0
  58. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_history_view.py +0 -0
  59. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_hostile_prompt.py +0 -0
  60. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_hotspots.py +0 -0
  61. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_html_report_sections.py +0 -0
  62. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_html_view.py +0 -0
  63. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_identity.py +0 -0
  64. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_in_loop.py +0 -0
  65. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_in_loop_view.py +0 -0
  66. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_jvm_adapters.py +0 -0
  67. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_markdown_sections.py +0 -0
  68. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_masking.py +0 -0
  69. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_audit.py +0 -0
  70. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_gate.py +0 -0
  71. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_grants.py +0 -0
  72. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_refusals.py +0 -0
  73. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_resources.py +0 -0
  74. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_mcp_setup.py +0 -0
  75. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_metric_adapters.py +0 -0
  76. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_metrics_types.py +0 -0
  77. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_operator_reads.py +0 -0
  78. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_pillars.py +0 -0
  79. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_practice.py +0 -0
  80. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_precommit.py +0 -0
  81. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_precommit_install.py +0 -0
  82. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_precommit_view.py +0 -0
  83. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_pressures.py +0 -0
  84. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_prompt_sections.py +0 -0
  85. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_c.py +0 -0
  86. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_cobol.py +0 -0
  87. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_core.py +0 -0
  88. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_cpp.py +0 -0
  89. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_csharp.py +0 -0
  90. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_fortran.py +0 -0
  91. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_go.py +0 -0
  92. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_java.py +0 -0
  93. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_js.py +0 -0
  94. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_php.py +0 -0
  95. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_ruby.py +0 -0
  96. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_rust.py +0 -0
  97. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ranges_swift.py +0 -0
  98. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ratchet.py +0 -0
  99. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_ratio_adapters.py +0 -0
  100. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_recurrence.py +0 -0
  101. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_run_comparison.py +0 -0
  102. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_runner.py +0 -0
  103. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_safe_write.py +0 -0
  104. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_scan_history.py +0 -0
  105. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_scan_view.py +0 -0
  106. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_second_source.py +0 -0
  107. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_selection.py +0 -0
  108. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_semantic.py +0 -0
  109. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_semantic_policy.py +0 -0
  110. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_semantic_ts.py +0 -0
  111. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_semantic_view.py +0 -0
  112. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_setup_errors.py +0 -0
  113. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_setup_persist.py +0 -0
  114. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  115. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  116. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  117. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  118. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  119. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  120. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_skill_install.py +0 -0
  121. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_stored_grants.py +0 -0
  122. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_tdd_view.py +0 -0
  123. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_test_commands.py +0 -0
  124. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_test_execution.py +0 -0
  125. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_test_pairing.py +0 -0
  126. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_tokens.py +0 -0
  127. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_tool_adapters.py +0 -0
  128. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_trends.py +0 -0
  129. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_user_config.py +0 -0
  130. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_verdict_adapters.py +0 -0
  131. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_verification.py +0 -0
  132. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_work_order.py +0 -0
  133. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_work_order_view.py +0 -0
  134. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_work_order_weights.py +0 -0
  135. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/_xml.py +0 -0
  136. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/baseline.py +0 -0
  137. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/cli.py +0 -0
  138. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/deadcode.py +0 -0
  139. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/declarations.py +0 -0
  140. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/duplication.py +0 -0
  141. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/evidence.py +0 -0
  142. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/git_tools.py +0 -0
  143. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/history.py +0 -0
  144. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/idioms.py +0 -0
  145. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/instructions.py +0 -0
  146. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/metrics.py +0 -0
  147. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/prompts.py +0 -0
  148. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/renderers.py +0 -0
  149. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/report.py +0 -0
  150. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/sarif.py +0 -0
  151. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/scoring.py +0 -0
  152. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/similarity.py +0 -0
  153. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/src/maintainability_audit/source.py +0 -0
  154. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_acquisition_trust.py +0 -0
  155. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_adapter_docs.py +0 -0
  156. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_adapter_recordings.py +0 -0
  157. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_adapters.py +0 -0
  158. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_added_lines.py +0 -0
  159. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analysis_coverage.py +0 -0
  160. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analysis_execution.py +0 -0
  161. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_bridge.py +0 -0
  162. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_config_isolation.py +0 -0
  163. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_estimate_claims.py +0 -0
  164. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_pinning.py +0 -0
  165. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_primary_estimate.py +0 -0
  166. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_provenance.py +0 -0
  167. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_provenance_exclusions.py +0 -0
  168. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_scoring_path.py +0 -0
  169. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_spread_range.py +0 -0
  170. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_analyzer_xml_bounds.py +0 -0
  171. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_anchor_and_mode.py +0 -0
  172. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
  173. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_anchor_disclosure.py +0 -0
  174. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_annotations_match_behaviour.py +0 -0
  175. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_anticipated_refusals.py +0 -0
  176. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_architecture.py +0 -0
  177. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_artifact_write_route_class.py +0 -0
  178. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_aspect_coverage.py +0 -0
  179. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_asset_snapshot_class.py +0 -0
  180. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_ast_reading_resolves_spellings.py +0 -0
  181. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_attestation.py +0 -0
  182. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_audit_components.py +0 -0
  183. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_authorization_freshness.py +0 -0
  184. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_authorship_gates.py +0 -0
  185. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_backfill.py +0 -0
  186. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_band_concealment_class.py +0 -0
  187. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_band_concealment_p3.py +0 -0
  188. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_band_pressures.py +0 -0
  189. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_bands.py +0 -0
  190. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_body_or_signature_class.py +0 -0
  191. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_build_output_is_not_the_repositorys_code.py +0 -0
  192. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_c_declarations.py +0 -0
  193. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_calibration_corpus.py +0 -0
  194. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_calibration_drift.py +0 -0
  195. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_calibration_tooling.py +0 -0
  196. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_catalog_selection.py +0 -0
  197. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_catalog_tier_promise.py +0 -0
  198. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_chat_leads_with_the_work_order.py +0 -0
  199. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_chat_primary_docs.py +0 -0
  200. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_check_refuses_plus_only_fragments.py +0 -0
  201. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_checkstyle_adapter.py +0 -0
  202. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_checkstyle_catalog.py +0 -0
  203. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_child_sandbox.py +0 -0
  204. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_ci_history_recipe.py +0 -0
  205. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  206. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_claimed_languages.py +0 -0
  207. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_cli.py +0 -0
  208. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_clone_group_class.py +0 -0
  209. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_cobol_declarations.py +0 -0
  210. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_cognitive_complexity.py +0 -0
  211. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_cohort_statistics.py +0 -0
  212. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_concealment_properties.py +0 -0
  213. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_config_shape.py +0 -0
  214. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_consent_and_grant.py +0 -0
  215. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_consumer_migration.py +0 -0
  216. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_contract_claims.py +0 -0
  217. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_corroborate.py +0 -0
  218. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_coverage_by_language.py +0 -0
  219. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_cpp_declarations.py +0 -0
  220. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_criteria_completion.py +0 -0
  221. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_csharp_declarations.py +0 -0
  222. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_d15_composition.py +0 -0
  223. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_d15_goal_directed.py +0 -0
  224. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_dead_code.py +0 -0
  225. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declaration_criteria_scope.py +0 -0
  226. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declaration_edge_cases.py +0 -0
  227. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declaration_grading.py +0 -0
  228. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declaration_ranges.py +0 -0
  229. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declaration_source.py +0 -0
  230. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declarative_parsers.py +0 -0
  231. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declared_authorship.py +0 -0
  232. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_declared_imports.py +0 -0
  233. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_delegated_security_pillar.py +0 -0
  234. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_demo_tree.py +0 -0
  235. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_derivation_mix.py +0 -0
  236. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_determinism.py +0 -0
  237. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_dimension_ratchet.py +0 -0
  238. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_direct_runner_availability_class.py +0 -0
  239. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_discovery.py +0 -0
  240. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_doc_claims.py +0 -0
  241. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_docs_links.py +0 -0
  242. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_economic_context.py +0 -0
  243. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_empty_output_not_clean.py +0 -0
  244. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_empty_output_not_clean_adapters.py +0 -0
  245. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_environment_work_order.py +0 -0
  246. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_every_surface_says_what_the_run_found.py +0 -0
  247. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_evidence_invariants.py +0 -0
  248. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_evidence_normalization.py +0 -0
  249. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_evidence_properties.py +0 -0
  250. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_example_config_opens_claimed_languages.py +0 -0
  251. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_exclusion_dialects.py +0 -0
  252. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_exposure_never_outranks_band.py +0 -0
  253. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_falsifier_standard.py +0 -0
  254. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_file_list_cap_class.py +0 -0
  255. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_finding_identity.py +0 -0
  256. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_first_run_elicitation.py +0 -0
  257. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_first_run_prompt.py +0 -0
  258. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_first_run_reelicitation.py +0 -0
  259. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_fix_breadth_window.py +0 -0
  260. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_fixed_form_fortran.py +0 -0
  261. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_format_ask.py +0 -0
  262. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_fortran_declarations.py +0 -0
  263. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_fortran_metrics.py +0 -0
  264. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_fortran_practice.py +0 -0
  265. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_git_argv.py +0 -0
  266. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_git_read_only.py +0 -0
  267. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_git_readonly_class.py +0 -0
  268. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_go_declarations.py +0 -0
  269. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_grammar_constructs.py +0 -0
  270. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_grammar_token_coverage.py +0 -0
  271. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_grant_only_user_tier.py +0 -0
  272. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_history.py +0 -0
  273. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_history_boundary.py +0 -0
  274. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_history_manifest.py +0 -0
  275. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_history_schema2.py +0 -0
  276. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_history_window.py +0 -0
  277. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_hostile_prompt.py +0 -0
  278. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_html_executive.py +0 -0
  279. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_html_section_parity_class.py +0 -0
  280. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_identity_docs.py +0 -0
  281. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_identity_resolution.py +0 -0
  282. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_idiom_divergence.py +0 -0
  283. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_in_loop_budgets.py +0 -0
  284. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_in_loop_check.py +0 -0
  285. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_installed_wheel_runtime.py +0 -0
  286. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_instruction_targets.py +0 -0
  287. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_java_range_guard.py +0 -0
  288. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_java_ranges.py +0 -0
  289. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_java_scored.py +0 -0
  290. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_java_wiring.py +0 -0
  291. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_js_complexity_operators.py +0 -0
  292. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_js_declarations.py +0 -0
  293. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_language_coverage.py +0 -0
  294. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_language_support_honesty.py +0 -0
  295. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_mcp_baseline_payload.py +0 -0
  296. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_mcp_format_contract.py +0 -0
  297. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_mcp_history.py +0 -0
  298. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_mcp_server.py +0 -0
  299. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_migration_1_0.py +0 -0
  300. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_near_duplicates.py +0 -0
  301. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_network_disclosure.py +0 -0
  302. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_one_setup_across_surfaces_class.py +0 -0
  303. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_operator_named_paths.py +0 -0
  304. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_operator_named_reads.py +0 -0
  305. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pairing_reads_imports.py +0 -0
  306. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pattern_budget.py +0 -0
  307. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_phase6_claims.py +0 -0
  308. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_php_declarations.py +0 -0
  309. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pillars_and_practice.py +0 -0
  310. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_platform_claim.py +0 -0
  311. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pmd_adapter.py +0 -0
  312. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pmd_audit_closures.py +0 -0
  313. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_policy_claims.py +0 -0
  314. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_pool_runs_by_config.py +0 -0
  315. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_population_floors.py +0 -0
  316. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_practice_nested_gates_class.py +0 -0
  317. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_precommit_staged.py +0 -0
  318. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_presentation_refusals.py +0 -0
  319. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_promises.py +0 -0
  320. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
  321. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_prompt_escalation_once.py +0 -0
  322. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_prompt_honesty.py +0 -0
  323. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_prompt_location_escalation_class.py +0 -0
  324. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_prove_falsifiers.py +0 -0
  325. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_python_complexity.py +0 -0
  326. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_python_declarations.py +0 -0
  327. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_read_boundary.py +0 -0
  328. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_readme_claims.py +0 -0
  329. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_recurrence.py +0 -0
  330. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_release_needs_an_empty_ledger.py +0 -0
  331. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_release_plan.py +0 -0
  332. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_release_plan_status.py +0 -0
  333. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_report_remedy_copy.py +0 -0
  334. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_roles_recorded.py +0 -0
  335. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_root_grants.py +0 -0
  336. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  337. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_ruby_declarations.py +0 -0
  338. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_run_comparison.py +0 -0
  339. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_runner.py +0 -0
  340. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_rust_declarations.py +0 -0
  341. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_sarif.py +0 -0
  342. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scan_history.py +0 -0
  343. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scan_scope.py +0 -0
  344. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scanner_unsafe_direction.py +0 -0
  345. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scanning.py +0 -0
  346. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_schema_fidelity.py +0 -0
  347. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scope_conformance.py +0 -0
  348. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_scoring_calibration.py +0 -0
  349. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_semantic_policy.py +0 -0
  350. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_setup_gate_completeness.py +0 -0
  351. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_setup_gate_independent_contract.py +0 -0
  352. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_setup_precondition.py +0 -0
  353. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_skill_install.py +0 -0
  354. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_sonar_resolve.py +0 -0
  355. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_source_index.py +0 -0
  356. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_spotbugs_adapter.py +0 -0
  357. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_spotbugs_catalog.py +0 -0
  358. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_stage8_contract.py +0 -0
  359. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_stdout_outputs.py +0 -0
  360. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_suite_isolation.py +0 -0
  361. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_swift_declarations.py +0 -0
  362. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_tdd_structure.py +0 -0
  363. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_terminal_asks_the_same_questions.py +0 -0
  364. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_test_commands.py +0 -0
  365. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_test_execution_class.py +0 -0
  366. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_three_presentations.py +0 -0
  367. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_tool_resolution.py +0 -0
  368. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
  369. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_tree_chosen_spawn.py +0 -0
  370. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_tree_reads_use_the_primitive.py +0 -0
  371. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_trends.py +0 -0
  372. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_type_fields_not_functions_class.py +0 -0
  373. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_uat_falsifiers.py +0 -0
  374. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_unanchored_set_matches_corpus.py +0 -0
  375. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_unread_code.py +0 -0
  376. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_user_config_tier.py +0 -0
  377. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_verification_audit_closures.py +0 -0
  378. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_verified_grade.py +0 -0
  379. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_version_claim.py +0 -0
  380. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_wheel_contents.py +0 -0
  381. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_work_items_state_their_own_finding.py +0 -0
  382. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_work_order.py +0 -0
  383. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
  384. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_work_order_items.py +0 -0
  385. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_work_order_selection.py +0 -0
  386. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_workflow_supply_chain.py +0 -0
  387. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_write_boundary.py +0 -0
  388. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/tests/test_write_route_class.py +0 -0
  389. {maintainability_agent-3.7.0 → maintainability_agent-3.7.3}/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.0
3
+ Version: 3.7.3
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -19,7 +19,6 @@ Classifier: Topic :: Software Development :: Quality Assurance
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: secure-code-agent<0.11,>=0.10
23
22
  Provides-Extra: test
24
23
  Requires-Dist: pytest>=8; extra == "test"
25
24
  Requires-Dist: pytest-cov>=5; extra == "test"
@@ -47,7 +46,7 @@ Dynamic: license-file
47
46
  **A deterministic, offline maintainability audit whose output is a _bounded
48
47
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
49
48
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
50
- Version **3.7.0**.
49
+ Version **3.7.3**.
51
50
 
52
51
  **Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
53
52
  COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -81,6 +80,18 @@ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
81
80
  disagree. Nothing here is required — the audit runs without any of it and tells
82
81
  you what it could not measure.
83
82
 
83
+ **Install secure-code-agent for the security pillar.** Every audit runs it; it is
84
+ installed alongside rather than as a dependency, so the two tools release
85
+ independently. Without it the report says the security pillar was not measured
86
+ and gives this command. Its scanners decide what it can grade — see
87
+ [machine setup](docs/machine-setup.md#4-toolchain) for which to install, and
88
+ don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
89
+
90
+ ```bash
91
+ pip install 'secure-code-agent>=0.12.1'
92
+ brew install gitleaks osv-scanner semgrep checkov # its scanners; pip install bandit
93
+ ```
94
+
84
95
  **One command to a work order.** A config file is the whole setup — with one
85
96
  present, nothing is asked and nothing is written into your tree:
86
97
 
@@ -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.0**.
8
+ Version **3.7.3**.
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
@@ -39,6 +39,18 @@ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
39
39
  disagree. Nothing here is required — the audit runs without any of it and tells
40
40
  you what it could not measure.
41
41
 
42
+ **Install secure-code-agent for the security pillar.** Every audit runs it; it is
43
+ installed alongside rather than as a dependency, so the two tools release
44
+ independently. Without it the report says the security pillar was not measured
45
+ and gives this command. Its scanners decide what it can grade — see
46
+ [machine setup](docs/machine-setup.md#4-toolchain) for which to install, and
47
+ don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
48
+
49
+ ```bash
50
+ pip install 'secure-code-agent>=0.12.1'
51
+ brew install gitleaks osv-scanner semgrep checkov # its scanners; pip install bandit
52
+ ```
53
+
42
54
  **One command to a work order.** A config file is the whole setup — with one
43
55
  present, nothing is asked and nothing is written into your tree:
44
56
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maintainability-agent"
7
- version = "3.7.0"
7
+ version = "3.7.3"
8
8
  description = "Maintainability gate and AI remediation prompt generator for CI."
9
9
  readme = "README.md"
10
10
  # 3.11, not 3.10. `_discovery`, `_pillars` and `_runner` all import
@@ -13,14 +13,6 @@ readme = "README.md"
13
13
  # metadata said a user could stand: the suite runs 3.12 and the
14
14
  # composite action pins 3.11 (D42).
15
15
  requires-python = ">=3.11"
16
- # The security pillar is complete (D177): every audit runs secure-code-agent,
17
- # so it installs with this package rather than being left to the operator.
18
- # Its own dependency is PyYAML; this package still imports no YAML
19
- # (`test_the_shipped_package_does_not_import_yaml`) — it runs the tool as a
20
- # child and reads the JSON document it writes.
21
- dependencies = [
22
- "secure-code-agent>=0.10,<0.11",
23
- ]
24
16
  license = { text = "MIT" }
25
17
  authors = [
26
18
  { name = "Marshall Guillory" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 3.7.0
3
+ Version: 3.7.3
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -19,7 +19,6 @@ Classifier: Topic :: Software Development :: Quality Assurance
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: secure-code-agent<0.11,>=0.10
23
22
  Provides-Extra: test
24
23
  Requires-Dist: pytest>=8; extra == "test"
25
24
  Requires-Dist: pytest-cov>=5; extra == "test"
@@ -47,7 +46,7 @@ Dynamic: license-file
47
46
  **A deterministic, offline maintainability audit whose output is a _bounded
48
47
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
49
48
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
50
- Version **3.7.0**.
49
+ Version **3.7.3**.
51
50
 
52
51
  **Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
53
52
  COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -81,6 +80,18 @@ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
81
80
  disagree. Nothing here is required — the audit runs without any of it and tells
82
81
  you what it could not measure.
83
82
 
83
+ **Install secure-code-agent for the security pillar.** Every audit runs it; it is
84
+ installed alongside rather than as a dependency, so the two tools release
85
+ independently. Without it the report says the security pillar was not measured
86
+ and gives this command. Its scanners decide what it can grade — see
87
+ [machine setup](docs/machine-setup.md#4-toolchain) for which to install, and
88
+ don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
89
+
90
+ ```bash
91
+ pip install 'secure-code-agent>=0.12.1'
92
+ brew install gitleaks osv-scanner semgrep checkov # its scanners; pip install bandit
93
+ ```
94
+
84
95
  **One command to a work order.** A config file is the whole setup — with one
85
96
  present, nothing is asked and nothing is written into your tree:
86
97
 
@@ -291,6 +291,7 @@ tests/test_mcp_baseline_payload.py
291
291
  tests/test_mcp_format_contract.py
292
292
  tests/test_mcp_history.py
293
293
  tests/test_mcp_server.py
294
+ tests/test_mcp_start_failure_names_what_is_installed.py
294
295
  tests/test_migration_1_0.py
295
296
  tests/test_near_duplicates.py
296
297
  tests/test_network_disclosure.py
@@ -341,6 +342,7 @@ tests/test_scanning.py
341
342
  tests/test_schema_fidelity.py
342
343
  tests/test_scope_conformance.py
343
344
  tests/test_scoring_calibration.py
345
+ tests/test_security_delegate_versions_agree.py
344
346
  tests/test_security_pillar_runs_and_shows.py
345
347
  tests/test_semantic_policy.py
346
348
  tests/test_setup_gate_completeness.py
@@ -1,4 +1,3 @@
1
- secure-code-agent<0.11,>=0.10
2
1
 
3
2
  [dev]
4
3
  pytest>=8
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "3.7.0"
3
+ __version__ = "3.7.3"
@@ -44,8 +44,19 @@ from typing import Any
44
44
  from ._delegated_pillar import read_produced
45
45
  from ._runner import Invocation, Outcome, run
46
46
 
47
- #: The distribution the pillar requires, and the range this tool reads.
48
- REQUIREMENT = "secure-code-agent>=0.10,<0.11"
47
+ #: The releases this audit runs, and the install command's requirement.
48
+ #:
49
+ #: **Not a package dependency.** 3.7.0 made it one, and within the day it
50
+ #: capped the tool below its current release — installing this package
51
+ #: downgraded a machine's secure-code-agent — and put the two tools' opposed
52
+ #: `mcp` pins into one environment. secure-code-agent's D3 and this project's
53
+ #: ADR 008 both hold the tools independently releasable. So the audit runs
54
+ #: whichever release is installed, when it falls in this range, and says so
55
+ #: when it does not. The ceiling is the next major: within 0.x the pillar
56
+ #: document is versioned by its own `schema_version`, which the reader checks.
57
+ SUPPORTED_FLOOR = (0, 12, 1)
58
+ SUPPORTED_CEILING = (1,)
59
+ REQUIREMENT = "secure-code-agent>=0.12.1,<1"
49
60
 
50
61
  #: How long the child may run before the pillar is reported as unmeasured.
51
62
  DEFAULT_TIMEOUT_SECONDS = 300
@@ -82,6 +93,12 @@ def run_security_delegate(
82
93
  if importlib.util.find_spec("secure_code_audit") is None:
83
94
  reason = "secure-code-agent is not installed for the interpreter running this audit"
84
95
  return DelegateRun(None, reason, [_install_remedy(reason)])
96
+ installed = _installed_version()
97
+ if installed is None or not (SUPPORTED_FLOOR <= installed < SUPPORTED_CEILING):
98
+ shown = ".".join(map(str, installed)) if installed else "an unreadable version"
99
+ reason = (f"secure-code-agent {shown} is installed; this audit runs "
100
+ f"{REQUIREMENT.removeprefix('secure-code-agent')}")
101
+ return DelegateRun(None, reason, [_install_remedy(reason)])
85
102
  with tempfile.TemporaryDirectory(prefix="ma-security-") as scratch:
86
103
  out = Path(scratch)
87
104
  pillar = out / "security-pillar.json"
@@ -116,6 +133,31 @@ def run_security_delegate(
116
133
  return DelegateRun(None, reason)
117
134
 
118
135
 
136
+ def _installed_version() -> tuple[int, ...] | None:
137
+ """The installed release as integers, or `None` when it cannot be read.
138
+
139
+ No `packaging` import: this package has no runtime dependencies. A
140
+ pre-release or local suffix is cut at the first non-numeric part, which
141
+ compares a `0.13.0rc1` as `0.13.0` — conservative at the ceiling.
142
+ """
143
+ import importlib.metadata as metadata
144
+ import re
145
+
146
+ try:
147
+ text = metadata.version("secure-code-agent")
148
+ except metadata.PackageNotFoundError:
149
+ return None
150
+ parts = []
151
+ for piece in text.split("."):
152
+ match = re.match(r"\d+", piece)
153
+ if not match:
154
+ break
155
+ parts.append(int(match.group()))
156
+ if match.group() != piece:
157
+ break
158
+ return tuple(parts) or None
159
+
160
+
119
161
  def _last_line(text: str | None) -> str:
120
162
  lines = [line.strip() for line in (text or "").splitlines() if line.strip()]
121
163
  return lines[-1][:200] if lines else ""
@@ -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.0"
23
+ VERSION = "3.7.3"
24
24
 
25
25
  PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
26
26
 
@@ -368,6 +368,46 @@ def _bind_prompts(server: Any) -> None:
368
368
  )
369
369
 
370
370
 
371
+ #: The `mcp` releases this server is written against, as the `mcp` extra pins.
372
+ MCP_REQUIREMENT = ">=2,<3"
373
+
374
+
375
+ def mcp_unavailable_message(error: BaseException | None = None) -> str:
376
+ """Why the server cannot start, naming what is actually installed (D178).
377
+
378
+ The message said "MCP support is not installed" whenever the import
379
+ failed. On the machine this was found on, `mcp` *was* installed — at
380
+ 1.23.3, because installing secure-code-agent's scanner extras pulled in
381
+ semgrep, which pins `mcp<2`, and pip replaced this package's 2.0.0 to
382
+ satisfy it. The chat door then failed to start, and the remedy it printed
383
+ was the install that had just been undone. A reader needs the version
384
+ that is there and the package that put it there.
385
+ """
386
+ import importlib.metadata as metadata
387
+ import re
388
+
389
+ try:
390
+ installed = metadata.version("mcp")
391
+ except metadata.PackageNotFoundError:
392
+ return ('MCP support is not installed. Install with: '
393
+ 'pip install "maintainability-agent[mcp]"')
394
+ major = installed.split(".", 1)[0]
395
+ if major.isdigit() and int(major) == 2:
396
+ return (f"MCP support cannot start: mcp {installed} is installed and satisfies "
397
+ f"mcp{MCP_REQUIREMENT}, but importing it failed: {error}")
398
+ names_mcp = re.compile(r"^mcp(?=$|[\s<>=!~\[;(])", re.IGNORECASE)
399
+ dependents = sorted({
400
+ dist.metadata["Name"] for dist in metadata.distributions()
401
+ if dist.metadata["Name"] and dist.metadata["Name"].lower() not in ("maintainability-agent", "mcp")
402
+ and any(names_mcp.match(requirement.strip()) for requirement in (dist.requires or ()))
403
+ })
404
+ pinned = (f" It is required here by {', '.join(dependents)}, which may be what "
405
+ "installed this version; give that tool its own environment, or the next "
406
+ "install will replace mcp again.") if dependents else ""
407
+ return (f"MCP support cannot start: mcp {installed} is installed, and this server needs "
408
+ f"mcp{MCP_REQUIREMENT}.{pinned} Restore it with: pip install \"mcp{MCP_REQUIREMENT}\"")
409
+
410
+
371
411
  def create_server(*, roots: tuple[Path, ...] | None = None):
372
412
  """Create the SDK server; importing the base package does not require MCP."""
373
413
  try:
@@ -376,10 +416,8 @@ def create_server(*, roots: tuple[Path, ...] | None = None):
376
416
  from mcp.server.mcpserver.resources import FunctionResource
377
417
  from mcp.server.mcpserver.resources.templates import ResourceSecurity
378
418
  from mcp.types import ToolAnnotations
379
- except ImportError as error: # pragma: no cover - exercised by the console entry point
380
- raise RuntimeError(
381
- 'MCP support is not installed. Install with: pip install "maintainability-agent[mcp]"'
382
- ) from error
419
+ except ImportError as error:
420
+ raise RuntimeError(mcp_unavailable_message(error)) from error
383
421
 
384
422
  ledger = _RootLedger(roots if roots is not None else allowed_roots())
385
423
  server = MCPServer(
@@ -0,0 +1,94 @@
1
+ """When the chat door cannot start, it says what is installed and what put it there (D178).
2
+
3
+ Found setting up a second machine for a demo. Installing secure-code-agent's
4
+ scanner extras into this package's environment pulled in semgrep, which pins
5
+ `mcp<2`; pip replaced `mcp` 2.0.0 with 1.23.3, and `maintainability-agent-mcp`
6
+ failed to start with "MCP support is not installed" and the remedy
7
+ `pip install "maintainability-agent[mcp]"` — describing a package that was
8
+ installed, and prescribing the install that had just been undone.
9
+
10
+ The claim: **for every way the import can fail, the message states the
11
+ installed version and, where one exists, the package that requires `mcp`.**
12
+ The states are the three the version metadata can be in: absent, outside
13
+ this server's range, and inside it but unimportable.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import importlib.metadata as metadata
18
+
19
+ import pytest
20
+
21
+
22
+ class _Dist:
23
+ def __init__(self, name: str, requires: list[str]) -> None:
24
+ self.metadata = {"Name": name}
25
+ self.requires = requires
26
+
27
+
28
+ def _patch(monkeypatch, version: str | None, dists: list[_Dist]) -> None:
29
+ def fake_version(name: str) -> str:
30
+ if name == "mcp" and version is not None:
31
+ return version
32
+ raise metadata.PackageNotFoundError(name)
33
+
34
+ monkeypatch.setattr(metadata, "version", fake_version)
35
+ monkeypatch.setattr(metadata, "distributions", lambda: iter(dists))
36
+
37
+
38
+ def test_a_version_outside_the_range_names_it_and_who_required_it(monkeypatch) -> None:
39
+ from maintainability_audit.mcp_server import MCP_REQUIREMENT, mcp_unavailable_message
40
+
41
+ _patch(monkeypatch, "1.23.3", [
42
+ _Dist("semgrep", ["mcp==1.23.3", "click>=8"]),
43
+ _Dist("mcp-helper", ["mcpx>=1"]), # a name that merely starts with mcp is not mcp
44
+ _Dist("maintainability-agent", ['mcp<3,>=2; extra == "mcp"']),
45
+ ])
46
+ message = mcp_unavailable_message(ImportError("cannot import name 'MCPServer'"))
47
+
48
+ assert "1.23.3" in message and MCP_REQUIREMENT in message, message
49
+ assert "semgrep" in message, f"the package that pinned mcp is not named: {message}"
50
+ assert "mcp-helper" not in message, f"a package that does not require mcp was blamed: {message}"
51
+ assert "not installed" not in message, f"an installed mcp was described as missing: {message}"
52
+
53
+
54
+ def test_an_absent_mcp_still_says_how_to_install_the_extra(monkeypatch) -> None:
55
+ """Covers existing behaviour: the absent case was already worded correctly.
56
+
57
+ Guards that naming versions did not change what a fresh environment is told.
58
+ """
59
+ from maintainability_audit.mcp_server import mcp_unavailable_message
60
+
61
+ _patch(monkeypatch, None, [])
62
+ message = mcp_unavailable_message(ImportError("No module named 'mcp'"))
63
+ assert "not installed" in message and "maintainability-agent[mcp]" in message, message
64
+
65
+
66
+ def test_a_version_inside_the_range_reports_the_import_error_itself(monkeypatch) -> None:
67
+ """An in-range mcp that will not import is not a version problem; do not say it is."""
68
+ from maintainability_audit.mcp_server import mcp_unavailable_message
69
+
70
+ _patch(monkeypatch, "2.0.0", [])
71
+ message = mcp_unavailable_message(ImportError("broken wheel: missing pydantic_core"))
72
+ assert "2.0.0" in message and "broken wheel" in message, message
73
+ assert "not installed" not in message, message
74
+
75
+
76
+ @pytest.mark.parametrize("version", ["1.23.3", "3.0.0"])
77
+ def test_the_console_entry_raises_the_named_message(monkeypatch, version) -> None:
78
+ """D178 at the seam the operator sees: `create_server` raises the named message."""
79
+ import builtins
80
+
81
+ from maintainability_audit import mcp_server
82
+
83
+ _patch(monkeypatch, version, [_Dist("semgrep", [f"mcp=={version}"])])
84
+ real_import = builtins.__import__
85
+
86
+ def failing_import(name, *args, **kwargs):
87
+ if name == "mcp.server" or name.startswith("mcp.server."):
88
+ raise ImportError(f"cannot import name 'MCPServer' from 'mcp.server' ({version})")
89
+ return real_import(name, *args, **kwargs)
90
+
91
+ monkeypatch.setattr(builtins, "__import__", failing_import)
92
+ with pytest.raises(RuntimeError) as raised:
93
+ mcp_server.create_server(roots=())
94
+ assert version in str(raised.value) and "semgrep" in str(raised.value), str(raised.value)
@@ -0,0 +1,86 @@
1
+ """The secure-code-agent this project gates on is one this audit will run.
2
+
3
+ 3.7.0 made secure-code-agent a package dependency pinned `>=0.10,<0.11`, repeated in
4
+ `_security_delegate.REQUIREMENT`, with CI on `==0.10.0` — all taken from the pin CI
5
+ already had, while the published tool was at 0.12.1. It is no longer a dependency
6
+ (secure-code-agent D3, ADR 008: independently releasable), so the audit's own supported
7
+ range is the one declaration, and every CI pin has to fall inside it.
8
+
9
+ Covers existing behaviour: CI's pin sat inside the declared range before this change
10
+ too — on the wrong version. Knowing the current release needs the index, which an
11
+ offline suite cannot read; this guard keeps the declarations together from here.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import re
16
+ import tomllib
17
+ from pathlib import Path
18
+
19
+ ROOT = Path(__file__).resolve().parents[1]
20
+
21
+
22
+ def _version_tuple(text: str) -> tuple[int, ...]:
23
+ return tuple(int(part) for part in text.split("."))
24
+
25
+
26
+ def test_the_supported_range_and_the_install_remedy_are_one_declaration() -> None:
27
+ from maintainability_audit._security_delegate import (
28
+ REQUIREMENT,
29
+ SUPPORTED_CEILING,
30
+ SUPPORTED_FLOOR,
31
+ )
32
+
33
+ bounds = dict(re.findall(r"(>=|<)([0-9][0-9.]*)", REQUIREMENT))
34
+ assert _version_tuple(bounds[">="]) == SUPPORTED_FLOOR, (REQUIREMENT, SUPPORTED_FLOOR)
35
+ assert _version_tuple(bounds["<"]) == SUPPORTED_CEILING, (REQUIREMENT, SUPPORTED_CEILING)
36
+
37
+
38
+ def test_secure_code_agent_is_not_a_package_dependency() -> None:
39
+ project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))["project"]
40
+ coupled = [dep for dep in project.get("dependencies", []) if dep.startswith("secure-code-agent")]
41
+ assert not coupled, (
42
+ f"secure-code-agent is a package dependency again ({coupled}); the tools are "
43
+ "independently releasable (secure-code-agent D3, ADR 008)"
44
+ )
45
+
46
+
47
+ def test_every_ci_pin_is_a_release_the_audit_runs() -> None:
48
+ from maintainability_audit._security_delegate import SUPPORTED_CEILING, SUPPORTED_FLOOR
49
+
50
+ workflows = sorted((ROOT / ".github" / "workflows").glob("*.yml"))
51
+ assert workflows, "no workflows found"
52
+ pins = [(path.name, pin) for path in workflows
53
+ for pin in re.findall(r"secure-code-agent==([0-9][0-9.]*)", path.read_text(encoding="utf-8"))]
54
+ assert pins, "no workflow pins secure-code-agent; the gate would run whatever pip picks"
55
+ outside = [(name, pin) for name, pin in pins
56
+ if not (SUPPORTED_FLOOR <= _version_tuple(pin) < SUPPORTED_CEILING)]
57
+ assert not outside, f"CI pins a secure-code-agent this audit refuses to run: {outside}"
58
+
59
+
60
+ def _jobs(text: str) -> dict[str, str]:
61
+ """Each job's text in a workflow, split on the two-space job keys under `jobs:`.
62
+
63
+ Read as text, as `test_ci_installs_the_analyzer_pool` does: the suite does
64
+ not import a YAML parser.
65
+ """
66
+ body = text.split("\njobs:\n", 1)[1] if "\njobs:\n" in text else ""
67
+ parts = re.split(r"^ ([A-Za-z0-9_-]+):\s*$", body, flags=re.MULTILINE)
68
+ return {parts[index]: parts[index + 1] for index in range(1, len(parts) - 1, 2)}
69
+
70
+
71
+ def test_every_job_that_runs_the_suite_installs_secure_code_agent() -> None:
72
+ """The 3.7.2 tag failed in `release.yml`: it ran the suite without the tool.
73
+
74
+ `test_every_ci_pin_is_a_release_the_audit_runs` checked the pins that
75
+ existed, and the release job had none. The population here is every job,
76
+ in every workflow, whose steps run pytest.
77
+ """
78
+ running = [
79
+ (path.name, job, body)
80
+ for path in sorted((ROOT / ".github" / "workflows").glob("*.yml"))
81
+ for job, body in _jobs(path.read_text(encoding="utf-8")).items()
82
+ if re.search(r"-m pytest\b", body)
83
+ ]
84
+ assert running, "no workflow job runs pytest; the sweep would pass vacuously"
85
+ missing = [(name, job) for name, job, body in running if "secure-code-agent==" not in body]
86
+ assert not missing, f"jobs that run the suite without installing secure-code-agent: {missing}"
@@ -151,6 +151,44 @@ def test_a_missing_delegate_is_stated_with_its_remedy(tmp_path, monkeypatch) ->
151
151
  assert remedies and "pip install" in remedies[0]["install"], report["environment_work_order"]
152
152
 
153
153
 
154
+ @pytest.mark.parametrize("installed", ["0.10.0", "0.12.0", "1.0.0"])
155
+ def test_an_unsupported_release_is_stated_not_run(tmp_path, monkeypatch, installed) -> None:
156
+ """D177: installed but outside the supported range is a reason and a remedy, never a run.
157
+
158
+ secure-code-agent is no longer a package dependency, so the version a machine has is
159
+ whatever it has. Running a release outside the range would read a contract this
160
+ audit has not been checked against.
161
+ """
162
+ import importlib.machinery
163
+ import importlib.metadata as metadata
164
+
165
+ from maintainability_audit import _security_delegate
166
+ from maintainability_audit import report as report_module
167
+ from maintainability_audit.config import load_config
168
+ from maintainability_audit.report import build_report
169
+
170
+ real_version = metadata.version
171
+ monkeypatch.setattr(metadata, "version",
172
+ lambda name: installed if name == "secure-code-agent" else real_version(name))
173
+ # Installed, as far as the audit can tell, whatever this environment holds:
174
+ # the release build ran this without secure-code-agent and read "not installed".
175
+ real_find = _security_delegate.importlib.util.find_spec
176
+ monkeypatch.setattr(_security_delegate.importlib.util, "find_spec",
177
+ lambda name, *a: importlib.machinery.ModuleSpec(name, None)
178
+ if name == "secure_code_audit" else real_find(name, *a))
179
+ monkeypatch.setattr(_security_delegate, "run",
180
+ lambda *a, **k: (_ for _ in ()).throw(AssertionError("an unsupported release ran")),
181
+ raising=False)
182
+ monkeypatch.setattr(report_module, "run_security_delegate",
183
+ _security_delegate.run_security_delegate, raising=False)
184
+
185
+ report = build_report(_repo(tmp_path), load_config(None), run_analyzers=False)
186
+ entry = _security(report)
187
+ assert installed in entry["reason"] and "is installed" in entry["reason"], entry["reason"]
188
+ remedies = [item for item in report["environment_work_order"] if item["tool"] == "secure-code-agent"]
189
+ assert remedies and "secure-code-agent>=" in remedies[0]["install"], report["environment_work_order"]
190
+
191
+
154
192
  def _states() -> dict[str, dict[str, Any]]:
155
193
  """Every state the security pillar can be in, as `pillar_report` builds it."""
156
194
  from maintainability_audit._pillars import pillar_report