agentirc-cli 4.1.2__tar.gz → 4.1.3__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 (308) hide show
  1. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/CHANGELOG.md +7 -0
  2. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/PKG-INFO +1 -1
  3. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/mesh.py +64 -11
  4. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/mesh_config.py +9 -0
  5. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/cli.md +5 -2
  6. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/pyproject.toml +1 -1
  7. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_mesh_config.py +37 -0
  8. agentirc_cli-4.1.3/tests/test_setup_update_cli.py +185 -0
  9. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/uv.lock +1 -1
  10. agentirc_cli-4.1.2/tests/test_setup_update_cli.py +0 -45
  11. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.claude/skills/pr-review/SKILL.md +0 -0
  12. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.claude/skills/run-tests/SKILL.md +0 -0
  13. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.claude/skills/run-tests/scripts/test.sh +0 -0
  14. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.flake8 +0 -0
  15. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.github/workflows/pages.yml +0 -0
  16. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.github/workflows/publish.yml +0 -0
  17. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.github/workflows/security-checks.yml +0 -0
  18. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.github/workflows/tests.yml +0 -0
  19. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.gitignore +0 -0
  20. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.markdownlint-cli2.yaml +0 -0
  21. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.pr_agent.toml +0 -0
  22. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.pre-commit-config.yaml +0 -0
  23. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/.pylintrc +0 -0
  24. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/CLAUDE.md +0 -0
  25. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/CNAME +0 -0
  26. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/Gemfile +0 -0
  27. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/Gemfile.lock +0 -0
  28. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/LICENSE +0 -0
  29. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/README.md +0 -0
  30. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/SECURITY.md +0 -0
  31. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/_config.yml +0 -0
  32. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/_sass/color_schemes/anthropic.scss +0 -0
  33. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/_sass/custom/custom.scss +0 -0
  34. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/__init__.py +0 -0
  35. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/__main__.py +0 -0
  36. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/__init__.py +0 -0
  37. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/bot.py +0 -0
  38. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/bot_manager.py +0 -0
  39. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/config.py +0 -0
  40. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/http_listener.py +0 -0
  41. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/template_engine.py +0 -0
  42. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/bots/virtual_client.py +0 -0
  43. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/__init__.py +0 -0
  44. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/_helpers.py +0 -0
  45. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/agent.py +0 -0
  46. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/bot.py +0 -0
  47. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/channel.py +0 -0
  48. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/server.py +0 -0
  49. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/cli/skills.py +0 -0
  50. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/__init__.py +0 -0
  51. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/__init__.py +0 -0
  52. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/agent_runner.py +0 -0
  53. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/config.py +0 -0
  54. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/daemon.py +0 -0
  55. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/ipc.py +0 -0
  56. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/irc_transport.py +0 -0
  57. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/message_buffer.py +0 -0
  58. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/skill/SKILL.md +0 -0
  59. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/skill/__init__.py +0 -0
  60. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/skill/irc_client.py +0 -0
  61. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/socket_server.py +0 -0
  62. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/supervisor.py +0 -0
  63. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/acp/webhook.py +0 -0
  64. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/__init__.py +0 -0
  65. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/__main__.py +0 -0
  66. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/agent_runner.py +0 -0
  67. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/config.py +0 -0
  68. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/daemon.py +0 -0
  69. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/ipc.py +0 -0
  70. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/irc_transport.py +0 -0
  71. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/message_buffer.py +0 -0
  72. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/skill/SKILL.md +0 -0
  73. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/skill/__init__.py +0 -0
  74. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/skill/irc_client.py +0 -0
  75. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/socket_server.py +0 -0
  76. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/supervisor.py +0 -0
  77. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/claude/webhook.py +0 -0
  78. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/__init__.py +0 -0
  79. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/agent_runner.py +0 -0
  80. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/config.py +0 -0
  81. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/daemon.py +0 -0
  82. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/ipc.py +0 -0
  83. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/irc_transport.py +0 -0
  84. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/message_buffer.py +0 -0
  85. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/skill/SKILL.md +0 -0
  86. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/skill/__init__.py +0 -0
  87. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/skill/irc_client.py +0 -0
  88. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/socket_server.py +0 -0
  89. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/supervisor.py +0 -0
  90. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/codex/webhook.py +0 -0
  91. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/__init__.py +0 -0
  92. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/agent_runner.py +0 -0
  93. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/config.py +0 -0
  94. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/daemon.py +0 -0
  95. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/ipc.py +0 -0
  96. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/irc_transport.py +0 -0
  97. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/message_buffer.py +0 -0
  98. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/skill/SKILL.md +0 -0
  99. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/skill/__init__.py +0 -0
  100. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/skill/irc_client.py +0 -0
  101. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/socket_server.py +0 -0
  102. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/supervisor.py +0 -0
  103. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/clients/copilot/webhook.py +0 -0
  104. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/__init__.py +0 -0
  105. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/app.py +0 -0
  106. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/client.py +0 -0
  107. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/commands.py +0 -0
  108. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/widgets/__init__.py +0 -0
  109. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/widgets/chat.py +0 -0
  110. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/widgets/info_panel.py +0 -0
  111. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/console/widgets/sidebar.py +0 -0
  112. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/credentials.py +0 -0
  113. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/learn_prompt.py +0 -0
  114. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/observer.py +0 -0
  115. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/__init__.py +0 -0
  116. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/collector.py +0 -0
  117. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/model.py +0 -0
  118. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/renderer_text.py +0 -0
  119. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/renderer_web.py +0 -0
  120. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/overview/web/style.css +0 -0
  121. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/persistence.py +0 -0
  122. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/pidfile.py +0 -0
  123. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/__init__.py +0 -0
  124. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/commands.py +0 -0
  125. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/federation.md +0 -0
  126. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/history.md +0 -0
  127. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/icons.md +0 -0
  128. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/rooms.md +0 -0
  129. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/tags.md +0 -0
  130. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/extensions/threads.md +0 -0
  131. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/message.py +0 -0
  132. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/protocol-index.md +0 -0
  133. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/protocol/replies.py +0 -0
  134. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/__init__.py +0 -0
  135. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/__main__.py +0 -0
  136. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/channel.py +0 -0
  137. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/client.py +0 -0
  138. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/config.py +0 -0
  139. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/ircd.py +0 -0
  140. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/remote_client.py +0 -0
  141. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/room_store.py +0 -0
  142. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/rooms_util.py +0 -0
  143. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/server_link.py +0 -0
  144. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skill.py +0 -0
  145. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skills/__init__.py +0 -0
  146. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skills/history.py +0 -0
  147. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skills/icon.py +0 -0
  148. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skills/rooms.py +0 -0
  149. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/skills/threads.py +0 -0
  150. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/server/thread_store.py +0 -0
  151. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/culture/skills/culture/SKILL.md +0 -0
  152. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/agent-lifecycle.md +0 -0
  153. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/agentic-self-learn.md +0 -0
  154. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/agent-client.md +0 -0
  155. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/agent-harness-spec.md +0 -0
  156. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/design.md +0 -0
  157. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/harness-conformance.md +0 -0
  158. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/index.md +0 -0
  159. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/layer1-core-irc.md +0 -0
  160. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/layer2-attention.md +0 -0
  161. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/layer3-skills.md +0 -0
  162. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/layer4-federation.md +0 -0
  163. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/layer5-agent-harness.md +0 -0
  164. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/server-architecture.md +0 -0
  165. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/architecture/threads.md +0 -0
  166. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/channel-polling.md +0 -0
  167. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/acp/overview.md +0 -0
  168. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/configuration.md +0 -0
  169. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/context-management.md +0 -0
  170. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/irc-tools.md +0 -0
  171. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/overview.md +0 -0
  172. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/setup.md +0 -0
  173. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/supervisor.md +0 -0
  174. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/claude/webhooks.md +0 -0
  175. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/configuration.md +0 -0
  176. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/context-management.md +0 -0
  177. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/irc-tools.md +0 -0
  178. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/overview.md +0 -0
  179. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/setup.md +0 -0
  180. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/supervisor.md +0 -0
  181. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/codex/webhooks.md +0 -0
  182. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/configuration.md +0 -0
  183. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/context-management.md +0 -0
  184. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/irc-tools.md +0 -0
  185. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/overview.md +0 -0
  186. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/setup.md +0 -0
  187. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/supervisor.md +0 -0
  188. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/clients/copilot/webhooks.md +0 -0
  189. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/culture-cli.md +0 -0
  190. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/getting-started.md +0 -0
  191. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/index.md +0 -0
  192. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/SECURITY.md +0 -0
  193. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/bots.md +0 -0
  194. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/ci.md +0 -0
  195. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/docs-site.md +0 -0
  196. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/index.md +0 -0
  197. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/ops-tooling.md +0 -0
  198. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/overview.md +0 -0
  199. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/operations/publishing.md +0 -0
  200. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  201. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/rooms.md +0 -0
  202. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/server-rename.md +0 -0
  203. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  204. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  205. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  206. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  207. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  208. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  209. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  210. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  211. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  212. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  213. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  214. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  215. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  216. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  217. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  218. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  219. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  220. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  221. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  222. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  223. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  224. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/01-pair-programming.md +0 -0
  225. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/02-code-review-ensemble.md +0 -0
  226. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/03-cross-server-delegation.md +0 -0
  227. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/04-knowledge-propagation.md +0 -0
  228. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/05-the-observer.md +0 -0
  229. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/06-cross-server-ops.md +0 -0
  230. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/07-supervisor-intervention.md +0 -0
  231. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/08-apps-as-agents.md +0 -0
  232. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/09-research-swarm.md +0 -0
  233. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases/10-agent-lifecycle.md +0 -0
  234. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/use-cases-index.md +0 -0
  235. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/docs/what-is-culture.md +0 -0
  236. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/README.md +0 -0
  237. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/config.py +0 -0
  238. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/daemon.py +0 -0
  239. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/ipc.py +0 -0
  240. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/irc_transport.py +0 -0
  241. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/message_buffer.py +0 -0
  242. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/skill/SKILL.md +0 -0
  243. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/skill/irc_client.py +0 -0
  244. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/socket_server.py +0 -0
  245. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/packages/agent-harness/webhook.py +0 -0
  246. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  247. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  248. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  249. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  250. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/sonar-project.properties +0 -0
  251. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/__init__.py +0 -0
  252. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/conftest.py +0 -0
  253. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_acp_daemon.py +0 -0
  254. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_agent_runner.py +0 -0
  255. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_bot.py +0 -0
  256. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_bot_config.py +0 -0
  257. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_bot_manager.py +0 -0
  258. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_bots_integration.py +0 -0
  259. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_channel.py +0 -0
  260. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_codex_daemon.py +0 -0
  261. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_connection.py +0 -0
  262. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_console_client.py +0 -0
  263. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_console_commands.py +0 -0
  264. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_console_connection.py +0 -0
  265. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_console_icons.py +0 -0
  266. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_console_integration.py +0 -0
  267. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_copilot_daemon.py +0 -0
  268. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_daemon.py +0 -0
  269. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_daemon_config.py +0 -0
  270. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_daemon_ipc.py +0 -0
  271. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_discovery.py +0 -0
  272. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_federation.py +0 -0
  273. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_history.py +0 -0
  274. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_http_listener.py +0 -0
  275. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_integration_layer5.py +0 -0
  276. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_ipc.py +0 -0
  277. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_irc_transport.py +0 -0
  278. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_link_reconnect.py +0 -0
  279. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_mention_alias.py +0 -0
  280. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_mention_target_cleanup.py +0 -0
  281. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_mentions.py +0 -0
  282. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_message.py +0 -0
  283. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_message_buffer.py +0 -0
  284. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_messaging.py +0 -0
  285. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_modes.py +0 -0
  286. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_overview_cli.py +0 -0
  287. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_overview_collector.py +0 -0
  288. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_overview_model.py +0 -0
  289. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_overview_renderer.py +0 -0
  290. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_overview_web.py +0 -0
  291. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_persistence.py +0 -0
  292. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_pidfile.py +0 -0
  293. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_poll_loop.py +0 -0
  294. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_room_persistence.py +0 -0
  295. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_rooms.py +0 -0
  296. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_rooms_federation.py +0 -0
  297. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_rooms_integration.py +0 -0
  298. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_server_icon_skill.py +0 -0
  299. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_skill_client.py +0 -0
  300. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_skills.py +0 -0
  301. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_socket_server.py +0 -0
  302. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_supervisor.py +0 -0
  303. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_template_engine.py +0 -0
  304. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_thread_buffer.py +0 -0
  305. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_threads.py +0 -0
  306. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_virtual_client.py +0 -0
  307. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_wait_for_port.py +0 -0
  308. {agentirc_cli-4.1.2 → agentirc_cli-4.1.3}/tests/test_webhook.py +0 -0
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
+ ## [4.1.3] - 2026-04-06
8
+
9
+
10
+ ### Fixed
11
+
12
+ - mesh update now discovers and restarts all running servers instead of only the one in mesh.yaml
13
+
7
14
  ## [4.1.2] - 2026-04-06
8
15
 
9
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 4.1.2
3
+ Version: 4.1.3
4
4
  Summary: Legacy alias for culture — install culture instead
5
5
  Project-URL: Homepage, https://github.com/OriNachum/culture
6
6
  Author: Ori Nachum
@@ -549,23 +549,76 @@ def _restart_mesh_services(
549
549
  check=False,
550
550
  )
551
551
 
552
- print("\nUpdate complete. All services restarted.")
553
-
554
-
555
- def _cmd_update(args: argparse.Namespace) -> None:
556
- from culture.mesh_config import load_mesh_config
552
+ print()
553
+
554
+
555
+ def _resolve_mesh_for_server(server_name: str, config_path: str):
556
+ """Find or build a MeshConfig for *server_name*.
557
+
558
+ Resolution order:
559
+ 1. mesh.yaml — use directly if its server.name matches.
560
+ 2. agents.yaml — build via from_daemon_config(), preserving host, port,
561
+ and links from the old mesh.yaml. Saves the updated mesh.yaml so
562
+ future runs are consistent.
563
+ """
564
+ from culture.mesh_config import (
565
+ from_daemon_config,
566
+ load_mesh_config,
567
+ merge_links,
568
+ save_mesh_config,
569
+ )
557
570
 
571
+ old_server = None
558
572
  try:
559
- mesh = load_mesh_config(args.config)
573
+ old_mesh = load_mesh_config(config_path)
574
+ if old_mesh.server.name == server_name:
575
+ return old_mesh
576
+ old_server = old_mesh.server
560
577
  except FileNotFoundError:
561
- mesh = generate_mesh_from_agents(args.config)
562
- if mesh is None:
563
- sys.exit(1)
578
+ pass
579
+
580
+ if os.path.isfile(DEFAULT_CONFIG):
581
+ daemon_config = load_config(DEFAULT_CONFIG)
582
+ if daemon_config.server.name == server_name:
583
+ mesh = from_daemon_config(daemon_config)
584
+ if old_server is not None:
585
+ mesh.server.host = old_server.host
586
+ mesh.server.port = old_server.port
587
+ merge_links(mesh, old_server.links)
588
+ save_mesh_config(mesh, config_path)
589
+ return mesh
590
+
591
+ return None
564
592
 
565
- server_name = mesh.server.name
593
+
594
+ def _cmd_update(args: argparse.Namespace) -> None:
595
+ from culture.mesh_config import load_mesh_config
596
+ from culture.pidfile import list_servers
566
597
 
567
598
  if not _upgrade_culture_package(args):
568
599
  return
569
600
 
570
601
  culture_bin = shutil.which("culture") or "culture"
571
- _restart_mesh_services(mesh, server_name, culture_bin, args.config, args.dry_run)
602
+
603
+ running = list_servers()
604
+
605
+ if running:
606
+ for srv in running:
607
+ mesh = _resolve_mesh_for_server(srv["name"], args.config)
608
+ if mesh is None:
609
+ print(
610
+ f" Warning: no config found for server '{srv['name']}', skipping",
611
+ file=sys.stderr,
612
+ )
613
+ continue
614
+ _restart_mesh_services(mesh, srv["name"], culture_bin, args.config, args.dry_run)
615
+ else:
616
+ try:
617
+ mesh = load_mesh_config(args.config)
618
+ except FileNotFoundError:
619
+ mesh = generate_mesh_from_agents(args.config)
620
+ if mesh is None:
621
+ sys.exit(1)
622
+ _restart_mesh_services(mesh, mesh.server.name, culture_bin, args.config, args.dry_run)
623
+
624
+ print("Update complete. All services restarted.")
@@ -108,6 +108,15 @@ def from_daemon_config(daemon_config: DaemonConfig) -> MeshConfig:
108
108
  return MeshConfig(server=server, agents=agents)
109
109
 
110
110
 
111
+ def merge_links(target: MeshConfig, source_links: list[MeshLinkConfig]) -> None:
112
+ """Copy link configs from *source_links* into *target* if not already present."""
113
+ existing = {link.name for link in target.server.links}
114
+ for link in source_links:
115
+ if link.name not in existing:
116
+ target.server.links.append(link)
117
+ existing.add(link.name)
118
+
119
+
111
120
  def save_mesh_config(config: MeshConfig, path: str | Path = DEFAULT_MESH_PATH) -> None:
112
121
  """Serialize mesh config to YAML and write atomically."""
113
122
  path = Path(path)
@@ -288,8 +288,11 @@ walkthrough.
288
288
 
289
289
  ### `culture update`
290
290
 
291
- Upgrade the `culture` package and restart all mesh services defined in
292
- `mesh.yaml`.
291
+ Upgrade the `culture` package and restart all running servers. The command
292
+ discovers running servers from PID files rather than relying solely on
293
+ `mesh.yaml`, so it restarts every server on the machine even if `mesh.yaml`
294
+ is stale or names a different server. When no servers are running, it falls
295
+ back to `mesh.yaml`.
293
296
 
294
297
  ```bash
295
298
  culture update # upgrade package + restart everything
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentirc-cli"
3
- version = "4.1.2"
3
+ version = "4.1.3"
4
4
  description = "Legacy alias for culture — install culture instead"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -11,6 +11,7 @@ from culture.mesh_config import (
11
11
  MeshServerConfig,
12
12
  from_daemon_config,
13
13
  load_mesh_config,
14
+ merge_links,
14
15
  save_mesh_config,
15
16
  )
16
17
 
@@ -153,3 +154,39 @@ def test_from_daemon_config_empty_agents():
153
154
  assert mesh.server.name == "test"
154
155
  assert mesh.server.port == 7000
155
156
  assert mesh.agents == []
157
+
158
+
159
+ def test_merge_links_appends_missing():
160
+ """merge_links adds links not already present."""
161
+ target = MeshConfig(
162
+ server=MeshServerConfig(
163
+ name="spark",
164
+ links=[MeshLinkConfig(name="thor", host="1.2.3.4", port=6667)],
165
+ ),
166
+ )
167
+ source = [
168
+ MeshLinkConfig(name="orin", host="5.6.7.8", port=6668),
169
+ ]
170
+ merge_links(target, source)
171
+ assert len(target.server.links) == 2
172
+ assert target.server.links[1].name == "orin"
173
+
174
+
175
+ def test_merge_links_skips_duplicates():
176
+ """merge_links does not duplicate links already present."""
177
+ target = MeshConfig(
178
+ server=MeshServerConfig(
179
+ name="spark",
180
+ links=[MeshLinkConfig(name="thor", host="1.2.3.4", port=6667)],
181
+ ),
182
+ )
183
+ source = [
184
+ MeshLinkConfig(name="thor", host="9.9.9.9", port=9999),
185
+ MeshLinkConfig(name="orin", host="5.6.7.8", port=6668),
186
+ ]
187
+ merge_links(target, source)
188
+ assert len(target.server.links) == 2
189
+ names = [l.name for l in target.server.links]
190
+ assert names == ["thor", "orin"]
191
+ # Original thor link is unchanged
192
+ assert target.server.links[0].host == "1.2.3.4"
@@ -0,0 +1,185 @@
1
+ # tests/test_setup_update_cli.py
2
+ """Lightweight parser tests for setup and update subcommands."""
3
+
4
+ from unittest.mock import patch
5
+
6
+ import pytest
7
+
8
+ from culture.cli import _build_parser
9
+ from culture.mesh_config import MeshAgentConfig, MeshConfig, MeshLinkConfig, MeshServerConfig
10
+
11
+
12
+ def test_setup_parser():
13
+ """setup subcommand parses --config and --uninstall."""
14
+ p = _build_parser()
15
+ args = p.parse_args(["mesh", "setup", "--uninstall"])
16
+ assert args.command == "mesh"
17
+ assert args.mesh_command == "setup"
18
+ assert args.uninstall is True
19
+
20
+ args = p.parse_args(["mesh", "setup", "--config", "/tmp/mesh.yaml"])
21
+ assert args.config == "/tmp/mesh.yaml"
22
+
23
+
24
+ def test_update_parser():
25
+ """update subcommand parses --dry-run, --skip-upgrade, --config."""
26
+ p = _build_parser()
27
+ args = p.parse_args(["mesh", "update", "--dry-run", "--skip-upgrade"])
28
+ assert args.command == "mesh"
29
+ assert args.mesh_command == "update"
30
+ assert args.dry_run is True
31
+ assert args.skip_upgrade is True
32
+
33
+ args = p.parse_args(["mesh", "update", "--config", "/tmp/mesh.yaml"])
34
+ assert args.config == "/tmp/mesh.yaml"
35
+
36
+
37
+ def test_setup_in_dispatch():
38
+ """setup command is wired into the mesh module."""
39
+ from culture.cli import mesh
40
+
41
+ assert hasattr(mesh, "_cmd_setup")
42
+ assert callable(mesh._cmd_setup)
43
+
44
+
45
+ def test_update_in_dispatch():
46
+ """update command is wired into the mesh module."""
47
+ from culture.cli import mesh
48
+
49
+ assert hasattr(mesh, "_cmd_update")
50
+ assert callable(mesh._cmd_update)
51
+
52
+
53
+ # ---- _cmd_update behaviour tests ----
54
+
55
+ _MESH_MOD = "culture.cli.mesh"
56
+
57
+
58
+ @pytest.fixture
59
+ def update_args(tmp_path):
60
+ """Minimal argparse namespace for _cmd_update."""
61
+ p = _build_parser()
62
+ config = str(tmp_path / "mesh.yaml")
63
+ return p.parse_args(["mesh", "update", "--skip-upgrade", "--dry-run", "--config", config])
64
+
65
+
66
+ @patch("culture.pidfile.list_servers")
67
+ @patch(f"{_MESH_MOD}._resolve_mesh_for_server")
68
+ @patch(f"{_MESH_MOD}._restart_mesh_services")
69
+ @patch(f"{_MESH_MOD}._upgrade_culture_package", return_value=True)
70
+ def test_update_discovers_running_servers(
71
+ _mock_upgrade, mock_restart, mock_resolve, mock_list, update_args
72
+ ):
73
+ """_cmd_update restarts every running server, not just mesh.yaml."""
74
+ from culture.cli.mesh import _cmd_update
75
+
76
+ spark_mesh = MeshConfig(server=MeshServerConfig(name="spark"))
77
+ mock_list.return_value = [{"name": "spark", "pid": 1, "port": 6667}]
78
+ mock_resolve.return_value = spark_mesh
79
+
80
+ _cmd_update(update_args)
81
+
82
+ mock_resolve.assert_called_once_with("spark", update_args.config)
83
+ mock_restart.assert_called_once()
84
+ assert mock_restart.call_args[0][1] == "spark"
85
+
86
+
87
+ @patch("culture.pidfile.list_servers", return_value=[])
88
+ @patch("culture.mesh_config.load_mesh_config")
89
+ @patch(f"{_MESH_MOD}._restart_mesh_services")
90
+ @patch(f"{_MESH_MOD}._upgrade_culture_package", return_value=True)
91
+ def test_update_falls_back_to_mesh_yaml_when_no_servers(
92
+ _mock_upgrade, mock_restart, mock_load, _mock_list, update_args
93
+ ):
94
+ """When no servers are running, fall back to mesh.yaml."""
95
+ from culture.cli.mesh import _cmd_update
96
+
97
+ mesh = MeshConfig(server=MeshServerConfig(name="culture"))
98
+ mock_load.return_value = mesh
99
+
100
+ _cmd_update(update_args)
101
+
102
+ mock_load.assert_called_once_with(update_args.config)
103
+ mock_restart.assert_called_once()
104
+ assert mock_restart.call_args[0][1] == "culture"
105
+
106
+
107
+ @patch("culture.pidfile.list_servers")
108
+ @patch(f"{_MESH_MOD}._restart_mesh_services")
109
+ @patch(f"{_MESH_MOD}._upgrade_culture_package", return_value=True)
110
+ def test_update_skips_server_without_config(
111
+ _mock_upgrade, mock_restart, mock_list, update_args, capsys
112
+ ):
113
+ """Servers with no matching config are skipped with a warning."""
114
+ from culture.cli.mesh import _cmd_update
115
+
116
+ mock_list.return_value = [{"name": "unknown", "pid": 1, "port": 6667}]
117
+
118
+ with patch(f"{_MESH_MOD}._resolve_mesh_for_server", return_value=None):
119
+ _cmd_update(update_args)
120
+
121
+ mock_restart.assert_not_called()
122
+ assert "no config found" in capsys.readouterr().err
123
+
124
+
125
+ # ---- _resolve_mesh_for_server tests ----
126
+
127
+
128
+ def test_resolve_uses_mesh_yaml_when_name_matches(tmp_path):
129
+ """_resolve_mesh_for_server returns mesh.yaml config when server name matches."""
130
+ from culture.cli.mesh import _resolve_mesh_for_server
131
+
132
+ mesh = MeshConfig(
133
+ server=MeshServerConfig(name="spark", links=[MeshLinkConfig(name="thor", host="1.2.3.4")]),
134
+ agents=[MeshAgentConfig(nick="claude", workdir="/tmp")],
135
+ )
136
+ config_path = str(tmp_path / "mesh.yaml")
137
+ from culture.mesh_config import save_mesh_config
138
+
139
+ save_mesh_config(mesh, config_path)
140
+
141
+ result = _resolve_mesh_for_server("spark", config_path)
142
+ assert result is not None
143
+ assert result.server.name == "spark"
144
+ assert len(result.server.links) == 1
145
+
146
+
147
+ def test_resolve_rebuilds_from_agents_yaml_preserving_links(tmp_path):
148
+ """When mesh.yaml has wrong name, rebuild from agents.yaml and keep links."""
149
+ from culture.cli.mesh import _resolve_mesh_for_server
150
+ from culture.clients.claude.config import AgentConfig, DaemonConfig, ServerConnConfig
151
+ from culture.mesh_config import save_mesh_config
152
+
153
+ # mesh.yaml says "culture" but running server is "spark"
154
+ old_mesh = MeshConfig(
155
+ server=MeshServerConfig(
156
+ name="culture",
157
+ host="127.0.0.1",
158
+ port=7000,
159
+ links=[MeshLinkConfig(name="thor", host="1.2.3.4")],
160
+ ),
161
+ )
162
+ config_path = str(tmp_path / "mesh.yaml")
163
+ save_mesh_config(old_mesh, config_path)
164
+
165
+ # agents.yaml says "spark"
166
+ daemon = DaemonConfig(
167
+ server=ServerConnConfig(name="spark", host="localhost", port=6667),
168
+ agents=[AgentConfig(nick="spark-claude", agent="claude", directory="/tmp")],
169
+ )
170
+
171
+ with patch(f"{_MESH_MOD}.DEFAULT_CONFIG", str(tmp_path / "agents.yaml")):
172
+ from culture.clients.claude.config import save_config
173
+
174
+ save_config(str(tmp_path / "agents.yaml"), daemon)
175
+ result = _resolve_mesh_for_server("spark", config_path)
176
+
177
+ assert result is not None
178
+ assert result.server.name == "spark"
179
+ assert len(result.agents) == 1
180
+ assert result.agents[0].nick == "claude"
181
+ # Server settings from old mesh.yaml are preserved
182
+ assert result.server.host == "127.0.0.1"
183
+ assert result.server.port == 7000
184
+ assert len(result.server.links) == 1
185
+ assert result.server.links[0].name == "thor"
@@ -561,7 +561,7 @@ wheels = [
561
561
 
562
562
  [[package]]
563
563
  name = "culture"
564
- version = "4.1.2"
564
+ version = "4.1.3"
565
565
  source = { editable = "." }
566
566
  dependencies = [
567
567
  { name = "aiohttp" },
@@ -1,45 +0,0 @@
1
- # tests/test_setup_update_cli.py
2
- """Lightweight parser tests for setup and update subcommands."""
3
-
4
- from culture.cli import _build_parser
5
-
6
-
7
- def test_setup_parser():
8
- """setup subcommand parses --config and --uninstall."""
9
- p = _build_parser()
10
- args = p.parse_args(["mesh", "setup", "--uninstall"])
11
- assert args.command == "mesh"
12
- assert args.mesh_command == "setup"
13
- assert args.uninstall is True
14
-
15
- args = p.parse_args(["mesh", "setup", "--config", "/tmp/mesh.yaml"])
16
- assert args.config == "/tmp/mesh.yaml"
17
-
18
-
19
- def test_update_parser():
20
- """update subcommand parses --dry-run, --skip-upgrade, --config."""
21
- p = _build_parser()
22
- args = p.parse_args(["mesh", "update", "--dry-run", "--skip-upgrade"])
23
- assert args.command == "mesh"
24
- assert args.mesh_command == "update"
25
- assert args.dry_run is True
26
- assert args.skip_upgrade is True
27
-
28
- args = p.parse_args(["mesh", "update", "--config", "/tmp/mesh.yaml"])
29
- assert args.config == "/tmp/mesh.yaml"
30
-
31
-
32
- def test_setup_in_dispatch():
33
- """setup command is wired into the mesh module."""
34
- from culture.cli import mesh
35
-
36
- assert hasattr(mesh, "_cmd_setup")
37
- assert callable(mesh._cmd_setup)
38
-
39
-
40
- def test_update_in_dispatch():
41
- """update command is wired into the mesh module."""
42
- from culture.cli import mesh
43
-
44
- assert hasattr(mesh, "_cmd_update")
45
- assert callable(mesh._cmd_update)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes