meshcode 2.11.37__tar.gz → 2.11.38__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 (231) hide show
  1. {meshcode-2.11.37 → meshcode-2.11.38}/PKG-INFO +1 -1
  2. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/server.py +77 -154
  4. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.11.37 → meshcode-2.11.38}/pyproject.toml +1 -1
  6. {meshcode-2.11.37 → meshcode-2.11.38}/README.md +0 -0
  7. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/__main__.py +0 -0
  8. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/_stop_hook_template.py +0 -0
  9. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/ascii_art.py +0 -0
  10. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/atomic_push.py +0 -0
  11. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/cli.py +0 -0
  12. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/comms_v4.py +0 -0
  13. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/compat.py +0 -0
  14. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/daemon.py +0 -0
  15. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/date_parse.py +0 -0
  16. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/doctor.py +0 -0
  17. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/error_hints.py +0 -0
  18. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/exceptions.py +0 -0
  19. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/invites.py +0 -0
  20. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/launcher.py +0 -0
  21. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/launcher_install.py +0 -0
  22. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/__init__.py +0 -0
  23. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/__main__.py +0 -0
  24. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/backend.py +0 -0
  25. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/realtime.py +0 -0
  26. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  27. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_backend.py +0 -0
  28. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  29. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  30. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  31. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  32. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  33. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/preferences.py +0 -0
  34. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/protocol_handler.py +0 -0
  35. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/protocol_v2.py +0 -0
  36. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/quickstart.py +0 -0
  37. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/rpc_allowlist.py +0 -0
  38. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/run_agent.py +0 -0
  39. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/scripts/check_secrets.py +0 -0
  40. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/scripts/race_rate_harness.py +0 -0
  41. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/secrets.py +0 -0
  42. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/self_update.py +0 -0
  43. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/setup_clients.py +0 -0
  44. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/supervisor.py +0 -0
  45. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/upload.py +0 -0
  46. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/comms_v4.py +0 -0
  47. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  48. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  49. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/cli.py +0 -0
  50. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  51. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/compat.py +0 -0
  52. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  53. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  54. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/invites.py +0 -0
  55. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  56. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  57. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  58. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  59. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  60. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  61. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  62. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  63. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  64. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  65. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  66. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  67. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  68. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  69. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  70. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  71. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  72. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  73. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/upload.py +0 -0
  74. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  75. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_core.py +0 -0
  76. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  77. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  78. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  79. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  80. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  81. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  82. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  83. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  84. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  85. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  86. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  87. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  88. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  89. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  90. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  91. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  92. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  93. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  94. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  95. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  96. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  97. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  98. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  99. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  100. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  101. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  102. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  103. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  104. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  105. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  106. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  107. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  108. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  109. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  110. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  111. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  112. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  113. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  114. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/comms_v4.py +0 -0
  115. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  116. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  117. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/cli.py +0 -0
  118. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  119. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/compat.py +0 -0
  120. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  121. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  122. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/invites.py +0 -0
  123. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  124. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  125. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  126. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  127. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  128. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  129. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  130. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  131. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  132. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  133. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  134. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  135. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  136. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  137. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  138. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  139. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  140. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  141. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/upload.py +0 -0
  142. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  143. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_core.py +0 -0
  144. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  145. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  146. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  147. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  148. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  149. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  150. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  151. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  152. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  153. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  154. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  155. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/comms_v4.py +0 -0
  156. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  157. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  158. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  159. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  160. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  161. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  162. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  163. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  164. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  165. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  166. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  167. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  168. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  169. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  170. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  171. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  172. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  173. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  174. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  175. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  176. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  177. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  178. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  179. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  180. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  181. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  182. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  183. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  184. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_core.py +0 -0
  185. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  186. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  187. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  188. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  189. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  190. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  191. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  192. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  193. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  194. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  195. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  196. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/SOURCES.txt +0 -0
  197. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/dependency_links.txt +0 -0
  198. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/entry_points.txt +0 -0
  199. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/requires.txt +0 -0
  200. {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/top_level.txt +0 -0
  201. {meshcode-2.11.37 → meshcode-2.11.38}/setup.cfg +0 -0
  202. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_auto_update_hardening.py +0 -0
  203. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_boot_bug_regression.py +0 -0
  204. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_color_truecolor.py +0 -0
  205. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_core.py +0 -0
  206. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_cross_agent_messaging.py +0 -0
  207. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_date_parse.py +0 -0
  208. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_doctor.py +0 -0
  209. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_epistemic_v1_python_sdk.py +0 -0
  210. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  211. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_esc_deaf_state.py +0 -0
  212. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_exceptions.py +0 -0
  213. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_init_device_code.py +0 -0
  214. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_install_guard.py +0 -0
  215. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_lease_sigterm_release.py +0 -0
  216. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_mark_read_batch.py +0 -0
  217. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_migration_integrity.py +0 -0
  218. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_realtime_event_freshness.py +0 -0
  219. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rls_cross_tenant.py +0 -0
  220. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rpc_grants.py +0 -0
  221. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rpc_migrations.py +0 -0
  222. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_run_agent_dry_run.py +0 -0
  223. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_run_agent_no_server_import.py +0 -0
  224. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_security_regressions.py +0 -0
  225. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_self_update_user_site.py +0 -0
  226. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_sentinel.py +0 -0
  227. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_setup_path.py +0 -0
  228. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_sleep_signals.py +0 -0
  229. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_status_enum_coverage.py +0 -0
  230. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_stay_on_loop_hook.py +0 -0
  231. {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_wait_open_tasks_contradiction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.37
3
+ Version: 2.11.38
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.11.37"
2
+ __version__ = "2.11.38"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -227,18 +227,18 @@ def _kill_stale_mcp_process() -> None:
227
227
  _force_clear_lease_by_name(reason="legacy-lockfile-orphan")
228
228
  return
229
229
  _mc_log(f"Killing stale MCP process (PID {old_pid})")
230
- # 2026-05-21 (Samuel directive RCA): the dying MCP server installs
231
- # _diag_ignore for SIGTERM to keep the channel alive during tool
232
- # cancellation (see run_server). SIGTERM is therefore always ignored
233
- # by stale meshcode servers — sending it + sleeping 1s before SIGKILL
234
- # was pure dead weight on the lifespan pre-yield critical path. Going
235
- # straight to SIGKILL saves ~1s on every cold boot where a stale
236
- # process exists. SIGKILL is uncatchable, so the kill is instant.
237
230
  try:
231
+ os.kill(old_pid, _signal.SIGTERM)
232
+ except OSError:
233
+ pass
234
+ import time
235
+ time.sleep(1)
236
+ try:
237
+ os.kill(old_pid, 0)
238
238
  os.kill(old_pid, _signal.SIGKILL)
239
239
  _mc_log(f"Force-killed stale MCP process (PID {old_pid})")
240
240
  except OSError:
241
- pass # already dead race with previous process's own shutdown
241
+ pass # already dead after SIGTERM (rare handler ignores it)
242
242
  if old_instance_id:
243
243
  _release_lease_for_instance(old_instance_id, reason="post-sigkill")
244
244
  else:
@@ -1646,6 +1646,8 @@ def _build_instructions() -> str:
1646
1646
 
1647
1647
  RULES: MCP tools only. Tasks > messages. Messages <100 tokens (long → task). No empty acks, JSON only. Thread via in_reply_to. sensitive=True for secrets. Sync vs async: for turn-based/shared-state work (chess, lock-step, "who goes first"), use meshcode_call (sync RPC, 30s) — async meshcode_send crosses ~50%/turn between same-model agents and yields-pongs.
1648
1648
 
1649
+ CLOSE TASKS IMMEDIATELY (#2 rule, sammybenu 2026-05-22T21:06Z): every time you finish/ship/deliver work for a claimed task, call meshcode_task_complete BEFORE re-entering wait. NO "I'll close it after one more thing." NO leaving claimed tasks lingering in_progress while you do something else — that creates phantom in-progress on the dashboard and the human gets angry. If the work needs human review, set requires_approval=true at task_create OR call meshcode_task_complete (it routes to in_review if reviewer set). The mesh dashboard reflects mc_tasks.status in real-time; stale in_progress = lying to the human.
1650
+
1649
1651
  SESSION START (run NOW, don't wait for input). If tool schemas are deferred:
1650
1652
  ToolSearch(query="select:meshcode_set_status,meshcode_check,meshcode_tasks,meshcode_auto_wake,meshcode_status,meshcode_wait,meshcode_send,meshcode_call,meshcode_claim,meshcode_task_claim,meshcode_task_complete,meshcode_remember,meshcode_recall")
1651
1653
  Then: set_status(online,ready) → check() → tasks() → auto_wake() → status() → wait(). Don't ask user "what to work on" — the mesh tells you.
@@ -2835,36 +2837,10 @@ def meshcode_send(to: Union[str, List[str]], message: Any, in_reply_to: Optional
2835
2837
  result["encrypted"] = True
2836
2838
  return result
2837
2839
 
2838
- _result = be.send_message(_PROJECT_ID, AGENT_NAME, to, payload,
2839
- msg_type=type or "msg",
2840
- parent_msg_id=in_reply_to, sensitive=sensitive,
2841
- api_key=_get_api_key(), encrypted=encrypted)
2842
-
2843
- # C2 (BACKEND-AUDIT-TASK-FRICTION F4, 2026-05-22): detect payloads that
2844
- # look like the agent is trying to "claim" a task via a status message
2845
- # instead of calling meshcode_task_claim. The status_msg path does NOT
2846
- # update mc_tasks.claimed_by → task sits open while the agent believes
2847
- # it's working it. Soft hint, never refuse.
2848
- try:
2849
- if isinstance(_result, dict) and _result.get("sent"):
2850
- _ptype = str(payload.get("type", "")).lower()
2851
- _ptext = str(payload.get("text", "")).lower()
2852
- _has_task_ref = any(k in payload for k in ("task", "task_id"))
2853
- _looks_like_claim = (
2854
- _ptype in {"claim", "claim_status", "status_claim"}
2855
- or ("claim" in _ptext and _has_task_ref)
2856
- or (_ptype.startswith("status") and "claim" in _ptext)
2857
- )
2858
- if _looks_like_claim:
2859
- _result["hint"] = (
2860
- "claim_via_status_msg_does_not_update_task_table — "
2861
- "call meshcode_task_claim(<task_id>) for the actual "
2862
- "claim. status_msg is fine as a peer notification "
2863
- "but is not the system-of-record."
2864
- )
2865
- except Exception:
2866
- pass
2867
- return _result
2840
+ return be.send_message(_PROJECT_ID, AGENT_NAME, to, payload,
2841
+ msg_type=type or "msg",
2842
+ parent_msg_id=in_reply_to, sensitive=sensitive,
2843
+ api_key=_get_api_key(), encrypted=encrypted)
2868
2844
 
2869
2845
 
2870
2846
  @mcp.tool()
@@ -3262,14 +3238,6 @@ _AUTO_SLEEP_THRESHOLD = int(os.environ.get("MESHCODE_AUTO_SLEEP_SECONDS", "600")
3262
3238
  _STAY_AWAKE = False # Set by meshcode_set_status("online") — prevents auto-sleep
3263
3239
  _LAST_SEEN_TS: Optional[str] = None # auto-persisted for message dedup
3264
3240
 
3265
- # M2 (SUPABASE-PROD-QUOTA-CRITICAL 2026-05-22): when an agent has been idle
3266
- # longer than _M2_IDLE_THRESHOLD seconds, skip the per-tick mc_tasks poll on
3267
- # (n-1)/n of timeouts — effective task-poll rate drops 1/N. Cuts mc_tasks
3268
- # RPC volume which accounted for ~26.95M cumulative calls in the audit.
3269
- _M2_IDLE_THRESHOLD = int(os.environ.get("MESHCODE_WAIT_IDLE_TASK_POLL_SKIP", "300")) # secs
3270
- _M2_POLL_EVERY_N = int(os.environ.get("MESHCODE_WAIT_IDLE_POLL_EVERY_N", "3"))
3271
- _M2_TICK_COUNTER = 0
3272
-
3273
3241
  # Hydrate _LAST_SEEN_TS from mesh memory on boot so restarts skip old messages
3274
3242
  try:
3275
3243
  _ls_result = be.sb_rpc("mc_memory_get", {
@@ -3333,83 +3301,6 @@ def _get_pending_tasks_summary() -> Optional[List[Dict[str, str]]]:
3333
3301
  return None
3334
3302
 
3335
3303
 
3336
- def _check_task_dedupe(title: str, assignee: str) -> Optional[Dict[str, Any]]:
3337
- """Find an open/in_progress task with similar title + same assignee.
3338
-
3339
- Samuel directive 2026-05-21T23:41Z (`commander_dedupe_before_task_from_status_msg`):
3340
- commanders kept creating duplicate tasks when reacting to status msgs from
3341
- agents that had already claimed/shipped the same work. The 5ac1d9fe /
3342
- dd41054d MOBILE-FIRST-3/4 dupes sat OPEN since 2026-05-20 because nobody
3343
- deduped before creating new ones. Server-side soft guard surfaces a
3344
- `dedupe_warning` in task_create responses when a likely duplicate
3345
- exists — non-blocking, so legitimate near-titles still create, but the
3346
- commander sees the dupe candidate and can cancel + reuse instead.
3347
- """
3348
- try:
3349
- api_key = _get_api_key()
3350
- if not api_key:
3351
- return None
3352
- result = be.task_list(api_key, _PROJECT_ID, AGENT_NAME, status_filter=None)
3353
- if not isinstance(result, dict) or not result.get("ok"):
3354
- return None
3355
- tasks = result.get("tasks", [])
3356
- target = (title or "").strip().lower()
3357
- if not target:
3358
- return None
3359
- target_prefix = target[:40]
3360
- for t in tasks:
3361
- if t.get("status") not in ("open", "in_progress"):
3362
- continue
3363
- if t.get("assignee") != assignee:
3364
- continue
3365
- t_title = (t.get("title") or "").strip().lower()
3366
- if not t_title:
3367
- continue
3368
- t_prefix = t_title[:40]
3369
- match = None
3370
- if t_prefix == target_prefix:
3371
- match = "prefix-40"
3372
- elif target in t_title or t_title in target:
3373
- match = "substring"
3374
- if match:
3375
- return {
3376
- "dupe_task_id": t.get("id"),
3377
- "dupe_title": t.get("title"),
3378
- "dupe_status": t.get("status"),
3379
- "match_type": match,
3380
- }
3381
- except Exception:
3382
- pass
3383
- return None
3384
-
3385
-
3386
- def _attach_pending_tasks_to_resp(resp: Dict[str, Any]) -> Dict[str, Any]:
3387
- """Surface this agent's open/in_progress assigned tasks on EVERY wait response.
3388
-
3389
- Samuel directive 2026-05-21T23:54Z: agents must always advance open tasks.
3390
- Previously `pending_tasks` only appeared in the timeout branch; when
3391
- messages kept arriving the agent ping-ponged replies and never saw the
3392
- hint, so tasks piled up. Now: every wait response (refused-by-messages,
3393
- got_message, timeout) carries pending_tasks + pending_directive when
3394
- this agent has open work. The agent's instruction prompt treats the
3395
- directive as priority-1 over optional message replies.
3396
- """
3397
- try:
3398
- pending = _get_pending_tasks_summary()
3399
- if pending and isinstance(resp, dict):
3400
- resp["pending_tasks"] = pending
3401
- resp["pending_tasks_count"] = len(pending)
3402
- titles = ", ".join(t.get("title", "")[:40] for t in pending[:3])
3403
- resp["pending_directive"] = (
3404
- f"You have {len(pending)} open task(s) assigned. Advance at least one "
3405
- f"(claim / progress / complete) BEFORE processing optional messages or "
3406
- f"re-entering wait. Tasks: {titles}"
3407
- )
3408
- except Exception:
3409
- pass
3410
- return resp
3411
-
3412
-
3413
3304
  def _try_auto_claim_task() -> Optional[Dict[str, str]]:
3414
3305
  """Auto-claim the oldest open task matching this agent's role.
3415
3306
 
@@ -3451,6 +3342,53 @@ def _try_auto_claim_task() -> Optional[Dict[str, str]]:
3451
3342
  return None
3452
3343
 
3453
3344
 
3345
+ # AGENT-INTEL-1-PY (task 38b1a0e2): mesh_online_snapshot in wait return.
3346
+ # Calls mc_roster_live (mig 348) and projects a compact list of live+idle
3347
+ # agents for the receiving agent's situational awareness. Cached 10s so
3348
+ # the common case (rapid wait cycles) doesn't hammer the roster RPC.
3349
+ _LAST_ROSTER_SNAPSHOT: Optional[List[Dict[str, Any]]] = None
3350
+ _LAST_ROSTER_SNAPSHOT_TS: float = 0.0
3351
+
3352
+
3353
+ def _get_mesh_online_snapshot(max_age_s: float = 10.0) -> Optional[List[Dict[str, Any]]]:
3354
+ global _LAST_ROSTER_SNAPSHOT, _LAST_ROSTER_SNAPSHOT_TS
3355
+ now_ts = _time.monotonic()
3356
+ if _LAST_ROSTER_SNAPSHOT is not None and (now_ts - _LAST_ROSTER_SNAPSHOT_TS) < max_age_s:
3357
+ return _LAST_ROSTER_SNAPSHOT
3358
+ try:
3359
+ api_key = _get_api_key()
3360
+ if not api_key:
3361
+ return None
3362
+ roster = be.sb_rpc("mc_roster_live", {
3363
+ "p_api_key": api_key,
3364
+ "p_project_id": _PROJECT_ID,
3365
+ })
3366
+ if not isinstance(roster, dict) or not roster.get("ok"):
3367
+ return None
3368
+ by_lane = (roster.get("roster") or {}).get("by_lane") or {}
3369
+ out: List[Dict[str, Any]] = []
3370
+ for lane, bucket in by_lane.items():
3371
+ if not isinstance(bucket, dict):
3372
+ continue
3373
+ for liveness in ("live", "idle"):
3374
+ for a in bucket.get(liveness) or []:
3375
+ if not isinstance(a, dict):
3376
+ continue
3377
+ out.append({
3378
+ "name": a.get("name"),
3379
+ "status": a.get("status"),
3380
+ "lane": lane,
3381
+ "last_heartbeat_age_s": a.get("hb_age_s"),
3382
+ })
3383
+ out.sort(key=lambda x: (x.get("lane") or "", x.get("name") or ""))
3384
+ _LAST_ROSTER_SNAPSHOT = out
3385
+ _LAST_ROSTER_SNAPSHOT_TS = now_ts
3386
+ return out
3387
+ except Exception as e:
3388
+ log.debug(f"[meshcode] mesh_online_snapshot fetch failed: {e}")
3389
+ return None
3390
+
3391
+
3454
3392
  @mcp.tool()
3455
3393
  @with_working_status
3456
3394
  async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -> Dict[str, Any]:
@@ -3516,7 +3454,12 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
3516
3454
  if split["done_signals"]:
3517
3455
  resp["must_exit"] = True
3518
3456
  resp["exit_reason"] = "sleep authorization received — set status=sleeping and end session"
3519
- return _attach_pending_tasks_to_resp(resp)
3457
+ # AGENT-INTEL-1-PY: snapshot on refused-path too.
3458
+ if os.environ.get("MESHCODE_WAIT_NO_SNAPSHOT", "").lower() not in ("1", "true", "yes"):
3459
+ _snap = _get_mesh_online_snapshot()
3460
+ if _snap is not None:
3461
+ resp["mesh_online_snapshot"] = _snap
3462
+ return resp
3520
3463
  # Ack-only batch — fall through to wait loop
3521
3464
  except Exception:
3522
3465
  pass
@@ -3549,16 +3492,8 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
3549
3492
  if result.get("timed_out"):
3550
3493
  _CONSECUTIVE_IDLE_SECONDS += capped_timeout
3551
3494
 
3552
- # M2 (2026-05-22): when idle >5min, poll mc_tasks every Nth
3553
- # tick instead of every tick. Active agents (recent msg)
3554
- # keep checking every tick.
3555
- global _M2_TICK_COUNTER
3556
- _check_tasks = True
3557
- if _CONSECUTIVE_IDLE_SECONDS >= _M2_IDLE_THRESHOLD and _M2_POLL_EVERY_N > 1:
3558
- _M2_TICK_COUNTER = (_M2_TICK_COUNTER + 1) % _M2_POLL_EVERY_N
3559
- _check_tasks = (_M2_TICK_COUNTER == 0)
3560
3495
  # Check if new tasks appeared while we waited
3561
- pending_tasks = _get_pending_tasks_summary() if _check_tasks else None
3496
+ pending_tasks = _get_pending_tasks_summary()
3562
3497
  if pending_tasks:
3563
3498
  result["pending_tasks"] = pending_tasks
3564
3499
  break # Return so agent can work tasks
@@ -3635,7 +3570,13 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
3635
3570
  result.setdefault("must_exit", True)
3636
3571
  result.setdefault("exit_reason",
3637
3572
  "sleep authorization received — set status=sleeping and end session")
3638
- return _attach_pending_tasks_to_resp(result) if isinstance(result, dict) else result
3573
+ # AGENT-INTEL-1-PY: attach mesh_online_snapshot for situational
3574
+ # awareness (cached 10s). Env opt-out: MESHCODE_WAIT_NO_SNAPSHOT=1.
3575
+ if isinstance(result, dict) and os.environ.get("MESHCODE_WAIT_NO_SNAPSHOT", "").lower() not in ("1", "true", "yes"):
3576
+ _snapshot = _get_mesh_online_snapshot()
3577
+ if _snapshot is not None:
3578
+ result["mesh_online_snapshot"] = _snapshot
3579
+ return result
3639
3580
  finally:
3640
3581
  _IN_WAIT = False
3641
3582
 
@@ -4073,18 +4014,13 @@ def meshcode_set_status(status: str, task: str = "") -> Dict[str, Any]:
4073
4014
  task: Optional human-readable task description.
4074
4015
  """
4075
4016
  global _STAY_AWAKE, _CONSECUTIVE_IDLE_SECONDS
4076
- # PRODUCT RULE: Cannot sleep/idle/standby with ANY open tasks (claimed
4077
- # or just assigned). Samuel directive 2026-05-22T01:01Z confirmed the
4078
- # strict rule is intentional — agents MUST work their assigned queue
4079
- # before sleeping. Reverting the 2026-05-22T00:55Z "claimed-only" relax
4080
- # (2.11.34) per Samuel's correction. The wake-cron is BACKUP for
4081
- # disconnected sessions, NOT a license to sleep on assignments.
4017
+ # PRODUCT RULE: Cannot sleep/idle/standby with open tasks. Work first.
4082
4018
  if status in ("sleeping", "idle", "standby"):
4083
4019
  pending_tasks = _get_pending_tasks_summary()
4084
4020
  if pending_tasks:
4085
4021
  return {
4086
4022
  "refused": True,
4087
- "reason": f"Cannot set status '{status}' — you have {len(pending_tasks)} open task(s) assigned or claimed. Work them first (claim → progress → complete) or task_reject to release.",
4023
+ "reason": f"Cannot set status '{status}' — you have {len(pending_tasks)} open tasks. Work them first.",
4088
4024
  "pending_tasks": pending_tasks,
4089
4025
  }
4090
4026
  # Setting online/working = stay awake (prevent auto-sleep)
@@ -4173,24 +4109,11 @@ def meshcode_task_create(title: str, description: str = "", assignee: Optional[s
4173
4109
  except Exception as _de:
4174
4110
  return {"error": f"due_parse_failed: {_de}"}
4175
4111
  api_key = _get_api_key()
4176
- # Soft dedupe guard (Samuel directive 2026-05-21): surface likely-duplicate
4177
- # open/in_progress task with same assignee + similar title. Non-blocking —
4178
- # caller still gets the new task_id, but sees `dedupe_warning` and can
4179
- # cancel + reuse the existing task instead of accumulating dupes.
4180
- dedupe_hit = _check_task_dedupe(title.strip(), assignee) if assignee != "auto" else None
4181
4112
  result = be.task_create(api_key, _PROJECT_ID, AGENT_NAME, title.strip(),
4182
4113
  description=description, assignee=assignee,
4183
4114
  priority=priority, parent_task_id=parent_task_id,
4184
4115
  due_at=parsed_due_at, due_label=parsed_due_label,
4185
4116
  depends_on=depends_on or None)
4186
- if isinstance(result, dict) and result.get("ok") and dedupe_hit:
4187
- result["dedupe_warning"] = (
4188
- f"Possible duplicate of task {dedupe_hit['dupe_task_id'][:8]} "
4189
- f"('{dedupe_hit['dupe_title'][:60]}', status={dedupe_hit['dupe_status']}, "
4190
- f"match={dedupe_hit['match_type']}). Consider canceling this new task "
4191
- f"and reusing the existing one."
4192
- )
4193
- result["dedupe_candidate"] = dedupe_hit
4194
4117
  # Auto-notify the resolved assignee so they wake from meshcode_wait.
4195
4118
  # Read result["assignee"] (server may have resolved 'auto' to a real name).
4196
4119
  if isinstance(result, dict) and result.get("ok"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.37
3
+ Version: 2.11.38
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.37"
7
+ version = "2.11.38"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes