maintainability-agent 4.1.0__tar.gz → 4.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. {maintainability_agent-4.1.0/src/maintainability_agent.egg-info → maintainability_agent-4.3.0}/PKG-INFO +17 -4
  2. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/README.md +16 -3
  3. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0/src/maintainability_agent.egg-info}/PKG-INFO +17 -4
  4. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_agent.egg-info/SOURCES.txt +7 -0
  5. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/__init__.py +1 -1
  6. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_adapters.py +46 -1
  7. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_analysis.py +19 -0
  8. maintainability_agent-4.3.0/src/maintainability_audit/_changed_code_policy.py +98 -0
  9. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_gates.py +2 -1
  10. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_html_view.py +25 -4
  11. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_audit.py +3 -1
  12. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_metric_adapters.py +6 -4
  13. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_operator_reads.py +3 -1
  14. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ratio_adapters.py +4 -1
  15. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/config.py +21 -2
  16. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/renderers.py +25 -4
  17. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/report.py +31 -8
  18. maintainability_agent-4.3.0/tests/test_a_rendered_docs_site_is_not_scored_as_source.py +61 -0
  19. maintainability_agent-4.3.0/tests/test_analyzers_against_the_real_tools.py +42 -0
  20. maintainability_agent-4.3.0/tests/test_analyzers_report_what_actually_failed.py +108 -0
  21. maintainability_agent-4.3.0/tests/test_changed_code_policy.py +137 -0
  22. maintainability_agent-4.3.0/tests/test_exclude_additional_keeps_the_defaults.py +53 -0
  23. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_readme_claims.py +16 -0
  24. maintainability_agent-4.3.0/tests/test_regular_file_reads_work_without_o_nonblock.py +28 -0
  25. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/LICENSE +0 -0
  26. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/pyproject.toml +0 -0
  27. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/setup.cfg +0 -0
  28. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  29. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  30. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
  31. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  32. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/__main__.py +0 -0
  33. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_analyzer_sections.py +0 -0
  34. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_anchor.py +0 -0
  35. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_arguments.py +0 -0
  36. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_aspects.py +0 -0
  37. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  38. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_assets/standard.md +0 -0
  39. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_attestation.py +0 -0
  40. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_backfill.py +0 -0
  41. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_bands.py +0 -0
  42. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_banner.py +0 -0
  43. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_built_ins.py +0 -0
  44. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_calibration.py +0 -0
  45. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_catalog.py +0 -0
  46. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_charts.py +0 -0
  47. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_cognitive.py +0 -0
  48. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_config_defaults.py +0 -0
  49. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_conformance.py +0 -0
  50. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_corroborate.py +0 -0
  51. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_coverage_notes.py +0 -0
  52. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_criteria_scope.py +0 -0
  53. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_delegated_pillar.py +0 -0
  54. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_derive.py +0 -0
  55. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_discovery.py +0 -0
  56. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_documents.py +0 -0
  57. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_economics.py +0 -0
  58. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_economics_view.py +0 -0
  59. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_environment.py +0 -0
  60. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_evidence_reader.py +0 -0
  61. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_evidence_view.py +0 -0
  62. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_finding_match.py +0 -0
  63. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_first_run.py +0 -0
  64. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_formula.py +0 -0
  65. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_generic.py +0 -0
  66. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_grammar.py +0 -0
  67. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_grant_ledger.py +0 -0
  68. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_handoff.py +0 -0
  69. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_history_view.py +0 -0
  70. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
  71. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_hotspots.py +0 -0
  72. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_html_report_sections.py +0 -0
  73. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_identity.py +0 -0
  74. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_in_loop.py +0 -0
  75. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_in_loop_view.py +0 -0
  76. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
  77. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_markdown_sections.py +0 -0
  78. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_masking.py +0 -0
  79. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_gate.py +0 -0
  80. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_grants.py +0 -0
  81. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
  82. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_resources.py +0 -0
  83. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_mcp_setup.py +0 -0
  84. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_metrics_types.py +0 -0
  85. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_oracle.py +0 -0
  86. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_pillars.py +0 -0
  87. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_practice.py +0 -0
  88. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_precommit.py +0 -0
  89. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_precommit_install.py +0 -0
  90. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_precommit_view.py +0 -0
  91. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_pressures.py +0 -0
  92. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_prompt_sections.py +0 -0
  93. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_c.py +0 -0
  94. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
  95. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_core.py +0 -0
  96. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
  97. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
  98. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
  99. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_go.py +0 -0
  100. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_java.py +0 -0
  101. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_js.py +0 -0
  102. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_kotlin.py +0 -0
  103. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_php.py +0 -0
  104. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_ruby.py +0 -0
  105. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_rust.py +0 -0
  106. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_shell.py +0 -0
  107. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ranges_swift.py +0 -0
  108. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_ratchet.py +0 -0
  109. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_recurrence.py +0 -0
  110. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_run_comparison.py +0 -0
  111. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_runner.py +0 -0
  112. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_running_version.py +0 -0
  113. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_safe_write.py +0 -0
  114. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_scan_history.py +0 -0
  115. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_scan_view.py +0 -0
  116. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_second_source.py +0 -0
  117. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_security_delegate.py +0 -0
  118. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_security_work_order.py +0 -0
  119. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_selection.py +0 -0
  120. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_semantic.py +0 -0
  121. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_semantic_policy.py +0 -0
  122. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_semantic_ts.py +0 -0
  123. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_semantic_view.py +0 -0
  124. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_setup_errors.py +0 -0
  125. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_setup_persist.py +0 -0
  126. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  127. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  128. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  129. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  130. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  131. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  132. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_skill_install.py +0 -0
  133. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_stored_grants.py +0 -0
  134. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_tdd_view.py +0 -0
  135. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_test_commands.py +0 -0
  136. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_test_execution.py +0 -0
  137. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_test_pairing.py +0 -0
  138. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_tokens.py +0 -0
  139. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_tool_adapters.py +0 -0
  140. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_trends.py +0 -0
  141. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_user_config.py +0 -0
  142. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
  143. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_verification.py +0 -0
  144. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_work_order.py +0 -0
  145. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_work_order_view.py +0 -0
  146. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_work_order_weights.py +0 -0
  147. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/_xml.py +0 -0
  148. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/baseline.py +0 -0
  149. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/cli.py +0 -0
  150. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/deadcode.py +0 -0
  151. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/declarations.py +0 -0
  152. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/duplication.py +0 -0
  153. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/evidence.py +0 -0
  154. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/git_tools.py +0 -0
  155. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/history.py +0 -0
  156. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/idioms.py +0 -0
  157. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/instructions.py +0 -0
  158. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/mcp_server.py +0 -0
  159. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/metrics.py +0 -0
  160. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/prompts.py +0 -0
  161. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/sarif.py +0 -0
  162. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/scoring.py +0 -0
  163. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/similarity.py +0 -0
  164. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/src/maintainability_audit/source.py +0 -0
  165. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_clone_names_every_copy.py +0 -0
  166. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_dangling_source_link_is_named_not_fatal.py +0 -0
  167. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_format_override_is_disclosed.py +0 -0
  168. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_matching_format_stays_silent.py +0 -0
  169. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_published_question_offers_what_it_accepts.py +0 -0
  170. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_a_setup_question_keeps_its_contract.py +0 -0
  171. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_acquisition_trust.py +0 -0
  172. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_adapter_docs.py +0 -0
  173. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_adapter_recordings.py +0 -0
  174. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_adapters.py +0 -0
  175. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_added_lines.py +0 -0
  176. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_an_absent_work_order_renders_nothing.py +0 -0
  177. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_an_unmeasured_pillar_reports_no_number.py +0 -0
  178. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analysis_coverage.py +0 -0
  179. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analysis_execution.py +0 -0
  180. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_bridge.py +0 -0
  181. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_config_isolation.py +0 -0
  182. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_estimate_claims.py +0 -0
  183. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_file_lists_are_batched.py +0 -0
  184. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_pinning.py +0 -0
  185. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_primary_estimate.py +0 -0
  186. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_provenance.py +0 -0
  187. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
  188. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_scoring_path.py +0 -0
  189. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_spread_range.py +0 -0
  190. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_analyzer_xml_bounds.py +0 -0
  191. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_anchor_and_mode.py +0 -0
  192. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_anchor_caveat_and_counts_follow_the_run.py +0 -0
  193. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_anchor_disclosure.py +0 -0
  194. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_annotations_match_behaviour.py +0 -0
  195. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_anticipated_refusals.py +0 -0
  196. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_architecture.py +0 -0
  197. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_artifact_write_route_class.py +0 -0
  198. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_aspect_coverage.py +0 -0
  199. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_asset_snapshot_class.py +0 -0
  200. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
  201. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_attestation.py +0 -0
  202. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_audit_components.py +0 -0
  203. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_authorization_freshness.py +0 -0
  204. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_authorship_gates.py +0 -0
  205. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_backfill.py +0 -0
  206. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_band_concealment_class.py +0 -0
  207. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_band_concealment_p3.py +0 -0
  208. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_band_pressures.py +0 -0
  209. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_bands.py +0 -0
  210. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_behaviour_suites_are_tests.py +0 -0
  211. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_body_or_signature_class.py +0 -0
  212. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_both_setup_paths_ask_the_same_stage.py +0 -0
  213. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_build_output_is_not_the_repositorys_code.py +0 -0
  214. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_c_declarations.py +0 -0
  215. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_calibration_corpus.py +0 -0
  216. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_calibration_drift.py +0 -0
  217. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_calibration_tooling.py +0 -0
  218. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_catalog_selection.py +0 -0
  219. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_catalog_tier_promise.py +0 -0
  220. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_chat_leads_with_the_work_order.py +0 -0
  221. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_chat_primary_docs.py +0 -0
  222. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_check_refuses_plus_only_fragments.py +0 -0
  223. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_checkstyle_adapter.py +0 -0
  224. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_checkstyle_catalog.py +0 -0
  225. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_child_sandbox.py +0 -0
  226. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_ci_history_recipe.py +0 -0
  227. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  228. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_claimed_languages.py +0 -0
  229. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_clean_sees_the_weakened_oracle.py +0 -0
  230. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cli.py +0 -0
  231. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_clone_group_class.py +0 -0
  232. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cobol_declarations.py +0 -0
  233. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_code_scanning_gets_alerts_not_the_record.py +0 -0
  234. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cognitive_complexity.py +0 -0
  235. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cohesion_with_nothing_to_read_is_not_applicable.py +0 -0
  236. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cohort_statistics.py +0 -0
  237. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_concealment_properties.py +0 -0
  238. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_config_shape.py +0 -0
  239. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_conformance_reads_the_operators_ask.py +0 -0
  240. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_consent_and_grant.py +0 -0
  241. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_consent_is_per_repository.py +0 -0
  242. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_consent_survives_setup_and_is_asked.py +0 -0
  243. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_consent_without_command_has_a_remedy.py +0 -0
  244. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_consumer_migration.py +0 -0
  245. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_contract_claims.py +0 -0
  246. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_corpus_note_counts_come_from_the_corpus.py +0 -0
  247. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_corroborate.py +0 -0
  248. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_coverage_by_language.py +0 -0
  249. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_coverage_config_reaches_children.py +0 -0
  250. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_coverage_formats.py +0 -0
  251. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_cpp_declarations.py +0 -0
  252. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_criteria_completion.py +0 -0
  253. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_csharp_declarations.py +0 -0
  254. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_current_state_docs_name_every_parsed_language.py +0 -0
  255. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_d15_composition.py +0 -0
  256. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_d15_goal_directed.py +0 -0
  257. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_dead_code.py +0 -0
  258. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declaration_criteria_scope.py +0 -0
  259. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declaration_edge_cases.py +0 -0
  260. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declaration_grading.py +0 -0
  261. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declaration_ranges.py +0 -0
  262. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declaration_source.py +0 -0
  263. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declarative_parsers.py +0 -0
  264. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declared_capabilities_match_the_delegate.py +0 -0
  265. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_declared_imports.py +0 -0
  266. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_delegated_security_pillar.py +0 -0
  267. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_demo_tree.py +0 -0
  268. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_derivation_mix.py +0 -0
  269. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_determinism.py +0 -0
  270. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_dimension_ratchet.py +0 -0
  271. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_direct_runner_availability_class.py +0 -0
  272. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_discovery.py +0 -0
  273. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_doc_claims.py +0 -0
  274. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_docs_links.py +0 -0
  275. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_economic_context.py +0 -0
  276. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_empty_output_not_clean.py +0 -0
  277. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
  278. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_environment_work_order.py +0 -0
  279. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_built_presentation_is_offered.py +0 -0
  280. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_language_counts_its_own_loop.py +0 -0
  281. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_language_has_a_loop_fixture.py +0 -0
  282. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_pool_install_is_the_same_pool.py +0 -0
  283. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_question_can_be_answered.py +0 -0
  284. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_every_surface_says_what_the_run_found.py +0 -0
  285. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_evidence_invariants.py +0 -0
  286. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_evidence_normalization.py +0 -0
  287. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_evidence_properties.py +0 -0
  288. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_example_config_opens_claimed_languages.py +0 -0
  289. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_exclusion_dialects.py +0 -0
  290. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_exposure_never_outranks_band.py +0 -0
  291. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_falsifier_standard.py +0 -0
  292. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_file_list_cap_class.py +0 -0
  293. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_finding_identity.py +0 -0
  294. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_first_run_elicitation.py +0 -0
  295. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_first_run_prompt.py +0 -0
  296. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_first_run_reelicitation.py +0 -0
  297. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_first_stage_setup_wording_holds.py +0 -0
  298. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_fix_breadth_window.py +0 -0
  299. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_fixed_form_fortran.py +0 -0
  300. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_format_ask.py +0 -0
  301. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_fortran_declarations.py +0 -0
  302. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_fortran_metrics.py +0 -0
  303. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_fortran_practice.py +0 -0
  304. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_git_argv.py +0 -0
  305. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_git_read_only.py +0 -0
  306. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_git_readonly_class.py +0 -0
  307. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_go_declarations.py +0 -0
  308. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_grammar_constructs.py +0 -0
  309. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_grammar_token_coverage.py +0 -0
  310. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_grant_only_user_tier.py +0 -0
  311. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_grok_audit_of_3_11.py +0 -0
  312. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_history.py +0 -0
  313. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_history_boundary.py +0 -0
  314. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_history_manifest.py +0 -0
  315. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_history_schema2.py +0 -0
  316. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_history_window.py +0 -0
  317. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_hostile_prompt.py +0 -0
  318. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_html_executive.py +0 -0
  319. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_html_section_parity_class.py +0 -0
  320. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_identity_docs.py +0 -0
  321. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_identity_resolution.py +0 -0
  322. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_idiom_divergence.py +0 -0
  323. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_in_loop_budgets.py +0 -0
  324. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_in_loop_check.py +0 -0
  325. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_installed_wheel_runtime.py +0 -0
  326. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_instruction_targets.py +0 -0
  327. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_java_range_guard.py +0 -0
  328. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_java_ranges.py +0 -0
  329. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_java_scored.py +0 -0
  330. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_java_wiring.py +0 -0
  331. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_js_complexity_operators.py +0 -0
  332. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_js_declarations.py +0 -0
  333. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_kotlin_declarations.py +0 -0
  334. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_kotlin_metrics.py +0 -0
  335. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_language_coverage.py +0 -0
  336. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_language_support_honesty.py +0 -0
  337. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_list_tools_publishes_the_answer_path.py +0 -0
  338. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_maintenance_signals.py +0 -0
  339. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mcp_baseline_payload.py +0 -0
  340. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mcp_format_contract.py +0 -0
  341. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mcp_history.py +0 -0
  342. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mcp_server.py +0 -0
  343. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mcp_start_failure_names_what_is_installed.py +0 -0
  344. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_migration_1_0.py +0 -0
  345. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_missing_security_scanners_are_named_before_the_run.py +0 -0
  346. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_mutation_recorded.py +0 -0
  347. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_near_duplicates.py +0 -0
  348. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_network_disclosure.py +0 -0
  349. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
  350. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_operator_named_paths.py +0 -0
  351. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_operator_named_reads.py +0 -0
  352. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_oracle_weakening_precision_bar.py +0 -0
  353. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pairing_reads_imports.py +0 -0
  354. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pattern_budget.py +0 -0
  355. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_phase6_claims.py +0 -0
  356. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_php_declarations.py +0 -0
  357. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pillars_and_practice.py +0 -0
  358. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_platform_claim.py +0 -0
  359. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pmd_adapter.py +0 -0
  360. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pmd_audit_closures.py +0 -0
  361. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_policy_claims.py +0 -0
  362. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_pool_runs_by_config.py +0 -0
  363. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_population_floors.py +0 -0
  364. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_practice_nested_gates_class.py +0 -0
  365. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_precommit_staged.py +0 -0
  366. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_preflight_before_consent_runs_nothing_from_the_tree.py +0 -0
  367. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_presentation_refusals.py +0 -0
  368. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_previous_release_reached_pypi.py +0 -0
  369. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_promises.py +0 -0
  370. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_prompt_does_not_issue_rates_when_unscored.py +0 -0
  371. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_prompt_escalation_once.py +0 -0
  372. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_prompt_honesty.py +0 -0
  373. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_prompt_location_escalation_class.py +0 -0
  374. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_prove_falsifiers.py +0 -0
  375. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_python_complexity.py +0 -0
  376. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_python_declarations.py +0 -0
  377. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_read_boundary.py +0 -0
  378. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_recurrence.py +0 -0
  379. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_release_needs_an_empty_ledger.py +0 -0
  380. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_release_plan.py +0 -0
  381. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_release_plan_status.py +0 -0
  382. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_rendered_docs.py +0 -0
  383. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_report_remedy_copy.py +0 -0
  384. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_root_grants.py +0 -0
  385. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  386. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_ruby_declarations.py +0 -0
  387. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_run_comparison.py +0 -0
  388. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_runner.py +0 -0
  389. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_rust_declarations.py +0 -0
  390. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_sarif.py +0 -0
  391. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scan_history.py +0 -0
  392. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scan_scope.py +0 -0
  393. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scanner_fingerprint_covers_the_measurement_path.py +0 -0
  394. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scanner_unsafe_direction.py +0 -0
  395. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scanning.py +0 -0
  396. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_schema_fidelity.py +0 -0
  397. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scope_conformance.py +0 -0
  398. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_scoring_calibration.py +0 -0
  399. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_security_delegate_versions_agree.py +0 -0
  400. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_security_findings_keep_their_handoff.py +0 -0
  401. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_security_pillar_asserts_a_scanner_set.py +0 -0
  402. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_security_pillar_runs_and_shows.py +0 -0
  403. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_selection_covers_every_parsed_language.py +0 -0
  404. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_semantic_findings_stay_inside_the_audited_files.py +0 -0
  405. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_semantic_policy.py +0 -0
  406. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_answers_are_the_same_setup.py +0 -0
  407. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_gate_completeness.py +0 -0
  408. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_gate_independent_contract.py +0 -0
  409. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_instruction_describes_its_own_reply.py +0 -0
  410. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_precondition.py +0 -0
  411. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_setup_writes_a_valid_config.py +0 -0
  412. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_shell_declarations.py +0 -0
  413. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_shell_metrics.py +0 -0
  414. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_skill_install.py +0 -0
  415. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_sonar_resolve.py +0 -0
  416. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_source_index.py +0 -0
  417. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_spotbugs_adapter.py +0 -0
  418. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_spotbugs_catalog.py +0 -0
  419. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_stage8_contract.py +0 -0
  420. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_stamped_documents_stay_honest.py +0 -0
  421. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_stdout_outputs.py +0 -0
  422. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_suite_isolation.py +0 -0
  423. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_swift_declarations.py +0 -0
  424. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_tdd_structure.py +0 -0
  425. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_terminal_asks_the_same_questions.py +0 -0
  426. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_test_commands.py +0 -0
  427. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_test_execution_class.py +0 -0
  428. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_agent_knows_when_it_is_stale.py +0 -0
  429. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_changelog_covers_the_shipping_version.py +0 -0
  430. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_chat_payload_has_a_budget.py +0 -0
  431. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_condition_says_what_it_measured.py +0 -0
  432. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_handoff_rules_are_their_own_module.py +0 -0
  433. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_pillar_row_reads_cleanly.py +0 -0
  434. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_presentation_question_stays_answerable.py +0 -0
  435. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_previous_release_was_tagged.py +0 -0
  436. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_prompt_does_not_take_back_what_it_withheld.py +0 -0
  437. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_prompt_keeps_listing_what_it_did_not_withhold.py +0 -0
  438. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_release_process_describes_itself.py +0 -0
  439. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_release_record_stays_well_formed.py +0 -0
  440. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_report_is_saved_not_sent.py +0 -0
  441. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_security_run_has_a_configurable_limit.py +0 -0
  442. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_security_work_order_is_drawn.py +0 -0
  443. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_suite_names_the_program_it_ran.py +0 -0
  444. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_tree_cannot_redirect_a_read.py +0 -0
  445. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_the_version_has_one_source.py +0 -0
  446. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_three_presentations.py +0 -0
  447. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_tool_resolution.py +0 -0
  448. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
  449. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_tree_chosen_spawn.py +0 -0
  450. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_tree_reads_use_the_primitive.py +0 -0
  451. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_trends.py +0 -0
  452. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_type_fields_not_functions_class.py +0 -0
  453. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_uat_falsifiers.py +0 -0
  454. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_unanchored_set_matches_corpus.py +0 -0
  455. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_unread_code.py +0 -0
  456. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_user_config_tier.py +0 -0
  457. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_verification_audit_closures.py +0 -0
  458. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_verified_grade.py +0 -0
  459. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_version_claim.py +0 -0
  460. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_version_stamping.py +0 -0
  461. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_wheel_contents.py +0 -0
  462. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_withheld_work_keeps_its_boundary.py +0 -0
  463. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_work_items_state_their_own_finding.py +0 -0
  464. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_work_order.py +0 -0
  465. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
  466. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_work_order_items.py +0 -0
  467. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_work_order_selection.py +0 -0
  468. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_workflow_supply_chain.py +0 -0
  469. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_write_boundary.py +0 -0
  470. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_write_route_class.py +0 -0
  471. {maintainability_agent-4.1.0 → maintainability_agent-4.3.0}/tests/test_written_record.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 4.1.0
