maintainability-agent 3.3.0__tar.gz → 3.5.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 (379) hide show
  1. {maintainability_agent-3.3.0/src/maintainability_agent.egg-info → maintainability_agent-3.5.0}/PKG-INFO +59 -25
  2. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/README.md +57 -24
  3. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/pyproject.toml +2 -2
  4. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0/src/maintainability_agent.egg-info}/PKG-INFO +59 -25
  5. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_agent.egg-info/SOURCES.txt +3 -0
  6. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_agent.egg-info/requires.txt +1 -0
  7. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/__init__.py +1 -1
  8. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_prompt_sections.py +15 -1
  9. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_scan_history.py +37 -14
  10. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_work_order.py +74 -2
  11. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/cli.py +71 -10
  12. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/config.py +1 -1
  13. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/mcp_server.py +7 -3
  14. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/metrics.py +60 -2
  15. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/renderers.py +49 -13
  16. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_backfill.py +1 -1
  17. maintainability_agent-3.5.0/tests/test_chat_leads_with_the_work_order.py +171 -0
  18. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_child_sandbox.py +1 -1
  19. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_ci_installs_the_analyzer_pool.py +48 -0
  20. maintainability_agent-3.5.0/tests/test_demo_tree.py +172 -0
  21. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_determinism.py +1 -1
  22. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_dimension_ratchet.py +1 -1
  23. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_finding_identity.py +56 -0
  24. maintainability_agent-3.5.0/tests/test_mcp_format_contract.py +81 -0
  25. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_operator_named_reads.py +143 -0
  26. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_platform_claim.py +9 -1
  27. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_prove_falsifiers.py +59 -0
  28. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_recurrence.py +1 -1
  29. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_run_comparison.py +9 -3
  30. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scan_history.py +54 -4
  31. maintainability_agent-3.5.0/tests/test_stdout_outputs.py +130 -0
  32. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_trends.py +1 -1
  33. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_write_boundary.py +1 -1
  34. maintainability_agent-3.3.0/tests/test_mcp_format_contract.py +0 -22
  35. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/LICENSE +0 -0
  36. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/setup.cfg +0 -0
  37. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  38. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  39. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  40. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/__main__.py +0 -0
  41. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_adapters.py +0 -0
  42. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_analysis.py +0 -0
  43. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_analyzer_sections.py +0 -0
  44. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_anchor.py +0 -0
  45. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_arguments.py +0 -0
  46. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_aspects.py +0 -0
  47. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  48. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_assets/standard.md +0 -0
  49. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_attestation.py +0 -0
  50. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_backfill.py +0 -0
  51. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_bands.py +0 -0
  52. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_banner.py +0 -0
  53. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_built_ins.py +0 -0
  54. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_calibration.py +0 -0
  55. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_catalog.py +0 -0
  56. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_charts.py +0 -0
  57. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_cognitive.py +0 -0
  58. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_config_defaults.py +0 -0
  59. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_conformance.py +0 -0
  60. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_corroborate.py +0 -0
  61. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_coverage_notes.py +0 -0
  62. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_criteria_scope.py +0 -0
  63. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_delegated_pillar.py +0 -0
  64. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_derive.py +0 -0
  65. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_discovery.py +0 -0
  66. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_documents.py +0 -0
  67. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_economics.py +0 -0
  68. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_economics_view.py +0 -0
  69. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_environment.py +0 -0
  70. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_evidence_reader.py +0 -0
  71. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_evidence_view.py +0 -0
  72. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_finding_match.py +0 -0
  73. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_first_run.py +0 -0
  74. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_formula.py +0 -0
  75. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_gates.py +0 -0
  76. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_generic.py +0 -0
  77. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_grammar.py +0 -0
  78. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_grant_ledger.py +0 -0
  79. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_history_view.py +0 -0
  80. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
  81. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_hotspots.py +0 -0
  82. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_html_report_sections.py +0 -0
  83. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_html_view.py +0 -0
  84. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_identity.py +0 -0
  85. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_in_loop.py +0 -0
  86. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_in_loop_view.py +0 -0
  87. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
  88. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_markdown_sections.py +0 -0
  89. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_masking.py +0 -0
  90. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_audit.py +0 -0
  91. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_gate.py +0 -0
  92. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_grants.py +0 -0
  93. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
  94. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_resources.py +0 -0
  95. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_mcp_setup.py +0 -0
  96. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_metric_adapters.py +0 -0
  97. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_metrics_types.py +0 -0
  98. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_operator_reads.py +0 -0
  99. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_pillars.py +0 -0
  100. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_practice.py +0 -0
  101. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_precommit.py +0 -0
  102. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_precommit_install.py +0 -0
  103. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_precommit_view.py +0 -0
  104. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_pressures.py +0 -0
  105. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_c.py +0 -0
  106. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
  107. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_core.py +0 -0
  108. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
  109. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
  110. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
  111. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_go.py +0 -0
  112. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_java.py +0 -0
  113. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_js.py +0 -0
  114. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_php.py +0 -0
  115. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_ruby.py +0 -0
  116. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_rust.py +0 -0
  117. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ranges_swift.py +0 -0
  118. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ratchet.py +0 -0
  119. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_ratio_adapters.py +0 -0
  120. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_recurrence.py +0 -0
  121. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_run_comparison.py +0 -0
  122. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_runner.py +0 -0
  123. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_safe_write.py +0 -0
  124. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_scan_view.py +0 -0
  125. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_second_source.py +0 -0
  126. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_selection.py +0 -0
  127. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_semantic.py +0 -0
  128. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_semantic_policy.py +0 -0
  129. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_semantic_ts.py +0 -0
  130. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_semantic_view.py +0 -0
  131. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_setup_errors.py +0 -0
  132. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_setup_persist.py +0 -0
  133. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  134. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  135. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  136. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  137. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  138. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  139. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_skill_install.py +0 -0
  140. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_stored_grants.py +0 -0
  141. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_tdd_view.py +0 -0
  142. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_test_commands.py +0 -0
  143. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_test_execution.py +0 -0
  144. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_test_pairing.py +0 -0
  145. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_tokens.py +0 -0
  146. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_tool_adapters.py +0 -0
  147. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_trends.py +0 -0
  148. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_user_config.py +0 -0
  149. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
  150. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_verification.py +0 -0
  151. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_work_order_view.py +0 -0
  152. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_work_order_weights.py +0 -0
  153. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/_xml.py +0 -0
  154. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/baseline.py +0 -0
  155. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/deadcode.py +0 -0
  156. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/declarations.py +0 -0
  157. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/duplication.py +0 -0
  158. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/evidence.py +0 -0
  159. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/git_tools.py +0 -0
  160. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/history.py +0 -0
  161. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/idioms.py +0 -0
  162. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/instructions.py +0 -0
  163. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/prompts.py +0 -0
  164. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/report.py +0 -0
  165. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/sarif.py +0 -0
  166. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/scoring.py +0 -0
  167. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/similarity.py +0 -0
  168. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/src/maintainability_audit/source.py +0 -0
  169. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_acquisition_trust.py +0 -0
  170. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_adapter_docs.py +0 -0
  171. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_adapter_recordings.py +0 -0
  172. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_adapters.py +0 -0
  173. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_added_lines.py +0 -0
  174. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analysis_coverage.py +0 -0
  175. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analysis_execution.py +0 -0
  176. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_bridge.py +0 -0
  177. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_config_isolation.py +0 -0
  178. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_estimate_claims.py +0 -0
  179. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_pinning.py +0 -0
  180. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_primary_estimate.py +0 -0
  181. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_provenance.py +0 -0
  182. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
  183. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_scoring_path.py +0 -0
  184. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_spread_range.py +0 -0
  185. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_analyzer_xml_bounds.py +0 -0
  186. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_anchor_and_mode.py +0 -0
  187. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_anchor_disclosure.py +0 -0
  188. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_annotations_match_behaviour.py +0 -0
  189. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_anticipated_refusals.py +0 -0
  190. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_architecture.py +0 -0
  191. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_artifact_write_route_class.py +0 -0
  192. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_aspect_coverage.py +0 -0
  193. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_asset_snapshot_class.py +0 -0
  194. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
  195. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_attestation.py +0 -0
  196. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_audit_components.py +0 -0
  197. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_authorization_freshness.py +0 -0
  198. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_authorship_gates.py +0 -0
  199. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_band_concealment_class.py +0 -0
  200. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_band_concealment_p3.py +0 -0
  201. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_band_pressures.py +0 -0
  202. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_bands.py +0 -0
  203. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_body_or_signature_class.py +0 -0
  204. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_c_declarations.py +0 -0
  205. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_calibration_corpus.py +0 -0
  206. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_calibration_drift.py +0 -0
  207. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_calibration_tooling.py +0 -0
  208. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_catalog_selection.py +0 -0
  209. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_catalog_tier_promise.py +0 -0
  210. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_chat_primary_docs.py +0 -0
  211. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_check_refuses_plus_only_fragments.py +0 -0
  212. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_checkstyle_adapter.py +0 -0
  213. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_checkstyle_catalog.py +0 -0
  214. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_ci_history_recipe.py +0 -0
  215. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_claimed_languages.py +0 -0
  216. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_cli.py +0 -0
  217. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_clone_group_class.py +0 -0
  218. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_cobol_declarations.py +0 -0
  219. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_cognitive_complexity.py +0 -0
  220. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_cohort_statistics.py +0 -0
  221. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_concealment_properties.py +0 -0
  222. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_config_shape.py +0 -0
  223. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_consent_and_grant.py +0 -0
  224. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_consumer_migration.py +0 -0
  225. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_contract_claims.py +0 -0
  226. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_corroborate.py +0 -0
  227. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_coverage_by_language.py +0 -0
  228. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_cpp_declarations.py +0 -0
  229. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_criteria_completion.py +0 -0
  230. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_csharp_declarations.py +0 -0
  231. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_d15_composition.py +0 -0
  232. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_d15_goal_directed.py +0 -0
  233. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_dead_code.py +0 -0
  234. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declaration_criteria_scope.py +0 -0
  235. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declaration_edge_cases.py +0 -0
  236. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declaration_grading.py +0 -0
  237. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declaration_ranges.py +0 -0
  238. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declaration_source.py +0 -0
  239. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declarative_parsers.py +0 -0
  240. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declared_authorship.py +0 -0
  241. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_declared_imports.py +0 -0
  242. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_delegated_security_pillar.py +0 -0
  243. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_derivation_mix.py +0 -0
  244. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_direct_runner_availability_class.py +0 -0
  245. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_discovery.py +0 -0
  246. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_doc_claims.py +0 -0
  247. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_docs_links.py +0 -0
  248. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_economic_context.py +0 -0
  249. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_empty_output_not_clean.py +0 -0
  250. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
  251. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_environment_work_order.py +0 -0
  252. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_evidence_invariants.py +0 -0
  253. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_evidence_normalization.py +0 -0
  254. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_evidence_properties.py +0 -0
  255. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_exclusion_dialects.py +0 -0
  256. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_falsifier_standard.py +0 -0
  257. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_file_list_cap_class.py +0 -0
  258. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_first_run_elicitation.py +0 -0
  259. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_first_run_prompt.py +0 -0
  260. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_first_run_reelicitation.py +0 -0
  261. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_fix_breadth_window.py +0 -0
  262. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_fixed_form_fortran.py +0 -0
  263. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_format_ask.py +0 -0
  264. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_fortran_declarations.py +0 -0
  265. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_fortran_metrics.py +0 -0
  266. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_fortran_practice.py +0 -0
  267. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_git_argv.py +0 -0
  268. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_git_read_only.py +0 -0
  269. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_git_readonly_class.py +0 -0
  270. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_go_declarations.py +0 -0
  271. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_grammar_constructs.py +0 -0
  272. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_grammar_token_coverage.py +0 -0
  273. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_grant_only_user_tier.py +0 -0
  274. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_history.py +0 -0
  275. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_history_boundary.py +0 -0
  276. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_history_manifest.py +0 -0
  277. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_history_schema2.py +0 -0
  278. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_history_window.py +0 -0
  279. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_hostile_prompt.py +0 -0
  280. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_html_executive.py +0 -0
  281. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_html_section_parity_class.py +0 -0
  282. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_identity_docs.py +0 -0
  283. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_identity_resolution.py +0 -0
  284. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_idiom_divergence.py +0 -0
  285. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_in_loop_budgets.py +0 -0
  286. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_in_loop_check.py +0 -0
  287. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_installed_wheel_runtime.py +0 -0
  288. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_instruction_targets.py +0 -0
  289. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_java_range_guard.py +0 -0
  290. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_java_ranges.py +0 -0
  291. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_java_scored.py +0 -0
  292. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_java_wiring.py +0 -0
  293. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_js_complexity_operators.py +0 -0
  294. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_js_declarations.py +0 -0
  295. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_language_coverage.py +0 -0
  296. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_language_support_honesty.py +0 -0
  297. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_mcp_baseline_payload.py +0 -0
  298. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_mcp_history.py +0 -0
  299. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_mcp_server.py +0 -0
  300. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_migration_1_0.py +0 -0
  301. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_near_duplicates.py +0 -0
  302. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_network_disclosure.py +0 -0
  303. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
  304. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_operator_named_paths.py +0 -0
  305. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pairing_reads_imports.py +0 -0
  306. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pattern_budget.py +0 -0
  307. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_phase6_claims.py +0 -0
  308. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_php_declarations.py +0 -0
  309. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pillars_and_practice.py +0 -0
  310. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pmd_adapter.py +0 -0
  311. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pmd_audit_closures.py +0 -0
  312. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_policy_claims.py +0 -0
  313. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_pool_runs_by_config.py +0 -0
  314. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_population_floors.py +0 -0
  315. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_practice_nested_gates_class.py +0 -0
  316. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_precommit_staged.py +0 -0
  317. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_presentation_refusals.py +0 -0
  318. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_promises.py +0 -0
  319. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_prompt_escalation_once.py +0 -0
  320. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_prompt_honesty.py +0 -0
  321. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_prompt_location_escalation_class.py +0 -0
  322. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_python_complexity.py +0 -0
  323. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_python_declarations.py +0 -0
  324. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_read_boundary.py +0 -0
  325. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_readme_claims.py +0 -0
  326. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_release_needs_an_empty_ledger.py +0 -0
  327. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_release_plan.py +0 -0
  328. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_release_plan_status.py +0 -0
  329. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_report_remedy_copy.py +0 -0
  330. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_roles_recorded.py +0 -0
  331. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_root_grants.py +0 -0
  332. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  333. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_ruby_declarations.py +0 -0
  334. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_runner.py +0 -0
  335. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_rust_declarations.py +0 -0
  336. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_sarif.py +0 -0
  337. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scan_scope.py +0 -0
  338. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scanner_unsafe_direction.py +0 -0
  339. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scanning.py +0 -0
  340. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_schema_fidelity.py +0 -0
  341. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scope_conformance.py +0 -0
  342. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_scoring_calibration.py +0 -0
  343. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_semantic_policy.py +0 -0
  344. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_setup_gate_completeness.py +0 -0
  345. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_setup_gate_independent_contract.py +0 -0
  346. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_setup_precondition.py +0 -0
  347. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_skill_install.py +0 -0
  348. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_sonar_resolve.py +0 -0
  349. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_source_index.py +0 -0
  350. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_spotbugs_adapter.py +0 -0
  351. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_spotbugs_catalog.py +0 -0
  352. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_stage8_contract.py +0 -0
  353. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_suite_isolation.py +0 -0
  354. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_swift_declarations.py +0 -0
  355. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_tdd_structure.py +0 -0
  356. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_terminal_asks_the_same_questions.py +0 -0
  357. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_test_commands.py +0 -0
  358. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_test_execution_class.py +0 -0
  359. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_three_presentations.py +0 -0
  360. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_tool_resolution.py +0 -0
  361. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
  362. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_tree_chosen_spawn.py +0 -0
  363. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_tree_reads_use_the_primitive.py +0 -0
  364. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_type_fields_not_functions_class.py +0 -0
  365. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_uat_falsifiers.py +0 -0
  366. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_unanchored_set_matches_corpus.py +0 -0
  367. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_unread_code.py +0 -0
  368. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_user_config_tier.py +0 -0
  369. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_verification_audit_closures.py +0 -0
  370. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_verified_grade.py +0 -0
  371. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_version_claim.py +0 -0
  372. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_wheel_contents.py +0 -0
  373. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_work_order.py +0 -0
  374. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
  375. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_work_order_items.py +0 -0
  376. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_work_order_selection.py +0 -0
  377. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_workflow_supply_chain.py +0 -0
  378. {maintainability_agent-3.3.0 → maintainability_agent-3.5.0}/tests/test_write_route_class.py +0 -0
  379. {maintainability_agent-3.3.0 → maintainability_agent-3.5.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: 3.3.0
3
+ Version: 3.5.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -29,6 +29,7 @@ Requires-Dist: mcp<3,>=2; extra == "mcp"
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: pytest>=8; extra == "dev"
31
31
  Requires-Dist: pytest-cov>=5; extra == "dev"
32
+ Requires-Dist: pytest-xdist>=3.6; extra == "dev"
32
33
  Requires-Dist: jsonschema>=4; extra == "dev"
33
34
  Requires-Dist: ruff>=0.5; extra == "dev"
34
35
  Requires-Dist: pip-audit>=2.7; extra == "dev"
@@ -45,12 +46,7 @@ Dynamic: license-file
45
46
  **A deterministic, offline maintainability audit whose output is a _bounded
46
47
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
47
48
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
48
- Version **3.3.0**.
49
-
50
- **Planned, not shipped:** the audit tool will become `maintainability-audit`;
51
- a new `maintainability-agent` companion will run it and automate human-selected
52
- work orders within the user's agent chat. The installation commands below
53
- still describe the current product. See the [planned split](docs/product-intent.md#planned-product-split-and-companion-workflow).
49
+ Version **3.5.0**.
54
50
 
55
51
  **Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
56
52
  COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -65,6 +61,51 @@ pip install "maintainability-agent[mcp]" # optional local MCP server for chat
65
61
  cp -r skills/maintainability-agent ~/.claude/skills/ # Claude Code slash command
66
62
  ```
67
63
 
64
+ **Install the analyzer pool too, or you get the built-in tier.** This tool
65
+ prefers established analyzers and falls back to its own detectors when none is
66
+ present. The fallback is honest — the report says `Estimate source: built-in
67
+ detectors` and the coverage section names what nothing examined — but it is a
68
+ weaker reading than the tool is capable of, and a first run without these is
69
+ the commonest reason it looks thin.
70
+
71
+ ```bash
72
+ pip install cohesion complexipy flake8 fortitude-lint interrogate lizard \
73
+ multimetric mypy pydocstyle pylint radon ruff vulture
74
+ npm install -g jscpd eslint # duplication + JavaScript/TypeScript
75
+ brew install pmd checkstyle spotbugs # JVM languages, optional
76
+ ```
77
+
78
+ Unpinned on purpose: this is the exact set CI installs and calibrates against,
79
+ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
80
+ disagree. Nothing here is required — the audit runs without any of it and tells
81
+ you what it could not measure.
82
+
83
+ **One command to a work order.** A config file is the whole setup — with one
84
+ present, nothing is asked and nothing is written into your tree:
85
+
86
+ ```bash
87
+ curl -O https://raw.githubusercontent.com/marshallguillory86/maintainability-agent/main/maintainability-audit.example.json
88
+ maintainability-audit --config maintainability-audit.example.json \
89
+ --output report.md --prompt-output prompt.md
90
+ ```
91
+
92
+ `prompt.md` is the bounded work order: the findings worth fixing, in order,
93
+ each with its location, why it matters and the command that verifies it — and
94
+ the standing rule that nothing else gets refactored. Paste it into your agent.
95
+ `report.md` is the evidence behind it. The prompt is the product.
96
+
97
+ **Want to see the output before pointing it at your own code?**
98
+ [`examples/demo`](examples/demo/) is a two-module order system with real
99
+ problems in it — an overgrown pricing function, a money path nothing tests, and
100
+ a block duplicated between billing and invoicing. Four items, three finding
101
+ classes, a copy-paste prompt each, and it reads in under a minute. The work
102
+ order it produces is checked in at
103
+ [`expected-prompt.md`](examples/demo/expected-prompt.md).
104
+
105
+ Without `--config`, an interactive run asks the first-run questions instead —
106
+ analyzer pool, depth, licence policy, whether to run your suite — because those
107
+ are choices this tool will not make on your behalf.
108
+
68
109
  ---
69
110
 
70
111
  ## Executive summary
@@ -128,15 +169,6 @@ The full argument, including what this deliberately does not compete on:
128
169
  [why this exists](docs/why-this-exists.md) and
129
170
  [philosophy](docs/philosophy.md).
130
171
 
131
- ## The road to 1.0
132
-
133
- 1.0 was the line drawn under a long arc of **subtraction** — what remained after
134
- every claim the project could not stand behind was removed. A scoring engine
135
- rebuilt after it was found to grade repo *size*; a headline claim about AI
136
- authorship retracted against a matched control; a score that is withheld rather
137
- than guessed. That arc is the credibility, and it is recorded in full, with the
138
- figures quoted from their approved summaries, in [the track record](docs/track-record.md).
139
-
140
172
  ## Install
141
173
 
142
174
  ```bash
@@ -380,19 +412,21 @@ it was generated against — a provenance record, not a claim about HEAD.
380
412
 
381
413
  | Metric | Value |
382
414
  |---|---:|
383
- | Maintainability estimate | 4.2 / 5 |
415
+ | Maintainability estimate | 4.5 / 5 |
384
416
  | Verified grade | B |
385
- | Files scanned | 476 |
417
+ | Files scanned | 511 |
386
418
  | Hard gate failures | 0 |
387
419
 
388
420
  A **B**, and the report says why: the grade is verified against the evidence
389
- *floor* of 4.1 rather than the 4.2 point estimate, because an unmeasured aspect
390
- prices at 0 when a grade has to be defended; and testability is capped at 4.0 by
391
- an unpaired production unit in the fail band. Those are measured against
392
- thresholds this repo sets stricter than the shipped defaults, and every threshold
393
- gate is opted **on** for its own CI, so drifting below the bar fails the build
394
- rather than the README. The full stamped table — warnings, duplication, risk
395
- findings — is in the report itself.
421
+ *floor* of 4.2 rather than the 4.5 point estimate, because an unmeasured aspect
422
+ prices at 0 when a grade has to be defended. Every threshold gate is opted
423
+ **on** for this repository's own CI, so drifting below the bar fails the build
424
+ rather than the README.
425
+
426
+ The tool reports warn-band declarations here and they are not treated as
427
+ defects — see [what counts as a defect](docs/product-intent.md#what-counts-as-a-defect-and-what-does-not).
428
+ Restyling this codebase to raise its own grade is explicitly not work: a tool
429
+ that games its own metric has broken the only promise that matters.
396
430
 
397
431
  ## Platform support
398
432
 
@@ -5,12 +5,7 @@
5
5
  **A deterministic, offline maintainability audit whose output is a _bounded
6
6
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
7
7
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
8
- Version **3.3.0**.
9
-
10
- **Planned, not shipped:** the audit tool will become `maintainability-audit`;
11
- a new `maintainability-agent` companion will run it and automate human-selected
12
- work orders within the user's agent chat. The installation commands below
13
- still describe the current product. See the [planned split](docs/product-intent.md#planned-product-split-and-companion-workflow).
8
+ Version **3.5.0**.
14
9
 
15
10
  **Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
16
11
  COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -25,6 +20,51 @@ pip install "maintainability-agent[mcp]" # optional local MCP server for chat
25
20
  cp -r skills/maintainability-agent ~/.claude/skills/ # Claude Code slash command
26
21
  ```
27
22
 
23
+ **Install the analyzer pool too, or you get the built-in tier.** This tool
24
+ prefers established analyzers and falls back to its own detectors when none is
25
+ present. The fallback is honest — the report says `Estimate source: built-in
26
+ detectors` and the coverage section names what nothing examined — but it is a
27
+ weaker reading than the tool is capable of, and a first run without these is
28
+ the commonest reason it looks thin.
29
+
30
+ ```bash
31
+ pip install cohesion complexipy flake8 fortitude-lint interrogate lizard \
32
+ multimetric mypy pydocstyle pylint radon ruff vulture
33
+ npm install -g jscpd eslint # duplication + JavaScript/TypeScript
34
+ brew install pmd checkstyle spotbugs # JVM languages, optional
35
+ ```
36
+
37
+ Unpinned on purpose: this is the exact set CI installs and calibrates against,
38
+ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
39
+ disagree. Nothing here is required — the audit runs without any of it and tells
40
+ you what it could not measure.
41
+
42
+ **One command to a work order.** A config file is the whole setup — with one
43
+ present, nothing is asked and nothing is written into your tree:
44
+
45
+ ```bash
46
+ curl -O https://raw.githubusercontent.com/marshallguillory86/maintainability-agent/main/maintainability-audit.example.json
47
+ maintainability-audit --config maintainability-audit.example.json \
48
+ --output report.md --prompt-output prompt.md
49
+ ```
50
+
51
+ `prompt.md` is the bounded work order: the findings worth fixing, in order,
52
+ each with its location, why it matters and the command that verifies it — and
53
+ the standing rule that nothing else gets refactored. Paste it into your agent.
54
+ `report.md` is the evidence behind it. The prompt is the product.
55
+
56
+ **Want to see the output before pointing it at your own code?**
57
+ [`examples/demo`](examples/demo/) is a two-module order system with real
58
+ problems in it — an overgrown pricing function, a money path nothing tests, and
59
+ a block duplicated between billing and invoicing. Four items, three finding
60
+ classes, a copy-paste prompt each, and it reads in under a minute. The work
61
+ order it produces is checked in at
62
+ [`expected-prompt.md`](examples/demo/expected-prompt.md).
63
+
64
+ Without `--config`, an interactive run asks the first-run questions instead —
65
+ analyzer pool, depth, licence policy, whether to run your suite — because those
66
+ are choices this tool will not make on your behalf.
67
+
28
68
  ---
29
69
 
30
70
  ## Executive summary
@@ -88,15 +128,6 @@ The full argument, including what this deliberately does not compete on:
88
128
  [why this exists](docs/why-this-exists.md) and
89
129
  [philosophy](docs/philosophy.md).
90
130
 
91
- ## The road to 1.0
92
-
93
- 1.0 was the line drawn under a long arc of **subtraction** — what remained after
94
- every claim the project could not stand behind was removed. A scoring engine
95
- rebuilt after it was found to grade repo *size*; a headline claim about AI
96
- authorship retracted against a matched control; a score that is withheld rather
97
- than guessed. That arc is the credibility, and it is recorded in full, with the
98
- figures quoted from their approved summaries, in [the track record](docs/track-record.md).
99
-
100
131
  ## Install
101
132
 
102
133
  ```bash
@@ -340,19 +371,21 @@ it was generated against — a provenance record, not a claim about HEAD.
340
371
 
341
372
  | Metric | Value |
342
373
  |---|---:|
343
- | Maintainability estimate | 4.2 / 5 |
374
+ | Maintainability estimate | 4.5 / 5 |
344
375
  | Verified grade | B |
345
- | Files scanned | 476 |
376
+ | Files scanned | 511 |
346
377
  | Hard gate failures | 0 |
347
378
 
348
379
  A **B**, and the report says why: the grade is verified against the evidence
349
- *floor* of 4.1 rather than the 4.2 point estimate, because an unmeasured aspect
350
- prices at 0 when a grade has to be defended; and testability is capped at 4.0 by
351
- an unpaired production unit in the fail band. Those are measured against
352
- thresholds this repo sets stricter than the shipped defaults, and every threshold
353
- gate is opted **on** for its own CI, so drifting below the bar fails the build
354
- rather than the README. The full stamped table — warnings, duplication, risk
355
- findings — is in the report itself.
380
+ *floor* of 4.2 rather than the 4.5 point estimate, because an unmeasured aspect
381
+ prices at 0 when a grade has to be defended. Every threshold gate is opted
382
+ **on** for this repository's own CI, so drifting below the bar fails the build
383
+ rather than the README.
384
+
385
+ The tool reports warn-band declarations here and they are not treated as
386
+ defects — see [what counts as a defect](docs/product-intent.md#what-counts-as-a-defect-and-what-does-not).
387
+ Restyling this codebase to raise its own grade is explicitly not work: a tool
388
+ that games its own metric has broken the only promise that matters.
356
389
 
357
390
  ## Platform support
358
391
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maintainability-agent"
7
- version = "3.3.0"
7
+ version = "3.5.0"
8
8
  description = "Maintainability gate and AI remediation prompt generator for CI."
9
9
  readme = "README.md"
10
10
  # 3.11, not 3.10. `_discovery`, `_pillars` and `_runner` all import
@@ -58,7 +58,7 @@ mcp = ["mcp>=2,<3"]
58
58
  # development dependency, never a runtime one: nothing the product
59
59
  # ships imports it, and the oracle exists so a measurement can be
60
60
  # checked against something other than its author.
61
- dev = ["pytest>=8", "pytest-cov>=5", "jsonschema>=4", "ruff>=0.5", "pip-audit>=2.7", "mcp>=2,<3", "PyYAML>=6", "setuptools>=70", "lizard>=1.17"]
61
+ 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"]
62
62
 
63
63
  [tool.setuptools.package-data]
64
64
  # `_assets` carries the runtime data the code cannot work without: the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 3.3.0
3
+ Version: 3.5.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -29,6 +29,7 @@ Requires-Dist: mcp<3,>=2; extra == "mcp"
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: pytest>=8; extra == "dev"
31
31
  Requires-Dist: pytest-cov>=5; extra == "dev"
32
+ Requires-Dist: pytest-xdist>=3.6; extra == "dev"
32
33
  Requires-Dist: jsonschema>=4; extra == "dev"
33
34
  Requires-Dist: ruff>=0.5; extra == "dev"
34
35
  Requires-Dist: pip-audit>=2.7; extra == "dev"
@@ -45,12 +46,7 @@ Dynamic: license-file
45
46
  **A deterministic, offline maintainability audit whose output is a _bounded
46
47
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
47
48
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
48
- Version **3.3.0**.
49
-
50
- **Planned, not shipped:** the audit tool will become `maintainability-audit`;
51
- a new `maintainability-agent` companion will run it and automate human-selected
52
- work orders within the user's agent chat. The installation commands below
53
- still describe the current product. See the [planned split](docs/product-intent.md#planned-product-split-and-companion-workflow).
49
+ Version **3.5.0**.
54
50
 
55
51
  **Languages parsed:** Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift,
56
52
  COBOL, Fortran (free-form *and* fixed-form), and the JS/TS/HTML family — each
@@ -65,6 +61,51 @@ pip install "maintainability-agent[mcp]" # optional local MCP server for chat
65
61
  cp -r skills/maintainability-agent ~/.claude/skills/ # Claude Code slash command
66
62
  ```
67
63
 
64
+ **Install the analyzer pool too, or you get the built-in tier.** This tool
65
+ prefers established analyzers and falls back to its own detectors when none is
66
+ present. The fallback is honest — the report says `Estimate source: built-in
67
+ detectors` and the coverage section names what nothing examined — but it is a
68
+ weaker reading than the tool is capable of, and a first run without these is
69
+ the commonest reason it looks thin.
70
+
71
+ ```bash
72
+ pip install cohesion complexipy flake8 fortitude-lint interrogate lizard \
73
+ multimetric mypy pydocstyle pylint radon ruff vulture
74
+ npm install -g jscpd eslint # duplication + JavaScript/TypeScript
75
+ brew install pmd checkstyle spotbugs # JVM languages, optional
76
+ ```
77
+
78
+ Unpinned on purpose: this is the exact set CI installs and calibrates against,
79
+ and `test_the_readme_names_the_analyzer_pool_ci_installs` fails if the two ever
80
+ disagree. Nothing here is required — the audit runs without any of it and tells
81
+ you what it could not measure.
82
+
83
+ **One command to a work order.** A config file is the whole setup — with one
84
+ present, nothing is asked and nothing is written into your tree:
85
+
86
+ ```bash
87
+ curl -O https://raw.githubusercontent.com/marshallguillory86/maintainability-agent/main/maintainability-audit.example.json
88
+ maintainability-audit --config maintainability-audit.example.json \
89
+ --output report.md --prompt-output prompt.md
90
+ ```
91
+
92
+ `prompt.md` is the bounded work order: the findings worth fixing, in order,
93
+ each with its location, why it matters and the command that verifies it — and
94
+ the standing rule that nothing else gets refactored. Paste it into your agent.
95
+ `report.md` is the evidence behind it. The prompt is the product.
96
+
97
+ **Want to see the output before pointing it at your own code?**
98
+ [`examples/demo`](examples/demo/) is a two-module order system with real
99
+ problems in it — an overgrown pricing function, a money path nothing tests, and
100
+ a block duplicated between billing and invoicing. Four items, three finding
101
+ classes, a copy-paste prompt each, and it reads in under a minute. The work
102
+ order it produces is checked in at
103
+ [`expected-prompt.md`](examples/demo/expected-prompt.md).
104
+
105
+ Without `--config`, an interactive run asks the first-run questions instead —
106
+ analyzer pool, depth, licence policy, whether to run your suite — because those
107
+ are choices this tool will not make on your behalf.
108
+
68
109
  ---
69
110
 
70
111
  ## Executive summary
@@ -128,15 +169,6 @@ The full argument, including what this deliberately does not compete on:
128
169
  [why this exists](docs/why-this-exists.md) and
129
170
  [philosophy](docs/philosophy.md).
130
171
 
131
- ## The road to 1.0
132
-
133
- 1.0 was the line drawn under a long arc of **subtraction** — what remained after
134
- every claim the project could not stand behind was removed. A scoring engine
135
- rebuilt after it was found to grade repo *size*; a headline claim about AI
136
- authorship retracted against a matched control; a score that is withheld rather
137
- than guessed. That arc is the credibility, and it is recorded in full, with the
138
- figures quoted from their approved summaries, in [the track record](docs/track-record.md).
139
-
140
172
  ## Install
141
173
 
142
174
  ```bash
@@ -380,19 +412,21 @@ it was generated against — a provenance record, not a claim about HEAD.
380
412
 
381
413
  | Metric | Value |
382
414
  |---|---:|
383
- | Maintainability estimate | 4.2 / 5 |
415
+ | Maintainability estimate | 4.5 / 5 |
384
416
  | Verified grade | B |
385
- | Files scanned | 476 |
417
+ | Files scanned | 511 |
386
418
  | Hard gate failures | 0 |
387
419
 
388
420
  A **B**, and the report says why: the grade is verified against the evidence
389
- *floor* of 4.1 rather than the 4.2 point estimate, because an unmeasured aspect
390
- prices at 0 when a grade has to be defended; and testability is capped at 4.0 by
391
- an unpaired production unit in the fail band. Those are measured against
392
- thresholds this repo sets stricter than the shipped defaults, and every threshold
393
- gate is opted **on** for its own CI, so drifting below the bar fails the build
394
- rather than the README. The full stamped table — warnings, duplication, risk
395
- findings — is in the report itself.
421
+ *floor* of 4.2 rather than the 4.5 point estimate, because an unmeasured aspect
422
+ prices at 0 when a grade has to be defended. Every threshold gate is opted
423
+ **on** for this repository's own CI, so drifting below the bar fails the build
424
+ rather than the README.
425
+
426
+ The tool reports warn-band declarations here and they are not treated as
427
+ defects — see [what counts as a defect](docs/product-intent.md#what-counts-as-a-defect-and-what-does-not).
428
+ Restyling this codebase to raise its own grade is explicitly not work: a tool
429
+ that games its own metric has broken the only promise that matters.
396
430
 
397
431
  ## Platform support
398
432
 
@@ -187,6 +187,7 @@ tests/test_calibration_drift.py
187
187
  tests/test_calibration_tooling.py
188
188
  tests/test_catalog_selection.py
189
189
  tests/test_catalog_tier_promise.py
190
+ tests/test_chat_leads_with_the_work_order.py
190
191
  tests/test_chat_primary_docs.py
191
192
  tests/test_check_refuses_plus_only_fragments.py
192
193
  tests/test_checkstyle_adapter.py
@@ -222,6 +223,7 @@ tests/test_declarative_parsers.py
222
223
  tests/test_declared_authorship.py
223
224
  tests/test_declared_imports.py
224
225
  tests/test_delegated_security_pillar.py
226
+ tests/test_demo_tree.py
225
227
  tests/test_derivation_mix.py
226
228
  tests/test_determinism.py
227
229
  tests/test_dimension_ratchet.py
@@ -342,6 +344,7 @@ tests/test_source_index.py
342
344
  tests/test_spotbugs_adapter.py
343
345
  tests/test_spotbugs_catalog.py
344
346
  tests/test_stage8_contract.py
347
+ tests/test_stdout_outputs.py
345
348
  tests/test_suite_isolation.py
346
349
  tests/test_swift_declarations.py
347
350
  tests/test_tdd_structure.py
@@ -2,6 +2,7 @@
2
2
  [dev]
3
3
  pytest>=8
4
4
  pytest-cov>=5
5
+ pytest-xdist>=3.6
5
6
  jsonschema>=4
6
7
  ruff>=0.5
7
8
  pip-audit>=2.7
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "3.3.0"
3
+ __version__ = "3.5.0"
@@ -178,13 +178,27 @@ def prompt_work_order(report: dict[str, Any]) -> list[str]:
178
178
  for index, item in enumerate(items, start=1):
179
179
  location = item["path"] + (f":{item['line']}" if item.get("line") else "")
180
180
  lines.append(f"{index}. **{item['title']}** — {item['target']}")
181
- lines.append(f" - Location: `{location}`")
181
+ # One row now stands for its whole class (D159), so a count
182
+ # above one says where the rest are rather than leaving the
183
+ # single location reading as the only instance.
184
+ count = item.get("class_count") or 1
185
+ files = item.get("class_paths") or 1
186
+ if count > 1:
187
+ where = f"across {files} files, " if files > 1 else ""
188
+ lines.append(f" - First of {count} {where}starting at: `{location}`")
189
+ else:
190
+ lines.append(f" - Location: `{location}`")
182
191
  lines.append(f" - Why it matters: {item['rationale']}")
183
192
  if item["class_delta"]:
184
193
  lines.append(
185
194
  f" - Clearing all {item['class_count']} of these is worth "
186
195
  f"+{item['class_delta']:.2f} to the maintainability estimate."
187
196
  )
197
+ elif count > 1:
198
+ lines.append(
199
+ f" - The other {count - 1} are listed in the report; the "
200
+ "score does not move until the class is cleared."
201
+ )
188
202
  lines.extend([
189
203
  "",
190
204
  f"Verify with: `{items[0]['verification']}`",
@@ -57,7 +57,7 @@ from .config import PathNotAllowed, read_operator_file
57
57
  # followed. A schema-4 line read by an older build fails that one line's
58
58
  # parse and costs that scan, which is the tolerance `read_history` was
59
59
  # built with rather than a new risk.
60
- HISTORY_SCHEMA_VERSION = 4
60
+ HISTORY_SCHEMA_VERSION = 5
61
61
 
62
62
  DEFAULT_HISTORY_PATH = ".maintainability/history.jsonl"
63
63
 
@@ -70,7 +70,7 @@ DEFAULT_HISTORY_PATH = ".maintainability/history.jsonl"
70
70
  # score being added and not added here, after which trends silently span
71
71
  # a change in the instrument.
72
72
  COMPARABILITY_FIELDS: tuple[str, ...] = (
73
- "rubric_version",
73
+ "tool_version",
74
74
  "calibration",
75
75
  "thresholds_digest",
76
76
  "analyzers",
@@ -102,7 +102,14 @@ class ScanRecord:
102
102
  commit: str
103
103
  branch: str
104
104
  scope: str
105
- rubric_version: str
105
+ #: The version of *this tool* that produced the scan. Named
106
+ #: `rubric_version` until 3.5.0, which is what it was never: a
107
+ #: rubric version would move when the rubric moved, and this moves
108
+ #: on every release. A reader of a stored line saw
109
+ #: `"rubric_version": "3.4.0"` and concluded the rubric had changed
110
+ #: when a patch release was all that happened — on 38 of this
111
+ #: repository's 49 series breaks (D158).
112
+ tool_version: str
106
113
  calibration: float
107
114
  # A digest of the thresholds in force. Stored rather than the
108
115
  # thresholds themselves: the comparison is equality, and a digest
@@ -210,21 +217,28 @@ def comparability_key(record: ScanRecord) -> tuple[Any, ...]:
210
217
 
211
218
 
212
219
  # What each comparability field is, in words a reader can act on. The
213
- # stored names are terse and one of them actively misleads: the field
214
- # called `rubric_version` holds the *package* version, so a reader told
215
- # "rubric_version changed" hears that the rubric moved when a patch
216
- # release is all that happened — and on this repository's own history
217
- # that field accounts for 38 of 49 breaks. The name stays as stored
218
- # (renaming it is a migration of every written line); what the report
219
- # says about it is corrected here, which is where the claim is made.
220
+ # stored names are terse and prose is what a report should print: a
221
+ # break that names `thresholds_digest` tells a reader less than one
222
+ # saying the configured thresholds changed.
223
+ #
224
+ # `tool_version` was `rubric_version` until 3.5.0 and this map was
225
+ # where that lie was first corrected — the display said "the tool
226
+ # version" while the stored field still said otherwise. D158 finished
227
+ # it by renaming the field, so the map and the record now agree instead
228
+ # of one translating the other.
220
229
  FIELD_NAMES: dict[str, str] = {
221
- "rubric_version": "the tool version",
230
+ "tool_version": "the tool version",
222
231
  "calibration": "the calibration constant",
223
232
  "thresholds_digest": "the configured thresholds",
224
233
  "analyzers": "which analyzers contributed",
225
234
  "scored_languages": "the scored languages",
226
235
  "scope": "the scan scope",
227
- "delegated_producers": "a delegated pillar's producer or its version",
236
+ # Names the scoring model rather than the version, because that is
237
+ # what `_model_key` actually keys on. Saying "its version" sent a
238
+ # reader looking for a release that in the common case had not
239
+ # changed -- the v2 document breaks on `scoring_model`, and the
240
+ # version is only the v1 fallback.
241
+ "delegated_producers": "a delegated pillar's producer or its scoring model",
228
242
  }
229
243
 
230
244
 
@@ -408,6 +422,15 @@ def read_history(path: Path) -> list[ScanRecord]:
408
422
  try:
409
423
  payload = json.loads(line)
410
424
  payload.pop("history_schema_version", None)
425
+ # Schema 1-4 stored this as `rubric_version`. Renamed in 5
426
+ # because the name was never true (D158); every line written
427
+ # before that keeps loading, and keeps its place in a
428
+ # series, because the *value* never changed — only what it
429
+ # is called. A stored history is the one thing here that
430
+ # cannot be regenerated, so a rename that dropped it would
431
+ # cost more than the wrong name did.
432
+ if "rubric_version" in payload:
433
+ payload["tool_version"] = payload.pop("rubric_version")
411
434
  # Every sequence field back to a tuple. JSON has one list
412
435
  # type, so a field missed here returns as a list and the
413
436
  # record stops comparing equal to a freshly built one —
@@ -506,7 +529,7 @@ def _delegated_producers(report: dict[str, Any]) -> tuple[str, ...]:
506
529
  Sorted and joined into one string per pillar so the comparability
507
530
  key stays a plain value. Only delegated pillars carry a producer;
508
531
  the ones this tool measures itself are already covered by
509
- `rubric_version`.
532
+ `tool_version`.
510
533
 
511
534
  A pillar whose document names no version still contributes its
512
535
  producer, because "the same tool, version unknown" and "a different
@@ -575,7 +598,7 @@ def record_of(report: dict[str, Any], config: dict[str, Any], version: str,
575
598
  commit=report.get("git_commit") or "",
576
599
  branch=report.get("git_branch") or "",
577
600
  scope=report.get("mode") or "full",
578
- rubric_version=version,
601
+ tool_version=version,
579
602
  calibration=calibration,
580
603
  thresholds_digest=thresholds_digest(config.get("thresholds") or {}),
581
604
  analyzers=contributed,
@@ -427,7 +427,48 @@ def prompt_items(items: list[dict[str, Any]], limit: int = 12,
427
427
  ]
428
428
  severe = [item for item in eligible if item.get("risk") == 5]
429
429
  rest = [item for item in eligible if item.get("risk") != 5]
430
- return (severe + rest)[:limit]
430
+ return _one_per_class(severe + rest)[:limit]
431
+
432
+
433
+ def _one_per_class(ordered: list[dict[str, Any]]) -> list[dict[str, Any]]:
434
+ """The best member of each finding class, in the order they arrived.
435
+
436
+ **The paste is twelve kinds of work, not twelve rows.** Without this
437
+ a class with a hundred members takes every slot: measured on a real
438
+ tree, 100 of 125 items were one class and all twelve went to it,
439
+ six of them naming the same file, while 24 duplicate blocks and an
440
+ oversized file got none. The prompt says "the first items are the
441
+ highest value for the least change" and then spent its whole budget
442
+ on one rule while omitting two others entirely (D159).
443
+
444
+ One row per class is enough because the row already carries the
445
+ whole class: `class_count` and `class_delta` are on every item, so
446
+ it reads "clearing all 100 of these is worth +0.20" rather than
447
+ printing a hundred line numbers. An agent is better instructed by
448
+ one rule and its count than by twelve instances of it.
449
+
450
+ Order is preserved rather than re-sorted, so Severe still leads and
451
+ the economic ordering behind it still holds — this removes
452
+ repetition and decides nothing about priority.
453
+ """
454
+ spread: dict[str, set[str]] = {}
455
+ for item in ordered:
456
+ name = str(item.get("finding_class") or item.get("title"))
457
+ spread.setdefault(name, set()).add(str(item.get("path") or ""))
458
+
459
+ seen: set[str] = set()
460
+ first: list[dict[str, Any]] = []
461
+ for item in ordered:
462
+ name = str(item.get("finding_class") or item.get("title"))
463
+ if name in seen:
464
+ continue
465
+ seen.add(name)
466
+ # The surviving row keeps its own title, which names one file,
467
+ # so it must also say how far the class reaches — otherwise a
468
+ # row standing for 46 findings across seven files reads as one
469
+ # finding in the file it happens to name.
470
+ first.append({**item, "class_paths": len(spread[name])})
471
+ return first
431
472
 
432
473
 
433
474
  # The axes a reader can narrow by. Every one is a field already on the
@@ -462,6 +503,34 @@ def select(items: list[dict[str, Any]], **criteria: str) -> list[dict[str, Any]]
462
503
  return [item for item in items if matches(item)]
463
504
 
464
505
 
506
+ def prompt_advised(items: list[dict[str, Any]], limit: int = 12,
507
+ escalated: set[str] | None = None) -> list[dict[str, Any]]:
508
+ """Every eligible item the prompt's rows stand for.
509
+
510
+ `prompt_items` returns one row per class, because a paste of twelve
511
+ is twelve *kinds* of work (D159). What was advised is wider than
512
+ what was printed: a row reading "clearing all 68 of these" asks for
513
+ all 68, so recurrence has to remember all 68.
514
+
515
+ Derived from `prompt_items` rather than re-selected beside it. The
516
+ advised set is the classes those rows name, and this expands them —
517
+ one decision about what to advise, two views of it. Two independent
518
+ selections would drift, and the one that drifts is the one nobody
519
+ reads.
520
+ """
521
+ advised = {
522
+ str(item.get("finding_class") or item.get("title"))
523
+ for item in prompt_items(items, limit, escalated)
524
+ }
525
+ blocked = escalated or set()
526
+ return [
527
+ item for item in items
528
+ if item["band"] != Band.MAJOR_PROJECT.value
529
+ and item.get("fingerprint") not in blocked
530
+ and str(item.get("finding_class") or item.get("title")) in advised
531
+ ]
532
+
533
+
465
534
  def prompt_targets(report: dict[str, Any]) -> tuple[str, ...]:
466
535
  """The identities a generated prompt actually asked somebody to fix.
467
536
 
@@ -495,7 +564,10 @@ def prompt_targets(report: dict[str, Any]) -> tuple[str, ...]:
495
564
  }
496
565
  known = set(finding_fingerprints(report))
497
566
  targets = set()
498
- for item in prompt_items(report.get("work_order") or [], escalated=escalated):
567
+ # Every member of every advised class, not only the rows printed:
568
+ # the prompt asks for the whole class, so the told-fixed-returned
569
+ # signal has to cover the whole class (D159).
570
+ for item in prompt_advised(report.get("work_order") or [], escalated=escalated):
499
571
  fingerprint = item.get("fingerprint")
500
572
  if fingerprint is None:
501
573
  continue