maintainability-agent 4.3.1__tar.gz → 4.4.1__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 (477) hide show
  1. {maintainability_agent-4.3.1/src/maintainability_agent.egg-info → maintainability_agent-4.4.1}/PKG-INFO +9 -6
  2. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/README.md +7 -4
  3. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/pyproject.toml +4 -1
  4. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1/src/maintainability_agent.egg-info}/PKG-INFO +9 -6
  5. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_agent.egg-info/SOURCES.txt +4 -0
  6. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_agent.egg-info/requires.txt +1 -1
  7. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/__init__.py +1 -1
  8. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_analysis.py +55 -2
  9. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_analyzer_sections.py +6 -1
  10. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_catalog.py +31 -0
  11. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_coverage_notes.py +13 -1
  12. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_criteria_scope.py +23 -0
  13. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_first_run.py +25 -0
  14. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_refusals.py +6 -0
  15. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_setup.py +56 -2
  16. maintainability_agent-4.4.1/src/maintainability_audit/_pipeline_results.py +112 -0
  17. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_setup_persist.py +27 -1
  18. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/SKILL.md +10 -2
  19. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_verdict_adapters.py +4 -2
  20. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/cli.py +2 -1
  21. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/mcp_server.py +6 -0
  22. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_adapters.py +54 -0
  23. maintainability_agent-4.4.1/tests/test_analyzers_never_write.py +128 -0
  24. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_first_run_elicitation.py +1 -1
  25. maintainability_agent-4.4.1/tests/test_pipeline_results.py +267 -0
  26. maintainability_agent-4.4.1/tests/test_reported_but_not_scored.py +51 -0
  27. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_previous_release_was_tagged.py +16 -1
  28. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/LICENSE +0 -0
  29. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/setup.cfg +0 -0
  30. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  31. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  32. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  33. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/__main__.py +0 -0
  34. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_adapters.py +0 -0
  35. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_anchor.py +0 -0
  36. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_arguments.py +0 -0
  37. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_aspects.py +0 -0
  38. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  39. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_assets/standard.md +0 -0
  40. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_attestation.py +0 -0
  41. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_backfill.py +0 -0
  42. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_bands.py +0 -0
  43. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_banner.py +0 -0
  44. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_built_ins.py +0 -0
  45. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_calibration.py +0 -0
  46. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_changed_code_policy.py +0 -0
  47. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_charts.py +0 -0
  48. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_cognitive.py +0 -0
  49. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_config_defaults.py +0 -0
  50. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_conformance.py +0 -0
  51. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_corroborate.py +0 -0
  52. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_delegated_pillar.py +0 -0
  53. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_derive.py +0 -0
  54. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_discovery.py +0 -0
  55. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_documents.py +0 -0
  56. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_economics.py +0 -0
  57. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_economics_view.py +0 -0
  58. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_environment.py +0 -0
  59. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_evidence_reader.py +0 -0
  60. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_evidence_view.py +0 -0
  61. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_finding_match.py +0 -0
  62. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_formula.py +0 -0
  63. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_gates.py +0 -0
  64. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_generic.py +0 -0
  65. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_grammar.py +0 -0
  66. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_grant_ledger.py +0 -0
  67. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_handoff.py +0 -0
  68. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_history_view.py +0 -0
  69. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_hostile_prompt.py +0 -0
  70. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_hotspots.py +0 -0
  71. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_html_report_sections.py +0 -0
  72. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_html_view.py +0 -0
  73. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_identity.py +0 -0
  74. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_in_loop.py +0 -0
  75. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_in_loop_view.py +0 -0
  76. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_jvm_adapters.py +0 -0
  77. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_markdown_sections.py +0 -0
  78. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_masking.py +0 -0
  79. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_audit.py +0 -0
  80. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_gate.py +0 -0
  81. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_grants.py +0 -0
  82. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_mcp_resources.py +0 -0
  83. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_metric_adapters.py +0 -0
  84. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_metrics_types.py +0 -0
  85. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_operator_reads.py +0 -0
  86. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_oracle.py +0 -0
  87. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_pillars.py +0 -0
  88. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_practice.py +0 -0
  89. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_precommit.py +0 -0
  90. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_precommit_install.py +0 -0
  91. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_precommit_view.py +0 -0
  92. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_pressures.py +0 -0
  93. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_prompt_sections.py +0 -0
  94. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_c.py +0 -0
  95. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_cobol.py +0 -0
  96. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_core.py +0 -0
  97. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_cpp.py +0 -0
  98. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_csharp.py +0 -0
  99. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_fortran.py +0 -0
  100. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_go.py +0 -0
  101. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_java.py +0 -0
  102. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_js.py +0 -0
  103. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_kotlin.py +0 -0
  104. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_php.py +0 -0
  105. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_ruby.py +0 -0
  106. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_rust.py +0 -0
  107. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_shell.py +0 -0
  108. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ranges_swift.py +0 -0
  109. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ratchet.py +0 -0
  110. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_ratio_adapters.py +0 -0
  111. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_recurrence.py +0 -0
  112. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_run_comparison.py +0 -0
  113. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_runner.py +0 -0
  114. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_running_version.py +0 -0
  115. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_safe_write.py +0 -0
  116. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_scan_history.py +0 -0
  117. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_scan_view.py +0 -0
  118. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_second_source.py +0 -0
  119. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_security_delegate.py +0 -0
  120. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_security_work_order.py +0 -0
  121. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_selection.py +0 -0
  122. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_semantic.py +0 -0
  123. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_semantic_policy.py +0 -0
  124. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_semantic_ts.py +0 -0
  125. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_semantic_view.py +0 -0
  126. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_setup_errors.py +0 -0
  127. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  128. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  129. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  130. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  131. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  132. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_skill_install.py +0 -0
  133. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_stored_grants.py +0 -0
  134. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_tdd_view.py +0 -0
  135. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_test_commands.py +0 -0
  136. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_test_execution.py +0 -0
  137. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_test_pairing.py +0 -0
  138. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_tokens.py +0 -0
  139. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_tool_adapters.py +0 -0
  140. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_trends.py +0 -0
  141. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_user_config.py +0 -0
  142. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_verification.py +0 -0
  143. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_work_order.py +0 -0
  144. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_work_order_view.py +0 -0
  145. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_work_order_weights.py +0 -0
  146. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/_xml.py +0 -0
  147. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/baseline.py +0 -0
  148. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/config.py +0 -0
  149. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/deadcode.py +0 -0
  150. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/declarations.py +0 -0
  151. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/duplication.py +0 -0
  152. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/evidence.py +0 -0
  153. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/git_tools.py +0 -0
  154. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/history.py +0 -0
  155. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/idioms.py +0 -0
  156. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/instructions.py +0 -0
  157. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/metrics.py +0 -0
  158. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/prompts.py +0 -0
  159. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/renderers.py +0 -0
  160. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/report.py +0 -0
  161. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/sarif.py +0 -0
  162. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/scoring.py +0 -0
  163. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/similarity.py +0 -0
  164. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/src/maintainability_audit/source.py +0 -0
  165. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_clone_names_every_copy.py +0 -0
  166. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_dangling_source_link_is_named_not_fatal.py +0 -0
  167. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_format_override_is_disclosed.py +0 -0
  168. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_matching_format_stays_silent.py +0 -0
  169. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_published_question_offers_what_it_accepts.py +0 -0
  170. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_rendered_docs_site_is_not_scored_as_source.py +0 -0
  171. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_a_setup_question_keeps_its_contract.py +0 -0
  172. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_acquisition_trust.py +0 -0
  173. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_adapter_docs.py +0 -0
  174. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_adapter_recordings.py +0 -0
  175. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_added_lines.py +0 -0
  176. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_an_absent_work_order_renders_nothing.py +0 -0
  177. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_an_unmeasured_pillar_reports_no_number.py +0 -0
  178. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analysis_coverage.py +0 -0
  179. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analysis_execution.py +0 -0
  180. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_bridge.py +0 -0
  181. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_config_isolation.py +0 -0
  182. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_estimate_claims.py +0 -0
  183. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_file_lists_are_batched.py +0 -0
  184. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_pinning.py +0 -0
  185. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_primary_estimate.py +0 -0
  186. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_provenance.py +0 -0
  187. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_provenance_exclusions.py +0 -0
  188. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_scoring_path.py +0 -0
  189. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_spread_range.py +0 -0
  190. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzer_xml_bounds.py +0 -0
  191. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzers_against_the_real_tools.py +0 -0
  192. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_analyzers_report_what_actually_failed.py +0 -0
  193. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_anchor_and_mode.py +0 -0
  194. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
  195. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_anchor_disclosure.py +0 -0
  196. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_annotations_match_behaviour.py +0 -0
  197. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_anticipated_refusals.py +0 -0
  198. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_architecture.py +0 -0
  199. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_artifact_write_route_class.py +0 -0
  200. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_aspect_coverage.py +0 -0
  201. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_asset_snapshot_class.py +0 -0
  202. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_ast_reading_resolves_spellings.py +0 -0
  203. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_attestation.py +0 -0
  204. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_audit_components.py +0 -0
  205. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_authorization_freshness.py +0 -0
  206. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_authorship_gates.py +0 -0
  207. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_backfill.py +0 -0
  208. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_band_concealment_class.py +0 -0
  209. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_band_concealment_p3.py +0 -0
  210. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_band_pressures.py +0 -0
  211. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_bands.py +0 -0
  212. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_behaviour_suites_are_tests.py +0 -0
  213. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_body_or_signature_class.py +0 -0
  214. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_both_setup_paths_ask_the_same_stage.py +0 -0
  215. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_build_output_is_not_the_repositorys_code.py +0 -0
  216. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_c_declarations.py +0 -0
  217. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_calibration_corpus.py +0 -0
  218. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_calibration_drift.py +0 -0
  219. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_calibration_tooling.py +0 -0
  220. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_catalog_selection.py +0 -0
  221. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_catalog_tier_promise.py +0 -0
  222. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_changed_code_policy.py +0 -0
  223. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_chat_leads_with_the_work_order.py +0 -0
  224. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_chat_primary_docs.py +0 -0
  225. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_check_refuses_plus_only_fragments.py +0 -0
  226. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_checkstyle_adapter.py +0 -0
  227. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_checkstyle_catalog.py +0 -0
  228. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_child_sandbox.py +0 -0
  229. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_ci_history_recipe.py +0 -0
  230. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  231. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_claimed_languages.py +0 -0
  232. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_clean_sees_the_weakened_oracle.py +0 -0
  233. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cli.py +0 -0
  234. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_clone_group_class.py +0 -0
  235. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cobol_declarations.py +0 -0
  236. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_code_scanning_gets_alerts_not_the_record.py +0 -0
  237. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cognitive_complexity.py +0 -0
  238. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cohesion_with_nothing_to_read_is_not_applicable.py +0 -0
  239. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cohort_statistics.py +0 -0
  240. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_concealment_properties.py +0 -0
  241. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_config_shape.py +0 -0
  242. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_conformance_reads_the_operators_ask.py +0 -0
  243. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_consent_and_grant.py +0 -0
  244. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_consent_is_per_repository.py +0 -0
  245. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_consent_survives_setup_and_is_asked.py +0 -0
  246. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_consent_without_command_has_a_remedy.py +0 -0
  247. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_consumer_migration.py +0 -0
  248. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_contract_claims.py +0 -0
  249. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_corpus_note_counts_come_from_the_corpus.py +0 -0
  250. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_corroborate.py +0 -0
  251. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_coverage_by_language.py +0 -0
  252. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_coverage_config_reaches_children.py +0 -0
  253. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_coverage_formats.py +0 -0
  254. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_cpp_declarations.py +0 -0
  255. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_criteria_completion.py +0 -0
  256. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_csharp_declarations.py +0 -0
  257. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_current_state_docs_name_every_parsed_language.py +0 -0
  258. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_d15_composition.py +0 -0
  259. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_d15_goal_directed.py +0 -0
  260. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_dead_code.py +0 -0
  261. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declaration_criteria_scope.py +0 -0
  262. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declaration_edge_cases.py +0 -0
  263. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declaration_grading.py +0 -0
  264. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declaration_ranges.py +0 -0
  265. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declaration_source.py +0 -0
  266. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declarative_parsers.py +0 -0
  267. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declared_capabilities_match_the_delegate.py +0 -0
  268. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_declared_imports.py +0 -0
  269. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_delegated_security_pillar.py +0 -0
  270. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_demo_tree.py +0 -0
  271. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_derivation_mix.py +0 -0
  272. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_determinism.py +0 -0
  273. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_dimension_ratchet.py +0 -0
  274. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_direct_runner_availability_class.py +0 -0
  275. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_discovery.py +0 -0
  276. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_doc_claims.py +0 -0
  277. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_docs_links.py +0 -0
  278. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_economic_context.py +0 -0
  279. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_empty_output_not_clean.py +0 -0
  280. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_empty_output_not_clean_adapters.py +0 -0
  281. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_environment_work_order.py +0 -0
  282. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_built_presentation_is_offered.py +0 -0
  283. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_job_tests_the_pinned_oracle.py +0 -0
  284. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_language_counts_its_own_loop.py +0 -0
  285. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_language_has_a_loop_fixture.py +0 -0
  286. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_pool_install_is_the_same_pool.py +0 -0
  287. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_question_can_be_answered.py +0 -0
  288. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_every_surface_says_what_the_run_found.py +0 -0
  289. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_evidence_invariants.py +0 -0
  290. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_evidence_normalization.py +0 -0
  291. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_evidence_properties.py +0 -0
  292. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_example_config_opens_claimed_languages.py +0 -0
  293. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_exclude_additional_keeps_the_defaults.py +0 -0
  294. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_exclusion_dialects.py +0 -0
  295. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_exposure_never_outranks_band.py +0 -0
  296. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_falsifier_standard.py +0 -0
  297. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_file_list_cap_class.py +0 -0
  298. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_finding_identity.py +0 -0
  299. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_first_run_prompt.py +0 -0
  300. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_first_run_reelicitation.py +0 -0
  301. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_first_stage_setup_wording_holds.py +0 -0
  302. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_fix_breadth_window.py +0 -0
  303. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_fixed_form_fortran.py +0 -0
  304. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_format_ask.py +0 -0
  305. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_fortran_declarations.py +0 -0
  306. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_fortran_metrics.py +0 -0
  307. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_fortran_practice.py +0 -0
  308. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_git_argv.py +0 -0
  309. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_git_read_only.py +0 -0
  310. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_git_readonly_class.py +0 -0
  311. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_go_declarations.py +0 -0
  312. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_grammar_constructs.py +0 -0
  313. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_grammar_token_coverage.py +0 -0
  314. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_grant_only_user_tier.py +0 -0
  315. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_grok_audit_of_3_11.py +0 -0
  316. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_history.py +0 -0
  317. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_history_boundary.py +0 -0
  318. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_history_manifest.py +0 -0
  319. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_history_schema2.py +0 -0
  320. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_history_window.py +0 -0
  321. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_hostile_prompt.py +0 -0
  322. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_html_executive.py +0 -0
  323. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_html_section_parity_class.py +0 -0
  324. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_identity_docs.py +0 -0
  325. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_identity_resolution.py +0 -0
  326. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_idiom_divergence.py +0 -0
  327. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_in_loop_budgets.py +0 -0
  328. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_in_loop_check.py +0 -0
  329. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_installed_wheel_runtime.py +0 -0
  330. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_instruction_targets.py +0 -0
  331. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_java_range_guard.py +0 -0
  332. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_java_ranges.py +0 -0
  333. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_java_scored.py +0 -0
  334. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_java_wiring.py +0 -0
  335. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_js_complexity_operators.py +0 -0
  336. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_js_declarations.py +0 -0
  337. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_kotlin_declarations.py +0 -0
  338. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_kotlin_metrics.py +0 -0
  339. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_language_coverage.py +0 -0
  340. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_language_support_honesty.py +0 -0
  341. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_list_tools_publishes_the_answer_path.py +0 -0
  342. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_maintenance_signals.py +0 -0
  343. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mcp_baseline_payload.py +0 -0
  344. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mcp_format_contract.py +0 -0
  345. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mcp_history.py +0 -0
  346. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mcp_server.py +0 -0
  347. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mcp_start_failure_names_what_is_installed.py +0 -0
  348. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_migration_1_0.py +0 -0
  349. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_missing_security_scanners_are_named_before_the_run.py +0 -0
  350. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_mutation_recorded.py +0 -0
  351. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_near_duplicates.py +0 -0
  352. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_network_disclosure.py +0 -0
  353. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_no_private_names.py +0 -0
  354. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_one_setup_across_surfaces_class.py +0 -0
  355. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_operator_named_paths.py +0 -0
  356. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_operator_named_reads.py +0 -0
  357. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_oracle_weakening_precision_bar.py +0 -0
  358. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pairing_reads_imports.py +0 -0
  359. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pattern_budget.py +0 -0
  360. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_phase6_claims.py +0 -0
  361. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_php_declarations.py +0 -0
  362. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pillars_and_practice.py +0 -0
  363. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_platform_claim.py +0 -0
  364. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pmd_adapter.py +0 -0
  365. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pmd_audit_closures.py +0 -0
  366. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_policy_claims.py +0 -0
  367. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_pool_runs_by_config.py +0 -0
  368. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_population_floors.py +0 -0
  369. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_practice_nested_gates_class.py +0 -0
  370. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_precommit_staged.py +0 -0
  371. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_preflight_before_consent_runs_nothing_from_the_tree.py +0 -0
  372. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_presentation_refusals.py +0 -0
  373. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_previous_release_reached_pypi.py +0 -0
  374. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_promises.py +0 -0
  375. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
  376. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_prompt_escalation_once.py +0 -0
  377. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_prompt_honesty.py +0 -0
  378. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_prompt_location_escalation_class.py +0 -0
  379. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_prove_falsifiers.py +0 -0
  380. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_python_complexity.py +0 -0
  381. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_python_declarations.py +0 -0
  382. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_read_boundary.py +0 -0
  383. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_readme_claims.py +0 -0
  384. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_recurrence.py +0 -0
  385. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_regular_file_reads_work_without_o_nonblock.py +0 -0
  386. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_release_needs_an_empty_ledger.py +0 -0
  387. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_release_plan.py +0 -0
  388. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_release_plan_status.py +0 -0
  389. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_rendered_docs.py +0 -0
  390. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_report_remedy_copy.py +0 -0
  391. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_root_grants.py +0 -0
  392. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  393. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_ruby_declarations.py +0 -0
  394. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_run_comparison.py +0 -0
  395. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_runner.py +0 -0
  396. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_rust_declarations.py +0 -0
  397. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_sarif.py +0 -0
  398. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scan_history.py +0 -0
  399. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scan_scope.py +0 -0
  400. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scanner_fingerprint_covers_the_measurement_path.py +0 -0
  401. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scanner_unsafe_direction.py +0 -0
  402. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scanning.py +0 -0
  403. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_schema_fidelity.py +0 -0
  404. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scope_conformance.py +0 -0
  405. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_scoring_calibration.py +0 -0
  406. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_security_delegate_versions_agree.py +0 -0
  407. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_security_findings_keep_their_handoff.py +0 -0
  408. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_security_pillar_asserts_a_scanner_set.py +0 -0
  409. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_security_pillar_runs_and_shows.py +0 -0
  410. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_selection_covers_every_parsed_language.py +0 -0
  411. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_semantic_findings_stay_inside_the_audited_files.py +0 -0
  412. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_semantic_policy.py +0 -0
  413. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_answers_are_the_same_setup.py +0 -0
  414. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_gate_completeness.py +0 -0
  415. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_gate_independent_contract.py +0 -0
  416. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_instruction_describes_its_own_reply.py +0 -0
  417. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_precondition.py +0 -0
  418. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_setup_writes_a_valid_config.py +0 -0
  419. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_shell_declarations.py +0 -0
  420. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_shell_metrics.py +0 -0
  421. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_skill_install.py +0 -0
  422. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_sonar_resolve.py +0 -0
  423. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_source_index.py +0 -0
  424. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_spotbugs_adapter.py +0 -0
  425. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_spotbugs_catalog.py +0 -0
  426. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_stage8_contract.py +0 -0
  427. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_stamped_documents_stay_honest.py +0 -0
  428. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_stdout_outputs.py +0 -0
  429. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_suite_isolation.py +0 -0
  430. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_swift_declarations.py +0 -0
  431. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_tdd_structure.py +0 -0
  432. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_terminal_asks_the_same_questions.py +0 -0
  433. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_test_commands.py +0 -0
  434. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_test_execution_class.py +0 -0
  435. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_agent_knows_when_it_is_stale.py +0 -0
  436. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_changelog_covers_the_shipping_version.py +0 -0
  437. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_chat_payload_has_a_budget.py +0 -0
  438. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_condition_says_what_it_measured.py +0 -0
  439. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_handoff_rules_are_their_own_module.py +0 -0
  440. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_pillar_row_reads_cleanly.py +0 -0
  441. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_presentation_question_stays_answerable.py +0 -0
  442. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_prompt_does_not_take_back_what_it_withheld.py +0 -0
  443. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_prompt_keeps_listing_what_it_did_not_withhold.py +0 -0
  444. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_release_process_describes_itself.py +0 -0
  445. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_release_record_stays_well_formed.py +0 -0
  446. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_report_is_saved_not_sent.py +0 -0
  447. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_security_run_has_a_configurable_limit.py +0 -0
  448. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_security_work_order_is_drawn.py +0 -0
  449. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_suite_names_the_program_it_ran.py +0 -0
  450. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_tree_cannot_redirect_a_read.py +0 -0
  451. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_the_version_has_one_source.py +0 -0
  452. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_three_presentations.py +0 -0
  453. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_tool_resolution.py +0 -0
  454. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
  455. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_tree_chosen_spawn.py +0 -0
  456. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_tree_reads_use_the_primitive.py +0 -0
  457. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_trends.py +0 -0
  458. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_type_fields_not_functions_class.py +0 -0
  459. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_uat_falsifiers.py +0 -0
  460. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_unanchored_set_matches_corpus.py +0 -0
  461. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_unread_code.py +0 -0
  462. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_user_config_tier.py +0 -0
  463. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_verification_audit_closures.py +0 -0
  464. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_verified_grade.py +0 -0
  465. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_version_claim.py +0 -0
  466. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_version_stamping.py +0 -0
  467. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_wheel_contents.py +0 -0
  468. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_withheld_work_keeps_its_boundary.py +0 -0
  469. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_work_items_state_their_own_finding.py +0 -0
  470. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_work_order.py +0 -0
  471. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
  472. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_work_order_items.py +0 -0
  473. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_work_order_selection.py +0 -0
  474. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_workflow_supply_chain.py +0 -0
  475. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_write_boundary.py +0 -0
  476. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_write_route_class.py +0 -0
  477. {maintainability_agent-4.3.1 → maintainability_agent-4.4.1}/tests/test_written_record.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 4.3.1
3
+ Version: 4.4.1
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -37,7 +37,7 @@ Requires-Dist: mcp<3,>=2; extra == "dev"
37
37
  Requires-Dist: PyYAML>=6; extra == "dev"
38
38
  Requires-Dist: setuptools>=70; extra == "dev"
39
39
  Requires-Dist: lizard>=1.17; extra == "dev"
40
- Requires-Dist: markdown>=3.5; extra == "dev"
40
+ Requires-Dist: markdown==3.11.1; extra == "dev"
41
41
  Dynamic: license-file
42
42
 
43
43
  # Maintainability Agent
@@ -47,7 +47,7 @@ Dynamic: license-file
47
47
  **A deterministic, offline maintainability audit whose output is a _bounded
48
48
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
49
49
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
50
- Version **4.3.1**.
50
+ Version **4.4.1**.
51
51
 
52
52
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
53
53
  >
@@ -372,8 +372,11 @@ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
372
372
  The analyzer is intentionally conservative and under-reports rather than
373
373
  over-reports: an unrecognized declaration costs one missed finding, never a
374
374
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
375
- SonarQube, Qlty) rather than replacing them — their SARIF folds in via
376
- `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
375
+ SonarQube, Qlty) rather than replacing them. This tool runs a pinned handful of
376
+ the analyzers it catalogs; the rest run where you already run them, and their
377
+ SARIF is read, never run: declare each file in `analyzers.pipeline_results`
378
+ with the concerns it covers (first-run setup asks), and those concerns count as
379
+ examined for the languages it names. One-off files fold in via `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
377
380
 
378
381
  ## Language support
379
382
 
@@ -509,7 +512,7 @@ instead of an invokable skill:
509
512
  This repo ships `action.yml`, usable as a composite action:
510
513
 
511
514
  ```yaml
512
- - uses: marshallguillory86/maintainability-agent@v4.3.1
515
+ - uses: marshallguillory86/maintainability-agent@v4.4.1
513
516
  with:
514
517
  config: maintainability-agent.json
515
518
  changed-only: main...HEAD
@@ -5,7 +5,7 @@
5
5
  **A deterministic, offline maintainability audit whose output is a _bounded
6
6
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
7
7
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
8
- Version **4.3.1**.
8
+ Version **4.4.1**.
9
9
 
10
10
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
11
11
  >
@@ -330,8 +330,11 @@ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
330
330
  The analyzer is intentionally conservative and under-reports rather than
331
331
  over-reports: an unrecognized declaration costs one missed finding, never a
332
332
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
333
- SonarQube, Qlty) rather than replacing them — their SARIF folds in via
334
- `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
333
+ SonarQube, Qlty) rather than replacing them. This tool runs a pinned handful of
334
+ the analyzers it catalogs; the rest run where you already run them, and their
335
+ SARIF is read, never run: declare each file in `analyzers.pipeline_results`
336
+ with the concerns it covers (first-run setup asks), and those concerns count as
337
+ examined for the languages it names. One-off files fold in via `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
335
338
 
336
339
  ## Language support
337
340
 
@@ -467,7 +470,7 @@ instead of an invokable skill:
467
470
  This repo ships `action.yml`, usable as a composite action:
468
471
 
469
472
  ```yaml
470
- - uses: marshallguillory86/maintainability-agent@v4.3.1
473
+ - uses: marshallguillory86/maintainability-agent@v4.4.1
471
474
  with:
472
475
  config: maintainability-agent.json
473
476
  changed-only: main...HEAD
@@ -63,7 +63,10 @@ mcp = ["mcp>=2,<3"]
63
63
  # ships imports it, and the oracle exists so a measurement can be
64
64
  # checked against something other than its author. `markdown` renders the
65
65
  # docs/html reading copy (`tools/render_docs.py`); the product never does.
66
- dev = ["pytest>=8", "pytest-cov>=5", "pytest-xdist>=3.6", "jsonschema>=4", "ruff>=0.5", "pip-audit>=2.7", "mcp>=2,<3", "PyYAML>=6", "setuptools>=70", "lizard>=1.17", "markdown>=3.5"]
66
+ # It is pinned exactly: the committed copy is checked against a fresh render,
67
+ # and markdown 3.11 rendered two pages differently from 3.10, so an unpinned
68
+ # release failed CI on files nobody had touched (2026-10-14).
69
+ dev = ["pytest>=8", "pytest-cov>=5", "pytest-xdist>=3.6", "jsonschema>=4", "ruff>=0.5", "pip-audit>=2.7", "mcp>=2,<3", "PyYAML>=6", "setuptools>=70", "lizard>=1.17", "markdown==3.11.1"]
67
70
 
68
71
  [tool.pydocstyle]
69
72
  # D401 ("First line should be in imperative mood") is switched off, and the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 4.3.1
3
+ Version: 4.4.1
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -37,7 +37,7 @@ Requires-Dist: mcp<3,>=2; extra == "dev"
37
37
  Requires-Dist: PyYAML>=6; extra == "dev"
38
38
  Requires-Dist: setuptools>=70; extra == "dev"
39
39
  Requires-Dist: lizard>=1.17; extra == "dev"
40
- Requires-Dist: markdown>=3.5; extra == "dev"
40
+ Requires-Dist: markdown==3.11.1; extra == "dev"
41
41
  Dynamic: license-file
42
42
 
43
43
  # Maintainability Agent
@@ -47,7 +47,7 @@ Dynamic: license-file
47
47
  **A deterministic, offline maintainability audit whose output is a _bounded
48
48
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
49
49
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
50
- Version **4.3.1**.
50
+ Version **4.4.1**.
51
51
 
52
52
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
53
53
  >
@@ -372,8 +372,11 @@ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
372
372
  The analyzer is intentionally conservative and under-reports rather than
373
373
  over-reports: an unrecognized declaration costs one missed finding, never a
374
374
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
375
- SonarQube, Qlty) rather than replacing them — their SARIF folds in via
376
- `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
375
+ SonarQube, Qlty) rather than replacing them. This tool runs a pinned handful of
376
+ the analyzers it catalogs; the rest run where you already run them, and their
377
+ SARIF is read, never run: declare each file in `analyzers.pipeline_results`
378
+ with the concerns it covers (first-run setup asks), and those concerns count as
379
+ examined for the languages it names. One-off files fold in via `--sarif-input`. Accuracy and limits: [docs/language-support.md](docs/language-support.md).
377
380
 
378
381
  ## Language support
379
382
 
@@ -509,7 +512,7 @@ instead of an invokable skill:
509
512
  This repo ships `action.yml`, usable as a composite action:
510
513
 
511
514
  ```yaml
512
- - uses: marshallguillory86/maintainability-agent@v4.3.1
515
+ - uses: marshallguillory86/maintainability-agent@v4.4.1
513
516
  with:
514
517
  config: maintainability-agent.json
515
518
  changed-only: main...HEAD
@@ -69,6 +69,7 @@ src/maintainability_audit/_metrics_types.py
69
69
  src/maintainability_audit/_operator_reads.py
70
70
  src/maintainability_audit/_oracle.py
71
71
  src/maintainability_audit/_pillars.py
72
+ src/maintainability_audit/_pipeline_results.py
72
73
  src/maintainability_audit/_practice.py
73
74
  src/maintainability_audit/_precommit.py
74
75
  src/maintainability_audit/_precommit_install.py
@@ -181,6 +182,7 @@ tests/test_analyzer_scoring_path.py
181
182
  tests/test_analyzer_spread_range.py
182
183
  tests/test_analyzer_xml_bounds.py
183
184
  tests/test_analyzers_against_the_real_tools.py
185
+ tests/test_analyzers_never_write.py
184
186
  tests/test_analyzers_report_what_actually_failed.py
185
187
  tests/test_anchor_and_mode.py
186
188
  tests/test_anchor_caveat_and_counts_follow_the_run.py
@@ -353,6 +355,7 @@ tests/test_pattern_budget.py
353
355
  tests/test_phase6_claims.py
354
356
  tests/test_php_declarations.py
355
357
  tests/test_pillars_and_practice.py
358
+ tests/test_pipeline_results.py
356
359
  tests/test_platform_claim.py
357
360
  tests/test_pmd_adapter.py
358
361
  tests/test_pmd_audit_closures.py
@@ -381,6 +384,7 @@ tests/test_release_plan.py
381
384
  tests/test_release_plan_status.py
382
385
  tests/test_rendered_docs.py
383
386
  tests/test_report_remedy_copy.py
387
+ tests/test_reported_but_not_scored.py
384
388
  tests/test_root_grants.py
385
389
  tests/test_rubric_ignores_project_lint_config.py
386
390
  tests/test_ruby_declarations.py
@@ -10,7 +10,7 @@ mcp<3,>=2
10
10
  PyYAML>=6
11
11
  setuptools>=70
12
12
  lizard>=1.17
13
- markdown>=3.5
13
+ markdown==3.11.1
14
14
 
15
15
  [mcp]
16
16
  mcp<3,>=2
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "4.3.1"
3
+ __version__ = "4.4.1"
@@ -19,6 +19,7 @@ clean result.
19
19
 
20
20
  from __future__ import annotations
21
21
 
22
+ import hashlib
22
23
  from collections.abc import Sequence
23
24
  from dataclasses import dataclass, field, replace
24
25
  from pathlib import Path
@@ -40,6 +41,11 @@ from ._metrics_types import KNOWN_SOURCE_SUFFIXES, Finding, Measurement
40
41
  from ._runner import Outcome, Probe, ToolResult, run
41
42
  from ._selection import Selected, select_runnable
42
43
  from .config import acquisition_permitted
44
+ from .git_tools import GitCommandFailed, probe_git, run_git
45
+
46
+ #: Sources outside this package: an analyzer it ran, or a file the
47
+ #: developer's own pipeline wrote (Decision 17). Built-ins are not here.
48
+ EXTERNAL_TIERS = ("analyzer", "pipeline")
43
49
 
44
50
 
45
51
  @dataclass(frozen=True)
@@ -152,7 +158,7 @@ class Analysis:
152
158
  """
153
159
  covered: dict[str, set[str]] = {name: set() for name in self.languages}
154
160
  for item in self.coverage:
155
- if not item.contributed or item.tier != "analyzer":
161
+ if not item.contributed or item.tier not in EXTERNAL_TIERS:
156
162
  continue
157
163
  concerns = self._concerns_of(item.concepts)
158
164
  for name, slug in self.languages.items():
@@ -217,7 +223,7 @@ class Analysis:
217
223
  if name in self.scored_languages
218
224
  ]
219
225
  if not scored:
220
- return self._concerns_from("analyzer")
226
+ return self._concerns_from("analyzer") | self._concerns_from("pipeline")
221
227
  return set.intersection(*scored)
222
228
 
223
229
  def single_source_concerns(self) -> list[str]:
@@ -352,6 +358,43 @@ def analyze(root: Path, config: dict[str, Any], probe: Probe | None = None) -> A
352
358
  return analysis
353
359
 
354
360
 
361
+ class RepositoryModifiedError(Exception):
362
+ """An analyzer changed the repository it was auditing.
363
+
364
+ The audit never edits source. A tool that writes to the audited tree
365
+ (ruff honouring a repository's `fix = true` rewrote 102 files of
366
+ an audited repository on 2026-10-14) fails the audit loudly rather than handing back
367
+ a grade for code that is no longer what was audited.
368
+ """
369
+
370
+
371
+ def _tracked_state(root: Path) -> dict[str, str] | None:
372
+ """Each tracked file that differs from HEAD, by a hash of its diff.
373
+
374
+ None when `root` is not a git work tree: there is nothing to compare
375
+ against, so nothing is claimed.
376
+ """
377
+ if not probe_git(["rev-parse", "--is-inside-work-tree"], root):
378
+ return None
379
+ try:
380
+ diff = run_git(["diff", "HEAD", "--no-ext-diff", "--binary"], root, strip=False)
381
+ except GitCommandFailed:
382
+ return None
383
+ state: dict[str, str] = {}
384
+ for block in diff.split("\ndiff --git "):
385
+ if not block.strip():
386
+ continue
387
+ header = block.split("\n", 1)[0].removeprefix("diff --git ")
388
+ name = header.split(" b/", 1)[-1]
389
+ state[name] = hashlib.sha256(block.encode("utf-8", "replace")).hexdigest()
390
+ return state
391
+
392
+
393
+ def _changed_paths(before: dict[str, str], after: dict[str, str]) -> list[str]:
394
+ return sorted(path for path in set(before) | set(after)
395
+ if before.get(path) != after.get(path))
396
+
397
+
355
398
  def _run_one(root: Path, adapter: Any, probe: Probe, timeout: int,
356
399
  analysis: Analysis, excludes: Sequence[str] = (),
357
400
  inventory: Any = None) -> ToolCoverage:
@@ -367,6 +410,9 @@ def _run_one(root: Path, adapter: Any, probe: Probe, timeout: int,
367
410
  """
368
411
  try:
369
412
  return _attempt(root, adapter, probe, timeout, analysis, excludes, inventory)
413
+ except RepositoryModifiedError:
414
+ # Not an adapter defect to record quietly: the audited tree changed.
415
+ raise
370
416
  except Exception as error: # noqa: BLE001 - the backstop is the point
371
417
  return ToolCoverage(
372
418
  slug=adapter.slug, outcome="failed", concepts=tuple(adapter.concepts),
@@ -490,12 +536,19 @@ def _run_batches(adapter: Any, root: Path, excludes: Sequence[str],
490
536
  invocations = planned(root, excludes) if planned else [adapter.invocation(root, excludes=excludes)]
491
537
  results: list[ToolResult] = []
492
538
  parsed: list[Extraction] = []
539
+ before = _tracked_state(root)
493
540
  for invocation in invocations:
494
541
  result = run(adapter.slug, invocation, timeout_seconds=timeout)
495
542
  results.append(result)
496
543
  parsed.append(adapter.parse(result))
497
544
  if not result.usable:
498
545
  break
546
+ after = _tracked_state(root) if before is not None else None
547
+ if before is not None and after is not None and after != before:
548
+ changed = _changed_paths(before, after)
549
+ raise RepositoryModifiedError(
550
+ f"{adapter.slug} modified the audited repository: {', '.join(changed)}. "
551
+ "The audit never edits source; restore these files and report the adapter.")
499
552
  if len(results) == 1:
500
553
  return results[0], parsed[0]
501
554
  return _merged_result(results, len(invocations)), _merged_extraction(parsed)
@@ -12,7 +12,7 @@ from pathlib import Path
12
12
  from typing import Any
13
13
 
14
14
  from ._analysis import analyze
15
- from ._criteria_scope import built_in_readings
15
+ from ._criteria_scope import built_in_readings, reported_not_scored
16
16
  from ._documents import (
17
17
  coverage_document,
18
18
  findings_document,
@@ -21,6 +21,7 @@ from ._documents import (
21
21
  )
22
22
  from ._environment import environment_work_order
23
23
  from ._metrics_types import FunctionMetric
24
+ from ._pipeline_results import add_pipeline_results
24
25
  from ._pressures import (
25
26
  ExternalPressures,
26
27
  analyzer_pressures,
@@ -46,6 +47,9 @@ def analyzer_sections(
46
47
  return {"coverage": None, "findings": [], "measurements": {},
47
48
  "pressures": None, "environment": []}
48
49
  analysis = analyze(root, config)
50
+ # Decision 17: the files the developer's own pipeline wrote, read
51
+ # beside what this run's analyzers produced.
52
+ add_pipeline_results(analysis, root, config)
49
53
  coverage = coverage_document(analysis)
50
54
  # P8: where the analyzer tier could not drive a dimension, say so on
51
55
  # the coverage document rather than leaving the built-in fallback to
@@ -58,6 +62,7 @@ def analyzer_sections(
58
62
  built_in = built_in_readings(function_metrics, prefix)
59
63
  coverage["dimensions_declined"] = list(
60
64
  declined_dimensions(analysis.measurements, False, built_in, prefix))
65
+ coverage["reported_not_scored"] = reported_not_scored(coverage)
61
66
  return {
62
67
  "coverage": coverage,
63
68
  # ADR 006 §2c: what did not run and what it would take, for the
@@ -166,9 +166,40 @@ def settings_from(config: dict[str, Any]) -> dict[str, Any]:
166
166
  if unknown:
167
167
  raise PolicyError(f"unknown concerns {sorted(unknown)}; expected from {list(CONCERNS)}")
168
168
  settings["timeout_seconds"] = _bounded_timeout(settings["timeout_seconds"])
169
+ settings["pipeline_results"] = _pipeline_results(settings.get("pipeline_results"))
169
170
  return settings
170
171
 
171
172
 
173
+ def pipeline_results_from_answer(answer: str) -> list[dict[str, Any]]:
174
+ """The first-run answer, `path: concern, concern; path: concern`, as declarations."""
175
+ entries = []
176
+ for part in (answer or "").split(";"):
177
+ if not part.strip():
178
+ continue
179
+ path, _, covers = part.partition(":")
180
+ entries.append({"path": path.strip(),
181
+ "covers": [c.strip() for c in covers.split(",") if c.strip()]})
182
+ return _pipeline_results(entries)
183
+
184
+
185
+ def _pipeline_results(declared: Any) -> list[dict[str, Any]]:
186
+ """Each file the developer's pipeline writes, and what it covers (Decision 17).
187
+
188
+ Refused rather than skipped: a declaration that silently examined
189
+ nothing would leave a concern unexamined with the operator believing
190
+ it covered.
191
+ """
192
+ entries = list(declared or [])
193
+ for entry in entries:
194
+ if not isinstance(entry, dict) or not isinstance(entry.get("path"), str) or not entry["path"]:
195
+ raise PolicyError(f"analyzers.pipeline_results entry {entry!r} needs a `path`")
196
+ covers = entry.get("covers")
197
+ if not covers or not isinstance(covers, list) or set(covers) - set(CONCERNS):
198
+ raise PolicyError(
199
+ f"analyzers.pipeline_results {entry['path']!r} needs `covers` from {list(CONCERNS)}")
200
+ return entries
201
+
202
+
172
203
  #: The widest per-analyzer wall clock a configured value may ask for. An
173
204
  #: hour is far past any real analyzer on any real tree and still bounds
174
205
  #: the host against a repository config that names a number designed
@@ -48,6 +48,17 @@ def coverage_notes(coverage: dict[str, Any]) -> list[str]:
48
48
  "",
49
49
  ])
50
50
 
51
+ for unused in coverage.get("reported_not_scored") or []:
52
+ # The count sits in the findings beside a grade computed from
53
+ # something else; without this a reader takes it as ignored.
54
+ lines.extend([
55
+ f"**`{unused['tool']}` reported {unused['findings']} `{unused['concept']}` "
56
+ f"findings; they are listed and their count does not move the grade:** the "
57
+ f"`{unused['dimension']}` dimension is scored from the built-in "
58
+ "detectors only.",
59
+ "",
60
+ ])
61
+
51
62
  unexamined = coverage["concepts_unexamined"]
52
63
  if unexamined:
53
64
  # The point of the whole section. Silence about a concern is not
@@ -56,7 +67,8 @@ def coverage_notes(coverage: dict[str, Any]) -> list[str]:
56
67
  "**Nothing examined:** " + ", ".join(f"`{c}`" for c in unexamined) + ".",
57
68
  "",
58
69
  "These concerns are unmeasured, not clean. Install a tool that covers them, "
59
- "or widen `analyzers.depth`, to have them reported.",
70
+ "widen `analyzers.depth`, or declare the SARIF your own build or pipeline "
71
+ "already writes in `analyzers.pipeline_results` to have them reported.",
60
72
  "",
61
73
  ])
62
74
 
@@ -40,6 +40,29 @@ DECLARATION_CRITERIA: tuple[tuple[str, str, str], ...] = (
40
40
  # `risk` and `gates` are configured policy with no external equivalent.
41
41
  ANALYZER_DIMENSIONS: tuple[str, ...] = ("declarations",)
42
42
 
43
+ # Concepts an analyzer can report whose dimension is scored from the
44
+ # built-in detectors only. Their findings are listed, never scored.
45
+ BUILT_IN_SCORED_CONCEPTS: dict[str, str] = {"duplication": "duplication", "file_lines": "file_size"}
46
+
47
+
48
+ def reported_not_scored(coverage: dict) -> list[dict]:
49
+ """Analyzer findings listed in the report that do not move the grade.
50
+
51
+ A field report on a C# repository read jscpd's 439 duplicate blocks,
52
+ listed beside a duplication grade computed from the built-in detector,
53
+ as the analyzer's output being ignored. The design was right and the
54
+ page did not say it (P8).
55
+ """
56
+ return [
57
+ {"tool": entry["tool"], "concept": concept,
58
+ "dimension": BUILT_IN_SCORED_CONCEPTS[concept], "findings": entry["findings"]}
59
+ for entry in (coverage.get("by_outcome") or {}).get("ran", [])
60
+ if entry.get("tier") == "analyzer" and entry.get("findings")
61
+ for concept in entry.get("concepts", [])
62
+ if concept in BUILT_IN_SCORED_CONCEPTS
63
+ and BUILT_IN_SCORED_CONCEPTS[concept] not in ANALYZER_DIMENSIONS
64
+ ]
65
+
43
66
 
44
67
  def declaration_concepts_missing(covered: set[str]) -> tuple[str, ...]:
45
68
  """Criteria the analyzers did not supply, in rubric order.
@@ -111,6 +111,7 @@ def maybe_prompt_first_run(root: Path, explicit_config: str | None) -> None:
111
111
  "Add the economic scenario (loaded labor rate per hour) beside "
112
112
  "the score? Skip leaves money out of reports. "
113
113
  "(include/skip) [skip]: ", ("include", "skip"), "skip"),
114
+ "pipeline_results": _ask_pipeline_results(), # Decision 17
114
115
  }
115
116
  apply_answers(root, answers)
116
117
  print(f"Wrote {root / CONFIG_FILENAME}")
@@ -338,3 +339,27 @@ def _record_test_command(root: Path, config: dict, answer: str) -> None:
338
339
  if not answer:
339
340
  config["test_execution"] = {"requested": False}
340
341
  print(f"Wrote {target}")
342
+
343
+
344
+ def _ask_pipeline_results() -> str:
345
+ """Whether the developer's own pipeline writes SARIF; the files are the
346
+ second stage, `maybe_prompt_pipeline_files` (Decision 17)."""
347
+ from ._mcp_setup import pipeline_results_question
348
+
349
+ return _ask(pipeline_results_question()["prompt"] + " (none/declare) [none]: ",
350
+ ("none", "declare"), "none")
351
+
352
+
353
+ def maybe_prompt_pipeline_files(root: Path, config: dict) -> dict:
354
+ """The CLI half of the Decision 17 second stage: at a TTY, after `declare`.
355
+
356
+ Returns the configuration this run should use, so files declared at the
357
+ prompt are read by the audit that asked for them.
358
+ """
359
+ from ._mcp_setup import pipeline_files_pending, pipeline_files_questions
360
+ from ._setup_persist import _apply_pipeline_files
361
+
362
+ if not _stdin_is_a_tty() or not pipeline_files_pending(root):
363
+ return config
364
+ answer = input(pipeline_files_questions()[0]["prompt"] + " ").strip()
365
+ return _apply_pipeline_files(root, {"pipeline_files": answer})
@@ -18,6 +18,7 @@ D48.
18
18
 
19
19
  from __future__ import annotations
20
20
 
21
+ from ._analysis import RepositoryModifiedError
21
22
  from ._catalog import PolicyError
22
23
  from ._mcp_audit import InvalidAuditArgument, PathNotAllowed
23
24
  from ._mcp_setup import SetupRequired
@@ -37,6 +38,11 @@ ANTICIPATED_REFUSALS = (
37
38
  # type and `PathNotAllowed` both derive from it alongside the
38
39
  # internal ones that must stay crashes.
39
40
  ConfigUnreadable,
41
+ # An analyzer changed the audited repository. The message names the
42
+ # changed files and says to report the adapter: actionable, and a
43
+ # grade must never be returned for code that is no longer what was
44
+ # audited.
45
+ RepositoryModifiedError,
40
46
  )
41
47
 
42
48
  __all__ = ["ANTICIPATED_REFUSALS"]
@@ -28,13 +28,14 @@ from __future__ import annotations
28
28
  from pathlib import Path
29
29
  from typing import Any
30
30
 
31
- from ._catalog import LICENSE_POLICIES, PRESENTATIONS
31
+ from ._catalog import CONCERNS, LICENSE_POLICIES, PRESENTATIONS
32
32
  from ._setup_errors import SetupRequired as SetupRequired
33
33
  from ._setup_persist import (
34
34
  BOUNDS,
35
35
  _accepted,
36
36
  _apply_bounds,
37
37
  _apply_command,
38
+ _apply_pipeline_files,
38
39
  _economics_block,
39
40
  _is_bounds_only,
40
41
  _is_command_only,
@@ -88,6 +89,7 @@ def setup_questions(config: dict[str, Any]) -> list[dict[str, Any]]:
88
89
  },
89
90
  *_economics_questions(),
90
91
  *run_tests_question(),
92
+ pipeline_results_question(),
91
93
  {
92
94
  "name": "default_format",
93
95
  "prompt": "Default report presentation for this user.",
@@ -112,6 +114,48 @@ def setup_questions(config: dict[str, Any]) -> list[dict[str, Any]]:
112
114
  ]
113
115
 
114
116
 
117
+ def pipeline_results_question() -> dict[str, Any]:
118
+ """Whether the developer's own pipeline writes analyzer results (Decision 17).
119
+
120
+ A choice, like every first-stage question; the files are the second
121
+ stage, asked only on `declare`. This tool runs a pinned handful of the
122
+ catalog, and the rest are run where they already run and read here.
123
+ """
124
+ return {
125
+ "name": "pipeline_results",
126
+ "prompt": (
127
+ "Does your own build or pipeline already write analyzer results as "
128
+ "SARIF (Roslyn analyzers, Semgrep, CodeQL...)? Declare names the files "
129
+ "next; this reads them and never runs the tools."
130
+ ),
131
+ "options": ["none", "declare"],
132
+ "default": "none",
133
+ }
134
+
135
+
136
+ def pipeline_files_questions() -> list[dict[str, Any]]:
137
+ """The files, asked only of someone who said `declare`."""
138
+ return [{
139
+ "name": "pipeline_files",
140
+ "prompt": (
141
+ "Each SARIF file and the concerns it covers, from "
142
+ + ", ".join(CONCERNS) + " — e.g. `artifacts/roslyn.sarif: style, "
143
+ "documentation, dead-code`; separate files with `;`. Paths are "
144
+ "relative to the repository. Blank cancels."
145
+ ),
146
+ "options": [],
147
+ "default": "",
148
+ }]
149
+
150
+
151
+ def pipeline_files_pending(root: Path) -> bool:
152
+ """`declare` was answered and no file is declared yet."""
153
+ discovered = discovered_config(Path(root))
154
+ stored = _read_config(Path(discovered)) if discovered is not None else None
155
+ analyzers = (stored or {}).get("analyzers") or {}
156
+ return bool(analyzers.get("pipeline_requested")) and not analyzers.get("pipeline_results")
157
+
158
+
115
159
  def economics_bound_questions() -> list[dict[str, Any]]:
116
160
  """The three rates, asked only of someone who said yes to the gate."""
117
161
  return [
@@ -179,6 +223,8 @@ def published_questions(root: Path | None = None) -> dict[str, dict[str, Any]]:
179
223
  questions[question["name"]] = question
180
224
  for question in test_command_questions(root):
181
225
  questions[question["name"]] = question
226
+ for question in pipeline_files_questions():
227
+ questions[question["name"]] = question
182
228
  return questions
183
229
 
184
230
 
@@ -248,6 +294,7 @@ def submittable_answer_names() -> frozenset[str]:
248
294
  names = {question["name"] for question in setup_questions({})}
249
295
  names.update(name for name, _, _ in BOUNDS)
250
296
  names.add("test_command")
297
+ names.add("pipeline_files")
251
298
  return frozenset(names)
252
299
 
253
300
 
@@ -258,6 +305,8 @@ def apply_answers(root: Path, answers: dict[str, Any]) -> dict[str, Any]:
258
305
  return _apply_bounds(root, answers)
259
306
  if _is_command_only(answers):
260
307
  return _apply_command(root, answers)
308
+ if set(k for k, v in answers.items() if v is not None) == {"pipeline_files"}:
309
+ return _apply_pipeline_files(root, answers)
261
310
  payload: dict[str, Any] = {
262
311
  "version": 1,
263
312
  "analyzers": {
@@ -272,6 +321,8 @@ def apply_answers(root: Path, answers: dict[str, Any]) -> dict[str, Any]:
272
321
  # suite; the command is a staged second ask.
273
322
  "test_execution": {"requested": _accepted(answers.get("run_tests", "no"))},
274
323
  }
324
+ if answers.get("pipeline_results") == "declare":
325
+ payload["analyzers"]["pipeline_requested"] = True
275
326
  economics = _economics_block(answers)
276
327
  if economics is not None:
277
328
  payload["economic_context"] = economics
@@ -406,7 +457,8 @@ def setup_pending(root: Path) -> bool:
406
457
  # rates for someone who wanted the scenario, or the test command for
407
458
  # someone who opted to run the suite. Both are stage two of an ask
408
459
  # already begun, not a new one.
409
- return economics_bounds_pending(root) or test_command_pending(root)
460
+ return (economics_bounds_pending(root) or test_command_pending(root)
461
+ or pipeline_files_pending(root))
410
462
  # No repository file: the person's answers carry to it (first-run.md),
411
463
  # and it is asked only what is its own — its test command (Decision 4).
412
464
  return user_config_answers() is None or test_command_pending(root)
@@ -465,6 +517,8 @@ def staged_questions(root: Path | None = None) -> list[dict[str, Any]]:
465
517
  return economics_bound_questions()
466
518
  if root is not None and test_command_pending(root):
467
519
  return test_command_questions(root)
520
+ if root is not None and pipeline_files_pending(root):
521
+ return pipeline_files_questions()
468
522
  return setup_questions(load_config(None))
469
523
 
470
524