meshcode 2.11.20__tar.gz → 2.11.21__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 (228) hide show
  1. {meshcode-2.11.20 → meshcode-2.11.21}/PKG-INFO +1 -1
  2. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/__init__.py +1 -1
  3. meshcode-2.11.21/meshcode/atomic_push.py +257 -0
  4. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/server.py +74 -0
  5. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/PKG-INFO +1 -1
  6. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/SOURCES.txt +1 -0
  7. {meshcode-2.11.20 → meshcode-2.11.21}/pyproject.toml +1 -1
  8. {meshcode-2.11.20 → meshcode-2.11.21}/README.md +0 -0
  9. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/__main__.py +0 -0
  10. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/_stop_hook_template.py +0 -0
  11. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/ascii_art.py +0 -0
  12. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/cli.py +0 -0
  13. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/comms_v4.py +0 -0
  14. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/compat.py +0 -0
  15. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/daemon.py +0 -0
  16. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/date_parse.py +0 -0
  17. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/doctor.py +0 -0
  18. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/error_hints.py +0 -0
  19. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/exceptions.py +0 -0
  20. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/invites.py +0 -0
  21. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/launcher.py +0 -0
  22. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/launcher_install.py +0 -0
  23. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/__init__.py +0 -0
  24. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/__main__.py +0 -0
  25. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/backend.py +0 -0
  26. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/realtime.py +0 -0
  27. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  28. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_backend.py +0 -0
  29. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  30. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  31. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  32. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  33. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  34. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/preferences.py +0 -0
  35. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/protocol_handler.py +0 -0
  36. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/protocol_v2.py +0 -0
  37. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/quickstart.py +0 -0
  38. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/rpc_allowlist.py +0 -0
  39. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/run_agent.py +0 -0
  40. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/scripts/check_secrets.py +0 -0
  41. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/scripts/race_rate_harness.py +0 -0
  42. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/secrets.py +0 -0
  43. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/self_update.py +0 -0
  44. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/setup_clients.py +0 -0
  45. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/supervisor.py +0 -0
  46. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode/upload.py +0 -0
  47. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/comms_v4.py +0 -0
  48. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  49. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  50. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/cli.py +0 -0
  51. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  52. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/compat.py +0 -0
  53. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  54. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  55. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/invites.py +0 -0
  56. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  57. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  58. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  59. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  60. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  61. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  62. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  63. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  64. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  65. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  66. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  67. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  68. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  69. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  70. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  71. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  72. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  73. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  74. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/meshcode/upload.py +0 -0
  75. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  76. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_core.py +0 -0
  77. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  78. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  79. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  80. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  81. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  82. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  83. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  84. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  85. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  86. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  87. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  88. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  89. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  90. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  91. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  92. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  93. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  94. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  95. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  96. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  97. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  98. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  99. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  100. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  101. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  102. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  103. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  104. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  105. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  106. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  107. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  108. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  109. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  110. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  111. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  112. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  113. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  114. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  115. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/comms_v4.py +0 -0
  116. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  117. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  118. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/cli.py +0 -0
  119. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  120. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/compat.py +0 -0
  121. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  122. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  123. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/invites.py +0 -0
  124. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  125. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  126. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  127. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  128. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  129. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  130. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  131. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  132. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  133. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  134. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  135. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  136. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  137. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  138. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  139. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  140. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  141. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  142. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/meshcode/upload.py +0 -0
  143. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  144. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_core.py +0 -0
  145. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  146. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  147. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  148. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  149. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  150. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  151. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  152. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  153. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  154. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  155. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  156. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/comms_v4.py +0 -0
  157. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  158. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  159. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  160. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  161. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  162. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  163. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  164. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  165. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  166. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  167. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  168. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  169. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  170. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  171. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  172. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  173. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  174. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  175. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  176. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  177. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  178. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  179. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  180. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  181. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  182. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  183. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  184. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  185. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_core.py +0 -0
  186. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  187. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  188. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  189. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  190. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  191. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  192. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  193. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  194. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  195. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  196. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  197. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/dependency_links.txt +0 -0
  198. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/entry_points.txt +0 -0
  199. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/requires.txt +0 -0
  200. {meshcode-2.11.20 → meshcode-2.11.21}/meshcode.egg-info/top_level.txt +0 -0
  201. {meshcode-2.11.20 → meshcode-2.11.21}/setup.cfg +0 -0
  202. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_auto_update_hardening.py +0 -0
  203. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_boot_bug_regression.py +0 -0
  204. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_color_truecolor.py +0 -0
  205. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_core.py +0 -0
  206. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_cross_agent_messaging.py +0 -0
  207. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_date_parse.py +0 -0
  208. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_doctor.py +0 -0
  209. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_epistemic_v1_python_sdk.py +0 -0
  210. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  211. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_esc_deaf_state.py +0 -0
  212. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_exceptions.py +0 -0
  213. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_init_device_code.py +0 -0
  214. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_install_guard.py +0 -0
  215. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_lease_sigterm_release.py +0 -0
  216. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_mark_read_batch.py +0 -0
  217. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_migration_integrity.py +0 -0
  218. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_realtime_event_freshness.py +0 -0
  219. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_rls_cross_tenant.py +0 -0
  220. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_rpc_grants.py +0 -0
  221. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_rpc_migrations.py +0 -0
  222. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_security_regressions.py +0 -0
  223. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_sentinel.py +0 -0
  224. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_setup_path.py +0 -0
  225. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_sleep_signals.py +0 -0
  226. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_status_enum_coverage.py +0 -0
  227. {meshcode-2.11.20 → meshcode-2.11.21}/tests/test_stay_on_loop_hook.py +0 -0
  228. {meshcode-2.11.20 → meshcode-2.11.21}/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.20
3
+ Version: 2.11.21
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.20"
2
+ __version__ = "2.11.21"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -0,0 +1,257 @@
1
+ """Atomic multi-remote git push via GitHub REST API.
2
+
3
+ Implements MESH-IMPROVE-3 (feedback session 5651f137 — 4/4 cycle convergence).
4
+
5
+ MVP scope:
6
+ - strategy='same_tree_sha' only (defer cherry_pick_if_diverged + rest_api_blob_tree to v2)
7
+ - remotes hardcoded to {origin, lovable2} (param accepted but only those valid)
8
+ - idempotency_key: when same key seen twice within 1h, returns cached result
9
+ (avoids double-commit on retry — handles dulwich-shutdown-traceback pattern
10
+ front-2 reported in feedback cycle 2)
11
+ - auth_source: 'git_config' (parse PATs from .git/config) — most agents
12
+ have PATs there per the pattern established 2026-05-20
13
+
14
+ Used by meshcode_atomic_push MCP tool + callable from scripts.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import base64
19
+ import json
20
+ import os
21
+ import re
22
+ import time
23
+ import urllib.error
24
+ import urllib.request
25
+ from pathlib import Path
26
+ from typing import Any, Dict, List, Optional, Tuple
27
+
28
+ ALLOWED_REMOTES = ("origin", "lovable2")
29
+ _CACHE_TTL_S = 3600
30
+ _DEFAULT_REPO_ROOT = Path("/Users/anfexi/Desktop/meshcode")
31
+
32
+
33
+ def _cache_path() -> Path:
34
+ base = Path(os.path.expanduser("~/.meshcode"))
35
+ base.mkdir(parents=True, exist_ok=True)
36
+ return base / "atomic_push_cache.json"
37
+
38
+
39
+ def _load_cache() -> Dict[str, Any]:
40
+ p = _cache_path()
41
+ if not p.exists():
42
+ return {}
43
+ try:
44
+ with open(p) as f:
45
+ return json.load(f) or {}
46
+ except Exception:
47
+ return {}
48
+
49
+
50
+ def _save_cache(cache: Dict[str, Any]) -> None:
51
+ try:
52
+ with open(_cache_path(), "w") as f:
53
+ json.dump(cache, f)
54
+ except Exception:
55
+ pass
56
+
57
+
58
+ def _check_idempotency(key: Optional[str]) -> Optional[Dict[str, Any]]:
59
+ if not key:
60
+ return None
61
+ cache = _load_cache()
62
+ entry = cache.get(key)
63
+ if not entry:
64
+ return None
65
+ if (time.time() - entry.get("ts", 0)) > _CACHE_TTL_S:
66
+ return None
67
+ return entry.get("result")
68
+
69
+
70
+ def _store_idempotency(key: Optional[str], result: Dict[str, Any]) -> None:
71
+ if not key:
72
+ return
73
+ cache = _load_cache()
74
+ cache[key] = {"ts": time.time(), "result": result}
75
+ # Prune entries older than TTL
76
+ cutoff = time.time() - _CACHE_TTL_S
77
+ cache = {k: v for k, v in cache.items() if v.get("ts", 0) > cutoff}
78
+ _save_cache(cache)
79
+
80
+
81
+ def parse_git_config(repo_root: Path = _DEFAULT_REPO_ROOT) -> Dict[str, Tuple[str, str, str]]:
82
+ """Return {remote_alias: (owner, repo, pat)}."""
83
+ cfg_path = repo_root / ".git" / "config"
84
+ if not cfg_path.exists():
85
+ return {}
86
+ cfg = cfg_path.read_text()
87
+ remotes: Dict[str, Tuple[str, str, str]] = {}
88
+ for block in re.split(r"\n(?=\[)", cfg):
89
+ m = re.match(r'\[remote "([^"]+)"\]', block)
90
+ if not m:
91
+ continue
92
+ alias = m.group(1)
93
+ url_m = re.search(r"url\s*=\s*(\S+)", block)
94
+ if not url_m:
95
+ continue
96
+ url = url_m.group(1)
97
+ creds_m = re.match(
98
+ r"https://([^:]+):([^@]+)@github\.com/([^/]+)/([^/]+?)(?:\.git)?$",
99
+ url,
100
+ )
101
+ if not creds_m:
102
+ continue
103
+ _, pat, owner, repo = creds_m.groups()
104
+ remotes[alias] = (owner, repo, pat)
105
+ return remotes
106
+
107
+
108
+ def _api(method: str, url: str, pat: str, data: Any = None) -> Dict[str, Any]:
109
+ req = urllib.request.Request(url, method=method)
110
+ req.add_header("Authorization", f"Bearer {pat}")
111
+ req.add_header("Accept", "application/vnd.github+json")
112
+ req.add_header("X-GitHub-Api-Version", "2022-11-28")
113
+ body = None
114
+ if data is not None:
115
+ body = json.dumps(data).encode()
116
+ req.add_header("Content-Type", "application/json")
117
+ try:
118
+ with urllib.request.urlopen(req, data=body, timeout=30) as r:
119
+ return json.loads(r.read().decode())
120
+ except urllib.error.HTTPError as e:
121
+ msg = e.read().decode()[:300]
122
+ raise RuntimeError(f"{method} {url} -> {e.code}: {msg}") from e
123
+
124
+
125
+ def _push_one_remote(
126
+ owner: str,
127
+ repo: str,
128
+ pat: str,
129
+ branch: str,
130
+ commit_message: str,
131
+ files: List[str],
132
+ repo_root: Path,
133
+ ) -> Tuple[str, Dict[str, Any]]:
134
+ base = f"https://api.github.com/repos/{owner}/{repo}"
135
+ ref = _api("GET", f"{base}/git/ref/heads/{branch}", pat)
136
+ head_sha = ref["object"]["sha"]
137
+ base_commit = _api("GET", f"{base}/git/commits/{head_sha}", pat)
138
+ base_tree_sha = base_commit["tree"]["sha"]
139
+ tree_entries = []
140
+ for rel in files:
141
+ p = repo_root / rel
142
+ if not p.exists():
143
+ raise RuntimeError(f"file not found: {p}")
144
+ content = p.read_bytes()
145
+ blob = _api(
146
+ "POST",
147
+ f"{base}/git/blobs",
148
+ pat,
149
+ data={"content": base64.b64encode(content).decode(), "encoding": "base64"},
150
+ )
151
+ tree_entries.append({
152
+ "path": rel,
153
+ "mode": "100644",
154
+ "type": "blob",
155
+ "sha": blob["sha"],
156
+ })
157
+ new_tree = _api(
158
+ "POST",
159
+ f"{base}/git/trees",
160
+ pat,
161
+ data={"base_tree": base_tree_sha, "tree": tree_entries},
162
+ )
163
+ commit = _api(
164
+ "POST",
165
+ f"{base}/git/commits",
166
+ pat,
167
+ data={
168
+ "message": commit_message,
169
+ "tree": new_tree["sha"],
170
+ "parents": [head_sha],
171
+ },
172
+ )
173
+ new_sha = commit["sha"]
174
+ _api(
175
+ "PATCH",
176
+ f"{base}/git/refs/heads/{branch}",
177
+ pat,
178
+ data={"sha": new_sha, "force": False},
179
+ )
180
+ return new_sha, {
181
+ "head_before": head_sha,
182
+ "tree_sha": new_tree["sha"],
183
+ "commit_sha": new_sha,
184
+ }
185
+
186
+
187
+ def atomic_push(
188
+ commit_message: str,
189
+ files: List[str],
190
+ *,
191
+ branch: str = "main",
192
+ remotes: Optional[List[str]] = None,
193
+ strategy: str = "same_tree_sha",
194
+ idempotency_key: Optional[str] = None,
195
+ repo_root: Path = _DEFAULT_REPO_ROOT,
196
+ ) -> Dict[str, Any]:
197
+ """Push the same blob set to multiple remotes atomically.
198
+
199
+ Returns:
200
+ {
201
+ ok: bool,
202
+ landed: {remote_alias: commit_sha},
203
+ tree_sha_per_remote: {remote_alias: tree_sha},
204
+ drift_detected: bool,
205
+ transport_used: 'github_rest_api',
206
+ cached: bool,
207
+ strategy: str
208
+ }
209
+ """
210
+ if strategy != "same_tree_sha":
211
+ return {
212
+ "ok": False,
213
+ "error": "unsupported_strategy",
214
+ "hint": f"MVP supports 'same_tree_sha' only; got {strategy!r}",
215
+ }
216
+ remotes = remotes or list(ALLOWED_REMOTES)
217
+ for r in remotes:
218
+ if r not in ALLOWED_REMOTES:
219
+ return {
220
+ "ok": False,
221
+ "error": "unsupported_remote",
222
+ "hint": f"MVP accepts {ALLOWED_REMOTES}; got {r!r}",
223
+ }
224
+ cached = _check_idempotency(idempotency_key)
225
+ if cached is not None:
226
+ cached["cached"] = True
227
+ return cached
228
+ git_remotes = parse_git_config(repo_root)
229
+ missing = [r for r in remotes if r not in git_remotes]
230
+ if missing:
231
+ return {
232
+ "ok": False,
233
+ "error": "git_config_remote_missing",
234
+ "missing": missing,
235
+ "have": list(git_remotes.keys()),
236
+ }
237
+ landed: Dict[str, str] = {}
238
+ tree_sha_per: Dict[str, str] = {}
239
+ for alias in remotes:
240
+ owner, repo, pat = git_remotes[alias]
241
+ sha, meta = _push_one_remote(owner, repo, pat, branch, commit_message, files, repo_root)
242
+ landed[alias] = sha
243
+ tree_sha_per[alias] = meta["tree_sha"]
244
+ tree_shas = list(tree_sha_per.values())
245
+ same_tree = len(set(tree_shas)) == 1
246
+ result = {
247
+ "ok": True,
248
+ "landed": landed,
249
+ "tree_sha_per_remote": tree_sha_per,
250
+ "drift_detected": not same_tree,
251
+ "transport_used": "github_rest_api",
252
+ "cached": False,
253
+ "strategy": strategy,
254
+ "branch": branch,
255
+ }
256
+ _store_idempotency(idempotency_key, result)
257
+ return result
@@ -5398,6 +5398,80 @@ def meshcode_remember(
5398
5398
  return result
5399
5399
 
5400
5400
 
5401
+ @mcp.tool()
5402
+ @with_working_status
5403
+ def meshcode_atomic_push(
5404
+ commit_message: str,
5405
+ files: List[str],
5406
+ branch: str = "main",
5407
+ remotes: Optional[List[str]] = None,
5408
+ idempotency_key: Optional[str] = None,
5409
+ ) -> Dict[str, Any]:
5410
+ """Push same blob set to multiple git remotes atomically (same tree SHA).
5411
+ MESH-IMPROVE-3 (feedback session 5651f137 — 4/4 cycle convergence).
5412
+
5413
+ Args:
5414
+ commit_message: full commit message (multi-line ok).
5415
+ files: list of repo-relative paths to include in the commit.
5416
+ branch: target branch on each remote (default "main").
5417
+ remotes: subset of {"origin","lovable2"}; defaults to both.
5418
+ idempotency_key: if same key seen twice within 1h, returns cached result
5419
+ (avoids double-commit on retry — covers dulwich-shutdown-traceback).
5420
+
5421
+ Returns: {ok, landed:{remote:sha}, tree_sha_per_remote, drift_detected,
5422
+ transport_used:'github_rest_api', cached:bool, strategy, branch}
5423
+ """
5424
+ if not commit_message or not commit_message.strip():
5425
+ return {"error": "commit_message cannot be empty"}
5426
+ if not files:
5427
+ return {"error": "files list cannot be empty"}
5428
+ try:
5429
+ from meshcode import atomic_push as _ap
5430
+ return _ap.atomic_push(
5431
+ commit_message=commit_message,
5432
+ files=files,
5433
+ branch=branch,
5434
+ remotes=remotes,
5435
+ strategy="same_tree_sha",
5436
+ idempotency_key=idempotency_key,
5437
+ )
5438
+ except Exception as e:
5439
+ return {"error": str(e), "error_type": type(e).__name__}
5440
+
5441
+
5442
+ @mcp.tool()
5443
+ @with_working_status
5444
+ def meshcode_context_budget() -> Dict[str, Any]:
5445
+ """Self-pacing hint for the agent's reply verbosity.
5446
+ MESH-IMPROVE-10 (feedback session 5651f137).
5447
+
5448
+ Returns: {messages_seen, suggestion: 'short'|'normal'|'verbose',
5449
+ rationale: str}.
5450
+
5451
+ Note: server cannot know the actual conversation token count (Anthropic
5452
+ doesn't expose). Suggestion is derived from proxies the server CAN see —
5453
+ cumulative msg count + recent msg sizes. Treat as a hint, not a hard
5454
+ truth.
5455
+ """
5456
+ seen = len(_SEEN_MSG_IDS)
5457
+ # Heuristic: <50 msgs = verbose ok; 50-150 = normal; >150 = short
5458
+ if seen < 50:
5459
+ suggestion = "verbose"
5460
+ rationale = "fresh session — full detail is fine"
5461
+ elif seen < 150:
5462
+ suggestion = "normal"
5463
+ rationale = "mid-session — standard verbosity"
5464
+ else:
5465
+ suggestion = "short"
5466
+ rationale = "deep session — prefer tight prose, drop redundant context"
5467
+ return {
5468
+ "ok": True,
5469
+ "messages_seen": seen,
5470
+ "suggestion": suggestion,
5471
+ "rationale": rationale,
5472
+ }
5473
+
5474
+
5401
5475
  @mcp.tool()
5402
5476
  @with_working_status
5403
5477
  def meshcode_recall_mesh(key: str) -> Dict[str, Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.20
3
+ Version: 2.11.21
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,6 +4,7 @@ meshcode/__init__.py
4
4
  meshcode/__main__.py
5
5
  meshcode/_stop_hook_template.py
6
6
  meshcode/ascii_art.py
7
+ meshcode/atomic_push.py
7
8
  meshcode/cli.py
8
9
  meshcode/comms_v4.py
9
10
  meshcode/compat.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.20"
7
+ version = "2.11.21"
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