hanzo-mcp 0.8.5__tar.gz → 0.8.7__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.

Potentially problematic release.


This version of hanzo-mcp might be problematic. Click here for more details.

Files changed (241) hide show
  1. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/PKG-INFO +1 -1
  2. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/__init__.py +10 -1
  3. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/PKG-INFO +1 -1
  4. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/SOURCES.txt +1 -0
  5. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/pyproject.toml +1 -1
  6. hanzo_mcp-0.8.7/tests/test_no_stubs.py +288 -0
  7. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/README.md +0 -0
  8. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/__init__.py +0 -0
  9. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/__main__.py +0 -0
  10. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/analytics/__init__.py +0 -0
  11. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/analytics/posthog_analytics.py +0 -0
  12. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/bridge.py +0 -0
  13. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/cli.py +0 -0
  14. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/cli_enhanced.py +0 -0
  15. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/cli_plugin.py +0 -0
  16. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/compute_nodes.py +0 -0
  17. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/config/__init__.py +0 -0
  18. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/config/settings.py +0 -0
  19. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/config/tool_config.py +0 -0
  20. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/core/base_agent.py +0 -0
  21. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/core/model_registry.py +0 -0
  22. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/dev_server.py +0 -0
  23. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/__init__.py +0 -0
  24. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/compact_conversation.py +0 -0
  25. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/create_release.py +0 -0
  26. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/enhanced_prompts.py +0 -0
  27. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/example_custom_prompt.py +0 -0
  28. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/project_system.py +0 -0
  29. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/project_todo_reminder.py +0 -0
  30. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/tool_explorer.py +0 -0
  31. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/prompts/utils.py +0 -0
  32. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/server.py +0 -0
  33. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/server_enhanced.py +0 -0
  34. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/__init__.py +0 -0
  35. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/agent.py +0 -0
  36. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/agent_tool.py +0 -0
  37. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +0 -0
  38. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/clarification_protocol.py +0 -0
  39. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/clarification_tool.py +0 -0
  40. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/claude_cli_tool.py +0 -0
  41. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/claude_desktop_auth.py +0 -0
  42. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/cli_agent_base.py +0 -0
  43. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/cli_tools.py +0 -0
  44. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/code_auth.py +0 -0
  45. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/code_auth_tool.py +0 -0
  46. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/codex_cli_tool.py +0 -0
  47. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/critic_tool.py +0 -0
  48. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/gemini_cli_tool.py +0 -0
  49. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/grok_cli_tool.py +0 -0
  50. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/iching_tool.py +0 -0
  51. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/network_tool.py +0 -0
  52. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/prompt.py +0 -0
  53. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/review_tool.py +0 -0
  54. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/swarm_alias.py +0 -0
  55. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/swarm_tool.py +0 -0
  56. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +0 -0
  57. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/tool_adapter.py +0 -0
  58. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/agent/unified_cli_tools.py +0 -0
  59. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/__init__.py +0 -0
  60. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/base.py +0 -0
  61. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/batch_tool.py +0 -0
  62. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/config_tool.py +0 -0
  63. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/context.py +0 -0
  64. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/context_fix.py +0 -0
  65. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/critic_tool.py +0 -0
  66. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/decorators.py +0 -0
  67. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/enhanced_base.py +0 -0
  68. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/fastmcp_pagination.py +0 -0
  69. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/forgiving_edit.py +0 -0
  70. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/mode.py +0 -0
  71. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/mode_loader.py +0 -0
  72. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/paginated_base.py +0 -0
  73. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/paginated_response.py +0 -0
  74. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/pagination.py +0 -0
  75. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/permissions.py +0 -0
  76. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/personality.py +0 -0
  77. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/plugin_loader.py +0 -0
  78. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/stats.py +0 -0
  79. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/test_helpers.py +0 -0
  80. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/thinking_tool.py +0 -0
  81. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/tool_disable.py +0 -0
  82. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/tool_enable.py +0 -0
  83. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/tool_list.py +0 -0
  84. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/truncate.py +0 -0
  85. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/common/validation.py +0 -0
  86. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/config/__init__.py +0 -0
  87. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/config/config_tool.py +0 -0
  88. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/config/index_config.py +0 -0
  89. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/config/mode_tool.py +0 -0
  90. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/__init__.py +0 -0
  91. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/database_manager.py +0 -0
  92. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph.py +0 -0
  93. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph_add.py +0 -0
  94. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph_query.py +0 -0
  95. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph_remove.py +0 -0
  96. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph_search.py +0 -0
  97. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/graph_stats.py +0 -0
  98. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/sql.py +0 -0
  99. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/sql_query.py +0 -0
  100. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/sql_search.py +0 -0
  101. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/database/sql_stats.py +0 -0
  102. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/editor/__init__.py +0 -0
  103. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/editor/neovim_command.py +0 -0
  104. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/editor/neovim_edit.py +0 -0
  105. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/editor/neovim_session.py +0 -0
  106. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/__init__.py +0 -0
  107. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/ast_multi_edit.py +0 -0
  108. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/ast_tool.py +0 -0
  109. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/base.py +0 -0
  110. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/batch_search.py +0 -0
  111. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/content_replace.py +0 -0
  112. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/diff.py +0 -0
  113. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/directory_tree.py +0 -0
  114. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/directory_tree_paginated.py +0 -0
  115. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/edit.py +0 -0
  116. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/find.py +0 -0
  117. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/find_files.py +0 -0
  118. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/git_search.py +0 -0
  119. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/grep.py +0 -0
  120. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/multi_edit.py +0 -0
  121. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/read.py +0 -0
  122. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/rules_tool.py +0 -0
  123. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/search_tool.py +0 -0
  124. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/symbols_tool.py +0 -0
  125. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/tree.py +0 -0
  126. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/unix_aliases.py +0 -0
  127. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/watch.py +0 -0
  128. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/filesystem/write.py +0 -0
  129. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/jupyter/__init__.py +0 -0
  130. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/jupyter/base.py +0 -0
  131. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/jupyter/jupyter.py +0 -0
  132. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/jupyter/notebook_edit.py +0 -0
  133. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/jupyter/notebook_read.py +0 -0
  134. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/__init__.py +0 -0
  135. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/consensus_tool.py +0 -0
  136. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/llm_manage.py +0 -0
  137. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/llm_tool.py +0 -0
  138. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/llm_unified.py +0 -0
  139. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/llm/provider_tools.py +0 -0
  140. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/lsp/__init__.py +0 -0
  141. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/lsp/lsp_tool.py +0 -0
  142. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/mcp/__init__.py +0 -0
  143. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/mcp/mcp_add.py +0 -0
  144. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/mcp/mcp_remove.py +0 -0
  145. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/mcp/mcp_stats.py +0 -0
  146. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/mcp/mcp_tool.py +0 -0
  147. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/memory/__init__.py +0 -0
  148. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/memory/knowledge_tools.py +0 -0
  149. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/memory/memory_tools.py +0 -0
  150. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/search/__init__.py +0 -0
  151. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/search/find_tool.py +0 -0
  152. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/search/unified_search.py +0 -0
  153. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/__init__.py +0 -0
  154. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/auto_background.py +0 -0
  155. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/base.py +0 -0
  156. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/base_process.py +0 -0
  157. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/bash_session.py +0 -0
  158. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/bash_session_executor.py +0 -0
  159. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/bash_tool.py +0 -0
  160. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/command_executor.py +0 -0
  161. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/logs.py +0 -0
  162. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/npx.py +0 -0
  163. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/npx_background.py +0 -0
  164. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/npx_tool.py +0 -0
  165. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/open.py +0 -0
  166. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/pkill.py +0 -0
  167. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/process_tool.py +0 -0
  168. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/processes.py +0 -0
  169. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/run_background.py +0 -0
  170. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/run_command.py +0 -0
  171. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/run_command_windows.py +0 -0
  172. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/session_manager.py +0 -0
  173. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/session_storage.py +0 -0
  174. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/streaming_command.py +0 -0
  175. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/uvx.py +0 -0
  176. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/uvx_background.py +0 -0
  177. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/uvx_tool.py +0 -0
  178. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/shell/zsh_tool.py +0 -0
  179. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/todo/__init__.py +0 -0
  180. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/todo/base.py +0 -0
  181. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/todo/todo.py +0 -0
  182. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/todo/todo_read.py +0 -0
  183. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/todo/todo_write.py +0 -0
  184. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/__init__.py +0 -0
  185. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/ast_analyzer.py +0 -0
  186. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/git_ingester.py +0 -0
  187. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/index_tool.py +0 -0
  188. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/infinity_store.py +0 -0
  189. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/mock_infinity.py +0 -0
  190. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/project_manager.py +0 -0
  191. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/vector.py +0 -0
  192. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/vector_index.py +0 -0
  193. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/tools/vector/vector_search.py +0 -0
  194. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp/types.py +0 -0
  195. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/dependency_links.txt +0 -0
  196. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/entry_points.txt +0 -0
  197. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/requires.txt +0 -0
  198. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/hanzo_mcp.egg-info/top_level.txt +0 -0
  199. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/setup.cfg +0 -0
  200. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_agent_tools_ci.py +0 -0
  201. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_async_support.py +0 -0
  202. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_batch_tool_edge_cases.py +0 -0
  203. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_cli.py +0 -0
  204. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_cli_agents_consolidated.py +0 -0
  205. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_cli_tools.py +0 -0
  206. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_e2e_demo.py +0 -0
  207. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_e2e_simple.py +0 -0
  208. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_failure_cases.py +0 -0
  209. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_find_tool_ffind.py +0 -0
  210. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_find_tool_integration.py +0 -0
  211. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_find_tool_registration.py +0 -0
  212. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_git_ingestion.py +0 -0
  213. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_hanzo_agents_integration.py +0 -0
  214. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_hanzo_mcp_integration.py +0 -0
  215. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_hanzo_mcp_local.py +0 -0
  216. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_hanzo_mcp_simple.py +0 -0
  217. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_hanzo_network_integration.py +0 -0
  218. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_litellm_warnings.py +0 -0
  219. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_lsp_tool.py +0 -0
  220. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_manual.py +0 -0
  221. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_memory_base.py +0 -0
  222. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_memory_basic.py +0 -0
  223. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_memory_consolidated.py +0 -0
  224. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_memory_simple.py +0 -0
  225. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_memory_utils.py +0 -0
  226. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_new_tools.py +0 -0
  227. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_performance.py +0 -0
  228. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_search.py +0 -0
  229. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_search_quality.py +0 -0
  230. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_shell_features.py +0 -0
  231. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_shell_tools.py +0 -0
  232. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_simple.py +0 -0
  233. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_stdio_protocol.py +0 -0
  234. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_stdio_simple.py +0 -0
  235. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_streaming_command.py +0 -0
  236. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_swarm_simple.py +0 -0
  237. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_tools_suite.py +0 -0
  238. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_unified_search.py +0 -0
  239. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_utils.py +0 -0
  240. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_vector_store.py +0 -0
  241. {hanzo_mcp-0.8.5 → hanzo_mcp-0.8.7}/tests/test_web3_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.8.5
3
+ Version: 0.8.7
4
4
  Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
@@ -64,7 +64,16 @@ try: # pragma: no cover
64
64
  register_memory_tools = None # type: ignore
65
65
  except Exception:
66
66
  # Minimal surface to allow submodule imports elsewhere
67
- pass
67
+ # Define stub functions for required imports
68
+ def activate_mode_from_env():
69
+ pass
70
+ class ModeLoader:
71
+ @staticmethod
72
+ def get_enabled_tools_from_mode(base_enabled_tools=None, force_mode=None):
73
+ return base_enabled_tools or {}
74
+ @staticmethod
75
+ def apply_environment_from_mode():
76
+ pass
68
77
 
69
78
  # Try to import LSP tool
70
79
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.8.5
3
+ Version: 0.8.7
4
4
  Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
@@ -221,6 +221,7 @@ tests/test_memory_consolidated.py
221
221
  tests/test_memory_simple.py
222
222
  tests/test_memory_utils.py
223
223
  tests/test_new_tools.py
224
+ tests/test_no_stubs.py
224
225
  tests/test_performance.py
225
226
  tests/test_search.py
226
227
  tests/test_search_quality.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hanzo-mcp"
7
- version = "0.8.5"
7
+ version = "0.8.7"
8
8
  description = "The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -0,0 +1,288 @@