3
+ Version: 4.3.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -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.1.0**.
50
+ Version **4.3.0**.
51
51
 
52
52
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
53
53
  >
@@ -56,6 +56,11 @@ Version **4.1.0**.
56
56
  > taste, each pinned to the exact commit it was measured at, so anyone can
57
57
  > re-run the calibration and get the same numbers. The median of that corpus
58
58
  > scores a **B**. [How the corpus is chosen and measured](docs/standard.md#the-reference-corpus).
59
+ >
60
+ > So your grade places your code against those 201: a **B** means you are at
61
+ > the median of mature, widely used open source. The corpus is re-measured
62
+ > whenever the instrument changes — in 4.1.0 every file of even the largest
63
+ > repositories was read, and the scale came back unchanged to four decimals.
59
64
 
60
65
  **Languages parsed:** Python, Java, Kotlin, C, C++, C#, Go, Rust, PHP, Ruby,
61
66
  Swift, Shell, COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -93,7 +98,10 @@ you what it could not measure.
93
98
  **Install secure-code-agent for the security pillar.** Every audit runs it; it is
94
99
  installed alongside rather than as a dependency, so the two tools release
95
100
  independently. Without it the report says the security pillar was not measured
96
- and gives this command. Its scanners decide what it can grade — see
101
+ and gives this command. A full security run can take several minutes on a
102
+ large repository; the audit waits up to 15 minutes for it, and
103
+ `security.timeout_seconds` in `maintainability-agent.json` changes that. Its
104
+ scanners decide what it can grade — see
97
105
  [machine setup](docs/machine-setup.md#3-toolchain) for which to install, and
98
106
  don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
99
107
 
@@ -356,6 +364,11 @@ signals on:
356
364
  - an ISO/IEC 25010-inspired 0–5 estimate per category, and a verified grade —
357
365
  or a disclosed withholding when the evidence is thin.
358
366
 
367
+ **Large repositories are measured whole.** Every file is handed to the
368
+ analyzers, split across as many runs as the command line needs, so a big
369
+ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
370
+ 1,543 that fitted on one command line before 4.1.0.
371
+
359
372
  The analyzer is intentionally conservative and under-reports rather than
360
373
  over-reports: an unrecognized declaration costs one missed finding, never a
361
374
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
@@ -496,7 +509,7 @@ instead of an invokable skill:
496
509
  This repo ships `action.yml`, usable as a composite action:
497
510
 
498
511
  ```yaml
499
- - uses: marshallguillory86/maintainability-agent@v4.1.0
512
+ - uses: marshallguillory86/maintainability-agent@v4.3.0
500
513
  with:
501
514
  config: maintainability-agent.json
502
515
  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.1.0**.
8
+ Version **4.3.0**.
9
9
 
10
10
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
11
11
  >
@@ -14,6 +14,11 @@ Version **4.1.0**.
14
14
  > taste, each pinned to the exact commit it was measured at, so anyone can
15
15
  > re-run the calibration and get the same numbers. The median of that corpus
16
16
  > scores a **B**. [How the corpus is chosen and measured](docs/standard.md#the-reference-corpus).
17
+ >
18
+ > So your grade places your code against those 201: a **B** means you are at
19
+ > the median of mature, widely used open source. The corpus is re-measured
20
+ > whenever the instrument changes — in 4.1.0 every file of even the largest
21
+ > repositories was read, and the scale came back unchanged to four decimals.
17
22
 
18
23
  **Languages parsed:** Python, Java, Kotlin, C, C++, C#, Go, Rust, PHP, Ruby,
19
24
  Swift, Shell, COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -51,7 +56,10 @@ you what it could not measure.
51
56
  **Install secure-code-agent for the security pillar.** Every audit runs it; it is
52
57
  installed alongside rather than as a dependency, so the two tools release
53
58
  independently. Without it the report says the security pillar was not measured
54
- and gives this command. Its scanners decide what it can grade — see
59
+ and gives this command. A full security run can take several minutes on a
60
+ large repository; the audit waits up to 15 minutes for it, and
61
+ `security.timeout_seconds` in `maintainability-agent.json` changes that. Its
62
+ scanners decide what it can grade — see
55
63
  [machine setup](docs/machine-setup.md#3-toolchain) for which to install, and
56
64
  don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
57
65
 
@@ -314,6 +322,11 @@ signals on:
314
322
  - an ISO/IEC 25010-inspired 0–5 estimate per category, and a verified grade —
315
323
  or a disclosed withholding when the evidence is thin.
316
324
 
325
+ **Large repositories are measured whole.** Every file is handed to the
326
+ analyzers, split across as many runs as the command line needs, so a big
327
+ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
328
+ 1,543 that fitted on one command line before 4.1.0.
329
+
317
330
  The analyzer is intentionally conservative and under-reports rather than
318
331
  over-reports: an unrecognized declaration costs one missed finding, never a
319
332
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
@@ -454,7 +467,7 @@ instead of an invokable skill:
454
467
  This repo ships `action.yml`, usable as a composite action:
455
468
 
456
469
  ```yaml
457
- - uses: marshallguillory86/maintainability-agent@v4.1.0
470
+ - uses: marshallguillory86/maintainability-agent@v4.3.0
458
471
  with:
459
472
  config: maintainability-agent.json
460
473
  changed-only: main...HEAD
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 4.1.0
3
+ Version: 4.3.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -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.1.0**.
50
+ Version **4.3.0**.
51
51
 
52
52
  > ## **Calibrated against 201 mature open-source repositories in fifteen languages.**
53
53
  >
@@ -56,6 +56,11 @@ Version **4.1.0**.
56
56
  > taste, each pinned to the exact commit it was measured at, so anyone can
57
57
  > re-run the calibration and get the same numbers. The median of that corpus
58
58
  > scores a **B**. [How the corpus is chosen and measured](docs/standard.md#the-reference-corpus).
59
+ >
60
+ > So your grade places your code against those 201: a **B** means you are at
61
+ > the median of mature, widely used open source. The corpus is re-measured
62
+ > whenever the instrument changes — in 4.1.0 every file of even the largest
63
+ > repositories was read, and the scale came back unchanged to four decimals.
59
64
 
60
65
  **Languages parsed:** Python, Java, Kotlin, C, C++, C#, Go, Rust, PHP, Ruby,
61
66
  Swift, Shell, COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -93,7 +98,10 @@ you what it could not measure.
93
98
  **Install secure-code-agent for the security pillar.** Every audit runs it; it is
94
99
  installed alongside rather than as a dependency, so the two tools release
95
100
  independently. Without it the report says the security pillar was not measured
96
- and gives this command. Its scanners decide what it can grade — see
101
+ and gives this command. A full security run can take several minutes on a
102
+ large repository; the audit waits up to 15 minutes for it, and
103
+ `security.timeout_seconds` in `maintainability-agent.json` changes that. Its
104
+ scanners decide what it can grade — see
97
105
  [machine setup](docs/machine-setup.md#3-toolchain) for which to install, and
98
106
  don't add its `[mcp]` extra to this environment (it pins `mcp<2`).
99
107
 
@@ -356,6 +364,11 @@ signals on:
356
364
  - an ISO/IEC 25010-inspired 0–5 estimate per category, and a verified grade —
357
365
  or a disclosed withholding when the evidence is thin.
358
366
 
367
+ **Large repositories are measured whole.** Every file is handed to the
368
+ analyzers, split across as many runs as the command line needs, so a big
369
+ codebase is read rather than sampled — FFmpeg's 4,687 files, not the first
370
+ 1,543 that fitted on one command line before 4.1.0.
371
+
359
372
  The analyzer is intentionally conservative and under-reports rather than
360
373
  over-reports: an unrecognized declaration costs one missed finding, never a
361
374
  cascade of false ones. Pair it with native tools (ESLint, Ruff, Radon, Semgrep,
@@ -496,7 +509,7 @@ instead of an invokable skill:
496
509
  This repo ships `action.yml`, usable as a composite action:
497
510
 
498
511
  ```yaml
499
- - uses: marshallguillory86/maintainability-agent@v4.1.0
512
+ - uses: marshallguillory86/maintainability-agent@v4.3.0
500
513
  with:
501
514
  config: maintainability-agent.json
502
515
  changed-only: main...HEAD
@@ -22,6 +22,7 @@ src/maintainability_audit/_banner.py
22
22
  src/maintainability_audit/_built_ins.py
23
23
  src/maintainability_audit/_calibration.py
24
24
  src/maintainability_audit/_catalog.py
25
+ src/maintainability_audit/_changed_code_policy.py
25
26
  src/maintainability_audit/_charts.py
26
27
  src/maintainability_audit/_cognitive.py
27
28
  src/maintainability_audit/_config_defaults.py
@@ -157,6 +158,7 @@ tests/test_a_dangling_source_link_is_named_not_fatal.py
157
158
  tests/test_a_format_override_is_disclosed.py
158
159
  tests/test_a_matching_format_stays_silent.py
159
160
  tests/test_a_published_question_offers_what_it_accepts.py
161
+ tests/test_a_rendered_docs_site_is_not_scored_as_source.py
160
162
  tests/test_a_setup_question_keeps_its_contract.py
161
163
  tests/test_acquisition_trust.py
162
164
  tests/test_adapter_docs.py
@@ -178,6 +180,8 @@ tests/test_analyzer_provenance_exclusions.py
178
180
  tests/test_analyzer_scoring_path.py
179
181
  tests/test_analyzer_spread_range.py
180
182
  tests/test_analyzer_xml_bounds.py
183
+ tests/test_analyzers_against_the_real_tools.py
184
+ tests/test_analyzers_report_what_actually_failed.py
181
185
  tests/test_anchor_and_mode.py
182
186
  tests/test_anchor_caveat_and_counts_follow_the_run.py
183
187
  tests/test_anchor_disclosure.py
@@ -207,6 +211,7 @@ tests/test_calibration_drift.py
207
211
  tests/test_calibration_tooling.py
208
212
  tests/test_catalog_selection.py
209
213
  tests/test_catalog_tier_promise.py
214
+ tests/test_changed_code_policy.py
210
215
  tests/test_chat_leads_with_the_work_order.py
211
216
  tests/test_chat_primary_docs.py
212
217
  tests/test_check_refuses_plus_only_fragments.py
@@ -276,6 +281,7 @@ tests/test_evidence_invariants.py
276
281
  tests/test_evidence_normalization.py
277
282
  tests/test_evidence_properties.py
278
283
  tests/test_example_config_opens_claimed_languages.py
284
+ tests/test_exclude_additional_keeps_the_defaults.py
279
285
  tests/test_exclusion_dialects.py
280
286
  tests/test_exposure_never_outranks_band.py
281
287
  tests/test_falsifier_standard.py
@@ -367,6 +373,7 @@ tests/test_python_declarations.py
367
373
  tests/test_read_boundary.py
368
374
  tests/test_readme_claims.py
369
375
  tests/test_recurrence.py
376
+ tests/test_regular_file_reads_work_without_o_nonblock.py
370
377
  tests/test_release_needs_an_empty_ledger.py
371
378
  tests/test_release_plan.py
372
379
  tests/test_release_plan_status.py
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "4.1.0"
3
+ __version__ = "4.3.0"
@@ -118,6 +118,36 @@ def _format_default(_base: Path, tree: str) -> tuple[str, ...]:
118
118
  return (tree, f"{tree}/**")
119
119
 
120
120
 
121
+ _REGEX_DIALECTS = frozenset({"regex", "rel_regex"})
122
+
123
+
124
+ def _name_as_regex(pattern: str) -> str:
125
+ """A shell-style name as a regex that finds it as a path component anywhere.
126
+
127
+ `*` and `?` stay inside one component, as they do for the built-in
128
+ scan's own matcher; the name matches at the start of the path or after
129
+ a `/`, and ends at a `/` or the end, so `.venv/` is not `venv_tools.py`.
130
+ Works for `re.match` on an absolute path (pylint) and `re.search` on a
131
+ relative one (mypy) alike.
132
+ """
133
+ body = "".join("[^/]*" if ch == "*" else "[^/]" if ch == "?" else re.escape(ch)
134
+ for ch in pattern.strip("/"))
135
+ return f"(?:^|.*/){body}(?:/|$)"
136
+
137
+
138
+ def _names_as_paths(excludes: Sequence[str], root: Path) -> tuple[str, ...]:
139
+ """Plain path names as absolute paths under the root; wildcards dropped.
140
+
141
+ A path dialect (interrogate's `--exclude`) names locations, so
142
+ `calibration/.corpus/` becomes `<root>/calibration/.corpus`. A wildcard
143
+ such as `*.min.js` names no location and cannot be spelled here; it is
144
+ left out, which can only under-exclude — the scan's own filter still
145
+ applies it to what the tool reports.
146
+ """
147
+ return tuple(str(root / pattern.strip("/")) for pattern in excludes
148
+ if not any(ch in pattern for ch in "*?["))
149
+
150
+
121
151
  _TREE_FORMATTERS = {
122
152
  "fnmatch": _format_fnmatch,
123
153
  "regex": _format_regex,
@@ -267,7 +297,7 @@ class BaseAdapter:
267
297
  """
268
298
  if not self.exclude_flag:
269
299
  return ()
270
- entries = tuple(excludes) + self.tree_patterns(
300
+ entries = self.operator_patterns(excludes, root) + self.tree_patterns(
271
301
  getattr(excludes, "trees", ()), root
272
302
  )
273
303
  if not entries:
@@ -279,6 +309,21 @@ class BaseAdapter:
279
309
  return tuple(repeated)
280
310
  return (self.exclude_flag, self.exclude_separator.join(entries))
281
311
 
312
+ def operator_patterns(self, excludes: Sequence[str], root: Path | None = None) -> tuple[str, ...]:
313
+ """The operator's exclude names, spelled for this tool's matcher.
314
+
315
+ They are shell-style names — `.venv/`, `*.egg-info/` — and for most
316
+ dialects they pass through as written. A regex dialect compiles
317
+ them: pylint's `--ignore-paths` refused `*.egg-info` ("nothing to
318
+ repeat"), exited with an argument error, and analysed nothing, on
319
+ every repository whose config carried a glob (the default does).
320
+ """
321
+ if self.exclude_dialect == "abspath":
322
+ return _names_as_paths(excludes, Path(root) if root is not None else Path("."))
323
+ if self.exclude_dialect not in _REGEX_DIALECTS:
324
+ return tuple(excludes)
325
+ return tuple(_name_as_regex(pattern) for pattern in excludes)
326
+
282
327
  def tree_patterns(
283
328
  self, trees: Sequence[str], root: Path | None = None
284
329
  ) -> tuple[str, ...]:
@@ -447,6 +447,7 @@ def _attempt(root: Path, adapter: Any, probe: Probe, timeout: int,
447
447
  )
448
448
 
449
449
  result, parsed = _run_batches(adapter, root, excludes, timeout)
450
+ result = _silent_failure(adapter.slug, result, parsed)
450
451
  # Filtered before the counts are taken, not after. Recording 48
451
452
  # measurements and reporting 6 describes an activity rather than a
452
453
  # result, which is the defect this project keeps finding.
@@ -500,6 +501,24 @@ def _run_batches(adapter: Any, root: Path, excludes: Sequence[str],
500
501
  return _merged_result(results, len(invocations)), _merged_extraction(parsed)
501
502
 
502
503
 
504
+ def _silent_failure(slug: str, result: ToolResult, parsed: Extraction) -> ToolResult:
505
+ """A tool that wrote nothing failed, whatever its exit code says.
506
+
507
+ pylint's argument error exits 2, which is also its "error messages
508
+ issued" bit, so a run that analysed nothing counted as one that worked
509
+ and its empty output was reported as unreadable JSON while stderr held
510
+ the reason. secure-code-agent recorded the same class as its D30: let
511
+ the output decide, and let the failure carry what the tool said.
512
+ """
513
+ if not (parsed.parse_error and result.usable and not (result.stdout or "").strip()):
514
+ return result
515
+ said = " ".join((result.stderr or "").split())[:400]
516
+ if not said:
517
+ return result
518
+ return replace(result, outcome=Outcome.FAILED,
519
+ detail=f"{slug} exited {result.exit_code} and wrote no output; it said: {said}")
520
+
521
+
503
522
  def _merged_result(results: list[ToolResult], planned: int) -> ToolResult:
504
523
  failed = next((r for r in results if not r.usable), None)
505
524
  basis = failed or results[0]
@@ -0,0 +1,98 @@
1
+ """Code a change touches is held to a stricter bar (Decision 15).
2
+
3
+ A repository adopting a quality gate cannot fix every old long function
4
+ first, and a gate that fails on all of them is a gate nobody turns on.
5
+ `policy.changed_code` sets stricter function limits, and on a run against a
6
+ change only the functions that change touched are held to them; untouched
7
+ code is judged by the standard as before.
8
+
9
+ A function is *touched* when the change added or altered a line inside it —
10
+ `git diff --unified=0` lines, so context does not count and a pure deletion
11
+ touches nothing. Classes are not held to it: their budget is a container's,
12
+ and their methods are functions in their own right.
13
+
14
+ Two rules from the decision, enforced here rather than trusted:
15
+
16
+ - **A policy only tightens.** A limit looser than the standard threshold is
17
+ refused when the configuration loads, by name, as `PolicyError` — the
18
+ refusal both doors already turn into a message.
19
+ - **It never moves the grade.** Its result is `report["policy"]`, beside the
20
+ score rather than inside `hard_gate_failures`, which the scorer reads.
21
+ `--fail-on-gate` reads both.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any
27
+
28
+ from ._catalog import PolicyError
29
+
30
+ #: Each policy key: the standard threshold it may only tighten, the
31
+ #: function-metric field it reads, and the name a failure reports.
32
+ LIMITS: dict[str, tuple[str, str, str]] = {
33
+ "max_function_lines": ("max_function_lines", "lines", "function_lines"),
34
+ "max_complexity": ("max_complexity", "complexity", "complexity"),
35
+ "max_cognitive_complexity": ("max_cognitive_complexity", "cognitive", "cognitive_complexity"),
36
+ }
37
+
38
+
39
+ def changed_code_limits(config: dict[str, Any]) -> dict[str, int]:
40
+ """The configured limits, or empty when the repository sets none."""
41
+ return dict((config.get("policy") or {}).get("changed_code") or {})
42
+
43
+
44
+ def validate(config: dict[str, Any]) -> None:
45
+ """Refuse a limit that is unknown, not a positive integer, or looser than the standard."""
46
+ thresholds = config.get("thresholds") or {}
47
+ for key, value in changed_code_limits(config).items():
48
+ if key not in LIMITS:
49
+ raise PolicyError(
50
+ f"unknown policy.changed_code key {key!r}; expected one of {sorted(LIMITS)}")
51
+ if isinstance(value, bool) or not isinstance(value, int) or value < 1:
52
+ raise PolicyError(f"policy.changed_code.{key} must be a positive integer, not {value!r}")
53
+ standard = thresholds.get(LIMITS[key][0])
54
+ if isinstance(standard, int) and value > standard:
55
+ raise PolicyError(
56
+ f"policy.changed_code.{key} is {value}, looser than the standard "
57
+ f"thresholds.{LIMITS[key][0]} of {standard}; a policy may only tighten")
58
+
59
+
60
+ def evaluate(function_metrics: list[Any], touched_lines: dict[str, set[int]],
61
+ config: dict[str, Any], revspec: str) -> dict[str, Any] | None:
62
+ """Every touched function's breaches of the policy, or None without a policy."""
63
+ limits = changed_code_limits(config)
64
+ if not limits:
65
+ return None
66
+ touched = [metric for metric in function_metrics if _touched(metric, touched_lines)]
67
+ return {
68
+ "revspec": revspec,
69
+ "limits": limits,
70
+ "touched_functions": len(touched),
71
+ "failures": [failure for metric in touched for failure in _breaches(metric, limits)],
72
+ }
73
+
74
+
75
+ def failures(report: dict[str, Any]) -> list[dict[str, Any]]:
76
+ """The policy's failures in a finished report; empty when no policy ran."""
77
+ return list((report.get("policy") or {}).get("failures") or [])
78
+
79
+
80
+ def _touched(metric: Any, touched_lines: dict[str, set[int]]) -> bool:
81
+ if getattr(metric, "kind", "function") == "class":
82
+ return False
83
+ lines = touched_lines.get(metric.path)
84
+ if not lines:
85
+ return False
86
+ end = metric.start_line + metric.lines
87
+ return any(metric.start_line <= line < end for line in lines)
88
+
89
+
90
+ def _breaches(metric: Any, limits: dict[str, int]) -> list[dict[str, Any]]:
91
+ found = []
92
+ for key, limit in limits.items():
93
+ _standard, field, measure = LIMITS[key]
94
+ value = getattr(metric, field, None)
95
+ if isinstance(value, int) and value > limit:
96
+ found.append({"path": metric.path, "name": metric.name, "start_line": metric.start_line,
97
+ "measure": measure, "value": value, "limit": limit})
98
+ return found
@@ -18,6 +18,7 @@ import argparse
18
18
  import sys
19
19
  from pathlib import Path
20
20
 
21
+ from ._changed_code_policy import failures as policy_failures
21
22
  from .baseline import findings_not_in_baseline
22
23
  from .git_tools import added_lines, changed_paths, removed_lines
23
24
 
@@ -147,7 +148,7 @@ def audit_exit_code(args: argparse.Namespace, report: dict) -> int:
147
148
  root = Path(report["root"])
148
149
  if findings_not_in_baseline(report, args.baseline, root):
149
150
  return 1
150
- if args.fail_on_gate and report["hard_gate_failures"]:
151
+ if args.fail_on_gate and (report["hard_gate_failures"] or policy_failures(report)):
151
152
  return 1
152
153
  conformance = _conformance_exit(args, report)
153
154
  if conformance:
@@ -318,15 +318,36 @@ def _work_order_section(report: dict[str, Any]) -> list[str]:
318
318
 
319
319
  def _hard_gate_section(report: dict[str, Any]) -> list[str]:
320
320
  failures = report.get("hard_gate_failures") or []
321
+ rows: list[str] = []
322
+ if failures:
323
+ rows = [
324
+ "<h2>Hard gates</h2>",
325
+ "<table><tr><th>Severity</th><th>Gate</th></tr>",
326
+ ]
327
+ rows.extend(
328
+ f"<tr><td class='sev-Severe'>Severe</td><td>{escape(str(gate))}</td></tr>"
329
+ for gate in failures
330
+ )
331
+ rows.append("</table>")
332
+ return rows + _policy_section(report)
333
+
334
+
335
+ def _policy_section(report: dict[str, Any]) -> list[str]:
336
+ """The changed-code policy beside the gates, as the markdown prints it (Decision 15)."""
337
+ policy = report.get("policy")
338
+ failures = (policy or {}).get("failures") or []
321
339
  if not failures:
322
340
  return []
323
341
  rows = [
324
- "<h2>Hard gates</h2>",
325
- "<table><tr><th>Severity</th><th>Gate</th></tr>",
342
+ "<h2>Changed-code policy</h2>",
343
+ f"<p class='muted'>Functions touched by {escape(str(policy.get('revspec')))} are held to "
344
+ "this repository's stricter limits. The grade is unaffected.</p>",
345
+ "<table><tr><th>Location</th><th>Function</th><th>Measure</th><th>Value</th><th>Limit</th></tr>",
326
346
  ]
327
347
  rows.extend(
328
- f"<tr><td class='sev-Severe'>Severe</td><td>{escape(str(gate))}</td></tr>"
329
- for gate in failures
348
+ f"<tr><td>{escape(str(f['path']))}:{f['start_line']}</td><td>{escape(str(f['name']))}</td>"
349
+ f"<td>{escape(str(f['measure']))}</td><td>{f['value']}</td><td>{f['limit']}</td></tr>"
350
+ for f in failures
330
351
  )
331
352
  rows.append("</table>")
332
353
  return rows
@@ -21,6 +21,7 @@ from typing import Any
21
21
 
22
22
  from ._calibration import CALIBRATION_C
23
23
  from ._catalog import PRESENTATIONS
24
+ from ._changed_code_policy import failures as policy_failures
24
25
  from ._grant_ledger import (
25
26
  ALLOWED_ROOTS_ENV as ALLOWED_ROOTS_ENV, # noqa: PLC0414 - re-export
26
27
  )
@@ -396,7 +397,8 @@ def _top_level_result(report: dict[str, Any], root: Path, status: str,
396
397
  "audit_ran": True,
397
398
  "source_commit": probe_git(["rev-parse", "HEAD"], root) or None,
398
399
  "worktree_dirty": bool(status),
399
- "gate_passed": not report["hard_gate_failures"],
400
+ # The changed-code policy is a gate too (Decision 15); the CLI reads both.
401
+ "gate_passed": not (report["hard_gate_failures"] or policy_failures(report)),
400
402
  # Stated at the top level so a caller cannot mistake an audit that
401
403
  # ran six built-in detectors for one that ran ten tools. Two
402
404
  # reports with different coverage are not comparable (P8).
@@ -321,10 +321,12 @@ class CohesionAdapter(BaseAdapter):
321
321
  super().__init__(
322
322
  slug="cohesion", emits="metric", executable="cohesion",
323
323
  concepts=("cohesion",), exclude_dialect="files",
324
- # Its CLI takes files or a directory and has no version flag,
325
- # so availability is answered from package metadata, the same
326
- # arrangement multimetric already uses.
327
- distribution="cohesion",
324
+ # Its CLI takes files or a directory and has no version flag, so
325
+ # the version comes from package metadata — and availability
326
+ # from `--help`, the arrangement multimetric uses. The probe was
327
+ # `--version`, which argparse rejects with exit 2, so cohesion
328
+ # was recorded as failed without ever being asked to run.
329
+ version_flag="--help", distribution="cohesion",
328
330
  )
329
331
 
330
332
  def has_targets(self, root: Path, excludes: Sequence[str] = ()) -> bool:
@@ -55,7 +55,9 @@ def open_regular_file(path: Path, why: str) -> int:
55
55
  """
56
56
  import stat as stat_module
57
57
 
58
- handle = os.open(path, os.O_RDONLY | os.O_NONBLOCK)
58
+ # Windows has no `O_NONBLOCK` and no POSIX FIFO in the tree to guard
59
+ # against; using the flag unconditionally killed every read there.
60
+ handle = os.open(path, os.O_RDONLY | getattr(os, "O_NONBLOCK", 0))
59
61
  if not stat_module.S_ISREG(os.fstat(handle).st_mode):
60
62
  os.close(handle)
61
63
  raise PathNotAllowed(f"{path} is not a regular file. {why}")
@@ -134,7 +134,10 @@ class InterrogateAdapter(BaseAdapter):
134
134
  super().__init__(
135
135
  slug="interrogate", emits="metric", executable="interrogate",
136
136
  concepts=("documentation",), findings_exit_codes=(0, 1),
137
- exclude_flag="--exclude", exclude_separator=" ",
137
+ # One `--exclude` per path: interrogate names one location per
138
+ # flag, and a space-joined list named none, so excluded trees
139
+ # were analysed and one unparseable file in them crashed it.
140
+ exclude_flag="--exclude", exclude_repeat=True,
138
141
  exclude_dialect="abspath",
139
142
  )
140
143
 
@@ -7,6 +7,7 @@ from typing import Any
7
7
  # Re-exported: the defaults live in `_config_defaults`, this module is
8
8
  # still the door every caller comes through.
9
9
  from . import __version__ as _package_version
10
+ from ._changed_code_policy import validate as validate_changed_code_policy
10
11
  from ._config_defaults import DEFAULT_CONFIG, DEFAULT_IDIOM_GROUPS
11
12
  from ._operator_reads import (
12
13
  MAX_OPERATOR_FILE_BYTES as MAX_OPERATOR_FILE_BYTES,
@@ -161,12 +162,30 @@ def load_config(path: str | None) -> dict[str, Any]:
161
162
  return config
162
163
  config["analyzers"]["run"] = True
163
164
  if user_tier is not None:
164
- deep_update(config, user_tier)
165
+ _merge_tier(config, user_tier)
165
166
  if path:
166
- deep_update(config, _host_authority_stripped(_configured(Path(path))))
167
+ _merge_tier(config, _host_authority_stripped(_configured(Path(path))))
168
+ validate_changed_code_policy(config)
167
169
  return config
168
170
 
169
171
 
172
+ def _merge_tier(config: dict[str, Any], tier: dict[str, Any]) -> None:
173
+ """One tier over the ones before it, with `exclude_additional` appended.
174
+
175
+ `deep_update` replaces lists, so setting `paths.exclude_patterns` to add
176
+ one directory discarded every default exclusion and froze a copy that
177
+ drifts on the next release (#292). `exclude_additional` adds to whatever
178
+ the earlier tiers produced instead, so a repository can add without
179
+ restating.
180
+ """
181
+ added = list((tier.get("paths") or {}).get("exclude_additional") or [])
182
+ deep_update(config, tier)
183
+ paths = config["paths"]
184
+ paths.pop("exclude_additional", None)
185
+ paths["exclude_patterns"] = [*paths["exclude_patterns"],
186
+ *(p for p in added if p not in paths["exclude_patterns"])]
187
+
188
+
170
189
  #: The one key a repository may state and this tool will not act on,
171
190
  #: because acting on it runs a program of the tree's choosing on the host.
172
191
  #: The whole leaf is dropped, not merged.
@@ -178,11 +178,32 @@ def render_markdown(report: dict[str, Any], *, complete: bool = True) -> str:
178
178
 
179
179
 
180
180
  def _hard_gate_lines(report: dict[str, Any]) -> list[str]:
181
- """The hard-gate list, printed the same way wherever it appears."""
182
- if not report["hard_gate_failures"]:
181
+ """The hard-gate list, printed the same way wherever it appears.
182
+
183
+ The changed-code policy follows it: also a gate, never a grade
184
+ (Decision 15), so it is printed wherever the gates are.
185
+ """
186
+ lines: list[str] = []
187
+ if report["hard_gate_failures"]:
188
+ lines += ["## Hard Gate Failures", "",
189
+ *(f"- {gate}" for gate in report["hard_gate_failures"]), ""]
190
+ return lines + _policy_lines(report)
191
+
192
+
193
+ def _policy_lines(report: dict[str, Any]) -> list[str]:
194
+ policy = report.get("policy")
195
+ if not policy:
183
196
  return []
184
- return ["## Hard Gate Failures", "",
185
- *(f"- {gate}" for gate in report["hard_gate_failures"]), ""]
197
+ failures = policy.get("failures") or []
198
+ head = (f"{policy.get('touched_functions', 0)} function(s) touched by "
199
+ f"`{policy.get('revspec')}` are held to this repository's stricter limits; "
200
+ "the grade is unaffected.")
201
+ if not failures:
202
+ return ["## Changed-code policy", "", head + " All of them meet it.", ""]
203
+ rows = [f"| `{f['path']}:{f['start_line']}` | `{f['name']}` | {f['measure']} | {f['value']} | {f['limit']} |"
204
+ for f in failures]
205
+ return ["## Changed-code policy", "", head, "",
206
+ "| Location | Function | Measure | Value | Limit |", "|---|---|---|---|---|", *rows, ""]
186
207
 
187
208
 
188
209
  def _no_work_order_lines() -> list[str]: