meshcode 2.11.10__tar.gz → 2.11.11__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 (222) hide show
  1. {meshcode-2.11.10 → meshcode-2.11.11}/PKG-INFO +1 -1
  2. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/__init__.py +1 -1
  3. meshcode-2.11.11/meshcode/__main__.py +42 -0
  4. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/comms_v4.py +64 -1
  5. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/server.py +25 -2
  6. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/run_agent.py +10 -0
  7. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/PKG-INFO +1 -1
  8. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/SOURCES.txt +3 -0
  9. {meshcode-2.11.10 → meshcode-2.11.11}/pyproject.toml +1 -1
  10. meshcode-2.11.11/tests/test_color_truecolor.py +83 -0
  11. meshcode-2.11.11/tests/test_setup_path.py +66 -0
  12. {meshcode-2.11.10 → meshcode-2.11.11}/README.md +0 -0
  13. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/_stop_hook_template.py +0 -0
  14. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/ascii_art.py +0 -0
  15. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/cli.py +0 -0
  16. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/compat.py +0 -0
  17. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/daemon.py +0 -0
  18. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/doctor.py +0 -0
  19. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/error_hints.py +0 -0
  20. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/exceptions.py +0 -0
  21. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/invites.py +0 -0
  22. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/launcher.py +0 -0
  23. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/launcher_install.py +0 -0
  24. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/__init__.py +0 -0
  25. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/__main__.py +0 -0
  26. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/backend.py +0 -0
  27. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/realtime.py +0 -0
  28. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  29. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_backend.py +0 -0
  30. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  31. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  32. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  33. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  34. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  35. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/preferences.py +0 -0
  36. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/protocol_handler.py +0 -0
  37. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/protocol_v2.py +0 -0
  38. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/quickstart.py +0 -0
  39. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/scripts/check_secrets.py +0 -0
  40. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/scripts/race_rate_harness.py +0 -0
  41. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/secrets.py +0 -0
  42. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/self_update.py +0 -0
  43. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/setup_clients.py +0 -0
  44. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/supervisor.py +0 -0
  45. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode/upload.py +0 -0
  46. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/comms_v4.py +0 -0
  47. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  48. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  49. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/cli.py +0 -0
  50. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  51. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/compat.py +0 -0
  52. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  53. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  54. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/invites.py +0 -0
  55. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  56. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  57. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  58. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  59. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  60. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  61. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  62. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  63. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  64. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  65. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  66. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  67. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  68. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  69. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  70. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  71. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  72. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  73. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/meshcode/upload.py +0 -0
  74. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  75. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_core.py +0 -0
  76. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  77. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  78. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  79. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  80. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  81. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  82. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  83. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  84. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  85. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  86. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  87. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  88. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  89. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  90. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  91. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  92. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  93. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  94. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  95. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  96. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  97. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  98. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  99. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  100. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  101. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  102. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  103. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  104. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  105. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  106. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  107. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  108. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  109. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  110. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  111. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  112. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  113. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  114. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/comms_v4.py +0 -0
  115. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  116. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  117. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/cli.py +0 -0
  118. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  119. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/compat.py +0 -0
  120. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  121. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  122. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/invites.py +0 -0
  123. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  124. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  125. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  126. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  127. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  128. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  129. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  130. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  131. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  132. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  133. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  134. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  135. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  136. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  137. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  138. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  139. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  140. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  141. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/meshcode/upload.py +0 -0
  142. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  143. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_core.py +0 -0
  144. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  145. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  146. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  147. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  148. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  149. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  150. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  151. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  152. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  153. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  154. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  155. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/comms_v4.py +0 -0
  156. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  157. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  158. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  159. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  160. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  161. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  162. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  163. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  164. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  165. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  166. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  167. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  168. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  169. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  170. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  171. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  172. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  173. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  174. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  175. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  176. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  177. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  178. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  179. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  180. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  181. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  182. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  183. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  184. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_core.py +0 -0
  185. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  186. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  187. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  188. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  189. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  190. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  191. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  192. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  193. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  194. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  195. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  196. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/dependency_links.txt +0 -0
  197. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/entry_points.txt +0 -0
  198. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/requires.txt +0 -0
  199. {meshcode-2.11.10 → meshcode-2.11.11}/meshcode.egg-info/top_level.txt +0 -0
  200. {meshcode-2.11.10 → meshcode-2.11.11}/setup.cfg +0 -0
  201. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_auto_update_hardening.py +0 -0
  202. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_boot_bug_regression.py +0 -0
  203. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_core.py +0 -0
  204. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_cross_agent_messaging.py +0 -0
  205. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_doctor.py +0 -0
  206. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_epistemic_v1_python_sdk.py +0 -0
  207. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  208. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_esc_deaf_state.py +0 -0
  209. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_exceptions.py +0 -0
  210. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_install_guard.py +0 -0
  211. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_lease_sigterm_release.py +0 -0
  212. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_mark_read_batch.py +0 -0
  213. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_migration_integrity.py +0 -0
  214. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_realtime_event_freshness.py +0 -0
  215. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_rls_cross_tenant.py +0 -0
  216. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_rpc_migrations.py +0 -0
  217. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_security_regressions.py +0 -0
  218. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_sentinel.py +0 -0
  219. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_sleep_signals.py +0 -0
  220. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_status_enum_coverage.py +0 -0
  221. {meshcode-2.11.10 → meshcode-2.11.11}/tests/test_stay_on_loop_hook.py +0 -0
  222. {meshcode-2.11.10 → meshcode-2.11.11}/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.10
3
+ Version: 2.11.11
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.10"
2
+ __version__ = "2.11.11"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -0,0 +1,42 @@
1
+ """Helpful error when user invokes `python -m meshcode` because the
2
+ console-script isn't on PATH yet (B5 friction).
3
+
4
+ Also dispatches `python -m meshcode setup-path` to the real CLI so the
5
+ user can fix PATH without needing the `meshcode` binary on PATH first.
6
+ """
7
+ import os
8
+ import sys
9
+
10
+
11
+ def main():
12
+ # If the user explicitly asked to set up PATH, delegate to the real CLI.
13
+ if len(sys.argv) > 1 and sys.argv[1] == "setup-path":
14
+ from meshcode import comms_v4 as _cv # noqa: F401
15
+ sys.argv[0] = "meshcode"
16
+ # comms_v4 runs main() at module load via `if __name__ == "__main__"`.
17
+ # Re-exec the body by importing as __main__ would require executing
18
+ # the module again; simpler: invoke via runpy.
19
+ import runpy
20
+ runpy.run_module("meshcode.comms_v4", run_name="__main__", alter_sys=True)
21
+ return
22
+
23
+ # Otherwise: the user is here because `meshcode` isn't on PATH.
24
+ print()
25
+ print(" meshcode is installed but the `meshcode` command isn't on your PATH.")
26
+ print()
27
+ print(" Quick fix:")
28
+ print(f" {sys.executable} -m meshcode setup-path")
29
+ print()
30
+ print(" Or manually:")
31
+ v = sys.version_info
32
+ if sys.platform == "darwin":
33
+ print(f' export PATH="$HOME/Library/Python/{v.major}.{v.minor}/bin:$PATH"')
34
+ else:
35
+ print(' export PATH="$(python3 -m site --user-base)/bin:$PATH"')
36
+ print()
37
+ print(" Then re-run: meshcode --help")
38
+ sys.exit(1)
39
+
40
+
41
+ if __name__ == "__main__":
42
+ main()
@@ -2868,7 +2868,7 @@ if __name__ == "__main__":
2868
2868
  # doctor, help, version, login, prefs, launcher don't need auth.
2869
2869
  _NO_AUTH_CMDS = {"doctor", "compat", "upgrade", "help", "--help", "-h", "login",
2870
2870
  "init", "prefs", "launcher", "--version", "-V", "version",
2871
- "whoami", "profiles", "scan"}
2871
+ "whoami", "profiles", "scan", "setup-path"}
2872
2872
  if cmd not in _NO_AUTH_CMDS:
2873
2873
  _cli_key = _load_api_key_for_cli()
2874
2874
  if not _cli_key:
@@ -3479,6 +3479,69 @@ if __name__ == "__main__":
3479
3479
  print(" meshcode prefs reset")
3480
3480
  sys.exit(1)
3481
3481
 
3482
+ elif cmd == "setup-path":
3483
+ # B5: append Python user-bin to user's shell rc file (idempotent).
3484
+ # Friction #8 fix: after `pip install --user meshcode`, `meshcode`
3485
+ # isn't on PATH; this gives the user a one-command remediation.
3486
+ import platform as _pl
3487
+ import subprocess as _sp
3488
+ _v = sys.version_info
3489
+ if _pl.system() == "Darwin":
3490
+ user_bin = os.path.expanduser(f"~/Library/Python/{_v.major}.{_v.minor}/bin")
3491
+ else:
3492
+ try:
3493
+ user_bin = _sp.check_output(
3494
+ [sys.executable, "-m", "site", "--user-base"],
3495
+ text=True, timeout=5,
3496
+ ).strip() + "/bin"
3497
+ except Exception:
3498
+ user_bin = os.path.expanduser("~/.local/bin")
3499
+
3500
+ shell = os.environ.get("SHELL", "")
3501
+ if "zsh" in shell:
3502
+ rc = os.path.expanduser("~/.zshrc")
3503
+ fish = False
3504
+ elif "fish" in shell:
3505
+ rc = os.path.expanduser("~/.config/fish/config.fish")
3506
+ fish = True
3507
+ else:
3508
+ rc = os.path.expanduser("~/.bashrc")
3509
+ fish = False
3510
+
3511
+ marker = "# meshcode: PATH for user-installed Python binaries"
3512
+ line = (f"set -gx PATH {user_bin} $PATH" if fish
3513
+ else f'export PATH="{user_bin}:$PATH"')
3514
+
3515
+ existing = ""
3516
+ try:
3517
+ if os.path.exists(rc):
3518
+ with open(rc) as f:
3519
+ existing = f.read()
3520
+ except Exception:
3521
+ pass
3522
+
3523
+ if user_bin in existing:
3524
+ print(f"[meshcode] {rc} already exports {user_bin} — nothing to do.")
3525
+ sys.exit(0)
3526
+
3527
+ try:
3528
+ os.makedirs(os.path.dirname(rc), exist_ok=True)
3529
+ with open(rc, "a") as f:
3530
+ f.write(f"\n{marker}\n{line}\n")
3531
+ print(f"[meshcode] Appended PATH export to {rc}")
3532
+ print(f"[meshcode] Open a new terminal OR run: source {rc}")
3533
+ print(f"[meshcode] Then: meshcode --help")
3534
+ sys.exit(0)
3535
+ except PermissionError:
3536
+ print(f"[meshcode] ERROR: cannot write {rc} (permission denied).")
3537
+ print(f"[meshcode] Manually add this line to your shell rc:")
3538
+ print(f" {line}")
3539
+ sys.exit(1)
3540
+ except Exception as _spe:
3541
+ print(f"[meshcode] ERROR: {_spe}")
3542
+ print(f"[meshcode] Manually add: {line}")
3543
+ sys.exit(1)
3544
+
3482
3545
  elif cmd == "upgrade":
3483
3546
  # meshcode upgrade — interactive foreground upgrade
3484
3547
  import importlib
@@ -45,9 +45,21 @@ _ANSI_RGB = [
45
45
  (255, 85, 85), (85, 255, 255), (255, 85, 255), (85, 255, 85), (85, 85, 255),
46
46
  ]
47
47
 
48
+ # BUG-AUDIO-COLOR fix (task e552412a, 2026-05-19): use 24-bit truecolor
49
+ # escapes when the terminal supports them so every terminal renders the
50
+ # same agent color (4-bit palette indices are remapped by terminal themes,
51
+ # producing the cross-machine mismatch Samuel saw).
52
+ _TRUECOLOR_OK = os.environ.get("COLORTERM", "").lower() in ("truecolor", "24bit")
53
+
48
54
 
49
55
  def _hex_to_ansi(hex_color: str) -> str:
50
- """Map hex color to nearest ANSI code."""
56
+ """Return ANSI escape for a hex color.
57
+
58
+ On truecolor-capable terminals returns 24-bit truecolor (\\e[38;2;R;G;Bm) so
59
+ the color bypasses palette remapping. Falls back to nearest 4-bit ANSI
60
+ palette index when COLORTERM is not truecolor.
61
+ Returns None if hex is malformed.
62
+ """
51
63
  hx = hex_color.strip().lstrip("#")
52
64
  if len(hx) != 6:
53
65
  return None
@@ -55,6 +67,9 @@ def _hex_to_ansi(hex_color: str) -> str:
55
67
  r, g, b = int(hx[0:2], 16), int(hx[2:4], 16), int(hx[4:6], 16)
56
68
  except ValueError:
57
69
  return None
70
+ if _TRUECOLOR_OK:
71
+ return f"\033[38;2;{r};{g};{b}m"
72
+ # Fallback: map to nearest 4-bit ANSI palette index
58
73
  best_i, best_d = 0, float("inf")
59
74
  for i, (ar, ag, ab) in enumerate(_ANSI_RGB):
60
75
  d = (r - ar) ** 2 + (g - ag) ** 2 + (b - ab) ** 2
@@ -65,10 +80,18 @@ def _hex_to_ansi(hex_color: str) -> str:
65
80
 
66
81
 
67
82
  def _agent_color(name: str) -> str:
68
- """ANSI color from profile (dashboard) or MD5 hash fallback."""
83
+ """Profile-canonical color if cached, else a deterministic per-name color.
84
+ Never random — same name -> same color on every machine."""
69
85
  if _CACHED_AGENT_COLOR:
70
86
  return _CACHED_AGENT_COLOR
71
87
  h = int(_hashlib.md5(name.encode()).hexdigest()[:8], 16)
88
+ if _TRUECOLOR_OK:
89
+ # Pseudo-random but deterministic 24-bit color from the hash. Clamp
90
+ # mid-range so the color is readable on both dark and light terminals.
91
+ r = max(70, min(220, (h >> 16) & 0xFF))
92
+ g = max(70, min(220, (h >> 8) & 0xFF))
93
+ b = max(70, min(220, h & 0xFF))
94
+ return f"\033[38;2;{r};{g};{b}m"
72
95
  return _ANSI_COLORS[h % len(_ANSI_COLORS)]
73
96
 
74
97
 
@@ -846,6 +846,16 @@ def run(agent: str, project: Optional[str] = None, editor_override: Optional[str
846
846
  except Exception:
847
847
  pass # Soft-fail — boot must proceed regardless.
848
848
 
849
+ # BUG-AUDIO-COLOR fix: wait briefly for profile fetch to populate
850
+ # _CACHED_AGENT_COLOR before rendering the banner, so the boot art
851
+ # doesn't flash the deterministic-hash fallback color and then "jump"
852
+ # to the canonical profile color. Upper-bound 350ms.
853
+ try:
854
+ from .meshcode_mcp.server import _REGISTER_PROFILE_READY
855
+ _REGISTER_PROFILE_READY.wait(timeout=0.35)
856
+ except Exception:
857
+ pass
858
+
849
859
  # ── Welcome banner with unique ASCII art + personality ──────────
850
860
  try:
851
861
  from .ascii_art import generate_art, render_welcome
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.10
3
+ Version: 2.11.11
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,6 +1,7 @@
1
1
  README.md
2
2
  pyproject.toml
3
3
  meshcode/__init__.py
4
+ meshcode/__main__.py
4
5
  meshcode/_stop_hook_template.py
5
6
  meshcode/ascii_art.py
6
7
  meshcode/cli.py
@@ -195,6 +196,7 @@ meshcode/scripts/check_secrets.py
195
196
  meshcode/scripts/race_rate_harness.py
196
197
  tests/test_auto_update_hardening.py
197
198
  tests/test_boot_bug_regression.py
199
+ tests/test_color_truecolor.py
198
200
  tests/test_core.py
199
201
  tests/test_cross_agent_messaging.py
200
202
  tests/test_doctor.py
@@ -211,6 +213,7 @@ tests/test_rls_cross_tenant.py
211
213
  tests/test_rpc_migrations.py
212
214
  tests/test_security_regressions.py
213
215
  tests/test_sentinel.py
216
+ tests/test_setup_path.py
214
217
  tests/test_sleep_signals.py
215
218
  tests/test_status_enum_coverage.py
216
219
  tests/test_stay_on_loop_hook.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.10"
7
+ version = "2.11.11"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -0,0 +1,83 @@
1
+ """Tests for BUG-AUDIO-COLOR (task e552412a) — truecolor agent colors."""
2
+ import os
3
+
4
+ import pytest
5
+
6
+
7
+ @pytest.fixture(autouse=True)
8
+ def _set_required_env(monkeypatch):
9
+ """server.py requires these env vars at import."""
10
+ monkeypatch.setenv("MESHCODE_PROJECT", "test")
11
+ monkeypatch.setenv("MESHCODE_AGENT", "test")
12
+ monkeypatch.setenv("MESHCODE_PROJECT_ID", "00000000-0000-0000-0000-000000000000")
13
+ yield
14
+
15
+
16
+ def test_hex_to_ansi_truecolor_format(monkeypatch):
17
+ from meshcode.meshcode_mcp import server as srv
18
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", True)
19
+ assert srv._hex_to_ansi("#E53935") == "\033[38;2;229;57;53m"
20
+ assert srv._hex_to_ansi("E53935") == "\033[38;2;229;57;53m"
21
+
22
+
23
+ def test_hex_to_ansi_4bit_fallback(monkeypatch):
24
+ from meshcode.meshcode_mcp import server as srv
25
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", False)
26
+ result = srv._hex_to_ansi("#E53935")
27
+ # 4-bit ANSI escape, one of the palette entries
28
+ assert result in srv._ANSI_COLORS
29
+ assert result.startswith("\033[")
30
+
31
+
32
+ def test_hex_to_ansi_malformed_returns_none(monkeypatch):
33
+ from meshcode.meshcode_mcp import server as srv
34
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", True)
35
+ assert srv._hex_to_ansi("not-hex") is None
36
+ assert srv._hex_to_ansi("#zzzzzz") is None
37
+
38
+
39
+ def test_agent_color_deterministic_truecolor(monkeypatch):
40
+ """Same name → same color across calls in truecolor mode."""
41
+ from meshcode.meshcode_mcp import server as srv
42
+ monkeypatch.setattr(srv, "_CACHED_AGENT_COLOR", None)
43
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", True)
44
+ a = srv._agent_color("commander")
45
+ b = srv._agent_color("commander")
46
+ assert a == b
47
+ assert a.startswith("\033[38;2;") # truecolor
48
+
49
+
50
+ def test_agent_color_deterministic_4bit(monkeypatch):
51
+ from meshcode.meshcode_mcp import server as srv
52
+ monkeypatch.setattr(srv, "_CACHED_AGENT_COLOR", None)
53
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", False)
54
+ a = srv._agent_color("commander")
55
+ b = srv._agent_color("commander")
56
+ assert a == b
57
+ assert a in srv._ANSI_COLORS
58
+
59
+
60
+ def test_agent_color_cached_overrides(monkeypatch):
61
+ """If _CACHED_AGENT_COLOR is set (from profile fetch), use that."""
62
+ from meshcode.meshcode_mcp import server as srv
63
+ monkeypatch.setattr(srv, "_CACHED_AGENT_COLOR", "\033[38;2;100;200;50m")
64
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", True)
65
+ assert srv._agent_color("any-name") == "\033[38;2;100;200;50m"
66
+
67
+
68
+ def test_agent_color_clamped_to_mid_range(monkeypatch):
69
+ """Truecolor RGB components clamped to [70, 220] for readability on
70
+ both dark and light terminals."""
71
+ from meshcode.meshcode_mcp import server as srv
72
+ monkeypatch.setattr(srv, "_CACHED_AGENT_COLOR", None)
73
+ monkeypatch.setattr(srv, "_TRUECOLOR_OK", True)
74
+ # Try many names to exercise the clamp
75
+ for name in ("a", "bbbb", "cccccc", "dddddddd", "eeeeeeeeee"):
76
+ c = srv._agent_color(name)
77
+ # Parse the \033[38;2;R;G;Bm
78
+ body = c.lstrip("\033[").rstrip("m")
79
+ parts = body.split(";")
80
+ r, g, b = int(parts[2]), int(parts[3]), int(parts[4])
81
+ assert 70 <= r <= 220, f"R={r} out of range for {name}"
82
+ assert 70 <= g <= 220, f"G={g} out of range for {name}"
83
+ assert 70 <= b <= 220, f"B={b} out of range for {name}"
@@ -0,0 +1,66 @@
1
+ """Tests for B5 — `meshcode setup-path` subcommand."""
2
+ import os
3
+ import subprocess
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ import pytest
8
+
9
+
10
+ def _run_setup_path(env_overrides: dict, expect_exit: int) -> tuple[str, str, int]:
11
+ """Spawn `python -m meshcode.comms_v4 setup-path` in subprocess for
12
+ isolation (avoids polluting parent env / sys.argv). Returns (stdout, stderr, rc)."""
13
+ env = {**os.environ, **env_overrides}
14
+ env.setdefault("MESHCODE_PROJECT", "test")
15
+ env.setdefault("MESHCODE_AGENT", "test")
16
+ cmd = [sys.executable, "-m", "meshcode.comms_v4", "setup-path"]
17
+ r = subprocess.run(cmd, env=env, capture_output=True, text=True, timeout=10)
18
+ assert r.returncode == expect_exit, f"rc={r.returncode}, stdout={r.stdout!r}, stderr={r.stderr!r}"
19
+ return r.stdout, r.stderr, r.returncode
20
+
21
+
22
+ def test_setup_path_writes_zsh_rc(tmp_path):
23
+ rc = tmp_path / ".zshrc"
24
+ out, err, _ = _run_setup_path(
25
+ {"HOME": str(tmp_path), "SHELL": "/bin/zsh"},
26
+ expect_exit=0,
27
+ )
28
+ assert rc.exists(), f"expected rc at {rc}"
29
+ body = rc.read_text()
30
+ assert "meshcode: PATH" in body
31
+ assert 'export PATH="' in body
32
+ assert "Appended" in out
33
+
34
+
35
+ def test_setup_path_idempotent(tmp_path):
36
+ """Running twice must not duplicate the export block."""
37
+ env = {"HOME": str(tmp_path), "SHELL": "/bin/zsh"}
38
+ _run_setup_path(env, expect_exit=0)
39
+ body1 = (tmp_path / ".zshrc").read_text()
40
+ out, _, _ = _run_setup_path(env, expect_exit=0)
41
+ body2 = (tmp_path / ".zshrc").read_text()
42
+ assert body1 == body2, "second run must not modify rc"
43
+ assert "already exports" in out
44
+
45
+
46
+ def test_setup_path_writes_fish_config(tmp_path):
47
+ rc = tmp_path / ".config" / "fish" / "config.fish"
48
+ _run_setup_path(
49
+ {"HOME": str(tmp_path), "SHELL": "/usr/local/bin/fish"},
50
+ expect_exit=0,
51
+ )
52
+ assert rc.exists()
53
+ body = rc.read_text()
54
+ assert "set -gx PATH" in body
55
+ assert "meshcode: PATH" in body
56
+
57
+
58
+ def test_setup_path_writes_bash_rc(tmp_path):
59
+ rc = tmp_path / ".bashrc"
60
+ _run_setup_path(
61
+ {"HOME": str(tmp_path), "SHELL": "/bin/bash"},
62
+ expect_exit=0,
63
+ )
64
+ assert rc.exists()
65
+ body = rc.read_text()
66
+ assert 'export PATH="' in body
File without changes
File without changes