maintainability-agent 2.3.0__tar.gz → 2.4.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 (314) hide show
  1. {maintainability_agent-2.3.0/src/maintainability_agent.egg-info → maintainability_agent-2.4.0}/PKG-INFO +8 -7
  2. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/README.md +7 -6
  3. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/pyproject.toml +1 -1
  4. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0/src/maintainability_agent.egg-info}/PKG-INFO +8 -7
  5. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_agent.egg-info/SOURCES.txt +2 -0
  6. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/__init__.py +1 -1
  7. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_cognitive.py +21 -4
  8. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_metrics_types.py +14 -0
  9. maintainability_agent-2.4.0/src/maintainability_audit/_ranges_swift.py +215 -0
  10. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/config.py +1 -1
  11. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/declarations.py +15 -2
  12. maintainability_agent-2.4.0/tests/test_swift_declarations.py +264 -0
  13. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/LICENSE +0 -0
  14. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/setup.cfg +0 -0
  15. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_agent.egg-info/dependency_links.txt +0 -0
  16. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_agent.egg-info/entry_points.txt +0 -0
  17. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_agent.egg-info/requires.txt +0 -0
  18. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_agent.egg-info/top_level.txt +0 -0
  19. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/__main__.py +0 -0
  20. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_adapters.py +0 -0
  21. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_analysis.py +0 -0
  22. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_aspects.py +0 -0
  23. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_assets/analyzer-catalog.json +0 -0
  24. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_assets/standard.md +0 -0
  25. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_attestation.py +0 -0
  26. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_backfill.py +0 -0
  27. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_bands.py +0 -0
  28. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_built_ins.py +0 -0
  29. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_calibration.py +0 -0
  30. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_catalog.py +0 -0
  31. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_charts.py +0 -0
  32. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_config_defaults.py +0 -0
  33. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_conformance.py +0 -0
  34. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_corroborate.py +0 -0
  35. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_coverage_notes.py +0 -0
  36. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_derive.py +0 -0
  37. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_discovery.py +0 -0
  38. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_documents.py +0 -0
  39. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_economics.py +0 -0
  40. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_economics_view.py +0 -0
  41. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_environment.py +0 -0
  42. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_evidence_view.py +0 -0
  43. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_finding_match.py +0 -0
  44. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_first_run.py +0 -0
  45. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_formula.py +0 -0
  46. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_gates.py +0 -0
  47. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_generic.py +0 -0
  48. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_grant_ledger.py +0 -0
  49. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_history_view.py +0 -0
  50. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_hostile_prompt.py +0 -0
  51. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_hotspots.py +0 -0
  52. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_html_report_sections.py +0 -0
  53. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_html_view.py +0 -0
  54. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_identity.py +0 -0
  55. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_jvm_adapters.py +0 -0
  56. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_markdown_sections.py +0 -0
  57. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_masking.py +0 -0
  58. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_audit.py +0 -0
  59. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_gate.py +0 -0
  60. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_grants.py +0 -0
  61. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_refusals.py +0 -0
  62. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_resources.py +0 -0
  63. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_mcp_setup.py +0 -0
  64. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_metric_adapters.py +0 -0
  65. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_pillars.py +0 -0
  66. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_practice.py +0 -0
  67. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_pressures.py +0 -0
  68. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_c.py +0 -0
  69. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_core.py +0 -0
  70. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_cpp.py +0 -0
  71. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_csharp.py +0 -0
  72. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_fortran.py +0 -0
  73. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_java.py +0 -0
  74. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ranges_js.py +0 -0
  75. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_ratchet.py +0 -0
  76. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_recurrence.py +0 -0
  77. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_runner.py +0 -0
  78. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_safe_write.py +0 -0
  79. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_scan_history.py +0 -0
  80. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_scan_view.py +0 -0
  81. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_second_source.py +0 -0
  82. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_selection.py +0 -0
  83. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_semantic.py +0 -0
  84. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_semantic_policy.py +0 -0
  85. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_semantic_ts.py +0 -0
  86. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_semantic_view.py +0 -0
  87. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_setup_errors.py +0 -0
  88. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_setup_persist.py +0 -0
  89. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/SKILL.md +0 -0
  90. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/agents/anthropic.yaml +0 -0
  91. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/agents/copilot.yaml +0 -0
  92. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/agents/openai.yaml +0 -0
  93. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/copilot/maintainability-agent.prompt.md +0 -0
  94. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_data/references/finding-taxonomy.md +0 -0
  95. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_skill_install.py +0 -0
  96. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_stored_grants.py +0 -0
  97. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_tdd_view.py +0 -0
  98. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_test_execution.py +0 -0
  99. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_test_pairing.py +0 -0
  100. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_tokens.py +0 -0
  101. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_tool_adapters.py +0 -0
  102. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_trends.py +0 -0
  103. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_user_config.py +0 -0
  104. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_verdict_adapters.py +0 -0
  105. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_verification.py +0 -0
  106. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_work_order.py +0 -0
  107. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_work_order_view.py +0 -0
  108. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_work_order_weights.py +0 -0
  109. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/_xml.py +0 -0
  110. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/baseline.py +0 -0
  111. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/cli.py +0 -0
  112. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/deadcode.py +0 -0
  113. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/duplication.py +0 -0
  114. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/evidence.py +0 -0
  115. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/git_tools.py +0 -0
  116. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/history.py +0 -0
  117. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/idioms.py +0 -0
  118. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/instructions.py +0 -0
  119. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/mcp_server.py +0 -0
  120. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/metrics.py +0 -0
  121. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/prompts.py +0 -0
  122. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/renderers.py +0 -0
  123. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/report.py +0 -0
  124. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/sarif.py +0 -0
  125. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/scoring.py +0 -0
  126. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/similarity.py +0 -0
  127. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/src/maintainability_audit/source.py +0 -0
  128. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_acquisition_trust.py +0 -0
  129. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_adapter_docs.py +0 -0
  130. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_adapter_recordings.py +0 -0
  131. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_adapters.py +0 -0
  132. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_added_lines.py +0 -0
  133. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analysis_coverage.py +0 -0
  134. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analysis_execution.py +0 -0
  135. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_bridge.py +0 -0
  136. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_config_isolation.py +0 -0
  137. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_estimate_claims.py +0 -0
  138. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_pinning.py +0 -0
  139. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_primary_estimate.py +0 -0
  140. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_provenance.py +0 -0
  141. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_provenance_exclusions.py +0 -0
  142. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_scoring_path.py +0 -0
  143. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_spread_range.py +0 -0
  144. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_analyzer_xml_bounds.py +0 -0
  145. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_annotations_match_behaviour.py +0 -0
  146. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_anticipated_refusals.py +0 -0
  147. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_architecture.py +0 -0
  148. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_artifact_write_route_class.py +0 -0
  149. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_aspect_coverage.py +0 -0
  150. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_asset_snapshot_class.py +0 -0
  151. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_ast_reading_resolves_spellings.py +0 -0
  152. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_attestation.py +0 -0
  153. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_audit_components.py +0 -0
  154. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_authorization_freshness.py +0 -0
  155. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_authorship_gates.py +0 -0
  156. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_backfill.py +0 -0
  157. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_band_concealment_class.py +0 -0
  158. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_band_concealment_p3.py +0 -0
  159. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_band_pressures.py +0 -0
  160. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_bands.py +0 -0
  161. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_body_or_signature_class.py +0 -0
  162. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_c_declarations.py +0 -0
  163. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_calibration_corpus.py +0 -0
  164. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_calibration_drift.py +0 -0
  165. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_calibration_tooling.py +0 -0
  166. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_catalog_selection.py +0 -0
  167. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_catalog_tier_promise.py +0 -0
  168. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_chat_primary_docs.py +0 -0
  169. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_checkstyle_adapter.py +0 -0
  170. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_checkstyle_catalog.py +0 -0
  171. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_ci_history_recipe.py +0 -0
  172. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_ci_installs_the_analyzer_pool.py +0 -0
  173. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_claimed_languages.py +0 -0
  174. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_cli.py +0 -0
  175. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_clone_group_class.py +0 -0
  176. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_cognitive_complexity.py +0 -0
  177. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_cohort_statistics.py +0 -0
  178. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_concealment_properties.py +0 -0
  179. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_config_shape.py +0 -0
  180. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_consent_and_grant.py +0 -0
  181. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_consumer_migration.py +0 -0
  182. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_contract_claims.py +0 -0
  183. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_corroborate.py +0 -0
  184. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_coverage_by_language.py +0 -0
  185. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_cpp_declarations.py +0 -0
  186. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_csharp_declarations.py +0 -0
  187. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_d15_composition.py +0 -0
  188. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_d15_goal_directed.py +0 -0
  189. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_dead_code.py +0 -0
  190. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declaration_edge_cases.py +0 -0
  191. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declaration_grading.py +0 -0
  192. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declaration_ranges.py +0 -0
  193. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declaration_source.py +0 -0
  194. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declared_authorship.py +0 -0
  195. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_declared_imports.py +0 -0
  196. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_derivation_mix.py +0 -0
  197. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_determinism.py +0 -0
  198. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_dimension_ratchet.py +0 -0
  199. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_direct_runner_availability_class.py +0 -0
  200. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_discovery.py +0 -0
  201. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_doc_claims.py +0 -0
  202. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_docs_links.py +0 -0
  203. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_economic_context.py +0 -0
  204. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_empty_output_not_clean.py +0 -0
  205. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_empty_output_not_clean_adapters.py +0 -0
  206. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_environment_work_order.py +0 -0
  207. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_evidence_invariants.py +0 -0
  208. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_evidence_normalization.py +0 -0
  209. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_evidence_properties.py +0 -0
  210. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_exclusion_dialects.py +0 -0
  211. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_falsifier_standard.py +0 -0
  212. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_file_list_cap_class.py +0 -0
  213. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_finding_identity.py +0 -0
  214. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_first_run_elicitation.py +0 -0
  215. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_first_run_prompt.py +0 -0
  216. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_first_run_reelicitation.py +0 -0
  217. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_fix_breadth_window.py +0 -0
  218. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_fixed_form_fortran.py +0 -0
  219. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_format_ask.py +0 -0
  220. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_fortran_declarations.py +0 -0
  221. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_fortran_metrics.py +0 -0
  222. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_fortran_practice.py +0 -0
  223. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_git_argv.py +0 -0
  224. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_git_read_only.py +0 -0
  225. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_git_readonly_class.py +0 -0
  226. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_grant_only_user_tier.py +0 -0
  227. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_history.py +0 -0
  228. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_history_boundary.py +0 -0
  229. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_history_manifest.py +0 -0
  230. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_history_schema2.py +0 -0
  231. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_history_window.py +0 -0
  232. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_hostile_prompt.py +0 -0
  233. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_html_executive.py +0 -0
  234. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_html_section_parity_class.py +0 -0
  235. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_identity_docs.py +0 -0
  236. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_identity_resolution.py +0 -0
  237. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_idiom_divergence.py +0 -0
  238. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_installed_wheel_runtime.py +0 -0
  239. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_instruction_targets.py +0 -0
  240. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_java_range_guard.py +0 -0
  241. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_java_ranges.py +0 -0
  242. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_java_scored.py +0 -0
  243. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_java_wiring.py +0 -0
  244. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_js_complexity_operators.py +0 -0
  245. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_js_declarations.py +0 -0
  246. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_language_coverage.py +0 -0
  247. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_mcp_baseline_payload.py +0 -0
  248. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_mcp_history.py +0 -0
  249. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_mcp_server.py +0 -0
  250. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_migration_1_0.py +0 -0
  251. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_near_duplicates.py +0 -0
  252. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_network_disclosure.py +0 -0
  253. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_one_setup_across_surfaces_class.py +0 -0
  254. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_pattern_budget.py +0 -0
  255. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_phase6_claims.py +0 -0
  256. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_pillars_and_practice.py +0 -0
  257. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_platform_claim.py +0 -0
  258. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_pmd_adapter.py +0 -0
  259. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_pmd_audit_closures.py +0 -0
  260. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_pool_runs_by_config.py +0 -0
  261. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_population_floors.py +0 -0
  262. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_practice_nested_gates_class.py +0 -0
  263. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_presentation_refusals.py +0 -0
  264. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_promises.py +0 -0
  265. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_prompt_escalation_once.py +0 -0
  266. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_prompt_honesty.py +0 -0
  267. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_prompt_location_escalation_class.py +0 -0
  268. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_prove_falsifiers.py +0 -0
  269. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_python_declarations.py +0 -0
  270. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_read_boundary.py +0 -0
  271. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_readme_claims.py +0 -0
  272. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_recurrence.py +0 -0
  273. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_release_plan.py +0 -0
  274. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_release_plan_status.py +0 -0
  275. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_report_remedy_copy.py +0 -0
  276. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_roles_recorded.py +0 -0
  277. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_root_grants.py +0 -0
  278. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_rubric_ignores_project_lint_config.py +0 -0
  279. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_runner.py +0 -0
  280. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_sarif.py +0 -0
  281. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_scan_history.py +0 -0
  282. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_scan_scope.py +0 -0
  283. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_scanning.py +0 -0
  284. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_schema_fidelity.py +0 -0
  285. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_scope_conformance.py +0 -0
  286. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_scoring_calibration.py +0 -0
  287. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_semantic_policy.py +0 -0
  288. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_setup_gate_completeness.py +0 -0
  289. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_setup_gate_independent_contract.py +0 -0
  290. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_setup_precondition.py +0 -0
  291. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_skill_install.py +0 -0
  292. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_source_index.py +0 -0
  293. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_spotbugs_adapter.py +0 -0
  294. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_spotbugs_catalog.py +0 -0
  295. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_stage8_contract.py +0 -0
  296. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_tdd_structure.py +0 -0
  297. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_test_execution_class.py +0 -0
  298. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_three_presentations.py +0 -0
  299. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_trends.py +0 -0
  300. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_type_fields_not_functions_class.py +0 -0
  301. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_uat_falsifiers.py +0 -0
  302. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_unread_code.py +0 -0
  303. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_user_config_tier.py +0 -0
  304. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_verification_audit_closures.py +0 -0
  305. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_verified_grade.py +0 -0
  306. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_version_claim.py +0 -0
  307. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_wheel_contents.py +0 -0
  308. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_work_order.py +0 -0
  309. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_work_order_items.py +0 -0
  310. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_work_order_selection.py +0 -0
  311. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_workflow_supply_chain.py +0 -0
  312. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_write_boundary.py +0 -0
  313. {maintainability_agent-2.3.0 → maintainability_agent-2.4.0}/tests/test_write_route_class.py +0 -0
  314. {maintainability_agent-2.3.0 → maintainability_agent-2.4.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.3.0
3
+ Version: 2.4.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -44,10 +44,10 @@ 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.3.0**.
47
+ Version **2.4.0**.
48
48
 
49
- **Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
50
- fixed-form), and the JS/TS family — each by a scanner written for it, and
49
+ **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
50
+ *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
51
51
  measured with that language's own reading of what a branch is.
52
52
  [What that means per language](#language-support).
53
53
 
@@ -252,9 +252,9 @@ SonarQube, Qlty) rather than replacing them — their SARIF folds in via
252
252
  and on an unrecognized language it will quietly under-report rather than fail.**
253
253
  Coverage comes from two layers.
254
254
 
255
- Eight languages are parsed as of **1.6.0**: Python (1.0), Java (1.0), C (1.1),
256
- C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), the JS/TS family,
257
- and HTML. Each has a scanner written for it and a documented list of what it
255
+ Nine languages are parsed as of **2.4.0**: Python (1.0), Java (1.0), C (1.1),
256
+ C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), Swift (2.4), the
257
+ JS/TS family, and HTML. Each has a scanner written for it and a documented list of what it
258
258
  misses — a language is claimed here only when both exist.
259
259
 
260
260
  **Built-in scanner (always on, no dependencies)** — reads function/class
@@ -268,6 +268,7 @@ these:
268
268
  | C (`.c`, `.h`) | dedicated brace-bounded scanner — functions, `struct`/`enum`/`union` | Bounded; prototypes and macros are not declarations |
269
269
  | C++ (`.cpp`, `.hpp`, `.cc`, `.cxx`, `.hh`) | dedicated brace-bounded scanner — functions, class members, namespaces, templates | Bounded; bodyless declarations are not definitions |
270
270
  | C# (`.cs`) | dedicated brace-bounded scanner — methods, constructors, `class`/`interface`/`struct`/`record`/`enum` | Bounded; properties are not declarations |
271
+ | Swift (`.swift`) | dedicated brace-bounded scanner — functions, initialisers, subscripts, `class`/`struct`/`enum`/`protocol`/`actor` | Bounded; extension members carry their type, protocol requirements and computed properties are not declarations |
271
272
  | Fortran, free-form (`.f90`, `.f95`, `.f03`, `.f08`, `.F90`, `.F95`, `.F03`, `.F08`, `.pf`) | dedicated **keyword**-bounded scanner — modules, subroutines, functions, derived types | Bounded by `end`; measured with Fortran's own branch and nesting reading |
272
273
  | Fortran, fixed-form (`.f`, `.for`, `.ftn`, `.F`, `.FOR`, `.FTN`) | the same scanner over card-column source; continuations joined, labelled `DO` loops understood | Bounded by `end` or by the loop's label |
273
274
  | JS / TS / JSX / TSX (`.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`) | brace/paren depth over a masked copy | Bounded by the declaration's own braces |
@@ -5,10 +5,10 @@
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.3.0**.
8
+ Version **2.4.0**.
9
9
 
10
- **Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
11
- fixed-form), and the JS/TS family — each by a scanner written for it, and
10
+ **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
11
+ *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
12
12
  measured with that language's own reading of what a branch is.
