meshcode 2.11.8__tar.gz → 2.11.9__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 (217) hide show
  1. {meshcode-2.11.8 → meshcode-2.11.9}/PKG-INFO +1 -1
  2. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/comms_v4.py +7 -2
  4. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/server.py +80 -32
  5. meshcode-2.11.9/meshcode/meshcode_mcp/test_install_guard.py +75 -0
  6. meshcode-2.11.9/meshcode/meshcode_mcp/test_prefs_claude_version.py +82 -0
  7. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/PKG-INFO +1 -1
  8. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/SOURCES.txt +2 -0
  9. {meshcode-2.11.8 → meshcode-2.11.9}/pyproject.toml +1 -1
  10. {meshcode-2.11.8 → meshcode-2.11.9}/README.md +0 -0
  11. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/_stop_hook_template.py +0 -0
  12. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/ascii_art.py +0 -0
  13. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/cli.py +0 -0
  14. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/compat.py +0 -0
  15. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/daemon.py +0 -0
  16. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/error_hints.py +0 -0
  17. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/exceptions.py +0 -0
  18. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/invites.py +0 -0
  19. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/launcher.py +0 -0
  20. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/launcher_install.py +0 -0
  21. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/__init__.py +0 -0
  22. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/__main__.py +0 -0
  23. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/backend.py +0 -0
  24. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/realtime.py +0 -0
  25. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  26. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/test_backend.py +0 -0
  27. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  28. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  29. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  30. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/preferences.py +0 -0
  31. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/protocol_handler.py +0 -0
  32. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/protocol_v2.py +0 -0
  33. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/quickstart.py +0 -0
  34. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/run_agent.py +0 -0
  35. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/scripts/check_secrets.py +0 -0
  36. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/scripts/race_rate_harness.py +0 -0
  37. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/secrets.py +0 -0
  38. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/self_update.py +0 -0
  39. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/setup_clients.py +0 -0
  40. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/supervisor.py +0 -0
  41. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode/upload.py +0 -0
  42. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/comms_v4.py +0 -0
  43. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  44. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  45. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/cli.py +0 -0
  46. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  47. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/compat.py +0 -0
  48. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  49. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  50. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/invites.py +0 -0
  51. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  52. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  53. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  54. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  55. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  56. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  57. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  58. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  59. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  60. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  61. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  62. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  63. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  64. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  65. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  66. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  67. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  68. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  69. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/meshcode/upload.py +0 -0
  70. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  71. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_core.py +0 -0
  72. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  73. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  74. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  75. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  76. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  77. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  78. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  79. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  80. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  81. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  82. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  83. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  84. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  85. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  86. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  87. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  88. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  89. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  90. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  91. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  92. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  93. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  94. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  95. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  96. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  97. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  98. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  99. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  100. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  101. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  102. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  103. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  104. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  105. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  106. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  107. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  108. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  109. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  110. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/comms_v4.py +0 -0
  111. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  112. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  113. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/cli.py +0 -0
  114. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  115. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/compat.py +0 -0
  116. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  117. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  118. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/invites.py +0 -0
  119. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  120. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  121. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  122. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  123. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  124. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  125. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  126. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  127. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  128. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  129. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  130. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  131. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  132. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  133. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  134. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  135. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  136. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  137. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/meshcode/upload.py +0 -0
  138. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  139. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_core.py +0 -0
  140. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  141. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  142. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  143. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  144. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  145. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  146. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  147. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  148. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  149. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  150. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  151. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/comms_v4.py +0 -0
  152. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  153. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  154. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  155. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  156. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  157. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  158. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  159. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  160. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  161. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  162. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  163. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  164. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  165. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  166. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  167. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  168. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  169. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  170. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  171. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  172. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  173. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  174. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  175. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  176. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  177. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  178. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  179. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  180. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_core.py +0 -0
  181. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  182. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  183. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  184. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  185. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  186. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  187. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  188. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  189. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  190. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  191. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  192. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/dependency_links.txt +0 -0
  193. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/entry_points.txt +0 -0
  194. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/requires.txt +0 -0
  195. {meshcode-2.11.8 → meshcode-2.11.9}/meshcode.egg-info/top_level.txt +0 -0
  196. {meshcode-2.11.8 → meshcode-2.11.9}/setup.cfg +0 -0
  197. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_auto_update_hardening.py +0 -0
  198. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_boot_bug_regression.py +0 -0
  199. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_core.py +0 -0
  200. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_cross_agent_messaging.py +0 -0
  201. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_epistemic_v1_python_sdk.py +0 -0
  202. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  203. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_esc_deaf_state.py +0 -0
  204. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_exceptions.py +0 -0
  205. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_install_guard.py +0 -0
  206. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_lease_sigterm_release.py +0 -0
  207. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_mark_read_batch.py +0 -0
  208. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_migration_integrity.py +0 -0
  209. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_realtime_event_freshness.py +0 -0
  210. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_rls_cross_tenant.py +0 -0
  211. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_rpc_migrations.py +0 -0
  212. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_security_regressions.py +0 -0
  213. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_sentinel.py +0 -0
  214. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_sleep_signals.py +0 -0
  215. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_status_enum_coverage.py +0 -0
  216. {meshcode-2.11.8 → meshcode-2.11.9}/tests/test_stay_on_loop_hook.py +0 -0
  217. {meshcode-2.11.8 → meshcode-2.11.9}/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.8
3
+ Version: 2.11.9
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.8"
2
+ __version__ = "2.11.9"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -3397,11 +3397,16 @@ if __name__ == "__main__":
3397
3397
  from meshcode.preferences import load_prefs, save_prefs
3398
3398
  if len(sys.argv) > 3:
3399
3399
  ver = sys.argv[3].strip()
3400
- if ver in ("reset", "unpin", "latest"):
3400
+ if ver in ("reset", "unpin"):
3401
3401
  prefs = load_prefs()
3402
3402
  prefs.pop("claude_version", None)
3403
3403
  save_prefs(prefs)
3404
- print("[meshcode] Claude Code version pin removed — will use installed version")
3404
+ print("[meshcode] Claude Code version pin removed — will use default ESC-safe pin")
3405
+ elif ver in ("latest", "none", "skip"):
3406
+ prefs = load_prefs()
3407
+ prefs["claude_version"] = ver
3408
+ save_prefs(prefs)
3409
+ print(f"[meshcode] Claude Code version pinning disabled ({ver}) — using installed version")
3405
3410
  else:
3406
3411
  prefs = load_prefs()
3407
3412
  prefs["claude_version"] = ver
@@ -1699,61 +1699,109 @@ def _snapshot_pkg_mtimes():
1699
1699
  _PKG_PY_MTIMES = _snapshot_pkg_mtimes()
1700
1700
  log.info(f"install-guard: snapshotted {len(_PKG_PY_MTIMES)} *.py mtimes under {_PKG_DIR}")
1701
1701
 
1702
+ _INSTALL_GUARD_MODE = os.environ.get("MESHCODE_INSTALL_GUARD", "warn").lower()
1703
+ if _INSTALL_GUARD_MODE not in ("execv", "warn", "off"):
1704
+ log.warning(f"MESHCODE_INSTALL_GUARD={_INSTALL_GUARD_MODE!r} invalid; falling back to 'warn'")
1705
+ _INSTALL_GUARD_MODE = "warn"
1706
+ _INSTALL_GUARD_STALE_NOTIFIED = False
1707
+
1708
+
1709
+ def _is_agent_active() -> bool:
1710
+ """True if agent should NOT be execv-restarted right now."""
1711
+ if os.environ.get("MESHCODE_AGENT_ACTIVE", "").lower() in ("1", "true", "yes"):
1712
+ return True
1713
+ if _IN_WAIT:
1714
+ return True
1715
+ try:
1716
+ if (_time.time() - _last_tool_at) < 300:
1717
+ return True
1718
+ except Exception:
1719
+ pass
1720
+ return False
1721
+
1702
1722
 
1703
1723
  def _install_guard_check() -> None:
1704
- """Heartbeat-tick scan: if any *.py under the meshcode pkg path has
1705
- a fresher mtime than recorded at boot, the env was reinstalled while
1706
- the process is alive (class feedback_pip_install_into_live_mcp_env_self_kill).
1707
- The running image holds stale bytecode; lockfile collision and
1708
- orphan-watchdog will eventually kill us anyway. Pre-empt: release the
1709
- lease and execv-restart so the new wheel is picked up cleanly.
1710
-
1711
- The MCP socket to Claude Code WILL drop during the exec window.
1712
- Stop_hook _mcp_disconnected_without_reconnect (mig 68a3545e) catches
1713
- it; user runs `meshcode go <agent>` to pick up the new wheel.
1714
-
1715
- Soft-fail throughout: any exception here is logged and swallowed so
1716
- the heartbeat thread isn't taken down by a flaky filesystem call.
1724
+ """Heartbeat-tick scan: detect mid-session pkg reinstall.
1725
+
1726
+ Modes (MESHCODE_INSTALL_GUARD env var):
1727
+ - 'warn' (default): log + one-shot boot_version_drift msg; never execv.
1728
+ New wheel picked up on next cold boot. Removes mid-session surprise drops
1729
+ (RC of task 0c4524af 2026-05-19: pip install over live 2.11.7 sessions
1730
+ triggered execv on both backend+commander hb tick, dropping MCP socket).
1731
+ - 'execv': legacy auto-restart. Deferred to warn-mode when agent is active
1732
+ (in_wait, recent tool call <5min, or MESHCODE_AGENT_ACTIVE=1).
1733
+ - 'off': skip scan entirely.
1734
+
1735
+ Soft-fail throughout.
1717
1736
  """
1718
- if not _PKG_PY_MTIMES:
1737
+ global _INSTALL_GUARD_STALE_NOTIFIED
1738
+ if _INSTALL_GUARD_MODE == "off" or not _PKG_PY_MTIMES:
1719
1739
  return
1720
1740
  try:
1741
+ stale_path = None
1742
+ old_m = new_m = 0.0
1721
1743
  for path, old_mtime in list(_PKG_PY_MTIMES.items()):
1722
1744
  try:
1723
1745
  new_mtime = os.path.getmtime(path)
1724
1746
  except OSError:
1725
1747
  continue
1726
- # 0.5s slack — covers fs-timestamp resolution and tar extract
1727
- # re-emit jitter without false-positive on intentional touch.
1728
1748
  if new_mtime <= old_mtime + 0.5:
1729
1749
  continue
1750
+ stale_path = path
1751
+ old_m, new_m = old_mtime, new_mtime
1752
+ break
1753
+ if not stale_path:
1754
+ return
1755
+ if _INSTALL_GUARD_MODE == "execv" and not _is_agent_active():
1730
1756
  log.warning(
1731
- f"install-guard: self-modification detected on {path} "
1732
- f"(mtime {old_mtime:.0f} {new_mtime:.0f}). The running "
1733
- f"image holds stale bytecode; triggering clean execv-restart "
1734
- f"so the new wheel is picked up. MCP socket will drop briefly "
1735
- f"— stop_hook handles the agent release (mig 68a3545e). User "
1736
- f"runs `meshcode go <agent>` to relaunch under the new image. "
1737
- f"Class: feedback_pip_install_into_live_mcp_env_self_kill."
1757
+ f"install-guard: self-modification on {stale_path} "
1758
+ f"(mtime {old_m:.0f} -> {new_m:.0f}). Mode=execv, agent inactive "
1759
+ f"-- execv-restart. MCP socket will drop; stop_hook handles release."
1738
1760
  )
1739
1761
  try:
1740
1762
  _release_lease_synchronous(timeout_s=1.5)
1741
1763
  except Exception:
1742
1764
  pass
1743
1765
  _heartbeat_stop.set()
1744
- # execv replaces the current process; daemon threads die with
1745
- # it; new process inherits stdio. We pass the original argv so
1746
- # the entry-point command line is preserved verbatim.
1747
1766
  try:
1748
1767
  os.execv(sys.executable, [sys.executable] + sys.argv)
1749
1768
  except Exception as _exec_err:
1750
- log.error(
1751
- f"install-guard execv failed ({_exec_err}); "
1752
- f"falling back to os._exit(0). Lifespan finally + "
1753
- f"stop_hook still recover."
1754
- )
1769
+ log.error(f"install-guard execv failed ({_exec_err}); os._exit(0)")
1755
1770
  os._exit(0)
1756
- return # unreachable but explicit
1771
+ return
1772
+ if not _INSTALL_GUARD_STALE_NOTIFIED:
1773
+ _INSTALL_GUARD_STALE_NOTIFIED = True
1774
+ log.warning(
1775
+ f"install-guard: self-modification on {stale_path} "
1776
+ f"(mtime {old_m:.0f} -> {new_m:.0f}). Mode={_INSTALL_GUARD_MODE}, "
1777
+ f"agent_active={_is_agent_active()}. Running on STALE image -- new wheel "
1778
+ f"picked up on next `meshcode go <agent>` cold boot. "
1779
+ f"Set MESHCODE_INSTALL_GUARD=execv to opt into auto-restart."
1780
+ )
1781
+ try:
1782
+ import threading as _t
1783
+ def _notify():
1784
+ try:
1785
+ be.send_message(
1786
+ _PROJECT_ID, AGENT_NAME, "mesh-commander",
1787
+ {
1788
+ "type": "boot_version_drift",
1789
+ "subtype": "mid_session_stale_image",
1790
+ "path": stale_path,
1791
+ "old_mtime": old_m,
1792
+ "new_mtime": new_m,
1793
+ "agent": AGENT_NAME,
1794
+ "platform": sys.platform,
1795
+ "loaded_version": _SDK_VERSION,
1796
+ },
1797
+ msg_type="report",
1798
+ api_key=_get_api_key(),
1799
+ )
1800
+ except Exception as _e:
1801
+ log.debug(f"boot_version_drift notify failed (soft): {_e}")
1802
+ _t.Thread(target=_notify, daemon=True, name="meshcode-install-guard-notify").start()
1803
+ except Exception:
1804
+ pass
1757
1805
  except Exception as e:
1758
1806
  log.debug(f"install-guard scan failed (soft): {e}")
1759
1807
 
@@ -0,0 +1,75 @@
1
+ """Unit tests for the install-guard heartbeat scan.
2
+
3
+ RC for task 0c4524af (2026-05-19): pip install over live 2.11.7 sessions
4
+ triggered execv on both backend+commander hb tick, dropping MCP socket.
5
+ Fix (task d7df438e): default mode is 'warn' — log + one-shot notify, never
6
+ execv mid-session. Legacy execv path preserved as opt-in (MESHCODE_INSTALL_GUARD=execv)
7
+ and further deferred when agent is active.
8
+
9
+ Server module requires MESHCODE_PROJECT and MESHCODE_AGENT at import time
10
+ (L616-621). MESHCODE_PROJECT_ID short-circuits the network resolve path.
11
+ """
12
+ import os
13
+
14
+ os.environ.setdefault("MESHCODE_PROJECT", "test-install-guard")
15
+ os.environ.setdefault("MESHCODE_AGENT", "test-agent")
16
+ os.environ.setdefault("MESHCODE_PROJECT_ID", "00000000-0000-0000-0000-000000000000")
17
+ os.environ.setdefault("MESHCODE_API_KEY", "mc_test_fake_key_not_used")
18
+
19
+ import time
20
+ import pytest
21
+ from unittest import mock
22
+ from meshcode.meshcode_mcp import server as srv
23
+
24
+
25
+ @pytest.fixture
26
+ def stale_setup(monkeypatch, tmp_path):
27
+ fake = tmp_path / "fake_pkg.py"
28
+ fake.write_text("# stale")
29
+ old = fake.stat().st_mtime
30
+ monkeypatch.setattr(srv, "_PKG_PY_MTIMES", {str(fake): old - 100.0})
31
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_STALE_NOTIFIED", False)
32
+ return fake
33
+
34
+
35
+ def test_default_warn_no_execv(stale_setup, monkeypatch):
36
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_MODE", "warn")
37
+ with mock.patch.object(os, "execv") as me, mock.patch.object(os, "_exit") as mex:
38
+ srv._install_guard_check()
39
+ assert not me.called and not mex.called
40
+
41
+
42
+ def test_off_skips(stale_setup, monkeypatch):
43
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_MODE", "off")
44
+ with mock.patch.object(os, "execv") as me:
45
+ srv._install_guard_check()
46
+ assert not me.called
47
+
48
+
49
+ def test_execv_inactive_fires(stale_setup, monkeypatch):
50
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_MODE", "execv")
51
+ monkeypatch.setattr(srv, "_IN_WAIT", False)
52
+ monkeypatch.setattr(srv, "_last_tool_at", 0.0)
53
+ monkeypatch.delenv("MESHCODE_AGENT_ACTIVE", raising=False)
54
+ with mock.patch.object(os, "execv") as me, \
55
+ mock.patch.object(srv, "_release_lease_synchronous", create=True):
56
+ srv._install_guard_check()
57
+ assert me.called
58
+
59
+
60
+ def test_execv_active_defers(stale_setup, monkeypatch):
61
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_MODE", "execv")
62
+ monkeypatch.setattr(srv, "_IN_WAIT", True)
63
+ with mock.patch.object(os, "execv") as me:
64
+ srv._install_guard_check()
65
+ assert not me.called
66
+
67
+
68
+ def test_one_shot_notify(stale_setup, monkeypatch):
69
+ monkeypatch.setattr(srv, "_INSTALL_GUARD_MODE", "warn")
70
+ sends = []
71
+ monkeypatch.setattr(srv.be, "send_message", lambda *a, **kw: sends.append((a, kw)))
72
+ srv._install_guard_check(); time.sleep(0.3)
73
+ n1 = len(sends)
74
+ srv._install_guard_check(); time.sleep(0.3)
75
+ assert len(sends) == n1, "second call must not duplicate notify"
@@ -0,0 +1,82 @@
1
+ """Regression test for B1 (task f1d34641) — friction #9.
2
+
3
+ `meshcode prefs claude-version latest` must save "latest" literally instead
4
+ of deleting the key. The disable sentinel "latest"/"none"/"skip" is read at
5
+ run_agent.py:475 to skip the ESC pin; if the CLI deletes the key, the user
6
+ falls back to the hardcoded 2.1.104 pin → npx fails for users without Node.
7
+
8
+ Bug location: comms_v4.py:3396-3416 (pre-fix grouped `latest` with
9
+ `reset`/`unpin` and popped the key).
10
+ """
11
+ import json
12
+ import os
13
+
14
+ os.environ.setdefault("MESHCODE_PROJECT", "test-prefs-b1")
15
+ os.environ.setdefault("MESHCODE_AGENT", "test-agent")
16
+
17
+ import pytest
18
+
19
+
20
+ @pytest.fixture
21
+ def isolated_prefs(tmp_path, monkeypatch):
22
+ pref_file = tmp_path / "preferences.json"
23
+ from meshcode import preferences
24
+ monkeypatch.setattr(preferences, "PREFS_PATH", pref_file)
25
+ return pref_file
26
+
27
+
28
+ def _apply_branch(ver: str):
29
+ """Mirror the post-fix branch in comms_v4.py:3396-3420."""
30
+ from meshcode.preferences import load_prefs, save_prefs
31
+ if ver in ("reset", "unpin"):
32
+ prefs = load_prefs()
33
+ prefs.pop("claude_version", None)
34
+ save_prefs(prefs)
35
+ elif ver in ("latest", "none", "skip"):
36
+ prefs = load_prefs()
37
+ prefs["claude_version"] = ver
38
+ save_prefs(prefs)
39
+ else:
40
+ prefs = load_prefs()
41
+ prefs["claude_version"] = ver
42
+ save_prefs(prefs)
43
+
44
+
45
+ def test_claude_version_latest_saves_literal(isolated_prefs):
46
+ """Repro for friction #9: `meshcode prefs claude-version latest` must
47
+ save "latest" to JSON, NOT delete the key."""
48
+ from meshcode.preferences import save_prefs
49
+ save_prefs({"claude_version": "2.1.50"})
50
+ _apply_branch("latest")
51
+ data = json.loads(isolated_prefs.read_text())
52
+ assert data.get("claude_version") == "latest", \
53
+ f"expected 'latest' literal, got {data!r}"
54
+
55
+
56
+ def test_claude_version_none_saves_literal(isolated_prefs):
57
+ _apply_branch("none")
58
+ assert json.loads(isolated_prefs.read_text()).get("claude_version") == "none"
59
+
60
+
61
+ def test_claude_version_skip_saves_literal(isolated_prefs):
62
+ _apply_branch("skip")
63
+ assert json.loads(isolated_prefs.read_text()).get("claude_version") == "skip"
64
+
65
+
66
+ def test_claude_version_reset_clears_key(isolated_prefs):
67
+ from meshcode.preferences import save_prefs, load_prefs
68
+ save_prefs({"claude_version": "2.1.50"})
69
+ _apply_branch("reset")
70
+ assert "claude_version" not in load_prefs()
71
+
72
+
73
+ def test_claude_version_unpin_clears_key(isolated_prefs):
74
+ from meshcode.preferences import save_prefs, load_prefs
75
+ save_prefs({"claude_version": "2.1.50"})
76
+ _apply_branch("unpin")
77
+ assert "claude_version" not in load_prefs()
78
+
79
+
80
+ def test_claude_version_pin_saves_specific_version(isolated_prefs):
81
+ _apply_branch("2.1.108")
82
+ assert json.loads(isolated_prefs.read_text()).get("claude_version") == "2.1.108"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.8
3
+ Version: 2.11.9
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -186,6 +186,8 @@ meshcode/meshcode_mcp/server.py
186
186
  meshcode/meshcode_mcp/sleep_signals.py
187
187
  meshcode/meshcode_mcp/test_backend.py
188
188
  meshcode/meshcode_mcp/test_boot_timing.py
189
+ meshcode/meshcode_mcp/test_install_guard.py
190
+ meshcode/meshcode_mcp/test_prefs_claude_version.py
189
191
  meshcode/meshcode_mcp/test_realtime.py
190
192
  meshcode/meshcode_mcp/test_server_wrapper.py
191
193
  meshcode/scripts/check_secrets.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.8"
7
+ version = "2.11.9"
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
File without changes
File without changes
File without changes
File without changes
File without changes