1
+ """Test to ensure no stub/fake/incomplete code exists in production."""
2
+
3
+ import ast
4
+ import os
5
+ import re
6
+ from pathlib import Path
7
+ from typing import List, Tuple
8
+
9
+ import pytest
10
+
11
+
12
+ class StubDetector(ast.NodeVisitor):
13
+ """AST visitor to detect stub implementations."""
14
+
15
+ def __init__(self, filepath: str):
16
+ self.filepath = filepath
17
+ self.issues: List[Tuple[int, str]] = []
18
+ self.in_test_file = 'test' in filepath or 'mock' in filepath.lower()
19
+
20
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
21
+ """Check function definitions for stub patterns."""
22
+ # Skip test files for certain checks
23
+ if self.in_test_file and node.name.startswith('test_'):
24
+ self.generic_visit(node)
25
+ return
26
+
27
+ # Check for empty functions with just pass
28
+ if len(node.body) == 1 and isinstance(node.body[0], ast.Pass):
29
+ # Check if there's a comment indicating it's a stub
30
+ if node.body[0].lineno:
31
+ self.issues.append((
32
+ node.lineno,
33
+ f"Function '{node.name}' contains only 'pass' statement"
34
+ ))
35
+
36
+ # Check for functions that just raise NotImplementedError
37
+ if len(node.body) == 1 and isinstance(node.body[0], ast.Raise):
38
+ if isinstance(node.body[0].exc, ast.Call):
39
+ if (hasattr(node.body[0].exc.func, 'id') and
40
+ node.body[0].exc.func.id == 'NotImplementedError'):
41
+ self.issues.append((
42
+ node.lineno,
43
+ f"Function '{node.name}' raises NotImplementedError"
44
+ ))
45
+
46
+ # Check for functions with only ellipsis
47
+ if len(node.body) == 1 and isinstance(node.body[0], ast.Expr):
48
+ if isinstance(node.body[0].value, ast.Constant):
49
+ if node.body[0].value.value is Ellipsis:
50
+ self.issues.append((
51
+ node.lineno,
52
+ f"Function '{node.name}' contains only ellipsis"
53
+ ))
54
+
55
+ self.generic_visit(node)
56
+
57
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
58
+ """Check async function definitions."""
59
+ # Treat async functions same as regular functions
60
+ self.visit_FunctionDef(node)
61
+
62
+
63
+ def find_stub_patterns(filepath: Path) -> List[Tuple[int, str, str]]:
64
+ """Find stub patterns in a Python file."""
65
+ issues = []
66
+
67
+ # Skip test files for most checks
68
+ is_test_file = 'test' in filepath.name or 'mock' in filepath.name.lower()
69
+
70
+ try:
71
+ content = filepath.read_text(encoding='utf-8')
72
+ except Exception:
73
+ return issues
74
+
75
+ # Regex patterns to find stub indicators
76
+ patterns = [
77
+ (r'#\s*(TODO|FIXME|STUB|FAKE|UNFINISHED|HACK|XXX)\s*:?', 'contains {0} comment'),
78
+ (r'raise\s+NotImplementedError', 'raises NotImplementedError'),
79
+ (r'assert\s+False,?\s*["\']Not implemented', 'has "Not implemented" assertion'),
80
+ ]
81
+
82
+ # Additional patterns for non-test files
83
+ if not is_test_file:
84
+ patterns.extend([
85
+ (r'pass\s*#\s*(stub|todo|fake)', 'has stub/todo/fake comment after pass'),
86
+ (r'return\s+["\']TODO', 'returns TODO string'),
87
+ (r'return\s+["\']STUB', 'returns STUB string'),
88
+ (r'return\s+None\s*#\s*(TODO|STUB|FAKE)', 'returns None with stub comment'),
89
+ ])
90
+
91
+ lines = content.split('\n')
92
+ for line_num, line in enumerate(lines, 1):
93
+ for pattern, message in patterns:
94
+ if match := re.search(pattern, line, re.IGNORECASE):
95
+ keyword = match.group(1) if match.groups() else 'stub pattern'
96
+ issues.append((
97
+ line_num,
98
+ message.format(keyword),
99
+ filepath.name
100
+ ))
101
+
102
+ # Parse AST for deeper inspection
103
+ try:
104
+ tree = ast.parse(content)
105
+ detector = StubDetector(str(filepath))
106
+ detector.visit(tree)
107
+ for line_num, message in detector.issues:
108
+ issues.append((line_num, message, filepath.name))
109
+ except SyntaxError:
110
+ pass # Ignore files with syntax errors
111
+
112
+ return issues
113
+
114
+
115
+ def get_python_files(root_dir: Path, exclude_dirs: set = None) -> List[Path]:
116
+ """Get all Python files in directory, excluding certain directories."""
117
+ if exclude_dirs is None:
118
+ exclude_dirs = {
119
+ '__pycache__', '.git', '.tox', '.pytest_cache',
120
+ 'build', 'dist', '*.egg-info', '.venv', 'venv',
121
+ 'node_modules', '.mypy_cache'
122
+ }
123
+
124
+ python_files = []
125
+ for path in root_dir.rglob('*.py'):
126
+ # Skip excluded directories
127
+ if any(excluded in path.parts for excluded in exclude_dirs):
128
+ continue
129
+ python_files.append(path)
130
+
131
+ return python_files
132
+
133
+
134
+ class TestNoStubs:
135
+ """Test suite to ensure no stub implementations exist."""
136
+
137
+ def test_no_stub_functions_in_source(self):
138
+ """Ensure no stub functions exist in source code."""
139
+ # Get the package root
140
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp'
141
+
142
+ if not package_root.exists():
143
+ pytest.skip(f"Package root {package_root} does not exist")
144
+
145
+ all_issues = []
146
+ python_files = get_python_files(package_root)
147
+
148
+ for filepath in python_files:
149
+ issues = find_stub_patterns(filepath)
150
+ for line_num, message, filename in issues:
151
+ all_issues.append(
152
+ f"{filepath.relative_to(package_root.parent)}:{line_num} - {message}"
153
+ )
154
+
155
+ if all_issues:
156
+ report = "\n".join(all_issues)
157
+ pytest.fail(
158
+ f"Found {len(all_issues)} stub/incomplete implementations:\n{report}"
159
+ )
160
+
161
+ def test_critical_functions_implemented(self):
162
+ """Ensure critical functions are actually implemented."""
163
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp'
164
+
165
+ # Critical modules and functions that must be implemented
166
+ critical_checks = [
167
+ ('tools/__init__.py', 'register_all_tools'),
168
+ ('server.py', '__init__'),
169
+ ('server.py', 'run'),
170
+ ('cli.py', 'main'),
171
+ ]
172
+
173
+ for module_path, function_name in critical_checks:
174
+ filepath = package_root / module_path
175
+ if not filepath.exists():
176
+ pytest.fail(f"Critical module {module_path} does not exist")
177
+
178
+ content = filepath.read_text()
179
+ # Check function exists and has more than just pass/raise
180
+ pattern = rf'def {function_name}\([^)]*\):[^:]*\n(?:\s+"""[^"]*"""\n)?(\s+.+)'
181
+ match = re.search(pattern, content, re.MULTILINE)
182
+
183
+ if not match:
184
+ pytest.fail(f"Function {function_name} not found in {module_path}")
185
+
186
+ function_body = match.group(1).strip()
187
+ if function_body in ['pass', 'raise NotImplementedError', 'raise NotImplementedError()', '...']:
188
+ pytest.fail(f"Function {function_name} in {module_path} is not implemented")
189
+
190
+ def test_no_pytest_skip_in_non_test_files(self):
191
+ """Ensure pytest.skip is only used in test files."""
192
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp'
193
+
194
+ for filepath in get_python_files(package_root):
195
+ # Skip test directories
196
+ if 'test' in str(filepath):
197
+ continue
198
+
199
+ content = filepath.read_text()
200
+ if 'pytest.skip' in content or '@pytest.mark.skip' in content:
201
+ pytest.fail(f"Found pytest.skip in non-test file: {filepath}")
202
+
203
+ def test_no_mock_implementations_in_production(self):
204
+ """Ensure no mock implementations exist in production code."""
205
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp'
206
+
207
+ for filepath in get_python_files(package_root):
208
+ # Skip test directories and legitimate mock modules
209
+ if 'test' in str(filepath) or 'mock' in filepath.name:
210
+ continue
211
+
212
+ content = filepath.read_text()
213
+
214
+ # Check for mock-related imports in production code
215
+ mock_patterns = [
216
+ r'from unittest\.mock import',
217
+ r'import unittest\.mock',
218
+ r'class Mock',
219
+ r'class Fake',
220
+ r'def fake_',
221
+ r'def mock_',
222
+ r'return\s+["\']fake',
223
+ r'return\s+["\']mock',
224
+ ]
225
+
226
+ for pattern in mock_patterns:
227
+ if re.search(pattern, content, re.IGNORECASE):
228
+ pytest.fail(
229
+ f"Found mock/fake pattern '{pattern}' in production file: {filepath}"
230
+ )
231
+
232
+ def test_all_tool_classes_have_run_method(self):
233
+ """Ensure all tool classes have a proper run method."""
234
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp' / 'tools'
235
+
236
+ if not package_root.exists():
237
+ pytest.skip("Tools directory does not exist")
238
+
239
+ for filepath in get_python_files(package_root):
240
+ if 'test' in str(filepath) or '__pycache__' in str(filepath):
241
+ continue
242
+
243
+ content = filepath.read_text()
244
+
245
+ # Find all class definitions that inherit from BaseTool or end with Tool
246
+ class_pattern = r'class\s+(\w*Tool\w*)\s*\([^)]*\):'
247
+ classes = re.findall(class_pattern, content)
248
+
249
+ for class_name in classes:
250
+ # Check if class has a run method
251
+ run_pattern = rf'class\s+{class_name}.*?def\s+run\s*\([^)]*\):'
252
+ if not re.search(run_pattern, content, re.DOTALL):
253
+ # Check if it's an abstract base class
254
+ if 'Base' not in class_name and 'Abstract' not in class_name:
255
+ pytest.fail(
256
+ f"Tool class {class_name} in {filepath.name} missing run() method"
257
+ )
258
+
259
+ def test_no_debug_prints_in_production(self):
260
+ """Ensure no debug print statements in production code."""
261
+ package_root = Path(__file__).parent.parent / 'hanzo_mcp'
262
+
263
+ for filepath in get_python_files(package_root):
264
+ # Skip test files
265
+ if 'test' in str(filepath):
266
+ continue
267
+
268
+ content = filepath.read_text()
269
+
270
+ # Check for debug patterns
271
+ debug_patterns = [
272
+ (r'print\s*\([^)]*#\s*DEBUG', 'debug print statement'),
273
+ (r'print\s*\([^)]*#\s*TODO', 'TODO print statement'),
274
+ (r'print\s*\([^)]*#\s*REMOVE', 'REMOVE print statement'),
275
+ (r'console\.log', 'console.log statement'),
276
+ (r'debugger;?', 'debugger statement'),
277
+ ]
278
+
279
+ for pattern, description in debug_patterns:
280
+ if re.search(pattern, content, re.IGNORECASE):
281
+ pytest.fail(
282
+ f"Found {description} in production file: {filepath}"
283
+ )
284
+
285
+
286
+ if __name__ == '__main__':
287
+ # Run tests directly
288
+ pytest.main([__file__, '-v'])
File without changes
File without changes
File without changes
File without changes