maintainability-agent 2.4.1__tar.gz → 2.6.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 (320) hide show
  1. {maintainability_agent-2.4.1/src/maintainability_agent.egg-info → maintainability_agent-2.6.0}/PKG-INFO +11 -7
  2. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/README.md +10 -6
  3. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/pyproject.toml +1 -1
  4. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0/src/maintainability_agent.egg-info}/PKG-INFO +11 -7
  5. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_agent.egg-info/SOURCES.txt +5 -0
  6. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/__init__.py +1 -1
  7. maintainability_agent-2.6.0/src/maintainability_audit/_arguments.py +186 -0
  8. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_first_run.py +54 -2
  9. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_gates.py +28 -4
  10. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_history_view.py +46 -0
  11. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_setup.py +18 -4
  12. maintainability_agent-2.6.0/src/maintainability_audit/_run_comparison.py +184 -0
  13. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_scan_history.py +19 -1
  14. maintainability_agent-2.6.0/src/maintainability_audit/_test_commands.py +251 -0
  15. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/cli.py +37 -165
  16. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/config.py +1 -1
  17. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/renderers.py +6 -1
  18. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_history_schema2.py +18 -3
  19. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_identity_resolution.py +4 -1
  20. maintainability_agent-2.6.0/tests/test_run_comparison.py +321 -0
  21. maintainability_agent-2.6.0/tests/test_test_commands.py +348 -0
  22. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/LICENSE +0 -0
  23. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/setup.cfg +0 -0
  24. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  25. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  26. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
  27. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  28. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/__main__.py +0 -0
  29. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_adapters.py +0 -0
  30. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_analysis.py +0 -0
  31. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_aspects.py +0 -0
  32. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  33. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_assets/standard.md +0 -0
  34. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_attestation.py +0 -0
  35. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_backfill.py +0 -0
  36. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_bands.py +0 -0
  37. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_built_ins.py +0 -0
  38. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_calibration.py +0 -0
  39. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_catalog.py +0 -0
  40. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_charts.py +0 -0
  41. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_cognitive.py +0 -0
  42. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_config_defaults.py +0 -0
  43. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_conformance.py +0 -0
  44. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_corroborate.py +0 -0
  45. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_coverage_notes.py +0 -0
  46. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_derive.py +0 -0
  47. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_discovery.py +0 -0
  48. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_documents.py +0 -0
  49. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_economics.py +0 -0
  50. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_economics_view.py +0 -0
  51. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_environment.py +0 -0
  52. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_evidence_view.py +0 -0
  53. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_finding_match.py +0 -0
  54. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_formula.py +0 -0
  55. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_generic.py +0 -0
  56. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_grant_ledger.py +0 -0
  57. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
  58. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_hotspots.py +0 -0
  59. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_html_report_sections.py +0 -0
  60. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_html_view.py +0 -0
  61. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_identity.py +0 -0
  62. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
  63. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_markdown_sections.py +0 -0
  64. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_masking.py +0 -0
  65. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_audit.py +0 -0
  66. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_gate.py +0 -0
  67. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_grants.py +0 -0
  68. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
  69. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_mcp_resources.py +0 -0
  70. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_metric_adapters.py +0 -0
  71. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_metrics_types.py +0 -0
  72. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_pillars.py +0 -0
  73. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_practice.py +0 -0
  74. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_pressures.py +0 -0
  75. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_c.py +0 -0
  76. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_core.py +0 -0
  77. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
  78. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
  79. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
  80. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_java.py +0 -0
  81. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_js.py +0 -0
  82. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ranges_swift.py +0 -0
  83. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_ratchet.py +0 -0
  84. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_recurrence.py +0 -0
  85. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_runner.py +0 -0
  86. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_safe_write.py +0 -0
  87. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_scan_view.py +0 -0
  88. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_second_source.py +0 -0
  89. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_selection.py +0 -0
  90. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_semantic.py +0 -0
  91. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_semantic_policy.py +0 -0
  92. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_semantic_ts.py +0 -0
  93. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_semantic_view.py +0 -0
  94. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_setup_errors.py +0 -0
  95. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_setup_persist.py +0 -0
  96. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  97. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  98. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  99. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  100. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  101. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  102. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_skill_install.py +0 -0
  103. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_stored_grants.py +0 -0
  104. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_tdd_view.py +0 -0
  105. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_test_execution.py +0 -0
  106. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_test_pairing.py +0 -0
  107. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_tokens.py +0 -0
  108. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_tool_adapters.py +0 -0
  109. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_trends.py +0 -0
  110. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_user_config.py +0 -0
  111. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
  112. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_verification.py +0 -0
  113. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_work_order.py +0 -0
  114. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_work_order_view.py +0 -0
  115. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_work_order_weights.py +0 -0
  116. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/_xml.py +0 -0
  117. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/baseline.py +0 -0
  118. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/deadcode.py +0 -0
  119. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/declarations.py +0 -0
  120. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/duplication.py +0 -0
  121. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/evidence.py +0 -0
  122. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/git_tools.py +0 -0
  123. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/history.py +0 -0
  124. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/idioms.py +0 -0
  125. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/instructions.py +0 -0
  126. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/mcp_server.py +0 -0
  127. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/metrics.py +0 -0
  128. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/prompts.py +0 -0
  129. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/report.py +0 -0
  130. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/sarif.py +0 -0
  131. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/scoring.py +0 -0
  132. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/similarity.py +0 -0
  133. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/src/maintainability_audit/source.py +0 -0
  134. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_acquisition_trust.py +0 -0
  135. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_adapter_docs.py +0 -0
  136. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_adapter_recordings.py +0 -0
  137. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_adapters.py +0 -0
  138. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_added_lines.py +0 -0
  139. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analysis_coverage.py +0 -0
  140. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analysis_execution.py +0 -0
  141. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_bridge.py +0 -0
  142. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_config_isolation.py +0 -0
  143. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_estimate_claims.py +0 -0
  144. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_pinning.py +0 -0
  145. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_primary_estimate.py +0 -0
  146. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_provenance.py +0 -0
  147. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
  148. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_scoring_path.py +0 -0
  149. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_spread_range.py +0 -0
  150. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_analyzer_xml_bounds.py +0 -0
  151. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_annotations_match_behaviour.py +0 -0
  152. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_anticipated_refusals.py +0 -0
  153. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_architecture.py +0 -0
  154. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_artifact_write_route_class.py +0 -0
  155. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_aspect_coverage.py +0 -0
  156. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_asset_snapshot_class.py +0 -0
  157. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
  158. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_attestation.py +0 -0
  159. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_audit_components.py +0 -0
  160. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_authorization_freshness.py +0 -0
  161. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_authorship_gates.py +0 -0
  162. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_backfill.py +0 -0
  163. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_band_concealment_class.py +0 -0
  164. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_band_concealment_p3.py +0 -0
  165. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_band_pressures.py +0 -0
  166. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_bands.py +0 -0
  167. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_body_or_signature_class.py +0 -0
  168. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_c_declarations.py +0 -0
  169. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_calibration_corpus.py +0 -0
  170. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_calibration_drift.py +0 -0
  171. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_calibration_tooling.py +0 -0
  172. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_catalog_selection.py +0 -0
  173. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_catalog_tier_promise.py +0 -0
  174. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_chat_primary_docs.py +0 -0
  175. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_checkstyle_adapter.py +0 -0
  176. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_checkstyle_catalog.py +0 -0
  177. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_ci_history_recipe.py +0 -0
  178. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  179. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_claimed_languages.py +0 -0
  180. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_cli.py +0 -0
  181. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_clone_group_class.py +0 -0
  182. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_cognitive_complexity.py +0 -0
  183. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_cohort_statistics.py +0 -0
  184. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_concealment_properties.py +0 -0
  185. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_config_shape.py +0 -0
  186. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_consent_and_grant.py +0 -0
  187. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_consumer_migration.py +0 -0
  188. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_contract_claims.py +0 -0
  189. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_corroborate.py +0 -0
  190. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_coverage_by_language.py +0 -0
  191. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_cpp_declarations.py +0 -0
  192. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_csharp_declarations.py +0 -0
  193. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_d15_composition.py +0 -0
  194. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_d15_goal_directed.py +0 -0
  195. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_dead_code.py +0 -0
  196. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declaration_edge_cases.py +0 -0
  197. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declaration_grading.py +0 -0
  198. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declaration_ranges.py +0 -0
  199. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declaration_source.py +0 -0
  200. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declared_authorship.py +0 -0
  201. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_declared_imports.py +0 -0
  202. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_derivation_mix.py +0 -0
  203. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_determinism.py +0 -0
  204. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_dimension_ratchet.py +0 -0
  205. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_direct_runner_availability_class.py +0 -0
  206. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_discovery.py +0 -0
  207. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_doc_claims.py +0 -0
  208. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_docs_links.py +0 -0
  209. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_economic_context.py +0 -0
  210. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_empty_output_not_clean.py +0 -0
  211. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
  212. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_environment_work_order.py +0 -0
  213. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_evidence_invariants.py +0 -0
  214. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_evidence_normalization.py +0 -0
  215. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_evidence_properties.py +0 -0
  216. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_exclusion_dialects.py +0 -0
  217. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_falsifier_standard.py +0 -0
  218. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_file_list_cap_class.py +0 -0
  219. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_finding_identity.py +0 -0
  220. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_first_run_elicitation.py +0 -0
  221. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_first_run_prompt.py +0 -0
  222. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_first_run_reelicitation.py +0 -0
  223. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_fix_breadth_window.py +0 -0
  224. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_fixed_form_fortran.py +0 -0
  225. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_format_ask.py +0 -0
  226. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_fortran_declarations.py +0 -0
  227. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_fortran_metrics.py +0 -0
  228. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_fortran_practice.py +0 -0
  229. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_git_argv.py +0 -0
  230. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_git_read_only.py +0 -0
  231. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_git_readonly_class.py +0 -0
  232. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_grant_only_user_tier.py +0 -0
  233. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_history.py +0 -0
  234. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_history_boundary.py +0 -0
  235. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_history_manifest.py +0 -0
  236. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_history_window.py +0 -0
  237. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_hostile_prompt.py +0 -0
  238. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_html_executive.py +0 -0
  239. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_html_section_parity_class.py +0 -0
  240. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_identity_docs.py +0 -0
  241. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_idiom_divergence.py +0 -0
  242. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_installed_wheel_runtime.py +0 -0
  243. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_instruction_targets.py +0 -0
  244. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_java_range_guard.py +0 -0
  245. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_java_ranges.py +0 -0
  246. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_java_scored.py +0 -0
  247. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_java_wiring.py +0 -0
  248. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_js_complexity_operators.py +0 -0
  249. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_js_declarations.py +0 -0
  250. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_language_coverage.py +0 -0
  251. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_mcp_baseline_payload.py +0 -0
  252. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_mcp_history.py +0 -0
  253. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_mcp_server.py +0 -0
  254. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_migration_1_0.py +0 -0
  255. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_near_duplicates.py +0 -0
  256. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_network_disclosure.py +0 -0
  257. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
  258. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_pattern_budget.py +0 -0
  259. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_phase6_claims.py +0 -0
  260. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_pillars_and_practice.py +0 -0
  261. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_platform_claim.py +0 -0
  262. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_pmd_adapter.py +0 -0
  263. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_pmd_audit_closures.py +0 -0
  264. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_pool_runs_by_config.py +0 -0
  265. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_population_floors.py +0 -0
  266. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_practice_nested_gates_class.py +0 -0
  267. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_presentation_refusals.py +0 -0
  268. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_promises.py +0 -0
  269. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_prompt_escalation_once.py +0 -0
  270. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_prompt_honesty.py +0 -0
  271. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_prompt_location_escalation_class.py +0 -0
  272. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_prove_falsifiers.py +0 -0
  273. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_python_declarations.py +0 -0
  274. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_read_boundary.py +0 -0
  275. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_readme_claims.py +0 -0
  276. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_recurrence.py +0 -0
  277. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_release_plan.py +0 -0
  278. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_release_plan_status.py +0 -0
  279. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_report_remedy_copy.py +0 -0
  280. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_roles_recorded.py +0 -0
  281. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_root_grants.py +0 -0
  282. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  283. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_runner.py +0 -0
  284. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_sarif.py +0 -0
  285. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_scan_history.py +0 -0
  286. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_scan_scope.py +0 -0
  287. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_scanning.py +0 -0
  288. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_schema_fidelity.py +0 -0
  289. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_scope_conformance.py +0 -0
  290. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_scoring_calibration.py +0 -0
  291. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_semantic_policy.py +0 -0
  292. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_setup_gate_completeness.py +0 -0
  293. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_setup_gate_independent_contract.py +0 -0
  294. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_setup_precondition.py +0 -0
  295. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_skill_install.py +0 -0
  296. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_source_index.py +0 -0
  297. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_spotbugs_adapter.py +0 -0
  298. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_spotbugs_catalog.py +0 -0
  299. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_stage8_contract.py +0 -0
  300. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_suite_isolation.py +0 -0
  301. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_swift_declarations.py +0 -0
  302. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_tdd_structure.py +0 -0
  303. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_test_execution_class.py +0 -0
  304. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_three_presentations.py +0 -0
  305. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_trends.py +0 -0
  306. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_type_fields_not_functions_class.py +0 -0
  307. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_uat_falsifiers.py +0 -0
  308. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_unread_code.py +0 -0
  309. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_user_config_tier.py +0 -0
  310. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_verification_audit_closures.py +0 -0
  311. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_verified_grade.py +0 -0
  312. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_version_claim.py +0 -0
  313. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_wheel_contents.py +0 -0
  314. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_work_order.py +0 -0
  315. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_work_order_items.py +0 -0
  316. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_work_order_selection.py +0 -0
  317. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_workflow_supply_chain.py +0 -0
  318. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_write_boundary.py +0 -0
  319. {maintainability_agent-2.4.1 → maintainability_agent-2.6.0}/tests/test_write_route_class.py +0 -0
  320. {maintainability_agent-2.4.1 → maintainability_agent-2.6.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: 2.4.1
3
+ Version: 2.6.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -44,7 +44,7 @@ Dynamic: license-file
44
44
  **A deterministic, offline maintainability audit whose output is a _bounded
45
45
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
46
46
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
47
- Version **2.4.1**.
47
+ Version **2.6.0**.
48
48
 
49
49
  **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
50
50
  *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
@@ -152,9 +152,8 @@ registered verdict stands at **INCONCLUSIVE**. Method, limits and raw data:
152
152
  every claim the project could not stand behind was removed. A scoring engine
153
153
  rebuilt after it was found to grade repo *size*; a headline claim about AI
154
154
  authorship retracted against a matched control; a score that is withheld rather
155
- than guessed. That arc is the credibility, and it is recorded in full — with the
156
- figures quoted from their approved summaries — in
157
- [the track record](docs/track-record.md).
155
+ than guessed. That arc is the credibility, and it is recorded in full, with the
156
+ figures quoted from their approved summaries, in [the track record](docs/track-record.md).
158
157
 
159
158
  ## Install
160
159
 
@@ -223,8 +222,8 @@ withheld and the scope is named as the reason.
223
222
  ### Checking that the agent did the work
224
223
 
225
224
  The work order tells an agent to fix exactly these findings and refactor nothing
226
- else. These flags check that the diff that came back obeyed it — read the
227
- diff's _shape_, not its correctness:
225
+ else. These flags check that the diff obeyed it — they read its _shape_, not its
226
+ correctness:
228
227
 
229
228
  ```bash
230
229
  maintainability-agent \
@@ -251,6 +250,11 @@ maintainability-agent \
251
250
  work order, and what moved. It is reproducible and **not signed** — nothing
252
251
  here holds a key, and the document says so in its own text. A check nobody ran
253
252
  renders as _not asked_, never as passed.
253
+ - **`--transformation NAME`** names the class of work a scan followed and
254
+ reports how this run of it compares with earlier ones. **A report, never a
255
+ gate.** It says one run "moved further" than another, never that it was
256
+ _better_ — two runs of one codemod land on different code — and it measures
257
+ the interval, not the transformation.
254
258
 
255
259
  The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
256
260
  has the history of why this was the hole under the product's central claim.
@@ -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 **2.4.1**.
8
+ Version **2.6.0**.
9
9
 
10
10
  **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
11
11
  *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
@@ -113,9 +113,8 @@ registered verdict stands at **INCONCLUSIVE**. Method, limits and raw data:
113
113
  every claim the project could not stand behind was removed. A scoring engine
114
114
  rebuilt after it was found to grade repo *size*; a headline claim about AI
115
115
  authorship retracted against a matched control; a score that is withheld rather
116
- than guessed. That arc is the credibility, and it is recorded in full — with the
117
- figures quoted from their approved summaries — in
118
- [the track record](docs/track-record.md).
116
+ than guessed. That arc is the credibility, and it is recorded in full, with the
117
+ figures quoted from their approved summaries, in [the track record](docs/track-record.md).
119
118
 
120
119
  ## Install
121
120
 
@@ -184,8 +183,8 @@ withheld and the scope is named as the reason.
184
183
  ### Checking that the agent did the work
185
184
 
186
185
  The work order tells an agent to fix exactly these findings and refactor nothing
187
- else. These flags check that the diff that came back obeyed it — read the
188
- diff's _shape_, not its correctness:
186
+ else. These flags check that the diff obeyed it — they read its _shape_, not its
187
+ correctness:
189
188
 
190
189
  ```bash
191
190
  maintainability-agent \
@@ -212,6 +211,11 @@ maintainability-agent \
212
211
  work order, and what moved. It is reproducible and **not signed** — nothing
213
212
  here holds a key, and the document says so in its own text. A check nobody ran
214
213
  renders as _not asked_, never as passed.
214
+ - **`--transformation NAME`** names the class of work a scan followed and
215
+ reports how this run of it compares with earlier ones. **A report, never a
216
+ gate.** It says one run "moved further" than another, never that it was
217
+ _better_ — two runs of one codemod land on different code — and it measures
218
+ the interval, not the transformation.
215
219
 
216
220
  The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
217
221
  has the history of why this was the hole under the product's central claim.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maintainability-agent"
7
- version = "2.4.1"
7
+ version = "2.6.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: 2.4.1
3
+ Version: 2.6.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -44,7 +44,7 @@ Dynamic: license-file
44
44
  **A deterministic, offline maintainability audit whose output is a _bounded
45
45
  work order_ for an AI coding agent** — a copy-paste prompt, per finding, that
46
46
  says *fix exactly these and refactor nothing else*. Chat-primary; CLI for CI.
47
- Version **2.4.1**.
47
+ Version **2.6.0**.
48
48
 
49
49
  **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
50
50
  *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
@@ -152,9 +152,8 @@ registered verdict stands at **INCONCLUSIVE**. Method, limits and raw data:
152
152
  every claim the project could not stand behind was removed. A scoring engine
153
153
  rebuilt after it was found to grade repo *size*; a headline claim about AI
154
154
  authorship retracted against a matched control; a score that is withheld rather
155
- than guessed. That arc is the credibility, and it is recorded in full — with the
156
- figures quoted from their approved summaries — in
157
- [the track record](docs/track-record.md).
155
+ than guessed. That arc is the credibility, and it is recorded in full, with the
156
+ figures quoted from their approved summaries, in [the track record](docs/track-record.md).
158
157
 
159
158
  ## Install
160
159
 
@@ -223,8 +222,8 @@ withheld and the scope is named as the reason.
223
222
  ### Checking that the agent did the work
224
223
 
225
224
  The work order tells an agent to fix exactly these findings and refactor nothing
226
- else. These flags check that the diff that came back obeyed it — read the
227
- diff's _shape_, not its correctness:
225
+ else. These flags check that the diff obeyed it — they read its _shape_, not its
226
+ correctness:
228
227
 
229
228
  ```bash
230
229
  maintainability-agent \
@@ -251,6 +250,11 @@ maintainability-agent \
251
250
  work order, and what moved. It is reproducible and **not signed** — nothing
252
251
  here holds a key, and the document says so in its own text. A check nobody ran
253
252
  renders as _not asked_, never as passed.
253
+ - **`--transformation NAME`** names the class of work a scan followed and
254
+ reports how this run of it compares with earlier ones. **A report, never a
255
+ gate.** It says one run "moved further" than another, never that it was
256
+ _better_ — two runs of one codemod land on different code — and it measures
257
+ the interval, not the transformation.
254
258
 
255
259
  The [roadmap](docs/roadmap.md#the-remediation-hole-closed-in-210-through-230)
256
260
  has the history of why this was the hole under the product's central claim.
@@ -11,6 +11,7 @@ src/maintainability_audit/__init__.py
11
11
  src/maintainability_audit/__main__.py
12
12
  src/maintainability_audit/_adapters.py
13
13
  src/maintainability_audit/_analysis.py
14
+ src/maintainability_audit/_arguments.py
14
15
  src/maintainability_audit/_aspects.py
15
16
  src/maintainability_audit/_attestation.py
16
17
  src/maintainability_audit/_backfill.py
@@ -67,6 +68,7 @@ src/maintainability_audit/_ranges_js.py
67
68
  src/maintainability_audit/_ranges_swift.py
68
69
  src/maintainability_audit/_ratchet.py
69
70
  src/maintainability_audit/_recurrence.py
71
+ src/maintainability_audit/_run_comparison.py
70
72
  src/maintainability_audit/_runner.py
71
73
  src/maintainability_audit/_safe_write.py
72
74
  src/maintainability_audit/_scan_history.py
@@ -82,6 +84,7 @@ src/maintainability_audit/_setup_persist.py
82
84
  src/maintainability_audit/_skill_install.py
83
85
  src/maintainability_audit/_stored_grants.py
84
86
  src/maintainability_audit/_tdd_view.py
87
+ src/maintainability_audit/_test_commands.py
85
88
  src/maintainability_audit/_test_execution.py
86
89
  src/maintainability_audit/_test_pairing.py
87
90
  src/maintainability_audit/_tokens.py
@@ -273,6 +276,7 @@ tests/test_report_remedy_copy.py
273
276
  tests/test_roles_recorded.py
274
277
  tests/test_root_grants.py
275
278
  tests/test_rubric_ignores_project_lint_config.py
279
+ tests/test_run_comparison.py
276
280
  tests/test_runner.py
277
281
  tests/test_sarif.py
278
282
  tests/test_scan_history.py
@@ -293,6 +297,7 @@ tests/test_stage8_contract.py
293
297
  tests/test_suite_isolation.py
294
298
  tests/test_swift_declarations.py
295
299
  tests/test_tdd_structure.py
300
+ tests/test_test_commands.py
296
301
  tests/test_test_execution_class.py
297
302
  tests/test_three_presentations.py
298
303
  tests/test_trends.py
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "2.4.1"
3
+ __version__ = "2.6.0"
@@ -0,0 +1,186 @@
1
+ """What the command line accepts, separate from what the command does.
2
+
3
+ Split out of `cli` when it crossed this project's own `max_file_lines`
4
+ gate — the second time that gate has shaped this module, after
5
+ `_add_gate_arguments` was split from `add_arguments` for the function
6
+ budget. Both splits were forced by the tool on a change to the tool, which
7
+ is the gate doing the job it exists for rather than an inconvenience.
8
+
9
+ The boundary is deliberate and not merely a line count: everything here
10
+ declares a flag and nothing here runs an audit. `cli` imports it, never
11
+ the reverse.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+
17
+ from .config import VERSION
18
+
19
+
20
+ def _add_gate_arguments(parser: argparse.ArgumentParser) -> None:
21
+ """What can make a run fail, and the conformance record behind one.
22
+
23
+ Split from `add_arguments` when the conformance flags took it past this
24
+ project's own function-length gate — which is the gate doing its job on
25
+ the change that added a gate.
26
+ """
27
+ parser.add_argument("--fail-on-gate", action="store_true", help="Exit 1 when hard gates fail.")
28
+ parser.add_argument(
29
+ "--conformance",
30
+ metavar="REVSPEC",
31
+ help="Report how a diff relates to the work order, e.g. `main...HEAD`. "
32
+ "The bounded work order says 'fix exactly these and refactor nothing "
33
+ "else'; without this the bound is an instruction nothing checks. "
34
+ "Reports only unless --fail-on-out-of-scope is passed.",
35
+ )
36
+ parser.add_argument(
37
+ "--fail-on-regression", action="store_true",
38
+ help="Exit 1 when any scoring category is lower than the previous "
39
+ "comparable scan. Reads the recorded history, and refuses to "
40
+ "compare across an instrument change rather than reporting a "
41
+ "false regression: two scans taken under different calibration "
42
+ "cannot be subtracted.",
43
+ )
44
+ parser.add_argument(
45
+ "--fail-on-out-of-scope", action="store_true",
46
+ help="With --conformance, exit 1 when the diff touched files the work "
47
+ "order did not name and that do not pair to one as its test, or "
48
+ "when it added a suppression to a file the work order flagged.",
49
+ )
50
+
51
+
52
+ def _add_artifact_arguments(parser: argparse.ArgumentParser) -> None:
53
+ """The documents a run can write beside its report, and the run's label.
54
+
55
+ Split out for the same reason `_add_gate_arguments` was, and by the same
56
+ gate: `--transformation` took `add_arguments` past this project's own
57
+ function-length threshold, so the gate failed the change that added a
58
+ reporting flag. Grouped by what they produce rather than alphabetically
59
+ — every one of these is an artifact for somebody other than the person
60
+ running the command.
61
+ """
62
+ parser.add_argument("--prompt-output", help="Optional Markdown prompt for AI-assisted remediation.")
63
+ parser.add_argument("--comment-output", help="Optional Markdown body suitable for a PR comment.")
64
+ parser.add_argument("--agent-instructions-output", help="Optional reusable instructions for AI coding agents.")
65
+ parser.add_argument(
66
+ "--attestation-output",
67
+ help="Write the attestation: an independent, reproducible record of "
68
+ "what was measured, what the change was told to do, what it did, "
69
+ "and what moved. Populated by --conformance and "
70
+ "--fail-on-regression; a generator cannot produce this about its "
71
+ "own output.",
72
+ )
73
+ parser.add_argument(
74
+ "--transformation",
75
+ metavar="NAME",
76
+ help="Name the class of work this scan followed, e.g. `react-18`. "
77
+ "Records the name on the scan and reports how this run of it "
78
+ "compares with earlier ones. Nothing in a tree says which "
79
+ "transformation produced it, so this is your claim and the tool "
80
+ "records it without verifying it. A report, never a gate.",
81
+ )
82
+ parser.add_argument("--hostile-prompt-output",
83
+ help="Optional adversarial audit brief seeded from this run (ADR 013). "
84
+ "Text only: it does not gate, score, or send anything.")
85
+
86
+
87
+ def add_arguments(parser: argparse.ArgumentParser) -> None:
88
+ parser.add_argument("--version", action="version", version=f"maintainability-agent {VERSION}")
89
+ parser.add_argument("--root", default=".", help="Repository root to scan.")
90
+ parser.add_argument("--config", help="Path to JSON config.")
91
+ # Default None, not "markdown": the TTY question (8.4) only fires
92
+ # when the user stated nothing, and argparse cannot distinguish a
93
+ # stated default from an omitted flag.
94
+ parser.add_argument("--format", choices=["json", "markdown", "html"], default=None)
95
+ parser.add_argument("--html-output", help="Write the single-file HTML report here (ADR 011).")
96
+ parser.add_argument("--output", help="Output file. Defaults to stdout.")
97
+ _add_artifact_arguments(parser)
98
+ parser.add_argument("--sarif-output", help="Optional SARIF output path for GitHub code scanning.")
99
+ parser.add_argument("--sarif-input", action="append", help="Optional external SARIF file to summarize in reports. Repeatable.")
100
+ parser.add_argument("--changed-only", help="Audit only files changed in a git revspec, for example main...HEAD.")
101
+ parser.add_argument("--baseline", help="Existing baseline JSON. With --fail-on-new, only new findings fail.")
102
+ parser.add_argument("--write-baseline", help="Write current findings to a baseline JSON file.")
103
+ parser.add_argument("--fail-on-new", action="store_true", help="Fail only when findings are not in --baseline.")
104
+ parser.add_argument(
105
+ "--analyzers", action="store_true",
106
+ help="Force the external analyzer pool on for this run. The pool is "
107
+ "the primary evidence source (ADR 006, docs/analyzer-pool.md); a "
108
+ "repository with a config file runs it by default, so this flag "
109
+ "matters only for unconfigured trees or to override "
110
+ "analyzers.run=false. Measurements move the point estimate where "
111
+ "the full concept set was measured; otherwise the built-in "
112
+ "fallback stands and the range widens around the two.",
113
+ )
114
+ parser.add_argument(
115
+ "--no-analyzers", action="store_true",
116
+ help="Force the analyzer pool off for this run, overriding the "
117
+ "config. The report will say the built-in fallback supplied the "
118
+ "evidence (P8); it is a faster scan, not the full audit.",
119
+ )
120
+ parser.add_argument(
121
+ "--work", action="append", metavar="AXIS=VALUE",
122
+ help="Narrow the work order, for example --work band=quick-win or "
123
+ "--work path=src/. Repeatable; every criterion must match. "
124
+ "Axes: band, finding_class, path, verification. Narrowing "
125
+ "changes what is shown and never what anything scored.",
126
+ )
127
+ parser.add_argument(
128
+ "--record-history", action="store_true",
129
+ help="Append this scan to the history at paths.history (default "
130
+ ".maintainability/history.jsonl). Opt-in, like every other write "
131
+ "this tool performs. Once the file exists, every later successful "
132
+ "scan appends to it and reads the resulting history.",
133
+ )
134
+ parser.add_argument(
135
+ "--backfill", metavar="REVSPEC",
136
+ help="Scan each commit in a range into the history and exit, for "
137
+ "example --backfill HEAD~50..HEAD. Each commit is checked out in "
138
+ "a temporary worktree, so the working tree is never touched. "
139
+ "Expensive and therefore explicit: it never runs as part of a "
140
+ "normal scan. Records are marked as reconstructed.",
141
+ )
142
+ parser.add_argument(
143
+ "--backfill-interval", type=int, default=1, metavar="N",
144
+ help="With --backfill, scan every Nth commit instead of all of them. "
145
+ "The shape of a series is what a trend reads, and a thousand "
146
+ "commits is hours of work nobody asked for.",
147
+ )
148
+ _add_gate_arguments(parser)
149
+ _add_setup_actions(parser)
150
+
151
+
152
+ def _add_setup_actions(parser: argparse.ArgumentParser) -> None:
153
+ """Flags that perform a setup action and exit instead of auditing."""
154
+ parser.add_argument("--init-agent-standards", action="store_true", help="Write model/tool-specific instruction files and exit.")
155
+ parser.add_argument(
156
+ "--install-skill", action="store_true",
157
+ help="Copy the packaged agent skill into the skills directory and "
158
+ "exit. Re-run after every upgrade: an installed skill that "
159
+ "drifts from the shipped one teaches agents a dead workflow.",
160
+ )
161
+ parser.add_argument(
162
+ "--skills-dir", default=None, metavar="DIR",
163
+ help="Where --install-skill writes (default: ~/.claude/skills).",
164
+ )
165
+ parser.add_argument(
166
+ "--force-skill", action="store_true",
167
+ help="With --install-skill: overwrite a differing installed copy "
168
+ "and remove files the package no longer ships. Without it, a "
169
+ "differing copy is refused with the list of differences.",
170
+ )
171
+ parser.add_argument(
172
+ "--target-path",
173
+ action="append",
174
+ metavar="TARGET=PATH",
175
+ help="Where a target's standing instructions go, e.g. "
176
+ "`--target-path bob=.bob/instructions.md`. Required for any agent "
177
+ "this tool has no built-in convention for; overrides the built-in "
178
+ "path for one it does. The target list will always trail the "
179
+ "market, and guessing a path writes a file the agent never opens.",
180
+ )
181
+ parser.add_argument(
182
+ "--target",
183
+ action="append",
184
+ help="Instruction target. Repeatable. Used with --init-agent-standards.",
185
+ )
186
+ parser.add_argument("--instructions-output-dir", default=".", help="Directory for generated instruction files.")
@@ -22,6 +22,7 @@ sat in ``DEFAULTS``, documented as reserved, read by nothing, from
22
22
  """
23
23
  from __future__ import annotations
24
24
 
25
+ import contextlib
25
26
  import json
26
27
  import sys
27
28
  from pathlib import Path
@@ -190,11 +191,53 @@ def maybe_prompt_economics(root: Path, config: dict) -> None:
190
191
  print(f"Wrote {written}")
191
192
 
192
193
 
194
+ def _input_with_default(prompt: str, default: str) -> str:
195
+ """`input()` with the line pre-filled, where the terminal allows it.
196
+
197
+ `readline` is what makes the default *editable* rather than merely
198
+ described: the text is inserted into the line buffer, so Enter submits
199
+ it, backspace edits it, and clearing it returns the empty string that
200
+ has always meant "cancel". Without that, a pre-filled default and a
201
+ blank-means-cancel rule cannot both be true on one keystroke.
202
+
203
+ Absent or unusable `readline` — Windows without pyreadline, a terminal
204
+ that refuses the hook — falls back to a plain `input()`. The default is
205
+ still named in the prompt text, so the operator loses the keystroke and
206
+ not the information. Never let this be the thing that fails a setup.
207
+ """
208
+ if not default:
209
+ return input(prompt)
210
+ try:
211
+ import readline
212
+ except ImportError:
213
+ return input(prompt)
214
+
215
+ def _prefill() -> None:
216
+ readline.insert_text(default)
217
+ readline.redisplay()
218
+
219
+ try:
220
+ readline.set_startup_hook(_prefill)
221
+ return input(prompt)
222
+ except Exception: # noqa: BLE001 - a cosmetic hook must not fail setup
223
+ return input(prompt)
224
+ finally:
225
+ # Global state: a hook left installed would pre-type this command
226
+ # into whatever the session asks next.
227
+ with contextlib.suppress(Exception):
228
+ readline.set_startup_hook()
229
+
230
+
193
231
  def maybe_prompt_test_command(root: Path, config: dict) -> None:
194
232
  """Ask the opted-in operator for the test command, once -- the CLI half
195
233
  of the Class 5 second stage, mirroring the labor-rate ask. Fires only at
196
234
  a TTY, only when the suite was opted into and no command is stored, and
197
235
  a blank answer cancels the opt-in. Nothing runs until a command exists.
236
+
237
+ Where the tree's manifests name a runner, the line is **pre-filled**
238
+ with that command rather than merely mentioning it, so this surface and
239
+ the MCP one carry the same default in the same field: Enter accepts,
240
+ editing replaces, and clearing the line cancels exactly as before.
198
241
  """
199
242
  import shlex
200
243
 
@@ -209,10 +252,19 @@ def maybe_prompt_test_command(root: Path, config: dict) -> None:
209
252
  if (config.get("expected_commands") or {}).get("test"):
210
253
  return
211
254
 
212
- answer = input(
255
+ from ._test_commands import suggested_test_command
256
+
257
+ suggested = suggested_test_command(root)
258
+ detected = " ".join(suggested.command) if suggested is not None else ""
259
+ prompt = (
260
+ f"Detected `{detected}` from {suggested.evidence}. The command that "
261
+ "runs this repository's test suite (Enter to accept, clear the line "
262
+ "to cancel running it): "
263
+ if suggested is not None else
213
264
  "The command that runs this repository's test suite, e.g. `pytest` "
214
265
  "(Enter to cancel running it): "
215
- ).strip()
266
+ )
267
+ answer = _input_with_default(prompt, detected).strip()
216
268
 
217
269
  from ._safe_write import write_bounded
218
270
 
@@ -51,18 +51,42 @@ def attach_ratchet(report: dict, history_path: Path) -> None:
51
51
  report["dimension_ratchet"] = dimension_ratchet(read_history(history_path))
52
52
 
53
53
 
54
+ def attach_run_comparison(
55
+ args: argparse.Namespace, report: dict, history_path: Path
56
+ ) -> None:
57
+ """Compare this run of a named transformation with earlier ones.
58
+
59
+ Only when the operator named one: an unnamed run belongs to no series,
60
+ and inventing a series for it would be the tool answering a question
61
+ nobody asked.
62
+ """
63
+ label = getattr(args, "transformation", None)
64
+ if not label or not history_path.exists():
65
+ return
66
+ from ._run_comparison import compare_runs
67
+ from ._scan_history import read_history
68
+
69
+ report["run_comparison"] = compare_runs(read_history(history_path), label)
70
+
71
+
54
72
  def _attach_post_audit_records(
55
73
  args: argparse.Namespace, report: dict, history_path: Path
56
74
  ) -> None:
57
75
  """Records composed from the finished report, before it is rendered.
58
76
 
59
- Both read the report rather than the tree, and neither reaches scoring:
60
- whether a diff obeyed its work order, and whether a dimension slipped
61
- since the last comparable scan, are facts about a change and its
62
- history — not evidence about the code's condition.
77
+ All three read the report or the history rather than the tree, and none
78
+ reaches scoring: whether a diff obeyed its work order, whether a
79
+ dimension slipped since the last comparable scan, and how this run of a
80
+ transformation compares with earlier ones are facts about a change and
81
+ its history — not evidence about the code's condition.
82
+
83
+ The third is the only one that cannot fail a build. It is a report, by
84
+ design: "run seven moved further than run six" is worth knowing and is
85
+ not a thing to block a merge on.
63
86
  """
64
87
  attach_conformance(args, report)
65
88
  attach_ratchet(report, history_path)
89
+ attach_run_comparison(args, report, history_path)
66
90
 
67
91
 
68
92
  def _conformance_exit(args: argparse.Namespace, report: dict) -> int:
@@ -120,3 +120,49 @@ def escalations_markdown(escalated: list[dict[str, Any]] | None) -> list[str]:
120
120
  ])
121
121
  lines.append("")
122
122
  return lines
123
+
124
+
125
+ def run_comparison_markdown(comparison: dict[str, Any] | None) -> list[str]:
126
+ """The markdown section. Presentation only — it computes no score.
127
+
128
+ Empty for a run nobody named, which is most of them.
129
+ """
130
+ if not comparison:
131
+ return []
132
+ label = comparison["label"]
133
+ lines = [f"## Runs of `{label}`", ""]
134
+ runs = comparison["runs"]
135
+ if not runs:
136
+ return [*lines, comparison["trend"].get("reason", "No runs recorded."), ""]
137
+
138
+ lines += ["| Recorded | Commit | Estimate | Moved | Files | Declarations |",
139
+ "|---|---|---|---|---|---|"]
140
+ for run in runs:
141
+ estimate = "withheld" if run["estimate"] is None else f"{run['estimate']:.2f}"
142
+ moved = "—" if run["moved"] is None else f"{run['moved']:+.2f}"
143
+ populations = run["populations"]
144
+ lines.append(
145
+ f"| {run['recorded_at']} | `{(run['commit'] or '')[:8]}` | {estimate} | "
146
+ f"{moved} | {populations.get('files_scanned', '—')} | "
147
+ f"{populations.get('declarations_scanned', '—')} |"
148
+ )
149
+ lines.append("")
150
+
151
+ trend = comparison["trend"]
152
+ lines.append(
153
+ f"**{trend['summary']}.**" if trend.get("comparable")
154
+ else f"**Not established:** {trend['reason']}."
155
+ )
156
+ if comparison.get("excluded_earlier_runs"):
157
+ lines += ["", (
158
+ f"{comparison['excluded_earlier_runs']} earlier run(s) under this "
159
+ f"name are excluded: {comparison['exclusion_reason']}."
160
+ )]
161
+ lines += ["", (
162
+ "*`Moved` is the change in estimate between the previous recorded "
163
+ "scan and this one — the movement across that interval, not the "
164
+ "effect of the transformation. Anything else that happened in the "
165
+ "same interval is inside the number, and two runs of one "
166
+ "transformation land on different code.*"
167
+ ), ""]
168
+ return lines
@@ -226,21 +226,35 @@ def run_tests_pending(root: Path) -> bool:
226
226
  and "test_execution" not in stored)
227
227
 
228
228
 
229
- def test_command_questions() -> list[dict[str, Any]]:
229
+ def test_command_questions(root: Path | None = None) -> list[dict[str, Any]]:
230
230
  """The one command, asked only of someone who opted into running it.
231
231
 
232
232
  A free-text answer (empty options), the second stage of the opt-in the
233
233
  way the labor rates are the second stage of the economic scenario.
234
+
235
+ When the tree's manifests name a runner, that command is the question's
236
+ `default` and the prompt says which file proposed it. It is a default,
237
+ not a decision: the operator's answer is what gets stored, and blank
238
+ still cancels the opt-in — a pre-filled field the operator clears is
239
+ the same cancellation it always was.
234
240
  """
241
+ from ._test_commands import suggested_test_command
242
+
243
+ suggested = suggested_test_command(root) if root is not None else None
244
+ detected = " ".join(suggested.command) if suggested is not None else ""
245
+ because = (
246
+ f"Detected `{detected}` from {suggested.evidence}. "
247
+ if suggested is not None else ""
248
+ )
235
249
  return [{
236
250
  "name": "test_command",
237
251
  "prompt": (
238
- "The command that runs this repository's test suite "
252
+ f"{because}The command that runs this repository's test suite "
239
253
  "(e.g. `pytest`, `npm test`). It runs in the repository root, "
240
254
  "and leaving it blank cancels the opt-in."
241
255
  ),
242
256
  "options": [],
243
- "default": "",
257
+ "default": detected,
244
258
  }]
245
259
 
246
260
 
@@ -334,7 +348,7 @@ def setup_schema(root: Path | None = None):
334
348
  if root is not None and economics_bounds_pending(root):
335
349
  return _schema_for(economics_bound_questions())
336
350
  if root is not None and test_command_pending(root):
337
- return _schema_for(test_command_questions())
351
+ return _schema_for(test_command_questions(root))
338
352
  return _schema_for(setup_questions(load_config(None)))
339
353
 
340
354