agentlint 2.5.2__tar.gz → 2.5.4__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 (281) hide show
  1. agentlint-2.5.4/.github/CODEOWNERS +7 -0
  2. agentlint-2.5.4/.github/dependabot.yml +16 -0
  3. agentlint-2.5.4/.github/workflows/ci.yml +78 -0
  4. agentlint-2.5.4/.github/workflows/publish.yml +76 -0
  5. agentlint-2.5.4/.github/workflows/test-publish.yml +55 -0
  6. {agentlint-2.5.2 → agentlint-2.5.4}/CHANGELOG.md +49 -0
  7. {agentlint-2.5.2 → agentlint-2.5.4}/PKG-INFO +12 -8
  8. {agentlint-2.5.2 → agentlint-2.5.4}/README.md +10 -7
  9. agentlint-2.5.4/RELEASE.md +83 -0
  10. {agentlint-2.5.2 → agentlint-2.5.4}/docs/adapters.md +3 -0
  11. {agentlint-2.5.2 → agentlint-2.5.4}/docs/custom-rules.md +9 -7
  12. {agentlint-2.5.2 → agentlint-2.5.4}/pyproject.toml +15 -1
  13. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/__init__.py +1 -1
  14. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/__main__.py +1 -0
  15. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/__init__.py +1 -0
  16. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/_utils.py +1 -0
  17. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/base.py +1 -1
  18. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/claude.py +6 -4
  19. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/codex.py +7 -5
  20. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/continue_dev.py +7 -5
  21. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/cursor.py +7 -5
  22. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/gemini.py +7 -5
  23. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/generic.py +8 -11
  24. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/grok.py +7 -5
  25. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/kimi.py +54 -17
  26. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/mcp.py +34 -14
  27. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/adapters/openai_agents.py +13 -4
  28. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/__init__.py +6 -1
  29. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/client.py +8 -17
  30. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/feeds.py +14 -16
  31. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/policy.py +12 -8
  32. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/queue.py +26 -8
  33. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/settings.py +4 -6
  34. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agentchute/sync.py +5 -12
  35. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/agents_md.py +39 -7
  36. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/circuit_breaker.py +56 -53
  37. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/cli.py +314 -163
  38. agentlint-2.5.4/src/agentlint/cli_queue.py +101 -0
  39. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/config.py +7 -4
  40. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/core/__init__.py +1 -0
  41. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/core/models.py +20 -12
  42. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/detector.py +9 -2
  43. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/engine.py +25 -8
  44. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/filters.py +8 -5
  45. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/__init__.py +1 -0
  46. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/base.py +3 -1
  47. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/claude_hooks.py +29 -17
  48. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/cursor_hooks.py +23 -14
  49. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/gemini_hooks.py +28 -19
  50. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/formats/plain_json.py +7 -4
  51. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/mcp_server.py +4 -4
  52. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/models.py +1 -0
  53. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/__init__.py +10 -2
  54. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/__init__.py +1 -0
  55. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/_dangerous_patterns.py +5 -1
  56. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/bash_rate_limiter.py +8 -4
  57. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/cloud_infra_mutation.py +51 -12
  58. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/cloud_paid_resource_creation.py +46 -9
  59. agentlint-2.5.4/src/agentlint/packs/autopilot/cloud_resource_deletion.py +142 -0
  60. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/cross_account_guard.py +12 -6
  61. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/destructive_confirmation_gate.py +24 -5
  62. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/docker_volume_guard.py +41 -8
  63. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/dry_run_required.py +3 -2
  64. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/network_firewall_guard.py +16 -4
  65. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/operation_journal.py +1 -0
  66. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/package_manager_in_chroot.py +16 -3
  67. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/production_guard.py +57 -33
  68. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/remote_boot_partition_guard.py +20 -5
  69. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/remote_chroot_guard.py +4 -1
  70. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/ssh_destructive_command_guard.py +11 -2
  71. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/subagent_safety_briefing.py +1 -0
  72. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/subagent_transcript_audit.py +12 -7
  73. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/autopilot/system_scheduler_guard.py +10 -5
  74. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/__init__.py +5 -4
  75. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/_helpers.py +2 -4
  76. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/a11y_form_labels.py +2 -1
  77. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/a11y_heading_hierarchy.py +1 -0
  78. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/a11y_image_alt.py +3 -1
  79. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/a11y_interactive_elements.py +1 -0
  80. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/mobile_responsive_patterns.py +1 -0
  81. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/mobile_touch_targets.py +1 -0
  82. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/style_focus_visible.py +1 -0
  83. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/frontend/style_no_arbitrary_values.py +7 -2
  84. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/__init__.py +4 -3
  85. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_bare_except.py +1 -0
  86. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_dangerous_migration.py +5 -4
  87. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_sql_injection.py +7 -4
  88. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_unnecessary_async.py +18 -3
  89. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_unsafe_shell.py +2 -1
  90. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/python/no_wildcard_import.py +1 -0
  91. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/__init__.py +1 -0
  92. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/commit_message_format.py +1 -0
  93. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/naming_conventions.py +21 -9
  94. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/no_dead_imports.py +2 -0
  95. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/no_error_handling_removal.py +2 -4
  96. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/no_file_creation_sprawl.py +11 -11
  97. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/no_large_diff.py +45 -19
  98. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/quality/self_review_prompt.py +1 -0
  99. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/react/__init__.py +2 -1
  100. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/react/react_empty_state.py +2 -1
  101. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/react/react_lazy_loading.py +11 -4
  102. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/react/react_query_loading_state.py +3 -2
  103. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/__init__.py +5 -4
  104. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/env_credential_reference.py +21 -11
  105. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_bash_file_write.py +8 -11
  106. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_blocked_domain_fetch.py +1 -3
  107. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_compromised_action.py +4 -15
  108. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_leaked_secret_pattern.py +2 -9
  109. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_malicious_url_fetch.py +2 -7
  110. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/security/no_network_exfil.py +46 -28
  111. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/__init__.py +2 -1
  112. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/_helpers.py +1 -0
  113. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/seo_open_graph.py +1 -2
  114. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/seo_page_metadata.py +9 -4
  115. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/seo_semantic_html.py +1 -0
  116. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/seo/seo_structured_data.py +4 -1
  117. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/__init__.py +10 -9
  118. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/cicd_pipeline_guard.py +1 -0
  119. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/cli_integration.py +31 -17
  120. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/dependency_hygiene.py +9 -2
  121. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/drift_detector.py +19 -3
  122. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/file_scope.py +16 -13
  123. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/git_checkpoint.py +2 -1
  124. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/max_file_size.py +4 -1
  125. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_debug_artifacts.py +2 -3
  126. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_destructive_commands.py +6 -1
  127. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_env_commit.py +2 -3
  128. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_force_push.py +1 -0
  129. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_nvd_critical_cve_install.py +15 -8
  130. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_push_to_main.py +1 -0
  131. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_secrets.py +14 -6
  132. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_skip_hooks.py +1 -0
  133. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_test_weakening.py +4 -1
  134. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_todo_left.py +1 -0
  135. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_vulnerable_import.py +72 -19
  136. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_vulnerable_version_install.py +25 -18
  137. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/package_publish_guard.py +9 -2
  138. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/test_with_changes.py +1 -0
  139. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/token_budget.py +1 -0
  140. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/token_burn_against_team_budget.py +5 -11
  141. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/recorder.py +16 -7
  142. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/reporter.py +47 -24
  143. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/session.py +3 -3
  144. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/setup.py +25 -1
  145. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/template.py +1 -0
  146. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/utils/bash.py +22 -10
  147. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/utils/git.py +2 -3
  148. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/utils/paths.py +1 -0
  149. agentlint-2.5.4/tests/conftest.py +27 -0
  150. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/security/test_no_blocked_domain_fetch.py +4 -10
  151. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/security/test_no_compromised_action.py +53 -56
  152. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/security/test_no_leaked_secret_pattern.py +44 -37
  153. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/security/test_no_malicious_url_fetch.py +18 -31
  154. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_autopilot_integration.py +1 -0
  155. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_autopilot_pack_loads.py +1 -0
  156. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_autopilot_post.py +1 -0
  157. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_autopilot_pre.py +15 -3
  158. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_cicd_pipeline_guard.py +1 -0
  159. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_cloud_infra_mutation.py +34 -11
  160. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_cloud_paid_resource_creation.py +8 -2
  161. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_cloud_resource_deletion.py +8 -2
  162. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_docker_volume_guard.py +7 -2
  163. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_edge_cases.py +2 -1
  164. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_env_credential_reference.py +11 -8
  165. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_frontend.py +350 -200
  166. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_git_checkpoint.py +5 -2
  167. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_network_firewall_guard.py +7 -2
  168. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_no_compromised_dependency.py +2 -6
  169. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_no_nvd_critical_cve_install.py +27 -18
  170. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_no_vulnerable_import.py +44 -36
  171. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_no_vulnerable_version_install.py +50 -54
  172. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_package_manager_in_chroot.py +10 -3
  173. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_package_publish_guard.py +1 -0
  174. agentlint-2.5.4/tests/packs/test_python_post.py +164 -0
  175. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_python_pre.py +423 -252
  176. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_quality_post.py +4 -2
  177. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_quality_pre.py +15 -2
  178. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_quality_stop.py +1 -0
  179. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_react.py +138 -78
  180. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_remote_boot_partition_guard.py +1 -0
  181. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_remote_chroot_guard.py +4 -1
  182. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_security_pre.py +107 -54
  183. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_seo.py +175 -97
  184. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_ssh_destructive_command_guard.py +1 -0
  185. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_subagent_safety_briefing.py +1 -0
  186. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_subagent_transcript_audit.py +151 -65
  187. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_system_scheduler_guard.py +1 -0
  188. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_token_budget.py +57 -43
  189. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_token_burn_against_team_budget.py +2 -2
  190. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_universal_post.py +21 -16
  191. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_universal_pre.py +453 -260
  192. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/test_universal_stop.py +4 -1
  193. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_adapter_utils.py +47 -8
  194. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_agentchute_client.py +14 -10
  195. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_agentchute_feeds.py +11 -30
  196. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_agentchute_policy_queue_sync.py +73 -15
  197. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_agents_md.py +2 -4
  198. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_bash_utils.py +5 -2
  199. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_ci.py +35 -9
  200. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_circuit_breaker.py +193 -159
  201. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_cli.py +804 -387
  202. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_cli_integration.py +378 -141
  203. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_codex_adapter.py +17 -5
  204. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_config.py +9 -4
  205. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_continue_adapter.py +27 -7
  206. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_cursor_adapter.py +45 -26
  207. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_custom_rules.py +1 -0
  208. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_detector.py +1 -0
  209. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_engine.py +149 -74
  210. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_file_scope.py +1 -1
  211. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_filters.py +4 -1
  212. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_gemini_adapter.py +48 -17
  213. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_generic_adapter.py +3 -0
  214. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_git.py +19 -6
  215. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_git_utils_checkpoint.py +18 -8
  216. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_grok_adapter.py +21 -6
  217. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_integration.py +18 -5
  218. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_kimi_adapter.py +61 -29
  219. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_main_module.py +1 -0
  220. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_mcp_adapter.py +14 -2
  221. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_mcp_server.py +52 -7
  222. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_models.py +29 -14
  223. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_openai_adapter.py +11 -0
  224. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_packs_loader.py +6 -2
  225. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_paths_utils.py +2 -3
  226. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_quality_new_rules.py +27 -13
  227. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_recorder.py +61 -32
  228. agentlint-2.5.4/tests/test_release_metadata.py +47 -0
  229. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_reporter.py +52 -39
  230. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_rule_inventory.py +1 -0
  231. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_session.py +2 -1
  232. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_setup.py +69 -22
  233. {agentlint-2.5.2 → agentlint-2.5.4}/tests/test_template.py +1 -0
  234. {agentlint-2.5.2 → agentlint-2.5.4}/uv.lock +28 -1
  235. agentlint-2.5.2/.github/workflows/ci.yml +0 -41
  236. agentlint-2.5.2/.github/workflows/publish.yml +0 -42
  237. agentlint-2.5.2/src/agentlint/packs/autopilot/cloud_resource_deletion.py +0 -77
  238. agentlint-2.5.2/tests/conftest.py +0 -12
  239. agentlint-2.5.2/tests/packs/test_python_post.py +0 -126
  240. {agentlint-2.5.2 → agentlint-2.5.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  241. {agentlint-2.5.2 → agentlint-2.5.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  242. {agentlint-2.5.2 → agentlint-2.5.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  243. {agentlint-2.5.2 → agentlint-2.5.4}/.gitignore +0 -0
  244. {agentlint-2.5.2 → agentlint-2.5.4}/.python-version +0 -0
  245. {agentlint-2.5.2 → agentlint-2.5.4}/CODE_OF_CONDUCT.md +0 -0
  246. {agentlint-2.5.2 → agentlint-2.5.4}/CONTRIBUTING.md +0 -0
  247. {agentlint-2.5.2 → agentlint-2.5.4}/LICENSE +0 -0
  248. {agentlint-2.5.2 → agentlint-2.5.4}/SECURITY.md +0 -0
  249. {agentlint-2.5.2 → agentlint-2.5.4}/agentlint.yml +0 -0
  250. {agentlint-2.5.2 → agentlint-2.5.4}/agentlint.yml.example +0 -0
  251. {agentlint-2.5.2 → agentlint-2.5.4}/codecov.yml +0 -0
  252. {agentlint-2.5.2 → agentlint-2.5.4}/docs/README.md +0 -0
  253. {agentlint-2.5.2 → agentlint-2.5.4}/docs/architecture.md +0 -0
  254. {agentlint-2.5.2 → agentlint-2.5.4}/docs/configuration.md +0 -0
  255. {agentlint-2.5.2 → agentlint-2.5.4}/docs/mcp.md +0 -0
  256. {agentlint-2.5.2 → agentlint-2.5.4}/docs/migration-v2.md +0 -0
  257. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-claude.md +0 -0
  258. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-codex.md +0 -0
  259. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-continue.md +0 -0
  260. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-cursor.md +0 -0
  261. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-gemini.md +0 -0
  262. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-generic.md +0 -0
  263. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-grok.md +0 -0
  264. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-kimi.md +0 -0
  265. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-mcp.md +0 -0
  266. {agentlint-2.5.2 → agentlint-2.5.4}/docs/setup-openai.md +0 -0
  267. {agentlint-2.5.2 → agentlint-2.5.4}/docs/subagent-safety.md +0 -0
  268. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/.claude-plugin/plugin.json +0 -0
  269. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/agents/doctor.md +0 -0
  270. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/agents/fix.md +0 -0
  271. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/agents/security-audit.md +0 -0
  272. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/bin/resolve-and-run.sh +0 -0
  273. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/commands/lint-config.md +0 -0
  274. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/commands/lint-status.md +0 -0
  275. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/hooks/hooks.json +0 -0
  276. {agentlint-2.5.2 → agentlint-2.5.4}/plugin/mcp.json +0 -0
  277. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/packs/universal/no_compromised_dependency.py +0 -0
  278. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/py.typed +0 -0
  279. {agentlint-2.5.2 → agentlint-2.5.4}/src/agentlint/utils/__init__.py +0 -0
  280. {agentlint-2.5.2 → agentlint-2.5.4}/tests/__init__.py +0 -0
  281. {agentlint-2.5.2 → agentlint-2.5.4}/tests/packs/__init__.py +0 -0
@@ -0,0 +1,7 @@
1
+ * @mauhpr
2
+
3
+ /agentlint.yml @mauhpr
4
+ /.github/workflows/ @mauhpr
5
+ /src/agentlint/cli.py @mauhpr
6
+ /src/agentlint/core/models.py @mauhpr
7
+ /src/agentlint/mcp_server.py @mauhpr
@@ -0,0 +1,16 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 5
8
+ groups:
9
+ python-development:
10
+ dependency-type: development
11
+
12
+ - package-ecosystem: github-actions
13
+ directory: /
14
+ schedule:
15
+ interval: weekly
16
+ open-pull-requests-limit: 5
@@ -0,0 +1,78 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ quality:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
17
+ with:
18
+ persist-credentials: false
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
22
+
23
+ - name: Set up Python
24
+ run: uv python install 3.13
25
+
26
+ - name: Install dependencies
27
+ run: uv sync --extra dev --frozen --python 3.13
28
+
29
+ - name: Check formatting
30
+ run: uv run ruff format --check .
31
+
32
+ - name: Lint
33
+ run: uv run ruff check .
34
+
35
+ - name: Build distributions
36
+ run: uv build
37
+
38
+ - name: Smoke-test wheel
39
+ run: |
40
+ uv venv --seed .wheel-venv
41
+ uv pip install --python .wheel-venv/bin/python dist/*.whl
42
+ .wheel-venv/bin/agentlint --version
43
+
44
+ test:
45
+ runs-on: ubuntu-latest
46
+ strategy:
47
+ fail-fast: false
48
+ matrix:
49
+ python-version: ["3.11", "3.12", "3.13"]
50
+
51
+ steps:
52
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
53
+ with:
54
+ persist-credentials: false
55
+
56
+ - name: Install uv
57
+ uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
58
+
59
+ - name: Set up Python
60
+ run: uv python install ${{ matrix.python-version }}
61
+
62
+ - name: Install dependencies
63
+ run: uv sync --extra dev --frozen --python ${{ matrix.python-version }}
64
+
65
+ - name: Run tests
66
+ run: uv run --python ${{ matrix.python-version }} pytest -v --cov=agentlint --cov-report=term-missing --cov-report=xml
67
+
68
+ - name: Upload coverage to Codecov
69
+ if: matrix.python-version == '3.13'
70
+ uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5.5.5
71
+ with:
72
+ token: ${{ secrets.CODECOV_TOKEN }}
73
+ files: ./coverage.xml
74
+ flags: unittests
75
+ name: agentlint-coverage
76
+ slug: mauhpr/agentlint
77
+ fail_ci_if_error: false
78
+ verbose: true
@@ -0,0 +1,76 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ concurrency:
11
+ group: publish-${{ github.event.release.tag_name }}
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ build:
16
+ name: Verify and build once
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
20
+ with:
21
+ persist-credentials: false
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
25
+
26
+ - name: Set up Python
27
+ run: uv python install 3.13
28
+
29
+ - name: Install dependencies
30
+ run: uv sync --extra dev --frozen --python 3.13
31
+
32
+ - name: Verify source
33
+ run: |
34
+ uv lock --check
35
+ uv run ruff format --check .
36
+ uv run ruff check .
37
+ uv run pytest -q
38
+
39
+ - name: Build distributions
40
+ run: uv build
41
+
42
+ - name: Smoke-test wheel
43
+ run: |
44
+ uv venv --seed .wheel-venv
45
+ uv pip install --python .wheel-venv/bin/python dist/*.whl
46
+ .wheel-venv/bin/agentlint --version
47
+
48
+ - name: Upload artifacts
49
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
50
+ with:
51
+ name: distributions
52
+ path: dist/
53
+ if-no-files-found: error
54
+ retention-days: 7
55
+
56
+ publish-pypi:
57
+ name: Trusted publish
58
+ needs: build
59
+ runs-on: ubuntu-latest
60
+ environment:
61
+ name: pypi
62
+ url: https://pypi.org/p/agentlint
63
+ permissions:
64
+ contents: read
65
+ id-token: write
66
+ steps:
67
+ - name: Download artifacts
68
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
69
+ with:
70
+ name: distributions
71
+ path: dist/
72
+
73
+ - name: Publish to PyPI
74
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
75
+ with:
76
+ attestations: true
@@ -0,0 +1,55 @@
1
+ name: Publish to TestPyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ concurrency:
10
+ group: test-publish
11
+ cancel-in-progress: false
12
+
13
+ jobs:
14
+ build:
15
+ name: Build test distribution
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
19
+ with:
20
+ persist-credentials: false
21
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
22
+ - run: uv python install 3.13
23
+ - run: uv sync --extra dev --frozen --python 3.13
24
+ - run: uv run pytest -q
25
+ - run: uv build
26
+ - run: |
27
+ uv venv --seed .test-wheel-venv
28
+ uv pip install --python .test-wheel-venv/bin/python dist/*.whl
29
+ .test-wheel-venv/bin/agentlint --version
30
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
31
+ with:
32
+ name: test-distributions
33
+ path: dist/
34
+ if-no-files-found: error
35
+ retention-days: 7
36
+
37
+ publish:
38
+ name: Trusted test publish
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ environment:
42
+ name: testpypi
43
+ url: https://test.pypi.org/p/agentlint
44
+ permissions:
45
+ contents: read
46
+ id-token: write
47
+ steps:
48
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
49
+ with:
50
+ name: test-distributions
51
+ path: dist/
52
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
53
+ with:
54
+ repository-url: https://test.pypi.org/legacy/
55
+ attestations: true
@@ -1,5 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.5.4 (2026-07-29) — Quality and Release Hardening
4
+
5
+ This patch release strengthens AgentLint's development and publishing controls
6
+ without intentionally changing its public rule or adapter APIs.
7
+
8
+ ### Changed
9
+
10
+ - Establishes a repository-wide Ruff formatting and linting baseline and
11
+ enforces it in CI.
12
+ - Enables branch-aware coverage with a 95% combined floor; the release suite
13
+ now contains 2,542 tests and reports 96.2% combined coverage.
14
+ - Extracts the local AgentChute queue command group from the main CLI module,
15
+ creating the first dedicated boundary for continued CLI decomposition.
16
+ - Expands MCP server coverage from 68% to 94%, including generic event checks,
17
+ session tools/resources, and server startup.
18
+ - Pins GitHub Actions to immutable commit SHAs, disables checkout credential
19
+ persistence, uses frozen lockfile installs, and smoke-tests the built wheel.
20
+ - Verifies source, tests, wheel installation, and trusted-publishing artifacts
21
+ before production releases; adds a manual TestPyPI workflow.
22
+ - Adds Dependabot, CODEOWNERS, and regression tests for version consistency,
23
+ immutable workflow actions, and OIDC-only publishing.
24
+
25
+ ### Compatibility
26
+
27
+ - Existing configurations, rules, adapters, hook payloads, and CLI command
28
+ names remain compatible.
29
+ - The legacy `agentlint.setup` re-exports remain available.
30
+
31
+ ---
32
+
33
+ ## v2.5.3 (2026-05-25) — AgentChute Queue Baseline
34
+
35
+ This patch release fixes AgentChute onboarding for existing AgentLint users
36
+ with local event history.
37
+
38
+ - Fixes `agentlint queue flush`, which could crash because the CLI wrapper did
39
+ not pass the newer queue batch/time-budget arguments.
40
+ - Baselines the local AgentChute queue when a machine is paired with a new
41
+ license key, so pre-pairing local history is not uploaded as fresh dashboard
42
+ activity.
43
+ - Adds `agentlint queue discard-pending --yes` for support cases where a user
44
+ intentionally wants to advance the local queue cursor without uploading
45
+ pending events.
46
+ - Improves `agentlint policy explain` by listing active rule IDs, making policy
47
+ template debugging easier.
48
+ - Adds regression coverage for the `block-curl-sh` policy template simulation.
49
+
50
+ ---
51
+
3
52
  ## v2.5.2 (2026-05-25) — AgentChute Credential Persistence
4
53
 
5
54
  This patch release fixes the first-run AgentChute pairing flow so users can run
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentlint
3
- Version: 2.5.2
3
+ Version: 2.5.4
4
4
  Summary: Real-time quality guardrails for AI coding agents
5
5
  Project-URL: Homepage, https://github.com/mauhpr/agentlint
6
6
  Project-URL: Repository, https://github.com/mauhpr/agentlint
@@ -30,6 +30,7 @@ Requires-Dist: fastmcp>=3.0; extra == 'dev'
30
30
  Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
31
31
  Requires-Dist: pytest-cov>=5.0; extra == 'dev'
32
32
  Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.9; extra == 'dev'
33
34
  Provides-Extra: mcp
34
35
  Requires-Dist: fastmcp>=3.0; extra == 'mcp'
35
36
  Description-Content-Type: text/markdown
@@ -62,7 +63,7 @@ We don't have a mature answer to that yet. Nobody does. The **autopilot pack** i
62
63
 
63
64
  AgentLint ships with 77 rules across 8 packs and normalizes tool events across supported AI coding agents. The 24 **universal** rules and 7 **quality** rules work with any tech stack; 4 additional packs auto-activate based on your project files; the **security** pack is opt-in; and the **autopilot** pack is opt-in and experimental.
64
65
 
65
- **v2.5.0 highlights:** Local-first AgentChute NVD enforcement with `no-nvd-critical-cve-install`, which consumes the cached `nvd-cves` feed and blocks exact critical/CISA KEV CPE product+version matches without network access in the hook path. Previous: AgentChute onboarding with `agentlint onboard`, dashboard pairing through `agentlint login`, `doctor --fix`, `status`, `test`, `test-policy`, policy cache diagnostics, durable queue inspection/flush commands, automatic background event upload, safer Codex hook enablement, sync dry-run diagnostics, FastAPI-aware `no-unnecessary-async`, grouped text CI findings, hybrid cloud feeds, privacy-safe event queueing, multi-platform adapter architecture, MCP server, warning suppression, auto-suppress, `diff_only` mode, and `auto-fix` mode.
66
+ **v2.5.4 highlights:** Repository-wide Ruff enforcement, branch-aware coverage floors, immutable CI actions, verified release artifacts, stronger MCP tests, and the first extraction from the main CLI module. Previous: local-first AgentChute NVD enforcement, AgentChute onboarding with `agentlint onboard`, dashboard pairing through `agentlint login`, durable queue delivery, safer Codex hook enablement, multi-platform adapters, MCP server support, warning suppression, and auto-fix workflows.
66
67
 
67
68
  | Rule | Severity | What it does |
68
69
  |------|----------|-------------|
@@ -441,6 +442,7 @@ Create a Python file in your custom rules directory:
441
442
  # .agentlint/rules/no_direct_db.py
442
443
  from agentlint.models import Rule, RuleContext, Violation, Severity, HookEvent
443
444
 
445
+
444
446
  class NoDirectDB(Rule):
445
447
  id = "no-direct-db"
446
448
  description = "API routes must not import database layer directly"
@@ -452,12 +454,14 @@ class NoDirectDB(Rule):
452
454
  if not context.file_path or "/routes/" not in context.file_path:
453
455
  return []
454
456
  if context.file_content and "from database" in context.file_content:
455
- return [Violation(
456
- rule_id=self.id,
457
- message="Route imports database directly. Use repository pattern.",
458
- severity=self.severity,
459
- file_path=context.file_path,
460
- )]
457
+ return [
458
+ Violation(
459
+ rule_id=self.id,
460
+ message="Route imports database directly. Use repository pattern.",
461
+ severity=self.severity,
462
+ file_path=context.file_path,
463
+ )
464
+ ]
461
465
  return []
462
466
  ```
463
467
 
@@ -26,7 +26,7 @@ We don't have a mature answer to that yet. Nobody does. The **autopilot pack** i
26
26
 
27
27
  AgentLint ships with 77 rules across 8 packs and normalizes tool events across supported AI coding agents. The 24 **universal** rules and 7 **quality** rules work with any tech stack; 4 additional packs auto-activate based on your project files; the **security** pack is opt-in; and the **autopilot** pack is opt-in and experimental.
28
28
 
29
- **v2.5.0 highlights:** Local-first AgentChute NVD enforcement with `no-nvd-critical-cve-install`, which consumes the cached `nvd-cves` feed and blocks exact critical/CISA KEV CPE product+version matches without network access in the hook path. Previous: AgentChute onboarding with `agentlint onboard`, dashboard pairing through `agentlint login`, `doctor --fix`, `status`, `test`, `test-policy`, policy cache diagnostics, durable queue inspection/flush commands, automatic background event upload, safer Codex hook enablement, sync dry-run diagnostics, FastAPI-aware `no-unnecessary-async`, grouped text CI findings, hybrid cloud feeds, privacy-safe event queueing, multi-platform adapter architecture, MCP server, warning suppression, auto-suppress, `diff_only` mode, and `auto-fix` mode.
29
+ **v2.5.4 highlights:** Repository-wide Ruff enforcement, branch-aware coverage floors, immutable CI actions, verified release artifacts, stronger MCP tests, and the first extraction from the main CLI module. Previous: local-first AgentChute NVD enforcement, AgentChute onboarding with `agentlint onboard`, dashboard pairing through `agentlint login`, durable queue delivery, safer Codex hook enablement, multi-platform adapters, MCP server support, warning suppression, and auto-fix workflows.
30
30
 
31
31
  | Rule | Severity | What it does |
32
32
  |------|----------|-------------|
@@ -405,6 +405,7 @@ Create a Python file in your custom rules directory:
405
405
  # .agentlint/rules/no_direct_db.py
406
406
  from agentlint.models import Rule, RuleContext, Violation, Severity, HookEvent
407
407
 
408
+
408
409
  class NoDirectDB(Rule):
409
410
  id = "no-direct-db"
410
411
  description = "API routes must not import database layer directly"
@@ -416,12 +417,14 @@ class NoDirectDB(Rule):
416
417
  if not context.file_path or "/routes/" not in context.file_path:
417
418
  return []
418
419
  if context.file_content and "from database" in context.file_content:
419
- return [Violation(
420
- rule_id=self.id,
421
- message="Route imports database directly. Use repository pattern.",
422
- severity=self.severity,
423
- file_path=context.file_path,
424
- )]
420
+ return [
421
+ Violation(
422
+ rule_id=self.id,
423
+ message="Route imports database directly. Use repository pattern.",
424
+ severity=self.severity,
425
+ file_path=context.file_path,
426
+ )
427
+ ]
425
428
  return []
426
429
  ```
427
430
 
@@ -0,0 +1,83 @@
1
+ # AgentLint release process
2
+
3
+ This repo publishes the `agentlint` Python package to PyPI from GitHub Actions.
4
+ Do not publish from a local machine.
5
+
6
+ ## Release owner checklist
7
+
8
+ 1. Merge all required product/API/dashboard dependencies first.
9
+ - If the release depends on AgentChute server behavior, merge and deploy
10
+ AgentChute before publishing AgentLint.
11
+
12
+ 2. Prepare a release PR from a branch like `release/vX.Y.Z-description`.
13
+ Update these files together:
14
+ - `pyproject.toml`
15
+ - `src/agentlint/__init__.py`
16
+ - `uv.lock`
17
+ - `CHANGELOG.md`
18
+
19
+ 3. Run local verification before opening or updating the PR.
20
+
21
+ ```bash
22
+ .venv/bin/pytest tests/test_cli.py tests/test_agentchute_policy_queue_sync.py -k "not test_list_rules_universal_pack"
23
+ uv run ruff check CHANGELOG.md pyproject.toml src/agentlint/__init__.py src/agentlint/cli.py src/agentlint/agentchute/queue.py tests/test_cli.py tests/test_agentchute_policy_queue_sync.py
24
+ ```
25
+
26
+ Adjust the test list when the release touches other areas.
27
+
28
+ 4. Open the PR and wait for required GitHub checks.
29
+ - Python matrix must pass.
30
+ - Codecov patch must pass.
31
+ - Resolve conflicts by merging `origin/main` into the release branch.
32
+
33
+ 5. Merge the PR into `main`.
34
+
35
+ 6. Create the GitHub Release from the final `main` commit.
36
+
37
+ ```bash
38
+ git fetch origin main --tags
39
+ TARGET_SHA="$(git rev-parse origin/main)"
40
+ gh release create vX.Y.Z \
41
+ --target "$TARGET_SHA" \
42
+ --title "AgentLint vX.Y.Z" \
43
+ --notes-file /path/to/release-notes.md
44
+ ```
45
+
46
+ `gh-personal` can be used instead of `gh` on machines configured with that
47
+ wrapper.
48
+
49
+ 7. Let GitHub Actions publish to PyPI.
50
+ - The workflow is `.github/workflows/publish.yml`.
51
+ - It runs on `release.published`.
52
+ - It builds with `uv build`.
53
+ - It publishes with trusted publishing through `pypa/gh-action-pypi-publish`.
54
+
55
+ Check it with:
56
+
57
+ ```bash
58
+ gh run list --limit 5
59
+ ```
60
+
61
+ 8. Verify the package after the publish workflow succeeds.
62
+
63
+ ```bash
64
+ uv tool install --upgrade --reinstall agentlint
65
+ agentlint --version
66
+ ```
67
+
68
+ Expected output:
69
+
70
+ ```text
71
+ agentlint X.Y.Z
72
+ ```
73
+
74
+ ## Important rules
75
+
76
+ - Do not run `uv publish` locally. PyPI credentials are intentionally owned by
77
+ GitHub trusted publishing.
78
+ - Do not move an already published release tag. If a release is wrong after
79
+ publishing, create a follow-up patch version.
80
+ - Keep release notes focused on user-visible behavior, fixes, and migration
81
+ notes.
82
+ - If the release changes AgentLint behavior consumed by `agentlint-plugin`,
83
+ release AgentLint first, verify PyPI, then release the plugin.
@@ -10,6 +10,7 @@ Create a class that inherits from `AgentAdapter`:
10
10
  from agentlint.adapters.base import AgentAdapter
11
11
  from agentlint.models import AgentEvent, HookEvent, NormalizedTool, RuleContext
12
12
 
13
+
13
14
  class MyFrameworkAdapter(AgentAdapter):
14
15
  @property
15
16
  def platform_name(self) -> str:
@@ -18,6 +19,7 @@ class MyFrameworkAdapter(AgentAdapter):
18
19
  @property
19
20
  def formatter(self):
20
21
  from agentlint.formats.plain_json import PlainJsonFormatter
22
+
21
23
  return PlainJsonFormatter()
22
24
 
23
25
  def resolve_project_dir(self) -> str:
@@ -83,6 +85,7 @@ You can also write custom formatters:
83
85
  from agentlint.formats.base import OutputFormatter
84
86
  from agentlint.models import AgentEvent, Severity, Violation
85
87
 
88
+
86
89
  class MyFormatter(OutputFormatter):
87
90
  def exit_code(self, violations, event=""):
88
91
  return 1 if any(v.severity == Severity.ERROR for v in violations) else 0
@@ -47,13 +47,15 @@ class NoRawSQL(Rule):
47
47
  sql_keywords = ["execute(", "raw_sql(", "cursor.execute("]
48
48
  for keyword in sql_keywords:
49
49
  if keyword in content:
50
- return [Violation(
51
- rule_id=self.id,
52
- message=f"Raw SQL detected ({keyword}). Use the ORM.",
53
- severity=self.severity,
54
- file_path=context.file_path,
55
- suggestion="Use Model.objects or the query builder instead.",
56
- )]
50
+ return [
51
+ Violation(
52
+ rule_id=self.id,
53
+ message=f"Raw SQL detected ({keyword}). Use the ORM.",
54
+ severity=self.severity,
55
+ file_path=context.file_path,
56
+ suggestion="Use Model.objects or the query builder instead.",
57
+ )
58
+ ]
57
59
  return []
58
60
  ```
59
61
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentlint"
3
- version = "2.5.2"
3
+ version = "2.5.4"
4
4
  description = "Real-time quality guardrails for AI coding agents"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -33,6 +33,7 @@ dev = [
33
33
  "pytest-cov>=5.0",
34
34
  "pytest-asyncio>=0.24",
35
35
  "fastmcp>=3.0",
36
+ "ruff>=0.9",
36
37
  ]
37
38
  mcp = [
38
39
  "fastmcp>=3.0",
@@ -64,3 +65,16 @@ asyncio_mode = "auto"
64
65
  [tool.coverage.run]
65
66
  relative_files = true
66
67
  source = ["src/agentlint"]
68
+ branch = true
69
+
70
+ [tool.coverage.report]
71
+ fail_under = 95
72
+ show_missing = true
73
+ skip_covered = true
74
+
75
+ [tool.ruff]
76
+ target-version = "py311"
77
+ line-length = 100
78
+
79
+ [tool.ruff.lint]
80
+ select = ["E4", "E7", "E9", "F", "I", "UP", "B", "SIM"]
@@ -1,6 +1,6 @@
1
1
  """AgentLint - Real-time quality guardrails for AI coding agents."""
2
2
 
3
- __version__ = "2.5.2"
3
+ __version__ = "2.5.4"
4
4
 
5
5
  from agentlint.core.models import (
6
6
  AgentEvent,
@@ -1,4 +1,5 @@
1
1
  """Allow running agentlint as a module: python -m agentlint."""
2
+
2
3
  from agentlint.cli import main
3
4
 
4
5
  if __name__ == "__main__":
@@ -3,6 +3,7 @@
3
3
  Each adapter translates a specific agent framework's events, tool names,
4
4
  session identifiers, and output expectations into AgentLint's generic core.
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from agentlint.adapters.base import AgentAdapter
@@ -2,6 +2,7 @@
2
2
 
3
3
  Internal module — not part of the public API. Subject to change without notice.
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  import json
@@ -1,8 +1,8 @@
1
1
  """Base adapter protocol for agent platform integration."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from abc import ABC, abstractmethod
5
- from pathlib import Path
6
6
  from typing import Any
7
7
 
8
8
  from agentlint.formats.base import OutputFormatter
@@ -1,4 +1,5 @@
1
1
  """Claude Code adapter for AgentLint."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import json
@@ -16,7 +17,6 @@ from agentlint.adapters.base import AgentAdapter
16
17
  from agentlint.formats.claude_hooks import ClaudeHookFormatter
17
18
  from agentlint.models import AgentEvent, HookEvent, NormalizedTool, RuleContext
18
19
 
19
-
20
20
  # Mapping from Claude Code native event names to generic AgentEvent
21
21
  _CLAUDE_EVENT_MAP: dict[str, AgentEvent] = {
22
22
  "PreToolUse": AgentEvent.PRE_TOOL_USE,
@@ -183,8 +183,8 @@ class ClaudeAdapter(AgentAdapter):
183
183
  def translate_event(self, native_event: str) -> AgentEvent:
184
184
  try:
185
185
  return _CLAUDE_EVENT_MAP[native_event]
186
- except KeyError:
187
- raise ValueError(f"Unknown Claude event: {native_event}")
186
+ except KeyError as exc:
187
+ raise ValueError(f"Unknown Claude event: {native_event}") from exc
188
188
 
189
189
  def normalize_tool_name(self, native_tool: str) -> str:
190
190
  return _CLAUDE_TOOL_MAP.get(native_tool, NormalizedTool.UNKNOWN).value
@@ -205,7 +205,8 @@ class ClaudeAdapter(AgentAdapter):
205
205
  config={},
206
206
  session_state=session_state,
207
207
  prompt=raw_payload.get("prompt"),
208
- subagent_output=raw_payload.get("last_assistant_message") or raw_payload.get("subagent_output"),
208
+ subagent_output=raw_payload.get("last_assistant_message")
209
+ or raw_payload.get("subagent_output"),
209
210
  notification_type=raw_payload.get("notification_type"),
210
211
  compact_source=raw_payload.get("compact_source"),
211
212
  agent_transcript_path=raw_payload.get("agent_transcript_path"),
@@ -240,6 +241,7 @@ class ClaudeAdapter(AgentAdapter):
240
241
 
241
242
  if dry_run:
242
243
  import click
244
+
243
245
  click.echo(f"\nDry run — would write to {path}:")
244
246
  click.echo(json.dumps(settings, indent=2))
245
247
  return