agentlint 2.5.2__tar.gz → 2.5.3__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 (270) hide show
  1. {agentlint-2.5.2 → agentlint-2.5.3}/CHANGELOG.md +19 -0
  2. {agentlint-2.5.2 → agentlint-2.5.3}/PKG-INFO +1 -1
  3. {agentlint-2.5.2 → agentlint-2.5.3}/pyproject.toml +1 -1
  4. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/__init__.py +1 -1
  5. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/queue.py +18 -0
  6. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/cli.py +67 -4
  7. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_agentchute_policy_queue_sync.py +30 -0
  8. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_cli.py +124 -8
  9. {agentlint-2.5.2 → agentlint-2.5.3}/uv.lock +1 -1
  10. {agentlint-2.5.2 → agentlint-2.5.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {agentlint-2.5.2 → agentlint-2.5.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  12. {agentlint-2.5.2 → agentlint-2.5.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  13. {agentlint-2.5.2 → agentlint-2.5.3}/.github/workflows/ci.yml +0 -0
  14. {agentlint-2.5.2 → agentlint-2.5.3}/.github/workflows/publish.yml +0 -0
  15. {agentlint-2.5.2 → agentlint-2.5.3}/.gitignore +0 -0
  16. {agentlint-2.5.2 → agentlint-2.5.3}/.python-version +0 -0
  17. {agentlint-2.5.2 → agentlint-2.5.3}/CODE_OF_CONDUCT.md +0 -0
  18. {agentlint-2.5.2 → agentlint-2.5.3}/CONTRIBUTING.md +0 -0
  19. {agentlint-2.5.2 → agentlint-2.5.3}/LICENSE +0 -0
  20. {agentlint-2.5.2 → agentlint-2.5.3}/README.md +0 -0
  21. {agentlint-2.5.2 → agentlint-2.5.3}/SECURITY.md +0 -0
  22. {agentlint-2.5.2 → agentlint-2.5.3}/agentlint.yml +0 -0
  23. {agentlint-2.5.2 → agentlint-2.5.3}/agentlint.yml.example +0 -0
  24. {agentlint-2.5.2 → agentlint-2.5.3}/codecov.yml +0 -0
  25. {agentlint-2.5.2 → agentlint-2.5.3}/docs/README.md +0 -0
  26. {agentlint-2.5.2 → agentlint-2.5.3}/docs/adapters.md +0 -0
  27. {agentlint-2.5.2 → agentlint-2.5.3}/docs/architecture.md +0 -0
  28. {agentlint-2.5.2 → agentlint-2.5.3}/docs/configuration.md +0 -0
  29. {agentlint-2.5.2 → agentlint-2.5.3}/docs/custom-rules.md +0 -0
  30. {agentlint-2.5.2 → agentlint-2.5.3}/docs/mcp.md +0 -0
  31. {agentlint-2.5.2 → agentlint-2.5.3}/docs/migration-v2.md +0 -0
  32. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-claude.md +0 -0
  33. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-codex.md +0 -0
  34. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-continue.md +0 -0
  35. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-cursor.md +0 -0
  36. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-gemini.md +0 -0
  37. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-generic.md +0 -0
  38. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-grok.md +0 -0
  39. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-kimi.md +0 -0
  40. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-mcp.md +0 -0
  41. {agentlint-2.5.2 → agentlint-2.5.3}/docs/setup-openai.md +0 -0
  42. {agentlint-2.5.2 → agentlint-2.5.3}/docs/subagent-safety.md +0 -0
  43. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/.claude-plugin/plugin.json +0 -0
  44. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/agents/doctor.md +0 -0
  45. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/agents/fix.md +0 -0
  46. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/agents/security-audit.md +0 -0
  47. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/bin/resolve-and-run.sh +0 -0
  48. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/commands/lint-config.md +0 -0
  49. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/commands/lint-status.md +0 -0
  50. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/hooks/hooks.json +0 -0
  51. {agentlint-2.5.2 → agentlint-2.5.3}/plugin/mcp.json +0 -0
  52. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/__main__.py +0 -0
  53. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/__init__.py +0 -0
  54. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/_utils.py +0 -0
  55. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/base.py +0 -0
  56. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/claude.py +0 -0
  57. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/codex.py +0 -0
  58. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/continue_dev.py +0 -0
  59. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/cursor.py +0 -0
  60. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/gemini.py +0 -0
  61. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/generic.py +0 -0
  62. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/grok.py +0 -0
  63. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/kimi.py +0 -0
  64. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/mcp.py +0 -0
  65. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/adapters/openai_agents.py +0 -0
  66. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/__init__.py +0 -0
  67. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/client.py +0 -0
  68. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/feeds.py +0 -0
  69. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/policy.py +0 -0
  70. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/settings.py +0 -0
  71. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agentchute/sync.py +0 -0
  72. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/agents_md.py +0 -0
  73. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/circuit_breaker.py +0 -0
  74. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/config.py +0 -0
  75. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/core/__init__.py +0 -0
  76. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/core/models.py +0 -0
  77. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/detector.py +0 -0
  78. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/engine.py +0 -0
  79. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/filters.py +0 -0
  80. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/__init__.py +0 -0
  81. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/base.py +0 -0
  82. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/claude_hooks.py +0 -0
  83. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/cursor_hooks.py +0 -0
  84. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/gemini_hooks.py +0 -0
  85. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/formats/plain_json.py +0 -0
  86. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/mcp_server.py +0 -0
  87. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/models.py +0 -0
  88. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/__init__.py +0 -0
  89. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/__init__.py +0 -0
  90. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/_dangerous_patterns.py +0 -0
  91. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/bash_rate_limiter.py +0 -0
  92. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/cloud_infra_mutation.py +0 -0
  93. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/cloud_paid_resource_creation.py +0 -0
  94. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/cloud_resource_deletion.py +0 -0
  95. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/cross_account_guard.py +0 -0
  96. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/destructive_confirmation_gate.py +0 -0
  97. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/docker_volume_guard.py +0 -0
  98. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/dry_run_required.py +0 -0
  99. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/network_firewall_guard.py +0 -0
  100. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/operation_journal.py +0 -0
  101. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/package_manager_in_chroot.py +0 -0
  102. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/production_guard.py +0 -0
  103. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/remote_boot_partition_guard.py +0 -0
  104. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/remote_chroot_guard.py +0 -0
  105. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/ssh_destructive_command_guard.py +0 -0
  106. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/subagent_safety_briefing.py +0 -0
  107. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/subagent_transcript_audit.py +0 -0
  108. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/autopilot/system_scheduler_guard.py +0 -0
  109. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/__init__.py +0 -0
  110. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/_helpers.py +0 -0
  111. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/a11y_form_labels.py +0 -0
  112. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/a11y_heading_hierarchy.py +0 -0
  113. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/a11y_image_alt.py +0 -0
  114. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/a11y_interactive_elements.py +0 -0
  115. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/mobile_responsive_patterns.py +0 -0
  116. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/mobile_touch_targets.py +0 -0
  117. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/style_focus_visible.py +0 -0
  118. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/frontend/style_no_arbitrary_values.py +0 -0
  119. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/__init__.py +0 -0
  120. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_bare_except.py +0 -0
  121. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_dangerous_migration.py +0 -0
  122. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_sql_injection.py +0 -0
  123. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_unnecessary_async.py +0 -0
  124. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_unsafe_shell.py +0 -0
  125. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/python/no_wildcard_import.py +0 -0
  126. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/__init__.py +0 -0
  127. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/commit_message_format.py +0 -0
  128. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/naming_conventions.py +0 -0
  129. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/no_dead_imports.py +0 -0
  130. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/no_error_handling_removal.py +0 -0
  131. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/no_file_creation_sprawl.py +0 -0
  132. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/no_large_diff.py +0 -0
  133. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/quality/self_review_prompt.py +0 -0
  134. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/react/__init__.py +0 -0
  135. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/react/react_empty_state.py +0 -0
  136. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/react/react_lazy_loading.py +0 -0
  137. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/react/react_query_loading_state.py +0 -0
  138. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/__init__.py +0 -0
  139. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/env_credential_reference.py +0 -0
  140. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_bash_file_write.py +0 -0
  141. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_blocked_domain_fetch.py +0 -0
  142. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_compromised_action.py +0 -0
  143. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_leaked_secret_pattern.py +0 -0
  144. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_malicious_url_fetch.py +0 -0
  145. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/security/no_network_exfil.py +0 -0
  146. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/__init__.py +0 -0
  147. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/_helpers.py +0 -0
  148. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/seo_open_graph.py +0 -0
  149. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/seo_page_metadata.py +0 -0
  150. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/seo_semantic_html.py +0 -0
  151. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/seo/seo_structured_data.py +0 -0
  152. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/__init__.py +0 -0
  153. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/cicd_pipeline_guard.py +0 -0
  154. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/cli_integration.py +0 -0
  155. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/dependency_hygiene.py +0 -0
  156. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/drift_detector.py +0 -0
  157. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/file_scope.py +0 -0
  158. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/git_checkpoint.py +0 -0
  159. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/max_file_size.py +0 -0
  160. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_compromised_dependency.py +0 -0
  161. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_debug_artifacts.py +0 -0
  162. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_destructive_commands.py +0 -0
  163. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_env_commit.py +0 -0
  164. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_force_push.py +0 -0
  165. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_nvd_critical_cve_install.py +0 -0
  166. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_push_to_main.py +0 -0
  167. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_secrets.py +0 -0
  168. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_skip_hooks.py +0 -0
  169. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_test_weakening.py +0 -0
  170. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_todo_left.py +0 -0
  171. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_vulnerable_import.py +0 -0
  172. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/no_vulnerable_version_install.py +0 -0
  173. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/package_publish_guard.py +0 -0
  174. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/test_with_changes.py +0 -0
  175. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/token_budget.py +0 -0
  176. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/packs/universal/token_burn_against_team_budget.py +0 -0
  177. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/py.typed +0 -0
  178. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/recorder.py +0 -0
  179. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/reporter.py +0 -0
  180. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/session.py +0 -0
  181. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/setup.py +0 -0
  182. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/template.py +0 -0
  183. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/utils/__init__.py +0 -0
  184. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/utils/bash.py +0 -0
  185. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/utils/git.py +0 -0
  186. {agentlint-2.5.2 → agentlint-2.5.3}/src/agentlint/utils/paths.py +0 -0
  187. {agentlint-2.5.2 → agentlint-2.5.3}/tests/__init__.py +0 -0
  188. {agentlint-2.5.2 → agentlint-2.5.3}/tests/conftest.py +0 -0
  189. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/__init__.py +0 -0
  190. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/security/test_no_blocked_domain_fetch.py +0 -0
  191. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/security/test_no_compromised_action.py +0 -0
  192. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/security/test_no_leaked_secret_pattern.py +0 -0
  193. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/security/test_no_malicious_url_fetch.py +0 -0
  194. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_autopilot_integration.py +0 -0
  195. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_autopilot_pack_loads.py +0 -0
  196. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_autopilot_post.py +0 -0
  197. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_autopilot_pre.py +0 -0
  198. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_cicd_pipeline_guard.py +0 -0
  199. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_cloud_infra_mutation.py +0 -0
  200. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_cloud_paid_resource_creation.py +0 -0
  201. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_cloud_resource_deletion.py +0 -0
  202. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_docker_volume_guard.py +0 -0
  203. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_edge_cases.py +0 -0
  204. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_env_credential_reference.py +0 -0
  205. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_frontend.py +0 -0
  206. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_git_checkpoint.py +0 -0
  207. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_network_firewall_guard.py +0 -0
  208. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_no_compromised_dependency.py +0 -0
  209. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_no_nvd_critical_cve_install.py +0 -0
  210. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_no_vulnerable_import.py +0 -0
  211. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_no_vulnerable_version_install.py +0 -0
  212. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_package_manager_in_chroot.py +0 -0
  213. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_package_publish_guard.py +0 -0
  214. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_python_post.py +0 -0
  215. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_python_pre.py +0 -0
  216. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_quality_post.py +0 -0
  217. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_quality_pre.py +0 -0
  218. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_quality_stop.py +0 -0
  219. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_react.py +0 -0
  220. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_remote_boot_partition_guard.py +0 -0
  221. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_remote_chroot_guard.py +0 -0
  222. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_security_pre.py +0 -0
  223. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_seo.py +0 -0
  224. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_ssh_destructive_command_guard.py +0 -0
  225. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_subagent_safety_briefing.py +0 -0
  226. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_subagent_transcript_audit.py +0 -0
  227. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_system_scheduler_guard.py +0 -0
  228. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_token_budget.py +0 -0
  229. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_token_burn_against_team_budget.py +0 -0
  230. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_universal_post.py +0 -0
  231. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_universal_pre.py +0 -0
  232. {agentlint-2.5.2 → agentlint-2.5.3}/tests/packs/test_universal_stop.py +0 -0
  233. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_adapter_utils.py +0 -0
  234. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_agentchute_client.py +0 -0
  235. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_agentchute_feeds.py +0 -0
  236. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_agents_md.py +0 -0
  237. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_bash_utils.py +0 -0
  238. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_ci.py +0 -0
  239. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_circuit_breaker.py +0 -0
  240. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_cli_integration.py +0 -0
  241. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_codex_adapter.py +0 -0
  242. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_config.py +0 -0
  243. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_continue_adapter.py +0 -0
  244. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_cursor_adapter.py +0 -0
  245. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_custom_rules.py +0 -0
  246. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_detector.py +0 -0
  247. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_engine.py +0 -0
  248. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_file_scope.py +0 -0
  249. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_filters.py +0 -0
  250. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_gemini_adapter.py +0 -0
  251. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_generic_adapter.py +0 -0
  252. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_git.py +0 -0
  253. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_git_utils_checkpoint.py +0 -0
  254. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_grok_adapter.py +0 -0
  255. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_integration.py +0 -0
  256. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_kimi_adapter.py +0 -0
  257. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_main_module.py +0 -0
  258. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_mcp_adapter.py +0 -0
  259. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_mcp_server.py +0 -0
  260. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_models.py +0 -0
  261. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_openai_adapter.py +0 -0
  262. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_packs_loader.py +0 -0
  263. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_paths_utils.py +0 -0
  264. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_quality_new_rules.py +0 -0
  265. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_recorder.py +0 -0
  266. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_reporter.py +0 -0
  267. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_rule_inventory.py +0 -0
  268. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_session.py +0 -0
  269. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_setup.py +0 -0
  270. {agentlint-2.5.2 → agentlint-2.5.3}/tests/test_template.py +0 -0
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.5.3 (2026-05-25) — AgentChute Queue Baseline
4
+
5
+ This patch release fixes AgentChute onboarding for existing AgentLint users
6
+ with local event history.
7
+
8
+ - Fixes `agentlint queue flush`, which could crash because the CLI wrapper did
9
+ not pass the newer queue batch/time-budget arguments.
10
+ - Baselines the local AgentChute queue when a machine is paired with a new
11
+ license key, so pre-pairing local history is not uploaded as fresh dashboard
12
+ activity.
13
+ - Adds `agentlint queue discard-pending --yes` for support cases where a user
14
+ intentionally wants to advance the local queue cursor without uploading
15
+ pending events.
16
+ - Improves `agentlint policy explain` by listing active rule IDs, making policy
17
+ template debugging easier.
18
+ - Adds regression coverage for the `block-curl-sh` policy template simulation.
19
+
20
+ ---
21
+
3
22
  ## v2.5.2 (2026-05-25) — AgentChute Credential Persistence
4
23
 
5
24
  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.3
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentlint"
3
- version = "2.5.2"
3
+ version = "2.5.3"
4
4
  description = "Real-time quality guardrails for AI coding agents"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -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.3"
4
4
 
5
5
  from agentlint.core.models import (
6
6
  AgentEvent,
@@ -89,6 +89,24 @@ def enqueue_event(event: dict, *, session_key: str, config: Any | None = None) -
89
89
  return event_id
90
90
 
91
91
 
92
+ def mark_existing_events_delivered() -> int:
93
+ """Advance delivery to the current queue tail without deleting events.
94
+
95
+ This is used when AgentChute is first paired, or when the local license key
96
+ changes. Local history can predate the cloud workspace and should not be
97
+ uploaded as new team activity.
98
+ """
99
+ lines = _read_lines()
100
+ total = len(lines)
101
+ cursor = int(_load_json(_cursor_path(), {"offset": 0}).get("offset", 0))
102
+ if cursor >= total:
103
+ _clear_retry()
104
+ return 0
105
+ _save_json(_cursor_path(), {"offset": total})
106
+ _clear_retry()
107
+ return total - cursor
108
+
109
+
92
110
  def trigger_background_flush(config: Any | None = None) -> None:
93
111
  """Start a detached flusher process if AgentChute is enabled.
94
112
 
@@ -91,6 +91,26 @@ def _agentchute_policy_metadata() -> dict:
91
91
  }
92
92
 
93
93
 
94
+ def _baseline_agentchute_queue_if_new_key(previous_key: str | None, next_key: str) -> int:
95
+ if previous_key == next_key:
96
+ return 0
97
+ try:
98
+ from agentlint.agentchute.queue import mark_existing_events_delivered
99
+
100
+ return mark_existing_events_delivered()
101
+ except Exception:
102
+ logger.debug("Failed to baseline AgentChute queue", exc_info=True)
103
+ return 0
104
+
105
+
106
+ def _echo_queue_baseline(skipped: int) -> None:
107
+ if skipped:
108
+ click.echo(
109
+ f"AgentChute queue: skipped {skipped} pre-pairing event(s); "
110
+ "future events will upload normally"
111
+ )
112
+
113
+
94
114
  def _codex_hooks_enabled() -> bool:
95
115
  """Return whether current Codex native hooks are enabled in config.toml."""
96
116
  config_path = Path.home() / ".codex" / "config.toml"
@@ -1145,6 +1165,7 @@ def onboard(
1145
1165
  click.echo(f"Would persist AgentChute credentials to {local_credentials_path()}")
1146
1166
  click.echo(f"Would persist AgentChute env vars to {_default_shell_profile()}")
1147
1167
  else:
1168
+ skipped = _baseline_agentchute_queue_if_new_key(existing_key, team_key)
1148
1169
  credentials_path = save_local_credentials(
1149
1170
  api_url=api_url,
1150
1171
  license_key=team_key,
@@ -1156,6 +1177,7 @@ def onboard(
1156
1177
  os.environ["AGENTCHUTE_ENABLED"] = "true"
1157
1178
  click.echo(f"Saved AgentChute credentials to {credentials_path}")
1158
1179
  click.echo(f"Saved AgentChute env vars to {profile}")
1180
+ _echo_queue_baseline(skipped)
1159
1181
 
1160
1182
  for platform in selected:
1161
1183
  state, path = _hook_status(platform, project_dir)
@@ -1399,9 +1421,10 @@ def env_group():
1399
1421
  @click.option("--profile", default=None, help="Shell profile to update")
1400
1422
  def env_install(team_key: str, api_url: str | None, profile: str | None):
1401
1423
  """Persist AgentChute env vars into the shell profile."""
1402
- from agentlint.agentchute.settings import get_api_url, save_local_credentials
1424
+ from agentlint.agentchute.settings import get_api_url, get_license_key, save_local_credentials
1403
1425
 
1404
1426
  resolved_api_url = api_url or get_api_url()
1427
+ skipped = _baseline_agentchute_queue_if_new_key(get_license_key(), team_key)
1405
1428
  credentials_path = save_local_credentials(
1406
1429
  api_url=resolved_api_url,
1407
1430
  license_key=team_key,
@@ -1417,6 +1440,7 @@ def env_install(team_key: str, api_url: str | None, profile: str | None):
1417
1440
  os.environ["AGENTCHUTE_ENABLED"] = "true"
1418
1441
  click.echo(f"Saved AgentChute credentials to {credentials_path}")
1419
1442
  click.echo(f"Saved AgentChute env vars to {path}")
1443
+ _echo_queue_baseline(skipped)
1420
1444
  click.echo("This terminal can use AgentChute immediately.")
1421
1445
  click.echo("Future terminals can also load env vars with: source " + str(path))
1422
1446
 
@@ -1478,10 +1502,11 @@ def env_remove(profile: str | None):
1478
1502
  @click.option("--manual", is_flag=True, help="Paste a license key instead of using dashboard pairing")
1479
1503
  def login(dashboard_url: str | None, api_url: str | None, project_dir: str | None, manual: bool):
1480
1504
  """Pair this machine with AgentChute through the dashboard."""
1481
- from agentlint.agentchute.settings import get_api_url, save_local_credentials
1505
+ from agentlint.agentchute.settings import get_api_url, get_license_key, save_local_credentials
1482
1506
 
1483
1507
  project_dir = _resolve_project_dir(project_dir)
1484
1508
  api_url = api_url or get_api_url()
1509
+ existing_key = get_license_key()
1485
1510
  dashboard_url = dashboard_url or (
1486
1511
  "http://localhost:3001/dashboard/settings/license"
1487
1512
  if "localhost" in api_url
@@ -1532,6 +1557,7 @@ def login(dashboard_url: str | None, api_url: str | None, project_dir: str | Non
1532
1557
  webbrowser.open(dashboard_url)
1533
1558
  team_key = click.prompt("Paste the AgentChute license key", hide_input=True)
1534
1559
 
1560
+ skipped = _baseline_agentchute_queue_if_new_key(existing_key, team_key)
1535
1561
  credentials_path = save_local_credentials(
1536
1562
  api_url=api_url,
1537
1563
  license_key=team_key,
@@ -1546,6 +1572,7 @@ def login(dashboard_url: str | None, api_url: str | None, project_dir: str | Non
1546
1572
  _ensure_agentchute_enabled_config(config_path)
1547
1573
  click.echo(f"Paired. AgentChute credentials saved to {credentials_path}")
1548
1574
  click.echo(f"Shell env vars saved to {profile}")
1575
+ _echo_queue_baseline(skipped)
1549
1576
  click.echo("This terminal can use AgentChute immediately.")
1550
1577
 
1551
1578
 
@@ -1569,9 +1596,41 @@ def queue_status_command():
1569
1596
 
1570
1597
  @queue_group.command("flush")
1571
1598
  @click.option("--max-events", default=None, type=int, help="Maximum events to flush")
1572
- def queue_flush_command(max_events: int | None):
1599
+ @click.option("--batch-size", default=50, type=int, help="Maximum events per API batch")
1600
+ @click.option("--time-budget", default=3.0, type=float, help="Maximum seconds to spend flushing")
1601
+ def queue_flush_command(max_events: int | None, batch_size: int, time_budget: float):
1573
1602
  """Flush queued AgentChute events now."""
1574
- _flush_agentchute_queue(max_events=max_events, dry_run=False, background=False)
1603
+ _flush_agentchute_queue(
1604
+ max_events=max_events,
1605
+ batch_size=batch_size,
1606
+ time_budget=time_budget,
1607
+ dry_run=False,
1608
+ background=False,
1609
+ )
1610
+
1611
+
1612
+ @queue_group.command("discard-pending")
1613
+ @click.option("--yes", is_flag=True, help="Skip confirmation")
1614
+ def queue_discard_pending_command(yes: bool):
1615
+ """Mark pending AgentChute events delivered without uploading them."""
1616
+ from agentlint.agentchute.queue import mark_existing_events_delivered, queue_status
1617
+
1618
+ status_data = queue_status()
1619
+ pending = int(status_data.get("pending", 0) or 0)
1620
+ if pending <= 0:
1621
+ click.echo("AgentChute queue: no pending events.")
1622
+ return
1623
+ if not yes and not click.confirm(
1624
+ f"Discard {pending} pending AgentChute event(s) without uploading?",
1625
+ default=False,
1626
+ ):
1627
+ click.echo("AgentChute queue unchanged.")
1628
+ return
1629
+ skipped = mark_existing_events_delivered()
1630
+ click.echo(
1631
+ f"AgentChute queue: discarded {skipped} pending event(s); "
1632
+ "future events will upload normally"
1633
+ )
1575
1634
 
1576
1635
 
1577
1636
  @queue_group.command("inspect")
@@ -2325,6 +2384,7 @@ def policy_explain_command(output_format: str):
2325
2384
  rules = [rule for rule in policy.get("rules") or [] if isinstance(rule, dict)]
2326
2385
  active_rules = [rule for rule in rules if rule.get("enabled", True) is not False]
2327
2386
  locked_rules = [rule for rule in active_rules if rule.get("locked") is True]
2387
+ active_rule_ids = [str(rule.get("id")) for rule in active_rules if rule.get("id")]
2328
2388
  packs = required_packs(policy)
2329
2389
  missing = missing_required_packs(policy)
2330
2390
  cloud_feeds = [
@@ -2339,6 +2399,7 @@ def policy_explain_command(output_format: str):
2339
2399
  "updated_at": policy.get("updated_at"),
2340
2400
  "organization_id": policy.get("organization_id"),
2341
2401
  "rules": len(active_rules),
2402
+ "rule_ids": active_rule_ids,
2342
2403
  "locked_rules": len(locked_rules),
2343
2404
  "required_packs": len(packs),
2344
2405
  "cloud_feeds": cloud_feeds,
@@ -2353,6 +2414,8 @@ def policy_explain_command(output_format: str):
2353
2414
  if policy.get("updated_at"):
2354
2415
  click.echo(f"Updated: {policy['updated_at']}")
2355
2416
  click.echo(f"Rules: {len(active_rules)} active, {len(locked_rules)} locked")
2417
+ if active_rule_ids:
2418
+ click.echo(f"Rule IDs: {', '.join(active_rule_ids[:10])}")
2356
2419
  click.echo(f"Required packs: {len(packs)}")
2357
2420
  if cloud_feeds:
2358
2421
  click.echo(f"Cloud feeds: {', '.join(cloud_feeds)}")
@@ -258,6 +258,36 @@ def test_queue_enqueue_flush_dry_run_and_status(tmp_path, monkeypatch):
258
258
  assert not (tmp_path / "flush.lock").exists()
259
259
 
260
260
 
261
+ def test_queue_mark_existing_events_delivered_preserves_future_pending(tmp_path, monkeypatch):
262
+ from agentlint.agentchute import queue
263
+
264
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(tmp_path))
265
+ (tmp_path / "queue.jsonl").write_text(
266
+ "\n".join(
267
+ [
268
+ json.dumps({"event_id": "old-1", "event": {"n": 1}}),
269
+ json.dumps({"event_id": "old-2", "event": {"n": 2}}),
270
+ ]
271
+ )
272
+ + "\n",
273
+ encoding="utf-8",
274
+ )
275
+ queue._save_json(tmp_path / "retry.json", {"failures": 2, "next_attempt_at": 123})
276
+
277
+ skipped = queue.mark_existing_events_delivered()
278
+
279
+ assert skipped == 2
280
+ assert queue.queue_status()["pending"] == 0
281
+ assert json.loads((tmp_path / "cursor.json").read_text())["offset"] == 2
282
+ assert not (tmp_path / "retry.json").exists()
283
+ assert queue.mark_existing_events_delivered() == 0
284
+
285
+ with open(tmp_path / "queue.jsonl", "a", encoding="utf-8") as f:
286
+ f.write(json.dumps({"event_id": "new-1", "event": {"n": 3}}) + "\n")
287
+
288
+ assert queue.queue_status()["pending"] == 1
289
+
290
+
261
291
  def test_queue_flush_dry_run_counts_limited_poison_entries(tmp_path, monkeypatch):
262
292
  from agentlint.agentchute import queue
263
293
 
@@ -19,7 +19,7 @@ class TestMainCommand:
19
19
  result = runner.invoke(main, ["--version"])
20
20
 
21
21
  assert result.exit_code == 0
22
- assert result.output.strip() == "agentlint 2.5.2"
22
+ assert result.output.strip() == "agentlint 2.5.3"
23
23
 
24
24
 
25
25
  class TestCheckCommand:
@@ -1106,6 +1106,48 @@ class TestMagicalUxCommands:
1106
1106
  explain = runner.invoke(main, ["policy", "explain"])
1107
1107
  assert "Updated: 2026-05-19T12:00:00Z" in status.output
1108
1108
  assert "Updated: 2026-05-19T12:00:00Z" in explain.output
1109
+ assert "Rule IDs: org-block-forbidden-domain" in explain.output
1110
+
1111
+ def test_curl_pipe_policy_template_matches_cached_policy(self, tmp_path, monkeypatch) -> None:
1112
+ policy_dir = tmp_path / "policy"
1113
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_POLICY_DIR", str(policy_dir))
1114
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(tmp_path / "queue"))
1115
+ monkeypatch.setenv("AGENTCHUTE_LICENSE_KEY", "ac_team_test_secret")
1116
+ (tmp_path / "agentlint.yml").write_text(
1117
+ "packs:\n - universal\nagentchute:\n enabled: true\n"
1118
+ )
1119
+ policy_dir.mkdir()
1120
+ (policy_dir / "policy.json").write_text(json.dumps({
1121
+ "version": 1,
1122
+ "updated_at": "2026-05-19T12:00:00Z",
1123
+ "rules": [{
1124
+ "id": "org-block-curl-pipe-sh",
1125
+ "enabled": True,
1126
+ "event": "PreToolUse",
1127
+ "tool": "Bash",
1128
+ "severity": "error",
1129
+ "match": {
1130
+ "field": "command",
1131
+ "operator": "contains",
1132
+ "value": "| sh",
1133
+ },
1134
+ "message": "Blocked curl piped to shell.",
1135
+ }],
1136
+ }))
1137
+
1138
+ result = CliRunner().invoke(
1139
+ main,
1140
+ [
1141
+ "test-policy",
1142
+ "block-curl-sh",
1143
+ "--project-dir",
1144
+ str(tmp_path),
1145
+ "--no-refresh",
1146
+ ],
1147
+ )
1148
+
1149
+ assert result.exit_code == 0
1150
+ assert "Matched: org-block-curl-pipe-sh (error)" in result.output
1109
1151
 
1110
1152
  def test_policy_template_unknown_name_errors(self) -> None:
1111
1153
  result = CliRunner().invoke(main, ["test-policy", "unknown-template", "--no-refresh"])
@@ -1248,8 +1290,17 @@ class TestMagicalUxCommands:
1248
1290
 
1249
1291
  def test_login_persists_key_and_enables_existing_config(self, tmp_path, monkeypatch) -> None:
1250
1292
  profile = tmp_path / ".zshrc"
1293
+ queue_dir = tmp_path / "queue"
1294
+ queue_dir.mkdir()
1295
+ (queue_dir / "queue.jsonl").write_text(
1296
+ json.dumps({"event_id": "old-1", "event": {}}) + "\n"
1297
+ + json.dumps({"event_id": "old-2", "event": {}}) + "\n",
1298
+ encoding="utf-8",
1299
+ )
1251
1300
  (tmp_path / "agentlint.yml").write_text("packs:\n - universal\n")
1252
1301
  monkeypatch.setenv("AGENTLINT_SHELL_PROFILE", str(profile))
1302
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(queue_dir))
1303
+ monkeypatch.delenv("AGENTCHUTE_LICENSE_KEY", raising=False)
1253
1304
  monkeypatch.setattr("webbrowser.open", lambda _url: True)
1254
1305
  runner = CliRunner()
1255
1306
 
@@ -1265,18 +1316,20 @@ class TestMagicalUxCommands:
1265
1316
  "--api-url",
1266
1317
  "http://localhost:8000",
1267
1318
  ],
1268
- input="ac_team_test_secret\n",
1319
+ input="ac_team_login_baseline\n",
1269
1320
  )
1270
1321
 
1271
1322
  assert result.exit_code == 0
1272
1323
  assert "Paired. AgentChute credentials saved" in result.output
1273
1324
  assert "Shell env vars saved" in result.output
1274
1325
  assert "This terminal can use AgentChute immediately." in result.output
1275
- assert "AGENTCHUTE_LICENSE_KEY=ac_team_test_secret" in profile.read_text()
1326
+ assert "AgentChute queue: skipped 2 pre-pairing event(s)" in result.output
1327
+ assert json.loads((queue_dir / "cursor.json").read_text())["offset"] == 2
1328
+ assert "AGENTCHUTE_LICENSE_KEY=ac_team_login_baseline" in profile.read_text()
1276
1329
  assert "agentchute:" in (tmp_path / "agentlint.yml").read_text()
1277
1330
  from agentlint.agentchute.settings import load_local_credentials
1278
1331
 
1279
- assert load_local_credentials()["license_key"] == "ac_team_test_secret"
1332
+ assert load_local_credentials()["license_key"] == "ac_team_login_baseline"
1280
1333
 
1281
1334
  def test_login_pairs_through_dashboard(self, tmp_path, monkeypatch) -> None:
1282
1335
  profile = tmp_path / ".zshrc"
@@ -1464,17 +1517,80 @@ class TestMagicalUxCommands:
1464
1517
  def test_queue_flush_command_delegates_to_flush_helper(self, monkeypatch) -> None:
1465
1518
  import agentlint.cli
1466
1519
 
1467
- calls: list[tuple[int | None, bool, bool]] = []
1520
+ calls: list[dict] = []
1468
1521
  monkeypatch.setattr(
1469
1522
  agentlint.cli,
1470
1523
  "_flush_agentchute_queue",
1471
- lambda max_events, dry_run, background: calls.append((max_events, dry_run, background)),
1524
+ lambda **kwargs: calls.append(kwargs),
1472
1525
  )
1473
1526
 
1474
- result = CliRunner().invoke(main, ["queue", "flush", "--max-events", "7"])
1527
+ result = CliRunner().invoke(
1528
+ main,
1529
+ ["queue", "flush", "--max-events", "7", "--batch-size", "3", "--time-budget", "1.5"],
1530
+ )
1475
1531
 
1476
1532
  assert result.exit_code == 0
1477
- assert calls == [(7, False, False)]
1533
+ assert calls == [{
1534
+ "max_events": 7,
1535
+ "batch_size": 3,
1536
+ "time_budget": 1.5,
1537
+ "dry_run": False,
1538
+ "background": False,
1539
+ }]
1540
+
1541
+ def test_queue_discard_pending_advances_cursor(self, tmp_path, monkeypatch) -> None:
1542
+ queue_dir = tmp_path / "queue"
1543
+ queue_dir.mkdir()
1544
+ (queue_dir / "queue.jsonl").write_text(
1545
+ json.dumps({"event_id": "old-1", "event": {}}) + "\n"
1546
+ + json.dumps({"event_id": "old-2", "event": {}}) + "\n",
1547
+ encoding="utf-8",
1548
+ )
1549
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(queue_dir))
1550
+
1551
+ result = CliRunner().invoke(main, ["queue", "discard-pending", "--yes"])
1552
+
1553
+ assert result.exit_code == 0
1554
+ assert "AgentChute queue: discarded 2 pending event(s)" in result.output
1555
+ assert json.loads((queue_dir / "cursor.json").read_text())["offset"] == 2
1556
+
1557
+ def test_queue_discard_pending_can_cancel(self, tmp_path, monkeypatch) -> None:
1558
+ queue_dir = tmp_path / "queue"
1559
+ queue_dir.mkdir()
1560
+ (queue_dir / "queue.jsonl").write_text(
1561
+ json.dumps({"event_id": "old-1", "event": {}}) + "\n",
1562
+ encoding="utf-8",
1563
+ )
1564
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(queue_dir))
1565
+
1566
+ result = CliRunner().invoke(main, ["queue", "discard-pending"], input="n\n")
1567
+
1568
+ assert result.exit_code == 0
1569
+ assert "AgentChute queue unchanged." in result.output
1570
+ assert not (queue_dir / "cursor.json").exists()
1571
+
1572
+ def test_queue_discard_pending_reports_empty_queue(self, tmp_path, monkeypatch) -> None:
1573
+ monkeypatch.setenv("AGENTLINT_AGENTCHUTE_QUEUE_DIR", str(tmp_path / "queue"))
1574
+
1575
+ result = CliRunner().invoke(main, ["queue", "discard-pending", "--yes"])
1576
+
1577
+ assert result.exit_code == 0
1578
+ assert "AgentChute queue: no pending events." in result.output
1579
+
1580
+ def test_queue_baseline_failure_is_non_fatal(self, monkeypatch) -> None:
1581
+ import agentlint.agentchute.queue
1582
+ import agentlint.cli
1583
+
1584
+ def fail_baseline() -> int:
1585
+ raise OSError("queue locked")
1586
+
1587
+ monkeypatch.setattr(
1588
+ agentlint.agentchute.queue,
1589
+ "mark_existing_events_delivered",
1590
+ fail_baseline,
1591
+ )
1592
+
1593
+ assert agentlint.cli._baseline_agentchute_queue_if_new_key("old-key", "new-key") == 0
1478
1594
 
1479
1595
  def test_status_reports_cached_policy_retry_and_error(self, tmp_path, monkeypatch) -> None:
1480
1596
  monkeypatch.setenv("AGENTCHUTE_ENABLED", "true")
@@ -4,7 +4,7 @@ requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
6
6
  name = "agentlint"
7
- version = "2.5.2"
7
+ version = "2.5.3"
8
8
  source = { editable = "." }
9
9
  dependencies = [
10
10
  { name = "click" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes