maintainability-agent 3.1.0__tar.gz → 3.2.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 (375) hide show
  1. {maintainability_agent-3.1.0/src/maintainability_agent.egg-info → maintainability_agent-3.2.0}/PKG-INFO +2 -2
  2. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/README.md +1 -1
  3. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/pyproject.toml +1 -1
  4. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0/src/maintainability_agent.egg-info}/PKG-INFO +2 -2
  5. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_agent.egg-info/SOURCES.txt +10 -0
  6. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/__init__.py +1 -1
  7. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_anchor.py +6 -3
  8. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_catalog.py +22 -2
  9. maintainability_agent-3.2.0/src/maintainability_audit/_delegated_pillar.py +181 -0
  10. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_derive.py +2 -1
  11. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_discovery.py +70 -26
  12. maintainability_agent-3.2.0/src/maintainability_audit/_evidence_reader.py +305 -0
  13. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_evidence_view.py +11 -4
  14. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_first_run.py +57 -16
  15. maintainability_agent-3.2.0/src/maintainability_audit/_grammar.py +93 -0
  16. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_grant_ledger.py +0 -8
  17. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_history_view.py +85 -24
  18. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_html_report_sections.py +78 -31
  19. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_html_view.py +5 -3
  20. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_in_loop_view.py +32 -15
  21. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_metric_adapters.py +14 -127
  22. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_pillars.py +77 -1
  23. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_practice.py +46 -24
  24. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_pressures.py +61 -70
  25. maintainability_agent-3.1.0/src/maintainability_audit/prompts.py → maintainability_agent-3.2.0/src/maintainability_audit/_prompt_sections.py +40 -114
  26. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_core.py +44 -0
  27. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_fortran.py +29 -11
  28. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_php.py +2 -28
  29. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_rust.py +2 -31
  30. maintainability_agent-3.2.0/src/maintainability_audit/_ratio_adapters.py +153 -0
  31. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_scan_history.py +36 -4
  32. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_scan_view.py +46 -18
  33. maintainability_agent-3.2.0/src/maintainability_audit/_selection.py +177 -0
  34. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_semantic_policy.py +18 -8
  35. maintainability_agent-3.2.0/src/maintainability_audit/_test_pairing.py +291 -0
  36. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_trends.py +1 -0
  37. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_verdict_adapters.py +50 -36
  38. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_work_order.py +39 -27
  39. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/config.py +1 -1
  40. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/evidence.py +1 -227
  41. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/idioms.py +22 -6
  42. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/metrics.py +17 -9
  43. maintainability_agent-3.2.0/src/maintainability_audit/prompts.py +128 -0
  44. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/report.py +25 -1
  45. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/scoring.py +2 -5
  46. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_primary_estimate.py +1 -1
  47. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_scoring_path.py +3 -3
  48. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_spread_range.py +1 -1
  49. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_anchor_disclosure.py +1 -1
  50. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_band_concealment_p3.py +2 -1
  51. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_consumer_migration.py +2 -1
  52. maintainability_agent-3.2.0/tests/test_declarative_parsers.py +220 -0
  53. maintainability_agent-3.2.0/tests/test_delegated_security_pillar.py +242 -0
  54. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_evidence_invariants.py +1 -1
  55. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_evidence_normalization.py +1 -1
  56. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_evidence_properties.py +1 -1
  57. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_history_window.py +10 -25
  58. maintainability_agent-3.2.0/tests/test_pairing_reads_imports.py +213 -0
  59. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_population_floors.py +1 -1
  60. maintainability_agent-3.2.0/tests/test_release_needs_an_empty_ledger.py +150 -0
  61. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_release_plan_status.py +8 -1
  62. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scan_scope.py +2 -6
  63. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scoring_calibration.py +2 -5
  64. maintainability_agent-3.2.0/tests/test_terminal_asks_the_same_questions.py +98 -0
  65. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_trends.py +14 -1
  66. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_unanchored_set_matches_corpus.py +7 -2
  67. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_verified_grade.py +1 -1
  68. maintainability_agent-3.1.0/src/maintainability_audit/_selection.py +0 -136
  69. maintainability_agent-3.1.0/src/maintainability_audit/_test_pairing.py +0 -149
  70. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/LICENSE +0 -0
  71. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/setup.cfg +0 -0
  72. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  73. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  74. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
  75. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  76. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/__main__.py +0 -0
  77. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_adapters.py +0 -0
  78. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_analysis.py +0 -0
  79. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_analyzer_sections.py +0 -0
  80. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_arguments.py +0 -0
  81. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_aspects.py +0 -0
  82. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  83. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_assets/standard.md +0 -0
  84. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_attestation.py +0 -0
  85. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_backfill.py +0 -0
  86. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_bands.py +0 -0
  87. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_banner.py +0 -0
  88. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_built_ins.py +0 -0
  89. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_calibration.py +0 -0
  90. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_charts.py +0 -0
  91. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_cognitive.py +0 -0
  92. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_config_defaults.py +0 -0
  93. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_conformance.py +0 -0
  94. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_corroborate.py +0 -0
  95. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_coverage_notes.py +0 -0
  96. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_criteria_scope.py +0 -0
  97. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_documents.py +0 -0
  98. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_economics.py +0 -0
  99. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_economics_view.py +0 -0
  100. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_environment.py +0 -0
  101. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_finding_match.py +0 -0
  102. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_formula.py +0 -0
  103. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_gates.py +0 -0
  104. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_generic.py +0 -0
  105. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
  106. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_hotspots.py +0 -0
  107. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_identity.py +0 -0
  108. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_in_loop.py +0 -0
  109. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
  110. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_markdown_sections.py +0 -0
  111. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_masking.py +0 -0
  112. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_audit.py +0 -0
  113. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_gate.py +0 -0
  114. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_grants.py +0 -0
  115. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
  116. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_resources.py +0 -0
  117. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_mcp_setup.py +0 -0
  118. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_metrics_types.py +0 -0
  119. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_operator_reads.py +0 -0
  120. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_precommit.py +0 -0
  121. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_precommit_install.py +0 -0
  122. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_precommit_view.py +0 -0
  123. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_c.py +0 -0
  124. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_cobol.py +0 -0
  125. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
  126. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
  127. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_go.py +0 -0
  128. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_java.py +0 -0
  129. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_js.py +0 -0
  130. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_ruby.py +0 -0
  131. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ranges_swift.py +0 -0
  132. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_ratchet.py +0 -0
  133. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_recurrence.py +0 -0
  134. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_run_comparison.py +0 -0
  135. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_runner.py +0 -0
  136. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_safe_write.py +0 -0
  137. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_second_source.py +0 -0
  138. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_semantic.py +0 -0
  139. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_semantic_ts.py +0 -0
  140. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_semantic_view.py +0 -0
  141. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_setup_errors.py +0 -0
  142. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_setup_persist.py +0 -0
  143. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  144. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  145. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  146. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  147. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  148. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  149. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_skill_install.py +0 -0
  150. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_stored_grants.py +0 -0
  151. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_tdd_view.py +0 -0
  152. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_test_commands.py +0 -0
  153. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_test_execution.py +0 -0
  154. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_tokens.py +0 -0
  155. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_tool_adapters.py +0 -0
  156. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_user_config.py +0 -0
  157. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_verification.py +0 -0
  158. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_work_order_view.py +0 -0
  159. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_work_order_weights.py +0 -0
  160. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/_xml.py +0 -0
  161. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/baseline.py +0 -0
  162. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/cli.py +0 -0
  163. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/deadcode.py +0 -0
  164. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/declarations.py +0 -0
  165. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/duplication.py +0 -0
  166. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/git_tools.py +0 -0
  167. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/history.py +0 -0
  168. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/instructions.py +0 -0
  169. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/mcp_server.py +0 -0
  170. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/renderers.py +0 -0
  171. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/sarif.py +0 -0
  172. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/similarity.py +0 -0
  173. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/src/maintainability_audit/source.py +0 -0
  174. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_acquisition_trust.py +0 -0
  175. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_adapter_docs.py +0 -0
  176. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_adapter_recordings.py +0 -0
  177. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_adapters.py +0 -0
  178. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_added_lines.py +0 -0
  179. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analysis_coverage.py +0 -0
  180. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analysis_execution.py +0 -0
  181. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_bridge.py +0 -0
  182. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_config_isolation.py +0 -0
  183. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_estimate_claims.py +0 -0
  184. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_pinning.py +0 -0
  185. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_provenance.py +0 -0
  186. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
  187. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_analyzer_xml_bounds.py +0 -0
  188. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_anchor_and_mode.py +0 -0
  189. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_annotations_match_behaviour.py +0 -0
  190. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_anticipated_refusals.py +0 -0
  191. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_architecture.py +0 -0
  192. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_artifact_write_route_class.py +0 -0
  193. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_aspect_coverage.py +0 -0
  194. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_asset_snapshot_class.py +0 -0
  195. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
  196. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_attestation.py +0 -0
  197. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_audit_components.py +0 -0
  198. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_authorization_freshness.py +0 -0
  199. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_authorship_gates.py +0 -0
  200. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_backfill.py +0 -0
  201. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_band_concealment_class.py +0 -0
  202. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_band_pressures.py +0 -0
  203. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_bands.py +0 -0
  204. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_body_or_signature_class.py +0 -0
  205. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_c_declarations.py +0 -0
  206. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_calibration_corpus.py +0 -0
  207. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_calibration_drift.py +0 -0
  208. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_calibration_tooling.py +0 -0
  209. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_catalog_selection.py +0 -0
  210. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_catalog_tier_promise.py +0 -0
  211. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_chat_primary_docs.py +0 -0
  212. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_check_refuses_plus_only_fragments.py +0 -0
  213. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_checkstyle_adapter.py +0 -0
  214. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_checkstyle_catalog.py +0 -0
  215. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_ci_history_recipe.py +0 -0
  216. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  217. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_claimed_languages.py +0 -0
  218. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_cli.py +0 -0
  219. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_clone_group_class.py +0 -0
  220. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_cobol_declarations.py +0 -0
  221. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_cognitive_complexity.py +0 -0
  222. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_cohort_statistics.py +0 -0
  223. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_concealment_properties.py +0 -0
  224. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_config_shape.py +0 -0
  225. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_consent_and_grant.py +0 -0
  226. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_contract_claims.py +0 -0
  227. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_corroborate.py +0 -0
  228. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_coverage_by_language.py +0 -0
  229. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_cpp_declarations.py +0 -0
  230. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_criteria_completion.py +0 -0
  231. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_csharp_declarations.py +0 -0
  232. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_d15_composition.py +0 -0
  233. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_d15_goal_directed.py +0 -0
  234. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_dead_code.py +0 -0
  235. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declaration_criteria_scope.py +0 -0
  236. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declaration_edge_cases.py +0 -0
  237. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declaration_grading.py +0 -0
  238. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declaration_ranges.py +0 -0
  239. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declaration_source.py +0 -0
  240. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declared_authorship.py +0 -0
  241. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_declared_imports.py +0 -0
  242. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_derivation_mix.py +0 -0
  243. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_determinism.py +0 -0
  244. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_dimension_ratchet.py +0 -0
  245. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_direct_runner_availability_class.py +0 -0
  246. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_discovery.py +0 -0
  247. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_doc_claims.py +0 -0
  248. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_docs_links.py +0 -0
  249. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_economic_context.py +0 -0
  250. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_empty_output_not_clean.py +0 -0
  251. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
  252. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_environment_work_order.py +0 -0
  253. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_exclusion_dialects.py +0 -0
  254. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_falsifier_standard.py +0 -0
  255. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_file_list_cap_class.py +0 -0
  256. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_finding_identity.py +0 -0
  257. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_first_run_elicitation.py +0 -0
  258. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_first_run_prompt.py +0 -0
  259. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_first_run_reelicitation.py +0 -0
  260. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_fix_breadth_window.py +0 -0
  261. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_fixed_form_fortran.py +0 -0
  262. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_format_ask.py +0 -0
  263. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_fortran_declarations.py +0 -0
  264. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_fortran_metrics.py +0 -0
  265. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_fortran_practice.py +0 -0
  266. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_git_argv.py +0 -0
  267. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_git_read_only.py +0 -0
  268. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_git_readonly_class.py +0 -0
  269. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_go_declarations.py +0 -0
  270. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_grammar_constructs.py +0 -0
  271. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_grammar_token_coverage.py +0 -0
  272. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_grant_only_user_tier.py +0 -0
  273. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_history.py +0 -0
  274. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_history_boundary.py +0 -0
  275. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_history_manifest.py +0 -0
  276. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_history_schema2.py +0 -0
  277. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_hostile_prompt.py +0 -0
  278. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_html_executive.py +0 -0
  279. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_html_section_parity_class.py +0 -0
  280. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_identity_docs.py +0 -0
  281. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_identity_resolution.py +0 -0
  282. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_idiom_divergence.py +0 -0
  283. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_in_loop_budgets.py +0 -0
  284. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_in_loop_check.py +0 -0
  285. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_installed_wheel_runtime.py +0 -0
  286. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_instruction_targets.py +0 -0
  287. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_java_range_guard.py +0 -0
  288. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_java_ranges.py +0 -0
  289. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_java_scored.py +0 -0
  290. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_java_wiring.py +0 -0
  291. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_js_complexity_operators.py +0 -0
  292. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_js_declarations.py +0 -0
  293. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_language_coverage.py +0 -0
  294. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_language_support_honesty.py +0 -0
  295. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_mcp_baseline_payload.py +0 -0
  296. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_mcp_history.py +0 -0
  297. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_mcp_server.py +0 -0
  298. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_migration_1_0.py +0 -0
  299. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_near_duplicates.py +0 -0
  300. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_network_disclosure.py +0 -0
  301. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
  302. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_operator_named_paths.py +0 -0
  303. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_operator_named_reads.py +0 -0
  304. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_pattern_budget.py +0 -0
  305. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_phase6_claims.py +0 -0
  306. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_php_declarations.py +0 -0
  307. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_pillars_and_practice.py +0 -0
  308. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_platform_claim.py +0 -0
  309. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_pmd_adapter.py +0 -0
  310. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_pmd_audit_closures.py +0 -0
  311. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_policy_claims.py +0 -0
  312. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_pool_runs_by_config.py +0 -0
  313. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_practice_nested_gates_class.py +0 -0
  314. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_precommit_staged.py +0 -0
  315. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_presentation_refusals.py +0 -0
  316. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_promises.py +0 -0
  317. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_prompt_escalation_once.py +0 -0
  318. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_prompt_honesty.py +0 -0
  319. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_prompt_location_escalation_class.py +0 -0
  320. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_prove_falsifiers.py +0 -0
  321. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_python_complexity.py +0 -0
  322. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_python_declarations.py +0 -0
  323. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_read_boundary.py +0 -0
  324. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_readme_claims.py +0 -0
  325. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_recurrence.py +0 -0
  326. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_release_plan.py +0 -0
  327. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_report_remedy_copy.py +0 -0
  328. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_roles_recorded.py +0 -0
  329. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_root_grants.py +0 -0
  330. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  331. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_ruby_declarations.py +0 -0
  332. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_run_comparison.py +0 -0
  333. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_runner.py +0 -0
  334. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_rust_declarations.py +0 -0
  335. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_sarif.py +0 -0
  336. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scan_history.py +0 -0
  337. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scanner_unsafe_direction.py +0 -0
  338. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scanning.py +0 -0
  339. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_schema_fidelity.py +0 -0
  340. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_scope_conformance.py +0 -0
  341. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_semantic_policy.py +0 -0
  342. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_setup_gate_completeness.py +0 -0
  343. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_setup_gate_independent_contract.py +0 -0
  344. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_setup_precondition.py +0 -0
  345. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_skill_install.py +0 -0
  346. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_sonar_resolve.py +0 -0
  347. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_source_index.py +0 -0
  348. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_spotbugs_adapter.py +0 -0
  349. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_spotbugs_catalog.py +0 -0
  350. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_stage8_contract.py +0 -0
  351. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_suite_isolation.py +0 -0
  352. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_swift_declarations.py +0 -0
  353. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_tdd_structure.py +0 -0
  354. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_test_commands.py +0 -0
  355. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_test_execution_class.py +0 -0
  356. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_three_presentations.py +0 -0
  357. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_tool_resolution.py +0 -0
  358. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_tree_cannot_opt_the_host_in.py +0 -0
  359. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_tree_chosen_spawn.py +0 -0
  360. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_tree_reads_use_the_primitive.py +0 -0
  361. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_type_fields_not_functions_class.py +0 -0
  362. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_uat_falsifiers.py +0 -0
  363. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_unread_code.py +0 -0
  364. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_user_config_tier.py +0 -0
  365. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_verification_audit_closures.py +0 -0
  366. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_version_claim.py +0 -0
  367. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_wheel_contents.py +0 -0
  368. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_work_order.py +0 -0
  369. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_work_order_binds_to_this_interpreter.py +0 -0
  370. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_work_order_items.py +0 -0
  371. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_work_order_selection.py +0 -0
  372. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_workflow_supply_chain.py +0 -0
  373. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_write_boundary.py +0 -0
  374. {maintainability_agent-3.1.0 → maintainability_agent-3.2.0}/tests/test_write_route_class.py +0 -0
  375. {maintainability_agent-3.1.0 → maintainability_agent-3.2.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.1.0
3
+ Version: 3.2.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -45,7 +45,7 @@ Dynamic: license-file
45
45
  **A deterministic, offline maintainability audit whose output is a _bounded
46
46
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
47
47
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
48
- Version **3.1.0**.
48
+ Version **3.2.0**.
49
49
 
50
50
  **Planned, not shipped:** the audit tool will become `maintainability-audit`;
51
51
  a new `maintainability-agent` companion will run it and automate human-selected
@@ -5,7 +5,7 @@
5
5
  **A deterministic, offline maintainability audit whose output is a _bounded
6
6
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
7
7
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
8
- Version **3.1.0**.
8
+ Version **3.2.0**.
9
9
 
10
10
  **Planned, not shipped:** the audit tool will become `maintainability-audit`;
11
11
  a new `maintainability-agent` companion will run it and automate human-selected
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maintainability-agent"
7
- version = "3.1.0"
7
+ version = "3.2.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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maintainability-agent
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -45,7 +45,7 @@ Dynamic: license-file
45
45
  **A deterministic, offline maintainability audit whose output is a _bounded
46
46
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
47
47
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
48
- Version **3.1.0**.
48
+ Version **3.2.0**.
49
49
 
50
50
  **Planned, not shipped:** the audit tool will become `maintainability-audit`;
51
51
  a new `maintainability-agent` companion will run it and automate human-selected
@@ -29,18 +29,21 @@ src/maintainability_audit/_conformance.py
29
29
  src/maintainability_audit/_corroborate.py
30
30
  src/maintainability_audit/_coverage_notes.py
31
31
  src/maintainability_audit/_criteria_scope.py
32
+ src/maintainability_audit/_delegated_pillar.py
32
33
  src/maintainability_audit/_derive.py
33
34
  src/maintainability_audit/_discovery.py
34
35
  src/maintainability_audit/_documents.py
35
36
  src/maintainability_audit/_economics.py
36
37
  src/maintainability_audit/_economics_view.py
37
38
  src/maintainability_audit/_environment.py
39
+ src/maintainability_audit/_evidence_reader.py
38
40
  src/maintainability_audit/_evidence_view.py
39
41
  src/maintainability_audit/_finding_match.py
40
42
  src/maintainability_audit/_first_run.py
41
43
  src/maintainability_audit/_formula.py
42
44
  src/maintainability_audit/_gates.py
43
45
  src/maintainability_audit/_generic.py
46
+ src/maintainability_audit/_grammar.py
44
47
  src/maintainability_audit/_grant_ledger.py
45
48
  src/maintainability_audit/_history_view.py
46
49
  src/maintainability_audit/_hostile_prompt.py
@@ -68,6 +71,7 @@ src/maintainability_audit/_precommit.py
68
71
  src/maintainability_audit/_precommit_install.py
69
72
  src/maintainability_audit/_precommit_view.py
70
73
  src/maintainability_audit/_pressures.py
74
+ src/maintainability_audit/_prompt_sections.py
71
75
  src/maintainability_audit/_ranges_c.py
72
76
  src/maintainability_audit/_ranges_cobol.py
73
77
  src/maintainability_audit/_ranges_core.py
@@ -82,6 +86,7 @@ src/maintainability_audit/_ranges_ruby.py
82
86
  src/maintainability_audit/_ranges_rust.py
83
87
  src/maintainability_audit/_ranges_swift.py
84
88
  src/maintainability_audit/_ratchet.py
89
+ src/maintainability_audit/_ratio_adapters.py
85
90
  src/maintainability_audit/_recurrence.py
86
91
  src/maintainability_audit/_run_comparison.py
87
92
  src/maintainability_audit/_runner.py
@@ -212,8 +217,10 @@ tests/test_declaration_edge_cases.py
212
217
  tests/test_declaration_grading.py
213
218
  tests/test_declaration_ranges.py
214
219
  tests/test_declaration_source.py
220
+ tests/test_declarative_parsers.py
215
221
  tests/test_declared_authorship.py
216
222
  tests/test_declared_imports.py
223
+ tests/test_delegated_security_pillar.py
217
224
  tests/test_derivation_mix.py
218
225
  tests/test_determinism.py
219
226
  tests/test_dimension_ratchet.py
@@ -280,6 +287,7 @@ tests/test_network_disclosure.py
280
287
  tests/test_one_setup_across_surfaces_class.py
281
288
  tests/test_operator_named_paths.py
282
289
  tests/test_operator_named_reads.py
290
+ tests/test_pairing_reads_imports.py
283
291
  tests/test_pattern_budget.py
284
292
  tests/test_phase6_claims.py
285
293
  tests/test_php_declarations.py
@@ -303,6 +311,7 @@ tests/test_python_declarations.py
303
311
  tests/test_read_boundary.py
304
312
  tests/test_readme_claims.py
305
313
  tests/test_recurrence.py
314
+ tests/test_release_needs_an_empty_ledger.py
306
315
  tests/test_release_plan.py
307
316
  tests/test_release_plan_status.py
308
317
  tests/test_report_remedy_copy.py
@@ -334,6 +343,7 @@ tests/test_stage8_contract.py
334
343
  tests/test_suite_isolation.py
335
344
  tests/test_swift_declarations.py
336
345
  tests/test_tdd_structure.py
346
+ tests/test_terminal_asks_the_same_questions.py
337
347
  tests/test_test_commands.py
338
348
  tests/test_test_execution_class.py
339
349
  tests/test_three_presentations.py
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "3.1.0"
3
+ __version__ = "3.2.0"
@@ -63,8 +63,11 @@ def unanchored_sentence() -> str:
63
63
  """One sentence naming what the anchor omits, for the corpus note."""
64
64
  if not UNANCHORED_LANGUAGES:
65
65
  return ""
66
+ from ._grammar import agreement
67
+
68
+ say = agreement(len(UNANCHORED_LANGUAGES))
66
69
  return (
67
- f"{unanchored_names()} are parsed but absent from it, so their "
68
- "findings are as good as their parser while their grade is "
69
- "provisional."
70
+ f"{unanchored_names()} {say.verb} parsed but absent from it, so "
71
+ f"{say.possessive} findings are as good as {say.possessive} "
72
+ f"parser while {say.possessive} grade is provisional."
70
73
  )
@@ -190,7 +190,23 @@ def decide(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
190
190
  3. the depth, licence and concern tiers.
191
191
  """
192
192
  slug = tool["slug"]
193
+ return (
194
+ _denial(tool, settings)
195
+ or (Selection(slug, True, "explicitly allowed by name")
196
+ if slug in settings["allow_tools"] else None)
197
+ or _tier_decision(tool, settings)
198
+ )
199
+
200
+
201
+ def _denial(tool: dict[str, Any], settings: dict[str, Any]) -> Selection | None:
202
+ """Step 1: every deny, which beats even an explicit allow.
193
203
 
204
+ `None` means nothing here refused the tool, not that it was admitted —
205
+ the caller has two more steps. Separate from the tiers because these
206
+ are the operator's own prohibitions and the tiers are policy: a deny
207
+ that could be overridden by an allow would not be a deny.
208
+ """
209
+ slug = tool["slug"]
194
210
  if slug in settings["deny_tools"]:
195
211
  return Selection(slug, False, "denied by name")
196
212
  if tool["license_class"] in settings["deny_license_classes"]:
@@ -198,10 +214,14 @@ def decide(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
198
214
  denied_concerns = set(tool["upstream_tags"]) & set(settings["deny_concerns"])
199
215
  if denied_concerns:
200
216
  return Selection(slug, False, f"concern {','.join(sorted(denied_concerns))} denied")
217
+ return None
201
218
 
202
- if slug in settings["allow_tools"]:
203
- return Selection(slug, True, "explicitly allowed by name")
204
219
 
220
+ def _tier_decision(tool: dict[str, Any], settings: dict[str, Any]) -> Selection:
221
+ """Step 3: the depth, licence and concern tiers, for a tool no deny
222
+ caught and no allow admitted. The only step that can end in `True`
223
+ on the tool's own merits."""
224
+ slug = tool["slug"]
205
225
  if tool["deprecated"]:
206
226
  return Selection(slug, False, "deprecated upstream")
207
227
  if not tool["languages"]:
@@ -0,0 +1,181 @@
1
+ """Reading a delegated pillar's own report of itself.
2
+
3
+ [ADR 007](adr-007-pillars-and-practice.md) makes the five pillars of the
4
+ source framework the top-level taxonomy and declares **Security
5
+ delegated to `secure-code-agent`**, reported as `NotApplicable` so that
6
+ silence is never read as safety. That entry was always a placeholder for
7
+ an artifact that did not exist yet: the other tool measures the pillar,
8
+ so the other tool has to be the one that reports it.
9
+
10
+ `secure-code-agent` 0.5.0 ships the emitter — `--security-pillar <path>`
11
+ writes `security-pillar.json`, schema `secure-code-agent/security-pillar`
12
+ — and it was built against *this* vocabulary rather than its own. The
13
+ scope words, the two-axis split and the posture matrix with its
14
+ thresholds all come from `_pillars.py`, because two tools saying "level
15
+ 3" or "healthy" about one repository have to mean the same thing by it
16
+ or the joined view is worse than either alone.
17
+
18
+ This module reads the document and checks it is the one expected. The
19
+ *shaping* of the pillar entry lives in `_pillars` beside the entries it
20
+ sits among — scoring may not import a scanner, and reading a path the
21
+ audited tree chooses is what makes this one. Neither half computes a
22
+ number: a delegated pillar's numbers belong to the tool that measured
23
+ them, and a consumer that recomputed anything would be a second opinion
24
+ nobody asked for.
25
+
26
+ **Absence is the normal case and stays the documented one.** No file
27
+ means the pillar reports exactly what it reported before — delegated,
28
+ `NotApplicable`, naming the other tool. That path is not a failure and
29
+ does not warn: most repositories run one tool.
30
+
31
+ **A file that cannot be trusted is refused rather than partly believed.**
32
+ Wrong schema, unreadable JSON, a shape that is not an object — each
33
+ returns `None`, and the pillar falls back to the honest placeholder. The
34
+ alternative is a security posture assembled from a document this tool
35
+ does not actually understand, which is worse than no posture at all.
36
+
37
+ A trailing note on where this sits: it reads a path from the audited
38
+ tree, so it is a scanner rather than part of the rubric.
39
+ `test_scoring_never_imports_scanners_or_assembly` holds that boundary,
40
+ and `report` is what joins the two.
41
+ """
42
+ from __future__ import annotations
43
+
44
+ import json
45
+ from pathlib import Path
46
+ from typing import Any
47
+
48
+ from ._operator_reads import PathNotAllowed, read_source_file
49
+
50
+ #: Written beside the other artifacts a repository keeps about itself.
51
+ #: The path is a convention rather than a search: a document this tool
52
+ #: trusts for a whole pillar should be somewhere a reader can find, not
53
+ #: wherever a glob happened to match.
54
+ DEFAULT_PILLAR_PATH = ".maintainability/security-pillar.json"
55
+
56
+ #: The contract this module understands. A document announcing anything
57
+ #: else is refused rather than read hopefully — the schema string is the
58
+ #: producer's promise about the shape, and guessing past it is how a
59
+ #: consumer starts reporting fields that mean something different.
60
+ SCHEMA = "secure-code-agent/security-pillar"
61
+ SCHEMA_VERSION = 1
62
+
63
+ #: What the pillar block takes from the document. Named rather than
64
+ #: copied wholesale so a field added upstream cannot silently appear in
65
+ #: this tool's report carrying meaning nobody here has checked.
66
+ CARRIED = (
67
+ "practice",
68
+ "condition",
69
+ "condition_letter",
70
+ "posture",
71
+ "verified_grade",
72
+ "evidence_status",
73
+ "evidence_reasons",
74
+ "coverage",
75
+ "findings_by_severity",
76
+ "reported_not_scored",
77
+ "loc_scanned",
78
+ )
79
+
80
+
81
+ def read_delegated(root: Path, relative: str = DEFAULT_PILLAR_PATH) -> dict[str, Any] | None:
82
+ """The delegated pillar's own report, or `None` when there is none.
83
+
84
+ `None` for every reason a reader might not get a usable document:
85
+ the file is absent, it is not a regular file, it does not parse, it
86
+ is not an object, or it announces a schema this tool does not know.
87
+ All five collapse to one answer because the caller does the same
88
+ thing with each — keep the placeholder that names the other tool.
89
+
90
+ Read through the regular-file primitive like every other path the
91
+ audited tree chooses (D145): a FIFO here would hang the audit rather
92
+ than fail it.
93
+ """
94
+ path = Path(root) / relative
95
+ if not path.exists():
96
+ return None
97
+ try:
98
+ payload = json.loads("\n".join(read_source_file(path)))
99
+ except (OSError, ValueError) as error:
100
+ if isinstance(error, PathNotAllowed):
101
+ raise
102
+ return None
103
+ if not isinstance(payload, dict):
104
+ return None
105
+ if payload.get("schema") != SCHEMA:
106
+ return None
107
+ if payload.get("schema_version") != SCHEMA_VERSION:
108
+ return None
109
+ return payload if _is_well_formed(payload) else None
110
+
111
+
112
+ #: Fields whose *shape* the consumer depends on. A header check alone
113
+ #: accepts any object announcing the right schema, and the pillar then
114
+ #: reads these as if the producer had promised them.
115
+ _SHAPES: tuple[tuple[str, type | tuple[type, ...]], ...] = (
116
+ ("producer", dict),
117
+ ("practice", dict),
118
+ ("condition", (int, float, type(None))),
119
+ ("posture", (str, type(None))),
120
+ ("evidence_status", (str, type(None))),
121
+ ("coverage", (dict, type(None))),
122
+ ("findings_by_severity", (dict, type(None))),
123
+ ("reported_not_scored", (dict, type(None))),
124
+ )
125
+
126
+ #: The postures this tool knows how to render. A document naming one it
127
+ #: does not is refused rather than printed through: the word is the
128
+ #: reader's whole summary of the pillar.
129
+ _POSTURES = frozenset({"healthy", "managed debt", "unmanaged debt", "unverified"})
130
+
131
+
132
+ def _is_well_formed(payload: dict[str, Any]) -> bool:
133
+ """Whether the document's fields are the shapes the pillar reads.
134
+
135
+ The header said what the document *claims to be*; this asks whether
136
+ it is. Checking only `schema` accepted
137
+ `{"producer": "not-an-object", ...}`, which the pillar then indexed
138
+ as a mapping and crashed on — a well-formed announcement with a
139
+ malformed body, which is the shape a header check cannot see.
140
+
141
+ Also refused: a `posture` this tool cannot render, and a `posture`
142
+ the document's own two axes do not support. The second is the one
143
+ worth stating. `healthy` requires practice at or above
144
+ `HIGH_PRACTICE` and a condition at or above `GOOD_CONDITION`; a
145
+ document claiming `healthy` at practice 1 is either a different
146
+ matrix or a mistake, and either way this tool must not print it.
147
+ Both tools are supposed to mean the same thing by the word — the
148
+ consumer is where that is checkable.
149
+ """
150
+ for name, kinds in _SHAPES:
151
+ if name in payload and not isinstance(payload[name], kinds):
152
+ return False
153
+ practice = payload.get("practice")
154
+ if isinstance(practice, dict) and not isinstance(practice.get("level"), int):
155
+ return False
156
+ posture = payload.get("posture")
157
+ if posture is not None and posture not in _POSTURES:
158
+ return False
159
+ return _posture_agrees(payload)
160
+
161
+
162
+ def _posture_agrees(payload: dict[str, Any]) -> bool:
163
+ """Whether the stated posture follows from the two axes given.
164
+
165
+ Recomputed rather than trusted. The matrix and its thresholds are
166
+ `_pillars.py`'s, copied into the producer by value, and a copied
167
+ constant is a constant that can drift — so the one place the two
168
+ can be compared is here, against a document carrying both inputs
169
+ and the answer.
170
+ """
171
+ from ._pillars import posture as compute
172
+
173
+ stated = payload.get("posture")
174
+ practice = payload.get("practice")
175
+ if stated is None or not isinstance(practice, dict):
176
+ return True
177
+ level = practice.get("level")
178
+ condition = payload.get("condition")
179
+ if not isinstance(level, int):
180
+ return False
181
+ return compute(level, condition) == stated
@@ -17,9 +17,10 @@ from statistics import median
17
17
  from typing import Any
18
18
 
19
19
  from ._aspects import evidence_aspect_scores, is_untested
20
+ from ._evidence_reader import normalize_report_evidence
20
21
  from ._formula import CALIBRATED_ASPECTS, curve, overall_from_aspects
21
22
  from ._pressures import production_pressures
22
- from .evidence import REPORT_SCHEMA_VERSION, SCHEMA_VERSION_KEY, normalize_report_evidence
23
+ from .evidence import REPORT_SCHEMA_VERSION, SCHEMA_VERSION_KEY
23
24
 
24
25
  # The stored column holding the analyzers' production reading. Named
25
26
  # once because both the refusal and the mix key on it.
@@ -35,6 +35,7 @@ from __future__ import annotations
35
35
 
36
36
  import json
37
37
  import re
38
+ from collections.abc import Iterator
38
39
  from dataclasses import dataclass, field
39
40
  from enum import StrEnum
40
41
  from pathlib import Path
@@ -228,25 +229,8 @@ def _generated_directories(root: Path, excludes: tuple[str, ...]) -> dict[str, s
228
229
  relative = manifest.relative_to(root).as_posix()
229
230
  if is_excluded(relative, list(excludes)):
230
231
  continue
231
- try:
232
- scripts = json.loads(_text_of(manifest)).get("scripts", {})
233
- except PathNotAllowed:
234
- # `PathNotAllowed` is a `ValueError`, so it would otherwise be
235
- # swallowed by the clause below and the manifest would read as
236
- # a malformed one rather than a refused one (D145). A FIFO
237
- # named `package.json` is not bad JSON; it is a path this tool
238
- # will not read, and saying so is the whole point of routing
239
- # the read through the primitive.
240
- raise
241
- except (OSError, ValueError, AttributeError):
242
- continue
243
- if not isinstance(scripts, dict):
244
- continue
245
- for name, command in scripts.items():
246
- for target in DELETES_DIRECTORY.findall(str(command)):
247
- cleaned = target.strip("./")
248
- if not cleaned or cleaned.startswith(".."):
249
- continue
232
+ for name, command in _manifest_scripts(manifest).items():
233
+ for cleaned in _deleted_targets(str(command)):
250
234
  directory = (manifest.parent / cleaned).relative_to(root).as_posix()
251
235
  found.setdefault(
252
236
  directory,
@@ -256,6 +240,40 @@ def _generated_directories(root: Path, excludes: tuple[str, ...]) -> dict[str, s
256
240
  return found
257
241
 
258
242
 
243
+ def _manifest_scripts(manifest: Path) -> dict[str, Any]:
244
+ """One `package.json`'s scripts block, or empty if it has none to read.
245
+
246
+ Empty covers unreadable, malformed and shaped-wrong alike, because
247
+ none of the three is a statement about generated directories. A
248
+ refusal is the exception: `PathNotAllowed` is re-raised.
249
+ """
250
+ try:
251
+ scripts = json.loads(_text_of(manifest)).get("scripts", {})
252
+ except PathNotAllowed:
253
+ # `PathNotAllowed` is a `ValueError`, so it would otherwise be
254
+ # swallowed by the clause below and the manifest would read as
255
+ # a malformed one rather than a refused one (D145). A FIFO
256
+ # named `package.json` is not bad JSON; it is a path this tool
257
+ # will not read, and saying so is the whole point of routing
258
+ # the read through the primitive.
259
+ raise
260
+ except (OSError, ValueError, AttributeError):
261
+ return {}
262
+ return scripts if isinstance(scripts, dict) else {}
263
+
264
+
265
+ def _deleted_targets(command: str) -> Iterator[str]:
266
+ """The directory names one script command deletes, normalized.
267
+
268
+ A target that cleans to nothing, or that climbs out of the manifest's
269
+ own directory, is not a directory this repository generates.
270
+ """
271
+ for target in DELETES_DIRECTORY.findall(command):
272
+ cleaned = target.strip("./")
273
+ if cleaned and not cleaned.startswith(".."):
274
+ yield cleaned
275
+
276
+
259
277
  def _vendored_directories(root: Path) -> dict[str, str]:
260
278
  """Directories the repository says belong to someone else."""
261
279
  found: dict[str, str] = {}
@@ -315,18 +333,44 @@ def _asset_snapshot_directories(root: Path, excludes: tuple[str, ...]) -> dict[s
315
333
  }
316
334
 
317
335
 
336
+ def _sorted_by_kind(
337
+ files: list[Path],
338
+ ) -> tuple[list[Path], list[Path], list[str]]:
339
+ """Markup pages, source files, and the other suffixes present.
340
+
341
+ One pass, three answers. It was three comprehensions re-testing the
342
+ same two memberships, which read as cyclomatic 15 in sixteen lines —
343
+ the joint-highest in the package and one branch from failing the
344
+ gate — for a function whose actual job is "sort these into three
345
+ piles".
346
+
347
+ The two tests deliberately stay independent rather than becoming an
348
+ `elif` chain: `.html` is both a markup suffix and a known source
349
+ suffix, so it belongs in *both* piles, and an `elif` would quietly
350
+ drop it from `code` and change what the ratio below compares.
351
+ """
352
+ markup: list[Path] = []
353
+ code: list[Path] = []
354
+ other: set[str] = set()
355
+ for found in files:
356
+ lowered = found.suffix.lower()
357
+ is_markup = lowered in _MARKUP_SUFFIXES
358
+ is_code = found.suffix in KNOWN_SOURCE_SUFFIXES
359
+ if is_markup:
360
+ markup.append(found)
361
+ if is_code:
362
+ code.append(found)
363
+ if found.suffix and not is_markup and not is_code:
364
+ other.add(lowered)
365
+ return markup, code, sorted(other)
366
+
367
+
318
368
  def _asset_evidence(files: list[Path]) -> str | None:
319
369
  """Why a directory is a saved page asset, or None."""
320
370
  versioned = sorted(f.name for f in files if _VERSIONED_SNAPSHOT.search(f.name))
321
371
  if versioned:
322
372
  return f"versioned page snapshot(s): {', '.join(versioned[:3])}"
323
- markup = [f for f in files if f.suffix.lower() in _MARKUP_SUFFIXES]
324
- code = [f for f in files if f.suffix in KNOWN_SOURCE_SUFFIXES]
325
- siblings = sorted({
326
- f.suffix.lower() for f in files
327
- if f.suffix and f.suffix.lower() not in _MARKUP_SUFFIXES
328
- and f.suffix not in KNOWN_SOURCE_SUFFIXES
329
- })
373
+ markup, code, siblings = _sorted_by_kind(files)
330
374
  if len(markup) >= 2 and len(markup) > len(code) and siblings:
331
375
  return (f"{len(markup)} HTML/CSS pages outnumbering source, beside "
332
376
  f"non-source assets ({', '.join(siblings[:4])})")