13
13
  [What that means per language](#language-support).
14
14
 
@@ -213,9 +213,9 @@ SonarQube, Qlty) rather than replacing them — their SARIF folds in via
213
213
  and on an unrecognized language it will quietly under-report rather than fail.**
214
214
  Coverage comes from two layers.
215
215
 
216
- Eight languages are parsed as of **1.6.0**: Python (1.0), Java (1.0), C (1.1),
217
- C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), the JS/TS family,
218
- and HTML. Each has a scanner written for it and a documented list of what it
216
+ Nine languages are parsed as of **2.4.0**: Python (1.0), Java (1.0), C (1.1),
217
+ C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), Swift (2.4), the
218
+ JS/TS family, and HTML. Each has a scanner written for it and a documented list of what it
219
219
  misses — a language is claimed here only when both exist.
220
220
 
221
221
  **Built-in scanner (always on, no dependencies)** — reads function/class
@@ -229,6 +229,7 @@ these:
229
229
  | C (`.c`, `.h`) | dedicated brace-bounded scanner — functions, `struct`/`enum`/`union` | Bounded; prototypes and macros are not declarations |
230
230
  | C++ (`.cpp`, `.hpp`, `.cc`, `.cxx`, `.hh`) | dedicated brace-bounded scanner — functions, class members, namespaces, templates | Bounded; bodyless declarations are not definitions |
231
231
  | C# (`.cs`) | dedicated brace-bounded scanner — methods, constructors, `class`/`interface`/`struct`/`record`/`enum` | Bounded; properties are not declarations |
232
+ | Swift (`.swift`) | dedicated brace-bounded scanner — functions, initialisers, subscripts, `class`/`struct`/`enum`/`protocol`/`actor` | Bounded; extension members carry their type, protocol requirements and computed properties are not declarations |
232
233
  | Fortran, free-form (`.f90`, `.f95`, `.f03`, `.f08`, `.F90`, `.F95`, `.F03`, `.F08`, `.pf`) | dedicated **keyword**-bounded scanner — modules, subroutines, functions, derived types | Bounded by `end`; measured with Fortran's own branch and nesting reading |
233
234
  | Fortran, fixed-form (`.f`, `.for`, `.ftn`, `.F`, `.FOR`, `.FTN`) | the same scanner over card-column source; continuations joined, labelled `DO` loops understood | Bounded by `end` or by the loop's label |
234
235
  | JS / TS / JSX / TSX (`.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`) | brace/paren depth over a masked copy | Bounded by the declaration's own braces |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maintainability-agent"
7
- version = "2.3.0"
7
+ version = "2.4.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.3.0
3
+ Version: 2.4.0
4
4
  Summary: Maintainability gate and AI remediation prompt generator for CI.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -44,10 +44,10 @@ 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.3.0**.
47
+ Version **2.4.0**.
48
48
 
49
- **Languages parsed:** Python, Java, C, C++, C#, Fortran (free-form *and*
50
- fixed-form), and the JS/TS family — each by a scanner written for it, and
49
+ **Languages parsed:** Python, Java, C, C++, C#, Swift, Fortran (free-form
50
+ *and* fixed-form), and the JS/TS family — each by a scanner written for it, and
51
51
  measured with that language's own reading of what a branch is.
52
52
  [What that means per language](#language-support).
53
53
 
@@ -252,9 +252,9 @@ SonarQube, Qlty) rather than replacing them — their SARIF folds in via
252
252
  and on an unrecognized language it will quietly under-report rather than fail.**
253
253
  Coverage comes from two layers.
254
254
 
255
- Eight languages are parsed as of **1.6.0**: Python (1.0), Java (1.0), C (1.1),
256
- C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), the JS/TS family,
257
- and HTML. Each has a scanner written for it and a documented list of what it
255
+ Nine languages are parsed as of **2.4.0**: Python (1.0), Java (1.0), C (1.1),
256
+ C++ (1.2), C# (1.3), Fortran (free-form 1.4, fixed-form 1.6), Swift (2.4), the
257
+ JS/TS family, and HTML. Each has a scanner written for it and a documented list of what it
258
258
  misses — a language is claimed here only when both exist.
259
259
 
260
260
  **Built-in scanner (always on, no dependencies)** — reads function/class
@@ -268,6 +268,7 @@ these:
268
268
  | C (`.c`, `.h`) | dedicated brace-bounded scanner — functions, `struct`/`enum`/`union` | Bounded; prototypes and macros are not declarations |
269
269
  | C++ (`.cpp`, `.hpp`, `.cc`, `.cxx`, `.hh`) | dedicated brace-bounded scanner — functions, class members, namespaces, templates | Bounded; bodyless declarations are not definitions |
270
270
  | C# (`.cs`) | dedicated brace-bounded scanner — methods, constructors, `class`/`interface`/`struct`/`record`/`enum` | Bounded; properties are not declarations |
271
+ | Swift (`.swift`) | dedicated brace-bounded scanner — functions, initialisers, subscripts, `class`/`struct`/`enum`/`protocol`/`actor` | Bounded; extension members carry their type, protocol requirements and computed properties are not declarations |
271
272
  | Fortran, free-form (`.f90`, `.f95`, `.f03`, `.f08`, `.F90`, `.F95`, `.F03`, `.F08`, `.pf`) | dedicated **keyword**-bounded scanner — modules, subroutines, functions, derived types | Bounded by `end`; measured with Fortran's own branch and nesting reading |
272
273
  | Fortran, fixed-form (`.f`, `.for`, `.ftn`, `.F`, `.FOR`, `.FTN`) | the same scanner over card-column source; continuations joined, labelled `DO` loops understood | Bounded by `end` or by the loop's label |
273
274
  | JS / TS / JSX / TSX (`.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`) | brace/paren depth over a masked copy | Bounded by the declaration's own braces |
@@ -64,6 +64,7 @@ src/maintainability_audit/_ranges_csharp.py
64
64
  src/maintainability_audit/_ranges_fortran.py
65
65
  src/maintainability_audit/_ranges_java.py
66
66
  src/maintainability_audit/_ranges_js.py
67
+ src/maintainability_audit/_ranges_swift.py
67
68
  src/maintainability_audit/_ratchet.py
68
69
  src/maintainability_audit/_recurrence.py
69
70
  src/maintainability_audit/_runner.py
@@ -289,6 +290,7 @@ tests/test_source_index.py
289
290
  tests/test_spotbugs_adapter.py
290
291
  tests/test_spotbugs_catalog.py
291
292
  tests/test_stage8_contract.py
293
+ tests/test_swift_declarations.py
292
294
  tests/test_tdd_structure.py
293
295
  tests/test_test_execution_class.py
294
296
  tests/test_three_presentations.py
@@ -1,3 +1,3 @@
1
1
  """Maintainability Audit CI."""
2
2
 
3
- __version__ = "2.3.0"
3
+ __version__ = "2.4.0"
@@ -45,6 +45,14 @@ _NESTING_NODES = (ast.If, ast.For, ast.AsyncFor, ast.While, ast.ExceptHandler, a
45
45
  _NESTING_ONLY = (ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda)
46
46
 
47
47
  _CONTROL_RE = re.compile(r"\b(if|for|while|catch|switch|case|elif|except)\b")
48
+ #: Swift adds `guard` — an early exit that is its primary branching idiom —
49
+ #: and `repeat`, its do-while. Without them a function built from guards
50
+ #: reads as having no branches at all, which is the Fortran `do` defect in
51
+ #: another language: six nested loops once scored complexity 1 because the
52
+ #: pattern did not know the keyword.
53
+ _SWIFT_CONTROL_RE = re.compile(
54
+ r"\b(if|for|while|catch|switch|case|guard|repeat)\b"
55
+ )
48
56
  _ELSE_RE = re.compile(r"\belse\b")
49
57
  _BOOLEAN_RE = re.compile(r"&&|\|\|")
50
58
 
@@ -167,7 +175,7 @@ def fortran_cognitive(lines: list[str]) -> int:
167
175
  return score
168
176
 
169
177
 
170
- def brace_cognitive(lines: list[str]) -> int:
178
+ def brace_cognitive(lines: list[str], control: re.Pattern[str] | None = None) -> int:
171
179
  """Approximate cognitive complexity for a C-family declaration body.
172
180
 
173
181
  Nesting is read from brace depth relative to the declaration's own
@@ -191,16 +199,25 @@ def brace_cognitive(lines: list[str]) -> int:
191
199
  if base is None and opens:
192
200
  base = depth
193
201
  nesting = max(0, depth - (base if base is not None else 0))
194
- score += _score_brace_line(line, nesting)
202
+ score += _score_brace_line(line, nesting, control or _CONTROL_RE)
195
203
  depth = max(0, depth + opens - closes)
196
204
  return score
197
205
 
198
206
 
199
- def _score_brace_line(line: str, nesting: int) -> int:
207
+ def _score_brace_line(line: str, nesting: int, control: re.Pattern[str]) -> int:
200
208
  score = 0
201
- for _ in _CONTROL_RE.finditer(line):
209
+ for _ in control.finditer(line):
202
210
  score += 1 + nesting
203
211
  if _ELSE_RE.search(line):
204
212
  score += 1
205
213
  score += len(_BOOLEAN_RE.findall(line))
206
214
  return score
215
+
216
+
217
+ def swift_cognitive(lines: list[str]) -> int:
218
+ """`brace_cognitive` reading Swift's control keywords.
219
+
220
+ Swift is braced, so nesting is read the same way; only the vocabulary
221
+ differs, and `guard` is the difference that matters.
222
+ """
223
+ return brace_cognitive(lines, _SWIFT_CONTROL_RE)
@@ -53,6 +53,20 @@ COMPLEXITY_RE = re.compile(
53
53
  )
54
54
 
55
55
 
56
+ #: Swift's `guard` is an early exit and its primary branching idiom, and
57
+ #: `repeat` is its do-while. Neither is in the C-family pattern, so a
58
+ #: guard-heavy function would read as branchless — the same defect Fortran
59
+ #: had with `do`.
60
+ SWIFT_COMPLEXITY_RE = re.compile(
61
+ r"\b(if|for|while|case|catch|guard|repeat)\b|&&|\|\||\?\?|\?(?![.?])"
62
+ )
63
+
64
+
65
+ def swift_branch_points(line: str) -> int:
66
+ """Decision points on one line of Swift."""
67
+ return len(SWIFT_COMPLEXITY_RE.findall(line))
68
+
69
+
56
70
  def branch_points(line: str) -> int:
57
71
  """Decision points on one line, for the C family and Python."""
58
72
  return len(COMPLEXITY_RE.findall(line))
@@ -0,0 +1,215 @@
1
+ """Declaration ranges for Swift.
2
+
3
+ Braced, so it reuses `scan_bounded` with C, C++, C# and Java. What is
4
+ different is worth stating, because two of the differences are the whole
5
+ job and one of them is a trap this project has already fallen into once.
6
+
7
+ **Every declaration is keyword-led.** `func`, `init`, `subscript`, `class`,
8
+ `struct`, `enum`, `protocol`, `actor`, `extension`. That makes recognition
9
+ *easier* than C++, where a bare `name(` is equally a call, a macro and a
10
+ constructor, and where a wrong guess let a macro swallow the next
11
+ declaration's braces. Nothing here has to guess.
12
+
13
+ **An `extension` adds members to a type declared elsewhere**, often in
14
+ another file. `extension Widget { func draw() }` must report `Widget.draw`
15
+ rather than a second bare `draw` indistinguishable from every other type's,
16
+ which is the same rule C++ applies to an out-of-line `void geo::Widget::draw()`.
17
+ The extension itself is walked into and not graded: it is a container, and
18
+ grading it would count its members twice.
19
+
20
+ **Computed properties are not declarations**, and this is the C# properties
21
+ problem in Swift spelling. `var area: Double { w * h }` has braces and would
22
+ bound perfectly cleanly; an ordinary Swift type has many, each a line or
23
+ two, none anybody's maintenance burden. Counting them would dilute the
24
+ population every declaration rate divides by. They are excluded by
25
+ construction rather than by a rule: every pattern here requires either a
26
+ parameter list or a type keyword, and a property has neither.
27
+
28
+ **A protocol requirement has no body** — `func draw()` with nothing after
29
+ it — so it mints nothing, exactly as a C prototype and a pure virtual do.
30
+ A protocol of forty requirements is not forty declarations.
31
+
32
+ One claim was corrected while writing this. The roadmap said Swift's string
33
+ interpolation "puts braces inside literals, so masking has to run before
34
+ depth counting". It does not: Swift interpolates with `\\(expr)` —
35
+ parentheses, not braces — and string contents are masked before any
36
+ counting regardless. The real reason masking matters here is the ordinary
37
+ one every language shares: a brace inside a string literal, `"{}"`, would
38
+ desync depth.
39
+ """
40
+ from __future__ import annotations
41
+
42
+ import re
43
+
44
+ from ._metrics_types import DeclRange
45
+ from ._ranges_core import _mask_generics, scan_bounded
46
+
47
+ # Stripped once per line so the patterns stay small: these lead a
48
+ # declaration and say nothing about what it is.
49
+ _SW_MODIFIER_RE = re.compile(
50
+ r"^\s*(?:(?:public|private|internal|fileprivate|open|static|final"
51
+ r"|override|mutating|nonmutating|convenience|required|lazy|weak|unowned"
52
+ r"|indirect|dynamic|optional|async|throws|rethrows|infix|prefix|postfix"
53
+ r"|package)\s+)*"
54
+ )
55
+ # `class` is both a declaration keyword and a modifier: `class Widget` is a
56
+ # type, `class func make()` is a type-level method. Stripping it with the
57
+ # other modifiers cost every `final class Store` its keyword — the type
58
+ # vanished and only its members were reported. So it is removed only where
59
+ # a declaration keyword follows it, and left alone otherwise.
60
+ _SW_CLASS_MODIFIER_RE = re.compile(r"^class\s+(?=(?:func|var|let|subscript)\b)")
61
+ # `@objc`, `@available(iOS 13, *)`, `@MainActor` — an attribute leads a
62
+ # declaration and is not one. Stripped, so what follows is still read.
63
+ _SW_ATTRIBUTE_RE = re.compile(r"^\s*(?:@[A-Za-z_]\w*(?:\([^)]*\))?\s*)+")
64
+ # `extension Widget`, `extension Widget: Drawable`, `extension Array where …`
65
+ _SW_EXTENSION_RE = re.compile(r"^extension\s+([A-Za-z_][\w.]*)")
66
+ # The container keywords. `protocol` is here so its body is walked into —
67
+ # its requirements are then skipped for having no body, which is what makes
68
+ # a forty-requirement protocol mint nothing.
69
+ _SW_TYPE_RE = re.compile(
70
+ r"^(?:class|struct|enum|protocol|actor)\s+([A-Za-z_]\w*)"
71
+ )
72
+ # `func name(`, and the three declarations that carry no `func` keyword.
73
+ _SW_FUNC_RE = re.compile(r"^func\s+([A-Za-z_]\w*|[^\s(]+)\s*(?:<[^>]*>)?\s*\(")
74
+ _SW_INIT_RE = re.compile(r"^(init\??|deinit|subscript)\b")
75
+
76
+
77
+ def _swift_declaration(text: str) -> tuple[str, str | None] | None:
78
+ """``(name, kind)`` for a Swift declaration on one masked line.
79
+
80
+ ``kind`` is ``None`` for an `extension`: walk in, grade nothing.
81
+ """
82
+ line = _SW_ATTRIBUTE_RE.sub("", _mask_generics(text), count=1)
83
+ body = line[_SW_MODIFIER_RE.match(line).end():]
84
+ body = _SW_CLASS_MODIFIER_RE.sub("", body, count=1)
85
+ body = body[_SW_MODIFIER_RE.match(body).end():]
86
+
87
+ extension = _SW_EXTENSION_RE.match(body)
88
+ if extension is not None:
89
+ # The extended type's name, carried so its members can be reported
90
+ # as `Widget.draw` rather than as a second bare `draw`.
91
+ return extension.group(1), None
92
+
93
+ type_match = _SW_TYPE_RE.match(body)
94
+ if type_match is not None:
95
+ return type_match.group(1), "class"
96
+
97
+ func = _SW_FUNC_RE.match(body)
98
+ if func is not None:
99
+ return (func.group(1), "function") if _opens_a_body(body) else None
100
+
101
+ special = _SW_INIT_RE.match(body)
102
+ if special is not None:
103
+ return (special.group(1).rstrip("?"), "function") if _opens_a_body(body) else None
104
+
105
+ # Anything else — `var`, `let`, a computed property, a `case` — is not
106
+ # a declaration this tool measures. Falling through rather than listing
107
+ # exclusions keeps the rule "a declaration is keyword-led and named".
108
+ return None
109
+
110
+
111
+ def _opens_a_body(body: str) -> bool:
112
+ """Whether this line starts a body, or is a requirement with none.
113
+
114
+ Swift has no statement terminator, so the shared `skip_bare` check
115
+ cannot work here: it looks for a signature that closes without opening
116
+ a brace, and in C or C# that is a `;`. A Swift protocol requirement
117
+ simply ends at the newline, so the end-finder walks on and adopts the
118
+ *next* declaration's brace — which is how `func describe() -> String`
119
+ inside a protocol came back measured as two lines of body.
120
+
121
+ The rule that replaces it: a signature whose parentheses balance on
122
+ this line and which then shows no `{` has no body. A wrapped signature
123
+ leaves its parentheses unbalanced, so it is still read as a
124
+ declaration and its body is found normally:
125
+
126
+ func draw( <- unbalanced here, kept
127
+ into: Canvas
128
+ ) throws {
129
+
130
+ A body written Allman — `func f()` with `{` alone on the next line —
131
+ is missed and mints nothing. That is legal Swift and vanishingly rare
132
+ in it, and missing one declaration is the cheaper error than counting
133
+ every protocol requirement in the tree.
134
+ """
135
+ if "{" in body:
136
+ return True
137
+ return body.count("(") != body.count(")")
138
+
139
+
140
+ def swift_declaration_ranges(lines: list[str]) -> tuple[list[DeclRange], list[str]]:
141
+ """Functions, initialisers and types, each bounded by its own body.
142
+
143
+ Types and extensions are descended into, because that is where members
144
+ live; a function body is stepped over, so nothing inside one is read as
145
+ a declaration.
146
+
147
+ Bodyless declarations mint nothing, as in C, C++ and C#: a protocol
148
+ requirement is a signature with nothing to measure, and grading it
149
+ would put one-line members into the population every rate divides by.
150
+
151
+ Everything it misses, it misses in the safe direction:
152
+
153
+ - **Computed properties** (`var area: Double { w * h }`) are not
154
+ declarations, the same call C# makes for the same reason.
155
+ - **A closure assigned to a property** is a body without a declaration
156
+ keyword and is not counted.
157
+ - **Declarations produced by a macro** (`@freestanding`, `#`-macros)
158
+ are not in the source and are not seen, as in C and C++.
159
+ - **Conditional compilation is not evaluated**, so a declaration in a
160
+ disabled `#if` arm still counts.
161
+ """
162
+ ranges, masked = scan_bounded(
163
+ lines, _swift_declaration, descend=("class",), skip_preprocessor=True
164
+ )
165
+ return _qualify_extension_members(ranges, masked), masked
166
+
167
+
168
+ def _extension_spans(masked: list[str]) -> list[tuple[int, int, str]]:
169
+ """Every `extension X { … }` as (start, end, extended type)."""
170
+ def only_extensions(text: str) -> tuple[str, str | None] | None:
171
+ found = _swift_declaration(text)
172
+ if found is None:
173
+ return None
174
+ name, kind = found
175
+ return (name, "class") if kind is None else None
176
+
177
+ spans, _ = scan_bounded(
178
+ masked, only_extensions, descend=(), skip_preprocessor=True
179
+ )
180
+ return [(item.start, item.end, item.name) for item in spans]
181
+
182
+
183
+ def _qualify_extension_members(
184
+ ranges: list[DeclRange], masked: list[str]
185
+ ) -> list[DeclRange]:
186
+ """Report an extension's members under the type they extend.
187
+
188
+ `extension Widget { func draw() }` becomes `Widget.draw`. Without it
189
+ the report carries a bare `draw` indistinguishable from every other
190
+ type's `draw`, and a reader given "shorten `draw`" cannot find which
191
+ one — the same reason C++ keeps the qualification on an out-of-line
192
+ `void geo::Widget::draw()`, except that in Swift the source does not
193
+ write it and the scanner has to carry it.
194
+
195
+ A member already qualified is left alone, and a nested type inside an
196
+ extension keeps its own name: the prefix answers "which type does this
197
+ belong to", which a named type already answers for itself.
198
+ """
199
+ spans = _extension_spans(masked)
200
+ if not spans:
201
+ return ranges
202
+ qualified = []
203
+ for item in ranges:
204
+ owner = next(
205
+ (name for start, end, name in spans
206
+ if start < item.start <= end and item.kind == "function"),
207
+ None,
208
+ )
209
+ if owner is None or "." in item.name:
210
+ qualified.append(item)
211
+ continue
212
+ qualified.append(
213
+ DeclRange(item.start, item.end, f"{owner}.{item.name}", item.kind)
214
+ )
215
+ return qualified
@@ -11,7 +11,7 @@ from ._config_defaults import DEFAULT_CONFIG, DEFAULT_IDIOM_GROUPS
11
11
  # still the door every caller comes through.
12
12
  __all__ = ["DEFAULT_CONFIG", "DEFAULT_IDIOM_GROUPS", "PROJECT_URL", "VERSION"]
13
13
 
14
- VERSION = "2.3.0"
14
+ VERSION = "2.4.0"
15
15
 
16
16
  PROJECT_URL = "https://github.com/marshallguillory86/maintainability-agent"
17
17
 
@@ -14,7 +14,12 @@ import ast
14
14
  import os
15
15
  from pathlib import Path
16
16
 
17
- from ._cognitive import brace_cognitive, fortran_cognitive, python_cognitive
17
+ from ._cognitive import (
18
+ brace_cognitive,
19
+ fortran_cognitive,
20
+ python_cognitive,
21
+ swift_cognitive,
22
+ )
18
23
  from ._finding_match import normalized_body_digest
19
24
  from ._metrics_types import (
20
25
  FUNC_PATTERNS,
@@ -22,6 +27,7 @@ from ._metrics_types import (
22
27
  FunctionMetric,
23
28
  branch_points,
24
29
  fortran_branch_points,
30
+ swift_branch_points,
25
31
  )
26
32
  from ._ranges_c import c_declaration_ranges
27
33
  from ._ranges_core import indent_bounded_end
@@ -33,6 +39,7 @@ from ._ranges_fortran import (
33
39
  )
34
40
  from ._ranges_java import java_declaration_ranges
35
41
  from ._ranges_js import js_declaration_ranges
42
+ from ._ranges_swift import swift_declaration_ranges
36
43
 
37
44
  # One set per language, then one table binding each to its scanner.
38
45
  #
@@ -60,6 +67,7 @@ CPP_SUFFIXES = {".cpp", ".hpp", ".cc", ".cxx", ".hh"}
60
67
  # generics — and still its own module: namespaces in two forms,
61
68
  # `record`, and properties, which are deliberately not declarations.
62
69
  CSHARP_SUFFIXES = {".cs"}
70
+ SWIFT_SUFFIXES = {".swift"}
63
71
  # Fortran (1.4.0), free-form only. `.F90` is the same language with the
64
72
  # C preprocessor run over it, and `.pf` is pFUnit test source — both are
65
73
  # free-form and both are read. Fixed-form (`.f`, `.for`, `.ftn`) is
@@ -97,6 +105,7 @@ SCANNERS: tuple[tuple[set[str], object], ...] = (
97
105
  (C_SUFFIXES, c_declaration_ranges),
98
106
  (CPP_SUFFIXES, cpp_declaration_ranges),
99
107
  (CSHARP_SUFFIXES, csharp_declaration_ranges),
108
+ (SWIFT_SUFFIXES, swift_declaration_ranges),
100
109
  (FORTRAN_SUFFIXES, fortran_declaration_ranges),
101
110
  (FIXED_FORM_SUFFIXES, fixed_form_declaration_ranges),
102
111
  (BRACE_SUFFIXES, js_declaration_ranges),
@@ -115,6 +124,10 @@ SCANNERS: tuple[tuple[set[str], object], ...] = (
115
124
  # was read from braces, which Fortran does not have, so four flat
116
125
  # `if`s and four deeply nested ones both scored 8.
117
126
  METRICS: tuple[tuple[set[str], object, object], ...] = (
127
+ # Swift is braced and reads its nesting the C-family way; only the
128
+ # keyword vocabulary differs, and `guard` is the difference that
129
+ # matters — without it a guard-heavy function reads as branchless.
130
+ (SWIFT_SUFFIXES, swift_branch_points, swift_cognitive),
118
131
  (FORTRAN_SUFFIXES, fortran_branch_points, fortran_cognitive),
119
132
  (FIXED_FORM_SUFFIXES, fortran_branch_points, fortran_cognitive),
120
133
  )
@@ -131,7 +144,7 @@ def metrics_for(suffix: str) -> tuple[object, object]:
131
144
  # Every extension we attempt declaration detection on at all.
132
145
  DECLARATION_SUFFIXES = (
133
146
  PYTHON_SUFFIXES | JAVA_SUFFIXES | C_SUFFIXES | CPP_SUFFIXES
134
- | CSHARP_SUFFIXES | FORTRAN_SUFFIXES | FIXED_FORM_SUFFIXES
147
+ | CSHARP_SUFFIXES | SWIFT_SUFFIXES | FORTRAN_SUFFIXES | FIXED_FORM_SUFFIXES
135
148
  | BRACE_SUFFIXES
136
149
  )
137
150